#define UDEBUG 0
#define PKMAX 10 /* max number of keys [GROUP BY fields] */
#define LOADMEMMAX 100000 /* max number of records in batch */
typedef short int DdSInt;
typedef long DdLong;
typedef unsigned long DdULong;
typedef float DdFloat;
typedef double DdDouble;
typedef struct DATAITEMINFO{
char pkName[64];
int pkDataType;
int pkDataLen;
int pkDataPosition;
}DATAITEMINFO;
typedef struct DATAITEMHEADER{
char *dihPtr;
int dihOrder; /* original 1-rel position in DataArray[] */
long dihRecno; /* record # or 0 if not found */
int dihFlags;
int dihReducedIndexBack; /* 1-rel back index from Reduced */
}DATAITEMHEADER;
typedef struct FINDCBCONTEXT{
DATAITEMHEADER *dih;
int pkCount;
DATAITEMINFO *pkInfo;
}FINDCBCONTEXT;
enum{
DihFlDuplicate = 0x01
};
static void ExtractUpdateParams(
CONTROL *ctl,
char *OptnStr,
char *ArgStr,
char *dgName, /* char dgName[64] */
char *rdName, /* char rdName[64] */
DATAITEMINFO *pkInfo,
int *pkCount,
int *rdLengthRef,
char *ErrorString); /* char ErrorString[256] */
static int STDCALL FindCb(
/* value 1 - continue FIND iteration; 0 - stop FIND iteration */
WtCastPtr UserWord,
long *FindRecArray, /* array of record numbers */
int FindRecCount, /* number of records found */
int DataArrayIndex);
static int UpdateSortComp(WtCastPtr UserWord,char *bi,char *bj);
static void UpdateSortSwap(WtCastPtr UserWord,char *bi,char *bj);
/*
Format of ArgStr:
1) Create shadow vector of DATAITEMHEADER{} structs; copy pointers
to shadow vector;
2) Sort shadow vector;
3) Eliminate duplicates from shadow vector;
4) Create new char* vector of sorted, reduced items;
5) Call ddlFindCb();
6) Do Updates
7) Do Inserts
8) Build Structures
*/
void DoUpdate(
CONTROL *ctl,
char *OptnStr,
char *ArgStr,
char *DataArray[],
int DataArrayCount, /* number of DataArray[] items */
int DataArrayItemSize, /* size of each DataArray[] item */
char *ErrorString) /* char ErrorString[256] */
{
DATAITEMHEADER *dih = 0;
DATAITEMINFO pkInfo[PKMAX];
FINDCBCONTEXT FindCbContext;
int rdLength = 0,pkCount = 0;
int i,j,iLatest,memneed = 0,iDataReducedCount = 0;
int iInsertRecCount = 0,iUpdateRecCount = 0;
int offset = 0,irc = 0,ircBatch = 0,ircCount = 0;
char **DataArrayReduced = 0,*DataLoadMemBlock = 0;
char command[2048];
char dgName[64] = "Sessions";
char rdName[64] = "Sessions_RD";
#if UDEBUG
ddlCalc(ctl,"/","SET %TimePrep = \' \'");
ddlCalc(ctl,"/","SET %TimeFind = \' \'");
ddlCalc(ctl,"/","SET %TimeUpdate = \' \'");
ddlCalc(ctl,"/","SET %TimeLoad = \' \'");
ddlCalc(ctl,"/","SET %TimeSession = \' \'");
ddlCalc(ctl,"/","SET %TimeStartTime = \' \'");
ddlCalc(ctl,"/","SET %TimeClientAddr = \' \'");
ddlCalc(ctl,"/","SET %TimeServerAddr = \' \'");
// CheckTime(ctl,"Elapsed","%TimeStart");
#endif
*ErrorString = 0;
setmem((char*)pkInfo,sizeof(pkInfo),0);
ExtractUpdateParams(ctl,OptnStr,ArgStr,dgName,rdName,pkInfo,&pkCount,&rdLength,ErrorString);
if(ErrorString[0] != 0){
return;
}
if(DataArrayCount == 0) return;
/* 1A) Create shadow vector of DATAITEMHEADER{} structs */
memneed = DataArrayCount * sizeof(DATAITEMHEADER);
dih = (DATAITEMHEADER*)malloc(memneed);
if(dih == 0){
sprintf(ErrorString,"Unable to allocate memory-1: %d bytes",memneed);
return;
}
setmem((char*)dih,memneed,0);
/* 1B) copy pointers to shadow vector */
for(i=0;idihPtr = DataArray[i];
(dih+i)->dihOrder = i+1;
}
FindCbContext.dih = dih;
FindCbContext.pkInfo = pkInfo;
FindCbContext.pkCount = pkCount;
/* 2) sort shadow vector */
ddlShellSort(ctl,
(char*)dih,
DataArrayCount,
sizeof(DATAITEMHEADER),
UpdateSortComp,
UpdateSortSwap,
(long)&FindCbContext);
if(ctl->Status != 0){
sprintf(ErrorString,"Error in ShellSort: %d",ctl->Status);
return;
}
/* 3) eliminate duplicates from shadow vector */
for(i=1,iLatest=0;idihPtr,(dih+i)->dihPtr,pkLength) == 0){
if(UpdateSortComp((long)&FindCbContext,(char*)(dih+i-1),(char*)(dih+i)) == 0){
(dih+i-1)->dihFlags |= DihFlDuplicate;
(dih+i)->dihFlags |= DihFlDuplicate;
if(iLatest == 0) iLatest = i; /* = (i-1) + 1 */
/* remember the latest in the original order */
if((dih+i)->dihOrder > (dih+iLatest-1)->dihOrder){
iLatest = i+1;
}
if(i == (DataArrayCount - 1)){
(dih+iLatest-1)->dihFlags &= ~DihFlDuplicate;
++iDataReducedCount;
iLatest = 0;
break;
}
}else{
if(iLatest != 0){
(dih+iLatest-1)->dihFlags &= ~DihFlDuplicate;
}else{
}
if(i == (DataArrayCount - 1)){
++iDataReducedCount;
}
++iDataReducedCount;
iLatest = 0;
}
}
if(DataArrayCount == 1) iDataReducedCount = 1;
/* 4) create new char* vector of sorted, reduced items */
memneed = iDataReducedCount * sizeof(char*);
DataArrayReduced = (char**)malloc(memneed);
if(DataArrayReduced == 0){
sprintf(ErrorString,"Unable to allocate memory-2: %d bytes",memneed);
if(dih) free((void*)dih);
return;
}
for(i=j=0;idihFlags & DihFlDuplicate) == 0){
(dih+j)->dihReducedIndexBack = i+1;
DataArrayReduced[j++] = (dih+i)->dihPtr;
}
}
#if UDEBUG
// CheckTime(ctl,"Elapsed","%TimePrep");
#endif
/* 5) call ddlFindCb() */
_snprintf(command,sizeof(command)-1,"%s %s %s",dgName,rdName,pkInfo[0].pkName);
for(i=1;iStatus != 0){
sprintf(ErrorString,"Error in FindCb: %d",ctl->Status);
goto Finish;
}
if(DataArrayReduced) free((void*)DataArrayReduced);
DataArrayReduced = 0;
#if UDEBUG
// CheckTime(ctl,"Elapsed","%TimeFind");
#endif
// for(i=0;idihOrder,(dih+i)->dihReducedIndexBack,(dih+i)->dihRecno,(dih+i)->dihPtr);
// }
/* 6) do Updates */
for(i=0;idihFlags & DihFlDuplicate) == 0 && (dih+i)->dihRecno != 0){
_snprintf(command,sizeof(command)-1,"%s %s %d",dgName,rdName,(dih+i)->dihRecno);
ddlRewriteB(ctl,"/",command,(dih+i)->dihPtr);
if(ctl->Status != 0){
sprintf(ErrorString,"Error in RewriteB: %d",ctl->Status);
goto Finish;
}
++iUpdateRecCount;
}
if(((dih+i)->dihFlags & DihFlDuplicate) == 0 && (dih+i)->dihRecno == 0){
++iInsertRecCount;
}
}
#if UDEBUG
// CheckTime(ctl,"Elapsed","%TimeUpdate");
#endif
/* 7) do Inserts */
if(iInsertRecCount > 0){
irc = iInsertRecCount;
memneed = LOADMEMMAX * rdLength;
if(irc < LOADMEMMAX) memneed = iInsertRecCount * rdLength;
DataLoadMemBlock = (char*)malloc(memneed+64);
if(DataLoadMemBlock == 0){
sprintf(ErrorString,"Unable to allocate memory-3: %d bytes",memneed);
if(dih) free((void*)dih);
return;
}
setmem(DataLoadMemBlock,memneed,0);
i = 0;
while(irc > 0){
ircBatch = irc;
if(ircBatch > LOADMEMMAX) ircBatch = LOADMEMMAX;
irc -= ircBatch;
ircCount = 0;
for(offset=0;idihFlags & DihFlDuplicate) == 0 && (dih+i)->dihRecno == 0){
// k = stccpy(DataLoadMemBlock+offset,(dih+i)->dihPtr,rdLength+1) - 1;
movmem((dih+i)->dihPtr,DataLoadMemBlock+offset,rdLength);
offset += rdLength;
if(++ircCount >= ircBatch) break;
}
}
_snprintf(command,sizeof(command)-1,"^S %s %s",dgName,rdName);
ddlLoadMem(ctl,"/B",command,DataLoadMemBlock,rdLength,ircCount);
if(ctl->Status != 0){
sprintf(ErrorString,"Error in LoadMem: %d",ctl->Status);
goto Finish;
}
}
#if UDEBUG
// CheckTime(ctl,"Elapsed","%TimeLoad");
#endif
#if !UDEBUG
ddlStructure(ctl,"/","");
#else
ddlStructure(ctl,"/","SESSION");
// CheckTime(ctl,"Elapsed","%TimeSession");
ddlStructure(ctl,"/","STARTTIME");
// CheckTime(ctl,"Elapsed","%TimeStartTime");
ddlStructure(ctl,"/","CLIENT_ADDR");
// CheckTime(ctl,"Elapsed","%TimeClientAddr");
ddlStructure(ctl,"/","SERVER_ADDR");
// CheckTime(ctl,"Elapsed","%TimeServerAddr");
#endif
if(ctl->Status != 0){
sprintf(ErrorString,"Error in Structure: %d",ctl->Status);
goto Finish;
}
}
Finish:
if(iInsertRecCount > 0 || iUpdateRecCount > 0){
printf("\n\n%d records updated; %d records inserted\n",iUpdateRecCount,iInsertRecCount);
}
if(DataLoadMemBlock) free((void*)DataLoadMemBlock);
DataLoadMemBlock = 0;
if(DataArrayReduced) free((void*)DataArrayReduced);
DataArrayReduced = 0;
if(dih) free((void*)dih);
dih = 0;
}
static void ExtractUpdateParams(
CONTROL *ctl,
char *OptnStr,
char *ArgStr,
char *dgName, /* char dgName[64] */
char *rdName, /* char rdName[64] */
DATAITEMINFO *pkInfo,
int *pkCountRef,
int *rdLengthRef,
char *ErrorString) /* char ErrorString[256] */
{
int pkCount = 0;
long pkHandle;
char tempName[64],command[512];
*dgName = 0;
*rdName = 0;
*pkCountRef = 0;
/* extract TABLE name */
MakeName(ArgStr,tempName,sizeof(tempName));
_snprintf(command,sizeof(command)-1,"DGNAME %s",tempName);
ddlVerify(ctl,"/",command);
if(strcmp(ctl->Ans1str,"NO") == 0){
sprintf(ErrorString,"Error: Table \"%s\" not found",tempName);
return;
}else{
strcpy(dgName,tempName);
}
ArgStr = nextarg(ArgStr);
/* extract RD name */
MakeName(ArgStr,tempName,sizeof(tempName));
_snprintf(command,sizeof(command)-1,"%s",tempName);
ddlGetRDHandle(ctl,"/",command);
if(ctl->Status != 0){
sprintf(ErrorString,"Error: RD \"%s\" not found",tempName);
return;
}else{
strcpy(rdName,tempName);
pkHandle = ctl->Ans1;
*rdLengthRef = (int)ctl->Ans3;
}
for(;;){
ArgStr = nextarg(ArgStr);
if(*ArgStr == 0) break;
/* extract PK name */
MakeName(ArgStr,tempName,sizeof(tempName));
_snprintf(command,sizeof(command)-1,"SIGNATURE %s %s",dgName,tempName);
ddlVerify(ctl,"/",command);
if(strcmp(ctl->Ans1str,"NO") == 0){
sprintf(ErrorString,"Error: PK \"%s\" not found",tempName);
return;
}else{
strcpy(pkInfo->pkName,tempName);
}
/* get PK RD info */
_snprintf(command,sizeof(command)-1,"%s %s",rdName,tempName);
ddlGetRDType(ctl,"/",command);
if(ctl->Status != 0){
sprintf(ErrorString,"Error: PK \"%s\" not found in RD",tempName);
return;
}else{
pkInfo->pkDataType = (int)ctl->Ans1;
pkInfo->pkDataPosition = (int)ctl->Ans2 + 1; /* make it 1-relative */
pkInfo->pkDataLen = (int)(ctl->Ans3 % 65536);
}
++pkCount;
++pkInfo;
}
*pkCountRef = pkCount;
}
static int STDCALL FindCb(
/* value 1 - continue FIND iteration; 0 - stop FIND iteration */
WtCastPtr UserWord,
long *FindRecArray, /* array of record numbers */
int FindRecCount, /* number of records found */
int DataArrayIndex)
{
FINDCBCONTEXT *FindCbContext = (FINDCBCONTEXT*)UserWord;
DATAITEMHEADER *dih = FindCbContext->dih;
int dihIndex = 0;
int result = 1;
dihIndex = (dih+DataArrayIndex-1)->dihReducedIndexBack;
if(dihIndex > 0){
(dih+dihIndex-1)->dihRecno = *FindRecArray;
}
return result;
}
static char **ReadFlatFile(
CONTROL *ctl,
char *rdName,
char *filename,
int *reccount,
int delta, /* flag for generating test data */
char *ErrorString) /* char ErrorString[256] */
{
int i = 0,l = 8,deltaT = delta,fn = _open(filename,0x8000);
int pkHandle = 0,rdLength = 0,nItem = 0;
int memneed = 0,memneedData = 0,memneedPtr = 0;
DdLong64 flen;
char **data = 0,*d = 0,*d1;
char deltaStr[12] = "\0";
char command[256],tempName[256];
if(delta){
setmem(deltaStr,sizeof(deltaStr),0);
setmem(deltaStr,l,'0');
for(i=l;;){
if(deltaT <= 0 || i <= 0) break;
deltaStr[--i] = ((deltaT - 1) % 26) + 'A';
deltaT /= 26;
}
}
if(fn == -1){
sprintf(ErrorString,"Error opening file \"%s\"",filename);
return 0;
}
flen = _lseek(fn,0,2);
_lseek(fn,0,0);
memneedData = (int)flen + 64;
/* extract RD name */
MakeName(rdName,tempName,sizeof(tempName));
_snprintf(command,sizeof(command)-1,"%.256s",tempName);
ddlGetRDHandle(ctl,"/",command);
if(ctl->Status != 0){
sprintf(ErrorString,"Error: RD \"%s\" not found",tempName);
return 0;
}else{
pkHandle = ctl->Ans1;
rdLength = (int)ctl->Ans3;
}
nItem = (int)flen / rdLength;
memneedPtr = sizeof(char*) * nItem + 64;
memneed = memneedData + memneedPtr;
data = (char**)malloc(memneed);
setmem((char*)data,memneed,0);
d = (char*)data + memneedPtr;
_read(fn,d,(long)flen);
_close(fn);
// {
// if(delta){
// for(i=0;i<(int)flen;++i){
// *(d+i) ^= (0x84 + i);
// }
// }
// }
#if 1
for(i=0,d1=d;;){
data[i++] = d1;
if(delta){
movmem(deltaStr,d1+45,l);
*((long*)(d1+55)) += delta * 3000; /* starttime */
*((long*)(d1+59)) += delta * 3000; /* endtime */
*((long*)(d1+124)) += (delta % 6) * 65536; /* endtime */
}
d1 += rdLength;
if(i >= nItem) break;
}
#else
for(d1=d2=d;;++d1){
if((chr = *d1) == 0) break;
if(chr == '\r'){
*d1 = 0;
data[i++] = d2;
while(*(d1+1) == '\r' || *(d1+1) == '\n') ++d1;
d2 = d1+1;
}
}
if(d1 > (d2+20)) data[i++] = d2;
#endif
if(i > 0 && strncmp(data[i-1],"/./././.",8) == 0) --i;
*reccount = i;
return data;
}
static int UpdateSortComp(WtCastPtr UserWord,char *bi,char *bj)
{
FINDCBCONTEXT *fcc = (FINDCBCONTEXT*)UserWord;
DATAITEMINFO *pkInfo = fcc->pkInfo;
int i = 0,k,pl,pkCount = fcc->pkCount;
char *pi = 0,*pj = 0;
for(i=0;idihPtr + pkInfo->pkDataPosition - 1;
pj = ((DATAITEMHEADER*)bj)->dihPtr + pkInfo->pkDataPosition - 1;
pl = pkInfo->pkDataLen;
switch(pkInfo->pkDataType){
case DdTypeAlpha:
if((k = strnicmp(pi,pj,pl)) < 0) return -1;
if(k > 0) return 1;
break;
case DdTypeShortInt:
if(*((DdSInt*)pi) < *((DdSInt*)pj)) return -1;
if(*((DdSInt*)pi) > *((DdSInt*)pj)) return 1;
break;
case DdTypeLongInt:
if(*((DdLong*)pi) < *((DdLong*)pj)) return -1;
if(*((DdLong*)pi) > *((DdLong*)pj)) return 1;
break;
case DdTypeLongInt64:
if(*((DdLong64*)pi) < *((DdLong64*)pj)) return -1;
if(*((DdLong64*)pi) > *((DdLong64*)pj)) return 1;
break;
case DdTypeFloat:
if(*((DdFloat*)pi) < *((DdFloat*)pj)) return -1;
if(*((DdFloat*)pi) > *((DdFloat*)pj)) return 1;
break;
case DdTypeDouble:
if(*((DdDouble*)pi) < *((DdDouble*)pj)) return -1;
if(*((DdDouble*)pi) > *((DdDouble*)pj)) return 1;
break;
case DdTypeULongInt:
if(*((DdULong*)pi) < *((DdULong*)pj)) return -1;
if(*((DdULong*)pi) > *((DdULong*)pj)) return 1;
break;
case DdTypeNumeric:
case DdTypeLogical:
case DdTypeVarChar:
default:
break;
}
}
return 0;
}
static void UpdateSortSwap(WtCastPtr UserWord,char *bi,char *bj)
{
DATAITEMHEADER dihTemp;
movmem((char*)bi,(char*)&dihTemp,sizeof(DATAITEMHEADER));
movmem((char*)bj,(char*)bi,sizeof(DATAITEMHEADER));
movmem((char*)&dihTemp,(char*)bj,sizeof(DATAITEMHEADER));
}
Copyright © 2019 , WhamTech, Inc. All rights reserved. This
document is provided for information purposes only and the contents hereof are
subject to change without notice. Names may be
trademarks of their respective owners.