Home page  
Help >
ddlFindCb() example
Version 7.11
ddlFindCb() example ddlFindCb() example
#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.