should be it
This commit is contained in:
764
external/duckdb/third_party/tpce-tool/include/main/CustomerAccountsAndPermissionsTable.h
vendored
Normal file
764
external/duckdb/third_party/tpce-tool/include/main/CustomerAccountsAndPermissionsTable.h
vendored
Normal file
@@ -0,0 +1,764 @@
|
||||
/*
|
||||
* Legal Notice
|
||||
*
|
||||
* This document and associated source code (the "Work") is a part of a
|
||||
* benchmark specification maintained by the TPC.
|
||||
*
|
||||
* The TPC reserves all right, title, and interest to the Work as provided
|
||||
* under U.S. and international laws, including without limitation all patent
|
||||
* and trademark rights therein.
|
||||
*
|
||||
* No Warranty
|
||||
*
|
||||
* 1.1 TO THE MAXIMUM EXTENT PERMITTED BY APPLICABLE LAW, THE INFORMATION
|
||||
* CONTAINED HEREIN IS PROVIDED "AS IS" AND WITH ALL FAULTS, AND THE
|
||||
* AUTHORS AND DEVELOPERS OF THE WORK HEREBY DISCLAIM ALL OTHER
|
||||
* WARRANTIES AND CONDITIONS, EITHER EXPRESS, IMPLIED OR STATUTORY,
|
||||
* INCLUDING, BUT NOT LIMITED TO, ANY (IF ANY) IMPLIED WARRANTIES,
|
||||
* DUTIES OR CONDITIONS OF MERCHANTABILITY, OF FITNESS FOR A PARTICULAR
|
||||
* PURPOSE, OF ACCURACY OR COMPLETENESS OF RESPONSES, OF RESULTS, OF
|
||||
* WORKMANLIKE EFFORT, OF LACK OF VIRUSES, AND OF LACK OF NEGLIGENCE.
|
||||
* ALSO, THERE IS NO WARRANTY OR CONDITION OF TITLE, QUIET ENJOYMENT,
|
||||
* QUIET POSSESSION, CORRESPONDENCE TO DESCRIPTION OR NON-INFRINGEMENT
|
||||
* WITH REGARD TO THE WORK.
|
||||
* 1.2 IN NO EVENT WILL ANY AUTHOR OR DEVELOPER OF THE WORK BE LIABLE TO
|
||||
* ANY OTHER PARTY FOR ANY DAMAGES, INCLUDING BUT NOT LIMITED TO THE
|
||||
* COST OF PROCURING SUBSTITUTE GOODS OR SERVICES, LOST PROFITS, LOSS
|
||||
* OF USE, LOSS OF DATA, OR ANY INCIDENTAL, CONSEQUENTIAL, DIRECT,
|
||||
* INDIRECT, OR SPECIAL DAMAGES WHETHER UNDER CONTRACT, TORT, WARRANTY,
|
||||
* OR OTHERWISE, ARISING IN ANY WAY OUT OF THIS OR ANY OTHER AGREEMENT
|
||||
* RELATING TO THE WORK, WHETHER OR NOT SUCH AUTHOR OR DEVELOPER HAD
|
||||
* ADVANCE NOTICE OF THE POSSIBILITY OF SUCH DAMAGES.
|
||||
*
|
||||
* Contributors
|
||||
* - Sergey Vasilevskiy
|
||||
* - Doug Johnson
|
||||
*/
|
||||
|
||||
/*
|
||||
* Class representing the Customer Accounts table.
|
||||
*/
|
||||
#ifndef CUSTOMER_ACCOUNTS_AND_PERMISSIONS_TABLE_H
|
||||
#define CUSTOMER_ACCOUNTS_AND_PERMISSIONS_TABLE_H
|
||||
|
||||
#include "EGenTables_common.h"
|
||||
#include "CustomerTable.h"
|
||||
#include "AddressTable.h"
|
||||
|
||||
#include "input/DataFileManager.h"
|
||||
|
||||
namespace TPCE {
|
||||
const UINT iMaxCAPerms = 3; // maximum # of customers having permissions to the same account
|
||||
const UINT iMinAccountsPerCustRange[3] = {1, 2, 5};
|
||||
const UINT iMaxAccountsPerCustRange[3] = {4, 8, 10};
|
||||
const UINT iMaxAccountsPerCust = 10; // must be the biggest number in iMaxAccountsPerCustRange array
|
||||
const TIdent iStartingBrokerID = 1;
|
||||
|
||||
// This is the fixed range from which person ids (like CIDs) are selected
|
||||
// for the *additional* permissions on the account that make the
|
||||
// content of ACCOUNT_PERMISSION table.
|
||||
//
|
||||
// The range is fixed for any size database in order for the parallel loaders
|
||||
// to select person ids the same way and be compatible with runtime driver
|
||||
// (and to avoid database size parameter to the loader executable).
|
||||
//
|
||||
const TIdent iAccountPermissionIDRange = INT64_CONST(4024) * 1024 * 1024 - iDefaultStartFromCustomer;
|
||||
|
||||
const UINT iPercentAccountsWithPositiveInitialBalance = 80;
|
||||
|
||||
const double fAccountInitialPositiveBalanceMax = 9999999.99;
|
||||
const double fAccountInitialNegativeBalanceMin = -9999999.99;
|
||||
|
||||
const UINT iPercentAccountAdditionalPermissions_0 = 60;
|
||||
const UINT iPercentAccountAdditionalPermissions_1 = 38;
|
||||
const UINT iPercentAccountAdditionalPermissions_2 = 2;
|
||||
|
||||
const UINT iPercentAccountTaxStatusNonTaxable = 20;
|
||||
const UINT iPercentAccountTaxStatusTaxableAndWithhold = 50;
|
||||
const UINT iPercentAccountTaxStatusTaxableAndDontWithhold = 30;
|
||||
|
||||
// Number of RNG calls to skip for one row in order
|
||||
// to not use any of the random values from the previous row.
|
||||
const UINT iRNGSkipOneRowCustomerAccount = 10; // real max count in v3.5: 7
|
||||
|
||||
enum eTaxStatus { eNone = -1, eNonTaxable = 0, eTaxableAndWithhold, eTaxableAndDontWithhold };
|
||||
|
||||
typedef struct CUSTOMER_ACCOUNT_AND_PERMISSION_ROW {
|
||||
CUSTOMER_ACCOUNT_ROW m_ca;
|
||||
ACCOUNT_PERMISSION_ROW m_perm[iMaxCAPerms + 1];
|
||||
} * PCUSTOMER_ACCOUNT_AND_PERMISSION_ROW;
|
||||
|
||||
class CCustomerAccountsAndPermissionsTable : public TableTemplate<CUSTOMER_ACCOUNT_AND_PERMISSION_ROW> {
|
||||
const TaxableAccountNameDataFile_t &m_TaxableAccountName;
|
||||
const NonTaxableAccountNameDataFile_t &m_NonTaxableAccountName;
|
||||
TIdent m_iStartFromCustomer;
|
||||
TIdent m_iCustomerCount;
|
||||
TIdent m_iStartingCA_ID; // first CA_ID for the current customer
|
||||
UINT m_iRowsToGenForCust; // total # of rows to generate for a given
|
||||
// portfolio
|
||||
UINT m_iRowsGeneratedForCust; // rows already generated for a particular
|
||||
// portfolio
|
||||
CCustomerTable m_cust;
|
||||
CPerson m_person;
|
||||
UINT m_iPermsForCA;
|
||||
TIdent m_iBrokersCount;
|
||||
CAddressTable m_addr; // ADDRESS table - to calculate tax for TRADE
|
||||
UINT m_iLoadUnitSize;
|
||||
CCustomerSelection m_CustomerSelection;
|
||||
bool m_bCacheEnabled;
|
||||
int m_iCacheSizeNA;
|
||||
TIdent m_iCacheOffsetNA;
|
||||
UINT *m_CacheNA;
|
||||
int m_iCacheSizeTS;
|
||||
TIdent m_iCacheOffsetTS;
|
||||
eTaxStatus *m_CacheTS;
|
||||
|
||||
/*
|
||||
* Generate only the Customer Account row.
|
||||
*
|
||||
* PARAMETERS:
|
||||
* none.
|
||||
*
|
||||
* RETURNS:
|
||||
* none.
|
||||
*/
|
||||
void GenerateCARow() {
|
||||
int iAcctType;
|
||||
|
||||
// Generate customer account row.
|
||||
//
|
||||
GenerateNextCA_AD();
|
||||
|
||||
m_row.m_ca.CA_C_ID = GetCurrentC_ID(); // get from CUSTOMER
|
||||
|
||||
// Generate broker id.
|
||||
m_row.m_ca.CA_B_ID = GenerateBrokerIdForAccount(m_row.m_ca.CA_ID);
|
||||
|
||||
// Generate tax status and account name.
|
||||
if ((m_row.m_ca.CA_TAX_ST = (char)GetAccountTaxStatus(m_row.m_ca.CA_ID)) ==
|
||||
eNonTaxable) { // non-taxable account
|
||||
iAcctType = (int)m_row.m_ca.CA_ID % m_NonTaxableAccountName.size(); // select account type
|
||||
|
||||
snprintf(m_row.m_ca.CA_NAME, sizeof(m_row.m_ca.CA_NAME), "%s %s %s",
|
||||
m_person.GetFirstName(m_row.m_ca.CA_C_ID).c_str(),
|
||||
m_person.GetLastName(m_row.m_ca.CA_C_ID).c_str(), m_NonTaxableAccountName[iAcctType].NAME_CSTR());
|
||||
} else { // taxable account
|
||||
iAcctType = (int)m_row.m_ca.CA_ID % m_TaxableAccountName.size(); // select account type
|
||||
|
||||
snprintf(m_row.m_ca.CA_NAME, sizeof(m_row.m_ca.CA_NAME), "%s %s %s",
|
||||
m_person.GetFirstName(m_row.m_ca.CA_C_ID).c_str(),
|
||||
m_person.GetLastName(m_row.m_ca.CA_C_ID).c_str(), m_TaxableAccountName[iAcctType].NAME_CSTR());
|
||||
}
|
||||
|
||||
if (m_rnd.RndPercent(iPercentAccountsWithPositiveInitialBalance)) {
|
||||
m_row.m_ca.CA_BAL = m_rnd.RndDoubleIncrRange(0.00, fAccountInitialPositiveBalanceMax, 0.01);
|
||||
} else {
|
||||
m_row.m_ca.CA_BAL = m_rnd.RndDoubleIncrRange(fAccountInitialNegativeBalanceMin, 0.00, 0.01);
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* Helper function to generate parts of an ACCOUNT_PERMISSION row.
|
||||
*
|
||||
* PARAMETERS:
|
||||
* IN CA_ID - customer account id
|
||||
* IN C_ID - customer id
|
||||
* IN szACL - Access-Control-List string on the account
|
||||
* OUT row - ACCOUNT_PERMISSION row structure to fill
|
||||
*
|
||||
* RETURNS:
|
||||
* none.
|
||||
*/
|
||||
void FillAPRow(TIdent CA_ID, TIdent C_ID, const char *szACL, ACCOUNT_PERMISSION_ROW &row) {
|
||||
row.AP_CA_ID = CA_ID;
|
||||
m_cust.GetC_TAX_ID(C_ID, row.AP_TAX_ID);
|
||||
strncpy(row.AP_L_NAME, m_person.GetLastName(C_ID).c_str(), sizeof(row.AP_L_NAME));
|
||||
strncpy(row.AP_F_NAME, m_person.GetFirstName(C_ID).c_str(), sizeof(row.AP_F_NAME));
|
||||
strncpy(row.AP_ACL, szACL, sizeof(row.AP_ACL));
|
||||
}
|
||||
|
||||
/*
|
||||
* Generate only the Account Permissions row(s).
|
||||
*
|
||||
* PARAMETERS:
|
||||
* none.
|
||||
*
|
||||
* RETURNS:
|
||||
* none.
|
||||
*/
|
||||
void GenerateAPRows() {
|
||||
int iAdditionalPerms;
|
||||
TIdent CID_1, CID_2;
|
||||
|
||||
// Generate account permissions rows.
|
||||
|
||||
// Generate the owner row
|
||||
FillAPRow(m_row.m_ca.CA_ID, m_row.m_ca.CA_C_ID, "0000", m_row.m_perm[0]);
|
||||
|
||||
iAdditionalPerms = GetNumPermsForCA(m_row.m_ca.CA_ID);
|
||||
switch (iAdditionalPerms) {
|
||||
case 0:
|
||||
m_iPermsForCA = 1; // 60%
|
||||
break;
|
||||
case 1:
|
||||
GetCIDsForPermissions(m_row.m_ca.CA_ID, m_row.m_ca.CA_C_ID, &CID_1, NULL);
|
||||
m_iPermsForCA = 2; // 38%
|
||||
// generate second account permission row
|
||||
FillAPRow(m_row.m_ca.CA_ID, CID_1, "0001", m_row.m_perm[1]);
|
||||
break;
|
||||
case 2:
|
||||
GetCIDsForPermissions(m_row.m_ca.CA_ID, m_row.m_ca.CA_C_ID, &CID_1, &CID_2);
|
||||
m_iPermsForCA = 3; // 2%
|
||||
// generate second account permission row
|
||||
FillAPRow(m_row.m_ca.CA_ID, CID_1, "0001", m_row.m_perm[1]);
|
||||
// generate third account permission row
|
||||
FillAPRow(m_row.m_ca.CA_ID, CID_2, "0011", m_row.m_perm[2]);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
public:
|
||||
/*
|
||||
* Constructor.
|
||||
*
|
||||
* PARAMETERS:
|
||||
* IN dfm - input flat files loaded in memory
|
||||
* IN iLoadUnitSize - should always be 1000
|
||||
* IN iCustomerCount - number of customers to generate
|
||||
* IN iStartFromCustomer - ordinal position of the first
|
||||
* customer in the sequence (Note: 1-based)
|
||||
*
|
||||
* RETURNS:
|
||||
* not applicable.
|
||||
*/
|
||||
CCustomerAccountsAndPermissionsTable(const DataFileManager &dfm,
|
||||
UINT iLoadUnitSize, // # of customers in one load unit
|
||||
TIdent iCustomerCount, TIdent iStartFromCustomer, bool bCacheEnabled = false)
|
||||
: TableTemplate<CUSTOMER_ACCOUNT_AND_PERMISSION_ROW>(), m_TaxableAccountName(dfm.TaxableAccountNameDataFile()),
|
||||
m_NonTaxableAccountName(dfm.NonTaxableAccountNameDataFile()), m_iStartFromCustomer(iStartFromCustomer),
|
||||
m_iCustomerCount(iCustomerCount), m_iRowsToGenForCust(0), m_iRowsGeneratedForCust(0),
|
||||
m_cust(dfm, iCustomerCount, iStartFromCustomer), m_person(dfm, iStartFromCustomer, bCacheEnabled),
|
||||
m_iPermsForCA(0), m_iBrokersCount(iLoadUnitSize / iBrokersDiv),
|
||||
m_addr(dfm, iCustomerCount, iStartFromCustomer, bCacheEnabled), m_iLoadUnitSize(iLoadUnitSize),
|
||||
m_bCacheEnabled(bCacheEnabled) {
|
||||
if (m_bCacheEnabled) {
|
||||
m_iCacheSizeNA = iDefaultLoadUnitSize;
|
||||
m_iCacheOffsetNA = iStartFromCustomer + iTIdentShift;
|
||||
m_CacheNA = new UINT[m_iCacheSizeNA];
|
||||
for (int i = 0; i < m_iCacheSizeNA; i++) {
|
||||
m_CacheNA[i] = 0;
|
||||
}
|
||||
|
||||
m_iCacheSizeTS = iDefaultLoadUnitSize * iMaxAccountsPerCust;
|
||||
m_iCacheOffsetTS = ((iStartFromCustomer - 1) + iTIdentShift) * iMaxAccountsPerCust;
|
||||
m_CacheTS = new eTaxStatus[m_iCacheSizeTS];
|
||||
for (int i = 0; i < m_iCacheSizeTS; i++) {
|
||||
m_CacheTS[i] = eNone;
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
/*
|
||||
* Destructor.
|
||||
*/
|
||||
~CCustomerAccountsAndPermissionsTable() {
|
||||
if (m_bCacheEnabled) {
|
||||
delete[] m_CacheNA;
|
||||
delete[] m_CacheTS;
|
||||
}
|
||||
};
|
||||
|
||||
/*
|
||||
* Reset the state for the next load unit.
|
||||
*
|
||||
* PARAMETERS:
|
||||
* none.
|
||||
*
|
||||
* RETURNS:
|
||||
* none.
|
||||
*/
|
||||
void InitNextLoadUnit() {
|
||||
m_rnd.SetSeed(m_rnd.RndNthElement(
|
||||
RNGSeedTableDefault, (RNGSEED)(GetCurrentC_ID() * iMaxAccountsPerCust * iRNGSkipOneRowCustomerAccount)));
|
||||
|
||||
ClearRecord(); // this is needed for EGenTest to work
|
||||
|
||||
if (m_bCacheEnabled) {
|
||||
m_iCacheOffsetNA += iDefaultLoadUnitSize;
|
||||
for (int i = 0; i < m_iCacheSizeNA; i++) {
|
||||
m_CacheNA[i] = 0;
|
||||
}
|
||||
m_iCacheOffsetTS += iDefaultLoadUnitSize * iMaxAccountsPerCust;
|
||||
for (int i = 0; i < m_iCacheSizeTS; i++) {
|
||||
m_CacheTS[i] = eNone;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* Generate the number of accounts for a given customer id.
|
||||
*
|
||||
* PARAMETERS:
|
||||
* IN CID - customer id
|
||||
* IN iCustomerTier - customer tier (indicating trading
|
||||
* frequency)
|
||||
*
|
||||
* RETURNS:
|
||||
* number of accounts
|
||||
*/
|
||||
UINT GetNumberOfAccounts(TIdent CID, eCustomerTier iCustomerTier) {
|
||||
UINT iNumAccounts = 0;
|
||||
|
||||
// We will sometimes get CID values that are outside the current
|
||||
// load unit (cached range). We need to check for this case
|
||||
// and avoid the lookup (as we will segfault or get bogus data.)
|
||||
TIdent index = CID - m_iCacheOffsetNA;
|
||||
bool bCheckCache = (index >= 0 && index < m_iCacheSizeNA);
|
||||
if (m_bCacheEnabled && bCheckCache) {
|
||||
iNumAccounts = m_CacheNA[index];
|
||||
}
|
||||
|
||||
if (iNumAccounts == 0) {
|
||||
UINT iMinAccountCount;
|
||||
UINT iMod;
|
||||
UINT iInverseCID;
|
||||
|
||||
iMinAccountCount = iMinAccountsPerCustRange[iCustomerTier - eCustomerTierOne];
|
||||
iMod = iMaxAccountsPerCustRange[iCustomerTier - eCustomerTierOne] - iMinAccountCount + 1;
|
||||
iInverseCID = m_CustomerSelection.GetInverseCID(CID);
|
||||
|
||||
// Note: the calculations below assume load unit contains 1000
|
||||
// customers.
|
||||
//
|
||||
if (iInverseCID < 200) // Tier 1
|
||||
{
|
||||
iNumAccounts = (iInverseCID % iMod) + iMinAccountCount;
|
||||
} else {
|
||||
if (iInverseCID < 800) // Tier 2
|
||||
{
|
||||
iNumAccounts = ((iInverseCID - 200 + 1) % iMod) + iMinAccountCount;
|
||||
} else // Tier 3
|
||||
{
|
||||
iNumAccounts = ((iInverseCID - 800 + 2) % iMod) + iMinAccountCount;
|
||||
}
|
||||
}
|
||||
|
||||
if (m_bCacheEnabled && bCheckCache) {
|
||||
m_CacheNA[index] = iNumAccounts;
|
||||
}
|
||||
}
|
||||
return iNumAccounts;
|
||||
}
|
||||
|
||||
/*
|
||||
* Generate a random account for the specified customer.
|
||||
* The distribution is uniform across all the accounts for the customer.
|
||||
*
|
||||
* PARAMETERS:
|
||||
* IN RND - external Random Number Generator
|
||||
* IN iCustomerId - customer id
|
||||
* IN iCustomerTier - customer tier (indicating trading
|
||||
* frequency) OUT piCustomerAccount - customer account id OUT
|
||||
* piAccountCount - total number of accounts that the customer has
|
||||
*
|
||||
* RETURNS:
|
||||
* none.
|
||||
*/
|
||||
void GenerateRandomAccountId(CRandom &RND, // in - external RNG
|
||||
TIdent iCustomerId, // in
|
||||
eCustomerTier iCustomerTier, // in
|
||||
TIdent *piCustomerAccount, // out
|
||||
int *piAccountCount) // out
|
||||
{
|
||||
TIdent iCustomerAccount;
|
||||
int iAccountCount;
|
||||
TIdent iStartingAccount;
|
||||
|
||||
iAccountCount = GetNumberOfAccounts(iCustomerId, iCustomerTier);
|
||||
|
||||
iStartingAccount = GetStartingCA_ID(iCustomerId);
|
||||
|
||||
// Select random account for the customer
|
||||
//
|
||||
iCustomerAccount = RND.RndInt64Range(iStartingAccount, iStartingAccount + iAccountCount - 1);
|
||||
|
||||
if (piCustomerAccount != NULL) {
|
||||
*piCustomerAccount = iCustomerAccount;
|
||||
}
|
||||
|
||||
if (piAccountCount != NULL) {
|
||||
*piAccountCount = iAccountCount;
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* Generate a random account for the specified customer.
|
||||
*
|
||||
* PARAMETERS:
|
||||
* IN RND - external Random Number Generator
|
||||
* IN iCustomerId - customer id
|
||||
* IN iCustomerTier - customer tier (indicating trading
|
||||
* frequency)
|
||||
*
|
||||
* RETURNS:
|
||||
* customer account id.
|
||||
*/
|
||||
TIdent GenerateRandomAccountId(CRandom &RND, TIdent iCustomerId, eCustomerTier iCustomerTier) {
|
||||
TIdent iAccountOffset;
|
||||
INT32 iAccountCount;
|
||||
TIdent iStartingAccount;
|
||||
|
||||
iAccountCount = GetNumberOfAccounts(iCustomerId, iCustomerTier);
|
||||
|
||||
iStartingAccount = GetStartingCA_ID(iCustomerId);
|
||||
|
||||
iAccountOffset = (TIdent)RND.RndInt64Range(0, (INT64)iAccountCount - 1);
|
||||
|
||||
return (iStartingAccount + iAccountOffset);
|
||||
}
|
||||
|
||||
/*
|
||||
* Get starting account id for a given customer id.
|
||||
* This is needed for the driver to know what account ids belong to a
|
||||
* given customer.
|
||||
*
|
||||
* PARAMETERS:
|
||||
* IN CID - customer id
|
||||
*
|
||||
* RETURNS:
|
||||
* first account id of the customer.
|
||||
*/
|
||||
TIdent GetStartingCA_ID(TIdent CID) {
|
||||
// start account ids on the next boundary for the new customer
|
||||
return ((CID - 1) * iMaxAccountsPerCust + 1);
|
||||
}
|
||||
|
||||
/*
|
||||
* Get (maximum potential) ending account id for a given customer id.
|
||||
* This is needed for the driver to restrict query results to active
|
||||
* accounts.
|
||||
*
|
||||
* PARAMETERS:
|
||||
* IN CID - customer id
|
||||
*
|
||||
* RETURNS:
|
||||
* last account id of the customer.
|
||||
*/
|
||||
TIdent GetEndingCA_ID(TIdent CID) {
|
||||
return (CID + iTIdentShift) * iMaxAccountsPerCust;
|
||||
}
|
||||
|
||||
/*
|
||||
* Generate next CA_ID and update state information.
|
||||
* It is stored in the internal record structure and also returned.
|
||||
* The number of rows generated is incremented. This is why
|
||||
* this function cannot be called more than once for a record.
|
||||
*
|
||||
* PARAMETERS:
|
||||
* none.
|
||||
*
|
||||
* RETURNS:
|
||||
* next account id of the customer.
|
||||
*/
|
||||
TIdent GenerateNextCA_AD() {
|
||||
if (GetCurrentC_ID() % iDefaultLoadUnitSize == 0) {
|
||||
InitNextLoadUnit();
|
||||
}
|
||||
|
||||
++m_iLastRowNumber;
|
||||
|
||||
if (m_iRowsGeneratedForCust == m_iRowsToGenForCust) { // select next customer id as all the rows
|
||||
// for this customer have been generated
|
||||
m_cust.GenerateNextC_ID();
|
||||
m_addr.GenerateNextAD_ID(); // next address id (to get the one for
|
||||
// this customer)
|
||||
m_iRowsGeneratedForCust = 0; // no row generated yet
|
||||
// total # of accounts for this customer
|
||||
m_iRowsToGenForCust =
|
||||
GetNumberOfAccounts(m_cust.GetCurrentC_ID(), m_cust.GetC_TIER(m_cust.GetCurrentC_ID()));
|
||||
|
||||
m_iStartingCA_ID = GetStartingCA_ID(m_cust.GetCurrentC_ID());
|
||||
}
|
||||
|
||||
m_row.m_ca.CA_ID = m_iStartingCA_ID + m_iRowsGeneratedForCust;
|
||||
|
||||
++m_iRowsGeneratedForCust;
|
||||
|
||||
// store state info
|
||||
m_bMoreRecords = m_cust.MoreRecords() || m_iRowsGeneratedForCust < m_iRowsToGenForCust;
|
||||
|
||||
return m_row.m_ca.CA_ID;
|
||||
}
|
||||
|
||||
/*
|
||||
* Generate the number (0-2) of additional permission rows for a certain
|
||||
* account. This number is needed by the driver.
|
||||
*
|
||||
* PARAMETERS:
|
||||
* IN CA_ID - customer account id
|
||||
*
|
||||
* RETURNS:
|
||||
* number of ACCOUNT_PERMISSION rows.
|
||||
*/
|
||||
int GetNumPermsForCA(TIdent CA_ID) {
|
||||
RNGSEED OldSeed;
|
||||
UINT iThreshold;
|
||||
UINT iNumberOfPermissions;
|
||||
|
||||
OldSeed = m_rnd.GetSeed();
|
||||
|
||||
m_rnd.SetSeed(m_rnd.RndNthElement(RNGSeedBaseNumberOfAccountPermissions, (RNGSEED)CA_ID));
|
||||
|
||||
iThreshold = m_rnd.RndGenerateIntegerPercentage();
|
||||
|
||||
if (iThreshold <= iPercentAccountAdditionalPermissions_0) {
|
||||
iNumberOfPermissions = 0; // 60% of accounts have just the owner row permissions
|
||||
} else {
|
||||
if (iThreshold <= iPercentAccountAdditionalPermissions_0 + iPercentAccountAdditionalPermissions_1) {
|
||||
iNumberOfPermissions = 1; // 38% of accounts have one additional permisison row
|
||||
} else {
|
||||
iNumberOfPermissions = 2; // 2% of accounts have two additional permission rows
|
||||
}
|
||||
}
|
||||
|
||||
m_rnd.SetSeed(OldSeed);
|
||||
return (iNumberOfPermissions);
|
||||
}
|
||||
|
||||
/*
|
||||
* Generate customer ids for ACCOUNT_PERMISSION table for a given account
|
||||
* id. Driver needs to know what those customer ids are based on the account
|
||||
* id.
|
||||
*
|
||||
* PARAMETERS:
|
||||
* IN CA_ID - customer account id
|
||||
* IN Owner_CID - customer id of the account owner
|
||||
* OUT CID_1 - first customer id in the ACL list of the
|
||||
* account OUT CID_2 - second customer id in the ACL list of the
|
||||
* account
|
||||
*
|
||||
* RETURNS:
|
||||
* none.
|
||||
*/
|
||||
void GetCIDsForPermissions(TIdent CA_ID, TIdent Owner_CID, TIdent *CID_1, TIdent *CID_2) {
|
||||
RNGSEED OldSeed;
|
||||
|
||||
if (CID_1 == NULL)
|
||||
return;
|
||||
|
||||
OldSeed = m_rnd.GetSeed();
|
||||
m_rnd.SetSeed(m_rnd.RndNthElement(RNGSeedBaseCIDForPermission1, (RNGSEED)CA_ID));
|
||||
|
||||
// Select from a fixed range that doesn't depend on the number of
|
||||
// customers in the database. This allows not to specify the total
|
||||
// number of customers to EGenLoader, only how many a particular
|
||||
// instance needs to generate (may be a fraction of total). Note: this
|
||||
// is not implemented right now.
|
||||
*CID_1 = m_rnd.RndInt64RangeExclude(iDefaultStartFromCustomer,
|
||||
iDefaultStartFromCustomer + iAccountPermissionIDRange, Owner_CID);
|
||||
|
||||
if (CID_2 != NULL) {
|
||||
// NOTE: Reseeding the RNG here for the second CID value. The use of
|
||||
// this sequence is fuzzy because the number of RNG values consumed
|
||||
// is dependant on not only the CA_ID, but also the CID value chosen
|
||||
// above for the first permission. Using a different sequence here
|
||||
// may help prevent potential overlaps that might occur if the same
|
||||
// sequence from above were used.
|
||||
m_rnd.SetSeed(m_rnd.RndNthElement(RNGSeedBaseCIDForPermission2, (RNGSEED)CA_ID));
|
||||
do // make sure the second id is different from the first
|
||||
{
|
||||
*CID_2 = m_rnd.RndInt64RangeExclude(iDefaultStartFromCustomer,
|
||||
iDefaultStartFromCustomer + iAccountPermissionIDRange, Owner_CID);
|
||||
} while (*CID_2 == *CID_1);
|
||||
}
|
||||
|
||||
m_rnd.SetSeed(OldSeed);
|
||||
}
|
||||
|
||||
/*
|
||||
* Generate tax id for a given CA_ID.
|
||||
* This is needed to calculate tax on sale proceeds for the TRADE table.
|
||||
*
|
||||
* PARAMETERS:
|
||||
* IN iCA_ID - customer account id
|
||||
*
|
||||
* RETURNS:
|
||||
* tax status for the account.
|
||||
*/
|
||||
eTaxStatus GetAccountTaxStatus(TIdent iCA_ID) {
|
||||
eTaxStatus eCATaxStatus = eNone;
|
||||
|
||||
// We will sometimes get CA values that are outside the current
|
||||
// load unit (cached range). We need to check for this case
|
||||
// and avoid the lookup (as we will segfault or get bogus data.)
|
||||
TIdent index = iCA_ID - m_iCacheOffsetTS;
|
||||
bool bCheckCache = (index >= 0 && index < m_iCacheSizeTS);
|
||||
if (m_bCacheEnabled && bCheckCache) {
|
||||
eCATaxStatus = m_CacheTS[index];
|
||||
}
|
||||
|
||||
if (eCATaxStatus == eNone) {
|
||||
RNGSEED OldSeed;
|
||||
UINT iThreshold;
|
||||
|
||||
OldSeed = m_rnd.GetSeed();
|
||||
|
||||
m_rnd.SetSeed(m_rnd.RndNthElement(RNGSeedBaseAccountTaxStatus, (RNGSEED)iCA_ID));
|
||||
|
||||
iThreshold = m_rnd.RndGenerateIntegerPercentage();
|
||||
if (iThreshold <= iPercentAccountTaxStatusNonTaxable) {
|
||||
eCATaxStatus = eNonTaxable;
|
||||
} else {
|
||||
if (iThreshold <= iPercentAccountTaxStatusNonTaxable + iPercentAccountTaxStatusTaxableAndWithhold) {
|
||||
eCATaxStatus = eTaxableAndWithhold;
|
||||
} else {
|
||||
eCATaxStatus = eTaxableAndDontWithhold;
|
||||
}
|
||||
}
|
||||
m_rnd.SetSeed(OldSeed);
|
||||
|
||||
if (m_bCacheEnabled && bCheckCache) {
|
||||
m_CacheTS[index] = eCATaxStatus;
|
||||
}
|
||||
}
|
||||
return eCATaxStatus;
|
||||
}
|
||||
|
||||
/*
|
||||
* Get the country and division address codes for the customer that
|
||||
* owns the current account.
|
||||
* These codes are used to get the tax rates and calculate tax on trades
|
||||
* in the TRADE table.
|
||||
*
|
||||
* PARAMETERS:
|
||||
* OUT iDivCode - division (state/province) code
|
||||
* OUT iCtryCode - country (USA/CANADA) code
|
||||
*
|
||||
* RETURNS:
|
||||
* none.
|
||||
*/
|
||||
void GetDivisionAndCountryCodesForCurrentAccount(UINT &iDivCode, UINT &iCtryCode) {
|
||||
m_addr.GetDivisionAndCountryCodes(iDivCode, iCtryCode);
|
||||
}
|
||||
|
||||
/*
|
||||
* Generate a broker id for a certain account.
|
||||
* Used in CTradeGen for updating YTD values.
|
||||
*
|
||||
* PARAMETERS:
|
||||
* IN iCA_ID - customer account id
|
||||
*
|
||||
* RETURNS:
|
||||
* broker id that corresponds to the account.
|
||||
*/
|
||||
TIdent GenerateBrokerIdForAccount(TIdent iCA_ID) {
|
||||
// Customer that own the account (actually, customer id minus 1)
|
||||
//
|
||||
TIdent iCustomerId = ((iCA_ID - 1) / iMaxAccountsPerCust) - iTIdentShift;
|
||||
|
||||
// Set the starting broker to be the first broker for the current load
|
||||
// unit of customers.
|
||||
//
|
||||
TIdent iStartFromBroker = (iCustomerId / m_iLoadUnitSize) * m_iBrokersCount + iStartingBrokerID + iTIdentShift;
|
||||
|
||||
// Note: this depends on broker ids being integer numbers from
|
||||
// contiguous range. The method of generating broker ids should be in
|
||||
// sync with the CBrokerTable.
|
||||
return m_rnd.RndNthInt64Range(RNGSeedBaseBrokerId, (RNGSEED)iCA_ID - (10 * iTIdentShift), iStartFromBroker,
|
||||
iStartFromBroker + m_iBrokersCount - 1);
|
||||
}
|
||||
|
||||
/*
|
||||
* Generate all column values for the next row
|
||||
* and store them in the internal record structure.
|
||||
* Increment the number of rows generated.
|
||||
*
|
||||
* PARAMETERS:
|
||||
* none.
|
||||
*
|
||||
* RETURNS:
|
||||
* TRUE, if there are more records in the ADDRESS table; FALSE
|
||||
* othewise.
|
||||
*/
|
||||
bool GenerateNextRecord() {
|
||||
GenerateCARow();
|
||||
GenerateAPRows();
|
||||
|
||||
// Return false if all the rows have been generated
|
||||
return (MoreRecords());
|
||||
}
|
||||
|
||||
/*
|
||||
* Return CUSTOMER_ACCOUNT row from the internal structure.
|
||||
*
|
||||
* PARAMETERS:
|
||||
* none.
|
||||
*
|
||||
* RETURNS:
|
||||
* current CUSTOMER_ACCOUNT record.
|
||||
*/
|
||||
// PCUSTOMER_ACCOUNT_ROW GetCARow() {return &m_row.m_ca;}
|
||||
const CUSTOMER_ACCOUNT_ROW &GetCARow() {
|
||||
return m_row.m_ca;
|
||||
}
|
||||
/*
|
||||
* Return ACCOUNT_PERMISSION row from the internal structure.
|
||||
*
|
||||
* PARAMETERS:
|
||||
* none.
|
||||
*
|
||||
* RETURNS:
|
||||
* current ACCOUNT_PERMISSION record.
|
||||
*/
|
||||
const ACCOUNT_PERMISSION_ROW &GetAPRow(UINT i) {
|
||||
if (i < m_iPermsForCA)
|
||||
return m_row.m_perm[i];
|
||||
else
|
||||
throw std::range_error("Account Permission row index out of bounds.");
|
||||
}
|
||||
|
||||
/*
|
||||
* Return the number of ACCOUNT_PERMISSION rows for the current
|
||||
* CUSTOMER_ACCOUNT row.
|
||||
*
|
||||
* PARAMETERS:
|
||||
* none.
|
||||
*
|
||||
* RETURNS:
|
||||
* the number of permissions for the account.
|
||||
*/
|
||||
UINT GetCAPermsCount() {
|
||||
return m_iPermsForCA;
|
||||
}
|
||||
|
||||
/*
|
||||
* Return the customer ID for the currently generated CA_ID id.
|
||||
*
|
||||
* PARAMETERS:
|
||||
* none.
|
||||
*
|
||||
* RETURNS:
|
||||
* customer id of the account in the current CUSTOMER_ACCOUNT
|
||||
* record.
|
||||
*/
|
||||
TIdent GetCurrentC_ID() {
|
||||
return m_cust.GetCurrentC_ID();
|
||||
}
|
||||
/*
|
||||
* Return the customer tier for the currently generated CA_ID id.
|
||||
*
|
||||
* PARAMETERS:
|
||||
* none.
|
||||
*
|
||||
* RETURNS:
|
||||
* customer tier of the customer, whose account is in the current
|
||||
* CUSTOMER_ACCOUNT record.
|
||||
*/
|
||||
eCustomerTier GetCurrentC_TIER() {
|
||||
return m_cust.GetC_TIER(m_cust.GetCurrentC_ID());
|
||||
}
|
||||
};
|
||||
|
||||
} // namespace TPCE
|
||||
|
||||
#endif // CUSTOMER_ACCOUNTS_AND_PERMISSIONS_TABLE_H
|
||||
Reference in New Issue
Block a user