| 1 | /************* BlkFil C++ Program Source Code File (.CPP) **************/ | 
| 2 | /* PROGRAM NAME: BLKFIL                                                */ | 
| 3 | /* -------------                                                       */ | 
| 4 | /*  Version 2.6                                                        */ | 
| 5 | /*                                                                     */ | 
| 6 | /* COPYRIGHT:                                                          */ | 
| 7 | /* ----------                                                          */ | 
| 8 | /*  (C) Copyright to the author Olivier BERTRAND          2004-2017    */ | 
| 9 | /*                                                                     */ | 
| 10 | /* WHAT THIS PROGRAM DOES:                                             */ | 
| 11 | /* -----------------------                                             */ | 
| 12 | /*  This program is the implementation of block indexing classes.      */ | 
| 13 | /*                                                                     */ | 
| 14 | /***********************************************************************/ | 
| 15 |  | 
| 16 | /***********************************************************************/ | 
| 17 | /*  Include relevant MariaDB header file.                              */ | 
| 18 | /***********************************************************************/ | 
| 19 | #include "my_global.h" | 
| 20 | #include "sql_class.h" | 
| 21 | //#include "sql_time.h" | 
| 22 |  | 
| 23 | #if defined(__WIN__) | 
| 24 | //#include <windows.h> | 
| 25 | #else   // !__WIN__ | 
| 26 | #include <string.h> | 
| 27 | #include <sys/types.h> | 
| 28 | #include <sys/stat.h> | 
| 29 | #endif  // !__WIN__ | 
| 30 |  | 
| 31 | /***********************************************************************/ | 
| 32 | /*  Include application header files:                                  */ | 
| 33 | /***********************************************************************/ | 
| 34 | #include "global.h"      // global declarations | 
| 35 | #include "plgdbsem.h"    // DB application declarations | 
| 36 | #include "xindex.h"      // Key Index class declarations | 
| 37 | #include "filamtxt.h"    // File access method dcls | 
| 38 | #include "tabdos.h"      // TDBDOS and DOSCOL class dcls | 
| 39 | #include "array.h"       // ARRAY classes dcls | 
| 40 | #include "blkfil.h"      // Block Filter classes dcls | 
| 41 |  | 
| 42 | /* ------------------------ Class BLOCKFILTER ------------------------ */ | 
| 43 |  | 
| 44 | /***********************************************************************/ | 
| 45 | /*  BLOCKFILTER constructor.                                           */ | 
| 46 | /***********************************************************************/ | 
| 47 | BLOCKFILTER::BLOCKFILTER(PTDBDOS tdbp, int op) | 
| 48 |   { | 
| 49 |   Tdbp = tdbp; | 
| 50 |   Correl = FALSE; | 
| 51 |   Opc = op; | 
| 52 |   Opm = 0; | 
| 53 |   Result = 0; | 
| 54 |   } // end of BLOCKFILTER constructor | 
| 55 |  | 
| 56 | /***********************************************************************/ | 
| 57 | /*  Make file output of BLOCKFILTER contents.                          */ | 
| 58 | /***********************************************************************/ | 
| 59 | void BLOCKFILTER::Printf(PGLOBAL, FILE *f, uint n) | 
| 60 |   { | 
| 61 |   char m[64]; | 
| 62 |  | 
| 63 |   memset(m, ' ', n);                    // Make margin string | 
| 64 |   m[n] = '\0'; | 
| 65 |  | 
| 66 |   fprintf(f, "%sBLOCKFILTER: at %p opc=%d opm=%d result=%d\n" , | 
| 67 |           m, this, Opc, Opm, Result); | 
| 68 |   } // end of Printf | 
| 69 |  | 
| 70 | /***********************************************************************/ | 
| 71 | /*  Make string output of BLOCKFILTER contents.                        */ | 
| 72 | /***********************************************************************/ | 
| 73 | void BLOCKFILTER::Prints(PGLOBAL, char *ps, uint z) | 
| 74 |   { | 
| 75 |   strncat(ps, "BlockFilter(s)" , z); | 
| 76 |   } // end of Prints | 
| 77 |  | 
| 78 |  | 
| 79 | /* ---------------------- Class BLKFILLOG ---------------------------- */ | 
| 80 |  | 
| 81 | /***********************************************************************/ | 
| 82 | /*  BLKFILLOG constructor.                                             */ | 
| 83 | /***********************************************************************/ | 
| 84 | BLKFILLOG::BLKFILLOG(PTDBDOS tdbp, int op, PBF *bfp, int n) | 
| 85 |          : BLOCKFILTER(tdbp, op) | 
| 86 |   { | 
| 87 |   N = n; | 
| 88 |   Fil = bfp; | 
| 89 |  | 
| 90 |   for (int i = 0; i < N; i++) | 
| 91 |     if (Fil[i]) | 
| 92 |       Correl |= Fil[i]->Correl; | 
| 93 |  | 
| 94 |   } // end of BLKFILLOG constructor | 
| 95 |  | 
| 96 | /***********************************************************************/ | 
| 97 | /*  Reset: this function is used only to check the existence of a      */ | 
| 98 | /*  BLKFILIN block and have it reset its Bot value for sorted columns. */ | 
| 99 | /***********************************************************************/ | 
| 100 | void BLKFILLOG::Reset(PGLOBAL g) | 
| 101 |   { | 
| 102 |   for (int i = 0; i < N; i++) | 
| 103 |     if (Fil[i]) | 
| 104 |       Fil[i]->Reset(g); | 
| 105 |  | 
| 106 |   } // end of Reset | 
| 107 |  | 
| 108 | /***********************************************************************/ | 
| 109 | /*  This function is used for block filter evaluation. We use here a   */ | 
| 110 | /*  fuzzy logic between the values returned by evaluation blocks:      */ | 
| 111 | /* -2: the condition will be always false for the rest of the file.    */ | 
| 112 | /* -1: the condition will be false for the whole group.                */ | 
| 113 | /*  0: the condition may be true for some of the group values.         */ | 
| 114 | /*  1: the condition will be true for the whole group.                 */ | 
| 115 | /*  2: the condition will be always true for the rest of the file.     */ | 
| 116 | /***********************************************************************/ | 
| 117 | int BLKFILLOG::BlockEval(PGLOBAL g) | 
| 118 |   { | 
| 119 |   int  i, rc; | 
| 120 |  | 
| 121 |   for (i = 0; i < N; i++) { | 
| 122 |     // 0: Means some block filter value may be True | 
| 123 |     rc = (Fil[i]) ? Fil[i]->BlockEval(g) : 0; | 
| 124 |  | 
| 125 |     if (!i) | 
| 126 |       Result = (Opc == OP_NOT) ? -rc : rc; | 
| 127 |     else switch (Opc) { | 
| 128 |       case OP_AND: | 
| 129 |         Result = MY_MIN(Result, rc); | 
| 130 |         break; | 
| 131 |       case OP_OR: | 
| 132 |         Result = MY_MAX(Result, rc); | 
| 133 |         break; | 
| 134 |       default: | 
| 135 |         // Should never happen | 
| 136 |         Result = 0; | 
| 137 |         return Result; | 
| 138 |       } // endswitch Opc | 
| 139 |  | 
| 140 |     } // endfor i | 
| 141 |  | 
| 142 |   return Result; | 
| 143 |   } // end of BlockEval | 
| 144 |  | 
| 145 | /* ---------------------- Class BLKFILARI----------------------------- */ | 
| 146 |  | 
| 147 | /***********************************************************************/ | 
| 148 | /*  BLKFILARI constructor.                                             */ | 
| 149 | /***********************************************************************/ | 
| 150 | BLKFILARI::BLKFILARI(PGLOBAL g, PTDBDOS tdbp, int op, PXOB *xp) | 
| 151 |          : BLOCKFILTER(tdbp, op) | 
| 152 |   { | 
| 153 |   Colp = (PDOSCOL)xp[0]; | 
| 154 |  | 
| 155 |   if (xp[1]->GetType() == TYPE_COLBLK) { | 
| 156 |     Cpx = (PCOL)xp[1];      // Subquery pseudo constant column | 
| 157 |     Correl = TRUE; | 
| 158 |   } else | 
| 159 |     Cpx = NULL; | 
| 160 |  | 
| 161 |   Sorted = Colp->IsSorted() > 0; | 
| 162 |  | 
| 163 |   // Don't remember why this was changed. Anyway it is no good for | 
| 164 |   // correlated subqueries because the Value must reflect changes | 
| 165 |   if (Cpx) | 
| 166 |     Valp = xp[1]->GetValue(); | 
| 167 |   else | 
| 168 |     Valp = AllocateValue(g, xp[1]->GetValue()); | 
| 169 |  | 
| 170 |   } // end of BLKFILARI constructor | 
| 171 |  | 
| 172 | /***********************************************************************/ | 
| 173 | /*  Reset: re-eval the constant value in the case of pseudo constant   */ | 
| 174 | /*  column use in a correlated subquery.                               */ | 
| 175 | /***********************************************************************/ | 
| 176 | void BLKFILARI::Reset(PGLOBAL g) | 
| 177 |   { | 
| 178 |   if (Cpx) { | 
| 179 |     Cpx->Reset(); | 
| 180 |     Cpx->Eval(g); | 
| 181 |     MakeValueBitmap();      // Does nothing for class BLKFILARI | 
| 182 |     } // endif Cpx | 
| 183 |  | 
| 184 |   } // end of Reset | 
| 185 |  | 
| 186 | /***********************************************************************/ | 
| 187 | /*  Evaluate block filter for arithmetic operators.                    */ | 
| 188 | /***********************************************************************/ | 
| 189 | int BLKFILARI::BlockEval(PGLOBAL) | 
| 190 |   { | 
| 191 |   int mincmp, maxcmp, n; | 
| 192 |  | 
| 193 | #if defined(_DEBUG) | 
| 194 |   assert (Colp->IsClustered()); | 
| 195 | #endif | 
| 196 |  | 
| 197 |   n = ((PTDBDOS)Colp->GetTo_Tdb())->GetCurBlk(); | 
| 198 |   mincmp = Colp->GetMin()->CompVal(Valp, n); | 
| 199 |   maxcmp = Colp->GetMax()->CompVal(Valp, n); | 
| 200 |  | 
| 201 |   switch (Opc) { | 
| 202 |     case OP_EQ: | 
| 203 |     case OP_NE: | 
| 204 |       if (mincmp < 0)                // Means minval > Val | 
| 205 |         Result = (Sorted) ? -2 : -1; | 
| 206 |       else if (maxcmp > 0)           // Means maxval < Val | 
| 207 |         Result = -1; | 
| 208 |       else if (!mincmp && !maxcmp)   // minval = maxval = val | 
| 209 |         Result = 1; | 
| 210 |       else | 
| 211 |         Result = 0; | 
| 212 |  | 
| 213 |       break; | 
| 214 |     case OP_GT: | 
| 215 |     case OP_LE: | 
| 216 |       if (mincmp < 0)                // minval > Val | 
| 217 |         Result = (Sorted) ? 2 : 1; | 
| 218 |       else if (maxcmp < 0)           // maxval > Val | 
| 219 |         Result = 0; | 
| 220 |       else                           // maxval <= Val | 
| 221 |         Result = -1; | 
| 222 |  | 
| 223 |       break; | 
| 224 |     case OP_GE: | 
| 225 |     case OP_LT: | 
| 226 |       if (mincmp <= 0)               // minval >= Val | 
| 227 |         Result = (Sorted) ? 2 : 1; | 
| 228 |       else if (maxcmp <= 0)          // Maxval >= Val | 
| 229 |         Result = 0; | 
| 230 |       else                           // Maxval < Val | 
| 231 |         Result = -1; | 
| 232 |  | 
| 233 |       break; | 
| 234 |     } // endswitch Opc | 
| 235 |  | 
| 236 |   switch (Opc) { | 
| 237 |     case OP_NE: | 
| 238 |     case OP_LE: | 
| 239 |     case OP_LT: | 
| 240 |       Result = -Result; | 
| 241 |       break; | 
| 242 |     } // endswitch Opc | 
| 243 |  | 
| 244 |   if (trace(1)) | 
| 245 |     htrc("BlockEval: op=%d n=%d rc=%d\n" , Opc, n, Result); | 
| 246 |  | 
| 247 |   return Result; | 
| 248 |   } // end of BlockEval | 
| 249 |  | 
| 250 | /* ---------------------- Class BLKFILAR2----------------------------- */ | 
| 251 |  | 
| 252 | /***********************************************************************/ | 
| 253 | /*  BLKFILAR2 constructor.                                             */ | 
| 254 | /***********************************************************************/ | 
| 255 | BLKFILAR2::BLKFILAR2(PGLOBAL g, PTDBDOS tdbp, int op, PXOB *xp) | 
| 256 |          : BLKFILARI(g, tdbp, op, xp) | 
| 257 |   { | 
| 258 |   MakeValueBitmap(); | 
| 259 |   } // end of BLKFILAR2 constructor | 
| 260 |  | 
| 261 | /***********************************************************************/ | 
| 262 | /*  MakeValueBitmap: Set the constant value bit map. It can be void    */ | 
| 263 | /*  if the constant value is not in the column distinct values list.   */ | 
| 264 | /***********************************************************************/ | 
| 265 | void BLKFILAR2::MakeValueBitmap(void) | 
| 266 |   { | 
| 267 |   int   i; // ndv = Colp->GetNdv(); | 
| 268 |   bool  found = FALSE; | 
| 269 |   PVBLK dval = Colp->GetDval(); | 
| 270 |  | 
| 271 |   assert(dval); | 
| 272 |  | 
| 273 |   /*********************************************************************/ | 
| 274 |   /*  Here we cannot use Find because we must get the index            */ | 
| 275 |   /*  of where to put the value if it is not found in the array.       */ | 
| 276 |   /*  This is needed by operators other than OP_EQ or OP_NE.           */ | 
| 277 |   /*********************************************************************/ | 
| 278 |   found = dval->Locate(Valp, i); | 
| 279 |  | 
| 280 |   /*********************************************************************/ | 
| 281 |   /*  Set the constant value bitmap. The bitmaps are really matching   */ | 
| 282 |   /*  the OP_EQ, OP_LE, and OP_LT operator but are also used for the   */ | 
| 283 |   /*  other operators for which the Result will be inverted.           */ | 
| 284 |   /*  The reason the bitmaps are not directly complemented for them is */ | 
| 285 |   /*  to be able to test easily the cases of sorted columns with Bxp,  */ | 
| 286 |   /*  and the case of a void bitmap, which happens if the constant     */ | 
| 287 |   /*  value is not in the column distinct values list.                 */ | 
| 288 |   /*********************************************************************/ | 
| 289 |   if (found) { | 
| 290 |     Bmp = 1 << i;               // Bit of the found value | 
| 291 |     Bxp = Bmp - 1;              // All smaller values | 
| 292 |  | 
| 293 |     if (Opc != OP_LT && Opc != OP_GE) | 
| 294 |       Bxp |= Bmp;               // Found value must be included | 
| 295 |  | 
| 296 |   } else { | 
| 297 |     Bmp = 0; | 
| 298 |     Bxp = (1 << i) - 1; | 
| 299 |   } // endif found | 
| 300 |  | 
| 301 |   if (!(Opc == OP_EQ || Opc == OP_NE)) | 
| 302 |     Bmp = Bxp; | 
| 303 |  | 
| 304 |   } // end of MakeValueBitmap | 
| 305 |  | 
| 306 | /***********************************************************************/ | 
| 307 | /*  Evaluate XDB2 block filter for arithmetic operators.               */ | 
| 308 | /***********************************************************************/ | 
| 309 | int BLKFILAR2::BlockEval(PGLOBAL) | 
| 310 |   { | 
| 311 | #if defined(_DEBUG) | 
| 312 |   assert (Colp->IsClustered()); | 
| 313 | #endif | 
| 314 |  | 
| 315 |   int   n = ((PTDBDOS)Colp->GetTo_Tdb())->GetCurBlk(); | 
| 316 |   uint  bkmp = *(uint*)Colp->GetBmap()->GetValPtr(n); | 
| 317 |   uint  bres = Bmp & bkmp; | 
| 318 |  | 
| 319 |   // Set result as if Opc were OP_EQ, OP_LT, or OP_LE | 
| 320 |   if (!bres) { | 
| 321 |     if (!Bmp) | 
| 322 |       Result = -2;              // No good block in the table file | 
| 323 |     else if (!Sorted) | 
| 324 |       Result = -1;              // No good values in this block | 
| 325 |     else    // Sorted column, test for no more good blocks in file | 
| 326 |       Result = (Bxp & bkmp) ? -1 : -2; | 
| 327 |  | 
| 328 |   } else | 
| 329 |     // Test whether all block values are good or only some ones | 
| 330 |     Result = (bres == bkmp) ? 1 : 0; | 
| 331 |  | 
| 332 |   // For OP_NE, OP_GE, and OP_GT the result must be inverted. | 
| 333 |   switch (Opc) { | 
| 334 |     case OP_NE: | 
| 335 |     case OP_GE: | 
| 336 |     case OP_GT: | 
| 337 |       Result = -Result; | 
| 338 |       break; | 
| 339 |     } // endswitch Opc | 
| 340 |  | 
| 341 |   if (trace(1)) | 
| 342 |     htrc("BlockEval2: op=%d n=%d rc=%d\n" , Opc, n, Result); | 
| 343 |  | 
| 344 |   return Result; | 
| 345 |   } // end of BlockEval | 
| 346 |  | 
| 347 | /* ---------------------- Class BLKFILMR2----------------------------- */ | 
| 348 |  | 
| 349 | /***********************************************************************/ | 
| 350 | /*  BLKFILMR2 constructor.                                             */ | 
| 351 | /***********************************************************************/ | 
| 352 | BLKFILMR2::BLKFILMR2(PGLOBAL g, PTDBDOS tdbp, int op, PXOB *xp) | 
| 353 |          : BLKFILARI(g, tdbp, op, xp) | 
| 354 |   { | 
| 355 |   Nbm = Colp->GetNbm(); | 
| 356 |   Bmp = (uint*)PlugSubAlloc(g, NULL, Nbm * sizeof(uint)); | 
| 357 |   Bxp = (uint*)PlugSubAlloc(g, NULL, Nbm * sizeof(uint)); | 
| 358 |   MakeValueBitmap(); | 
| 359 |   } // end of BLKFILMR2 constructor | 
| 360 |  | 
| 361 | /***********************************************************************/ | 
| 362 | /*  MakeValueBitmap: Set the constant value bit map. It can be void    */ | 
| 363 | /*  if the constant value is not in the column distinct values list.   */ | 
| 364 | /***********************************************************************/ | 
| 365 | void BLKFILMR2::MakeValueBitmap(void) | 
| 366 |   { | 
| 367 |   int   i; // ndv = Colp->GetNdv(); | 
| 368 |   bool  found = FALSE, noteq = !(Opc == OP_EQ || Opc == OP_NE); | 
| 369 |   PVBLK dval = Colp->GetDval(); | 
| 370 |  | 
| 371 |   assert(dval); | 
| 372 |  | 
| 373 |   for (i = 0; i < Nbm; i++) | 
| 374 |     Bmp[i] = Bxp[i] = 0; | 
| 375 |  | 
| 376 |   /*********************************************************************/ | 
| 377 |   /*  Here we cannot use Find because we must get the index            */ | 
| 378 |   /*  of where to put the value if it is not found in the array.       */ | 
| 379 |   /*  This is needed by operators other than OP_EQ or OP_NE.           */ | 
| 380 |   /*********************************************************************/ | 
| 381 |   found = dval->Locate(Valp, i); | 
| 382 |  | 
| 383 |   /*********************************************************************/ | 
| 384 |   /*  For bitmaps larger than a ULONG, we must know where Bmp and Bxp  */ | 
| 385 |   /*  are positioned in the ULONG bit map block array.                 */ | 
| 386 |   /*********************************************************************/ | 
| 387 |   N = i / MAXBMP; | 
| 388 |   i %= MAXBMP; | 
| 389 |  | 
| 390 |   /*********************************************************************/ | 
| 391 |   /*  Set the constant value bitmaps. The bitmaps are really matching  */ | 
| 392 |   /*  the OP_EQ, OP_LE, and OP_LT operator but are also used for the   */ | 
| 393 |   /*  other operators for which the Result will be inverted.           */ | 
| 394 |   /*  The reason the bitmaps are not directly complemented for them is */ | 
| 395 |   /*  to be able to easily test the cases of sorted columns with Bxp,  */ | 
| 396 |   /*  and the case of a void bitmap, which happens if the constant     */ | 
| 397 |   /*  value is not in the column distinct values list.                 */ | 
| 398 |   /*********************************************************************/ | 
| 399 |   if (found) { | 
| 400 |     Bmp[N] = 1 << i; | 
| 401 |     Bxp[N] = Bmp[N] - 1; | 
| 402 |  | 
| 403 |     if (Opc != OP_LT && Opc != OP_GE) | 
| 404 |       Bxp[N] |= Bmp[N];    // Found value must be included | 
| 405 |  | 
| 406 |   } else | 
| 407 |     Bxp[N] = (1 << i) - 1; | 
| 408 |  | 
| 409 |   if (noteq) | 
| 410 |     Bmp[N] = Bxp[N]; | 
| 411 |  | 
| 412 |   Void = !Bmp[N];          // There are no good values in the file | 
| 413 |  | 
| 414 |   for (i = 0; i < N; i++) { | 
| 415 |     Bxp[i] = ~0; | 
| 416 |  | 
| 417 |     if (noteq) | 
| 418 |       Bmp[i] = Bxp[i]; | 
| 419 |  | 
| 420 |     Void = Void && !Bmp[i]; | 
| 421 |     } // endfor i | 
| 422 |  | 
| 423 |   if (!Bmp[N] && !Bxp[N]) | 
| 424 |     N--; | 
| 425 |  | 
| 426 |   } // end of MakeValueBitmap | 
| 427 |  | 
| 428 | /***********************************************************************/ | 
| 429 | /*  Evaluate XDB2 block filter for arithmetic operators.               */ | 
| 430 | /***********************************************************************/ | 
| 431 | int BLKFILMR2::BlockEval(PGLOBAL) | 
| 432 |   { | 
| 433 | #if defined(_DEBUG) | 
| 434 |   assert (Colp->IsClustered()); | 
| 435 | #endif | 
| 436 |  | 
| 437 |   int    i, n = ((PTDBDOS)Colp->GetTo_Tdb())->GetCurBlk(); | 
| 438 |   bool   fnd = FALSE, all = TRUE, gt = TRUE; | 
| 439 |   uint   bres; | 
| 440 |   uint  *bkmp = (uint*)Colp->GetBmap()->GetValPtr(n * Nbm); | 
| 441 |  | 
| 442 |   // Set result as if Opc were OP_EQ, OP_LT, or OP_LE | 
| 443 |   for (i = 0; i < Nbm; i++) | 
| 444 |     if (i <= N) { | 
| 445 |       if ((bres = Bmp[i] & bkmp[i])) | 
| 446 |         fnd = TRUE;         // Some good value(s) found in the block | 
| 447 |  | 
| 448 |       if (bres != bkmp[i]) | 
| 449 |         all = FALSE;        // Not all block values are good | 
| 450 |  | 
| 451 |       if (Bxp[i] & bkmp[i]) | 
| 452 |         gt = FALSE;         // Not all block values are > good value(s) | 
| 453 |  | 
| 454 |     } else if (bkmp[i]) { | 
| 455 |       all = FALSE; | 
| 456 |       break; | 
| 457 |     } // endif's | 
| 458 |  | 
| 459 |   if (!fnd) { | 
| 460 |     if (Void || (gt && Sorted)) | 
| 461 |       Result = -2;          // No (more) good block in file | 
| 462 |     else | 
| 463 |       Result = -1;          // No good values in this block | 
| 464 |  | 
| 465 |   } else | 
| 466 |     Result = (all) ? 1 : 0;                 // All block values are good | 
| 467 |  | 
| 468 |   // For OP_NE, OP_GE, and OP_GT the result must be inverted. | 
| 469 |   switch (Opc) { | 
| 470 |     case OP_NE: | 
| 471 |     case OP_GE: | 
| 472 |     case OP_GT: | 
| 473 |       Result = -Result; | 
| 474 |       break; | 
| 475 |     } // endswitch Opc | 
| 476 |  | 
| 477 |   if (trace(1)) | 
| 478 |     htrc("BlockEval2: op=%d n=%d rc=%d\n" , Opc, n, Result); | 
| 479 |  | 
| 480 |   return Result; | 
| 481 |   } // end of BlockEval | 
| 482 |  | 
| 483 | /***********************************************************************/ | 
| 484 | /*  BLKSPCARI constructor.                                             */ | 
| 485 | /***********************************************************************/ | 
| 486 | BLKSPCARI::BLKSPCARI(PTDBDOS tdbp, int op, PXOB *xp, int bsize) | 
| 487 |          : BLOCKFILTER(tdbp, op) | 
| 488 |   { | 
| 489 |   if (xp[1]->GetType() == TYPE_COLBLK) { | 
| 490 |     Cpx = (PCOL)xp[1];      // Subquery pseudo constant column | 
| 491 |     Correl = TRUE; | 
| 492 |   } else | 
| 493 |     Cpx = NULL; | 
| 494 |  | 
| 495 |   Valp = xp[1]->GetValue(); | 
| 496 |   Val = (int)xp[1]->GetValue()->GetIntValue(); | 
| 497 |   Bsize = bsize; | 
| 498 |   } // end of BLKFILARI constructor | 
| 499 |  | 
| 500 | /***********************************************************************/ | 
| 501 | /*  Reset: re-eval the constant value in the case of pseudo constant   */ | 
| 502 | /*  column use in a correlated subquery.                               */ | 
| 503 | /***********************************************************************/ | 
| 504 | void BLKSPCARI::Reset(PGLOBAL g) | 
| 505 |   { | 
| 506 |   if (Cpx) { | 
| 507 |     Cpx->Reset(); | 
| 508 |     Cpx->Eval(g); | 
| 509 |     Val = (int)Valp->GetIntValue(); | 
| 510 |     } // endif Cpx | 
| 511 |  | 
| 512 |   } // end of Reset | 
| 513 |  | 
| 514 | /***********************************************************************/ | 
| 515 | /*  Evaluate block filter for arithmetic operators (ROWID)             */ | 
| 516 | /***********************************************************************/ | 
| 517 | int BLKSPCARI::BlockEval(PGLOBAL) | 
| 518 |   { | 
| 519 |   int mincmp, maxcmp, n, m; | 
| 520 |  | 
| 521 |   n = Tdbp->GetCurBlk(); | 
| 522 |   m = n * Bsize + 1;     // Minimum Rowid value for this block | 
| 523 |   mincmp = (Val > m) ? 1 : (Val < m) ? (-1) : 0; | 
| 524 |   m = (n + 1) * Bsize;   // Maximum Rowid value for this block | 
| 525 |   maxcmp = (Val > m) ? 1 : (Val < m) ? (-1) : 0; | 
| 526 |  | 
| 527 |   switch (Opc) { | 
| 528 |     case OP_EQ: | 
| 529 |     case OP_NE: | 
| 530 |       if (mincmp < 0)                // Means minval > Val | 
| 531 |         Result = -2;                 // Always sorted | 
| 532 |       else if (maxcmp > 0)           // Means maxval < Val | 
| 533 |         Result = -1; | 
| 534 |       else if (!mincmp && !maxcmp)   // minval = maxval = val | 
| 535 |         Result = 1; | 
| 536 |       else | 
| 537 |         Result = 0; | 
| 538 |  | 
| 539 |       break; | 
| 540 |     case OP_GT: | 
| 541 |     case OP_LE: | 
| 542 |       if (mincmp < 0)                // minval > Val | 
| 543 |         Result = 2;                  // Always sorted | 
| 544 |       else if (maxcmp < 0)           // maxval > Val | 
| 545 |         Result = 0; | 
| 546 |       else                           // maxval <= Val | 
| 547 |         Result = -1; | 
| 548 |  | 
| 549 |       break; | 
| 550 |     case OP_GE: | 
| 551 |     case OP_LT: | 
| 552 |       if (mincmp <= 0)               // minval >= Val | 
| 553 |         Result = 2;                  // Always sorted | 
| 554 |       else if (maxcmp <= 0)          // Maxval >= Val | 
| 555 |         Result = 0; | 
| 556 |       else                           // Maxval < Val | 
| 557 |         Result = -1; | 
| 558 |  | 
| 559 |       break; | 
| 560 |     } // endswitch Opc | 
| 561 |  | 
| 562 |   switch (Opc) { | 
| 563 |     case OP_NE: | 
| 564 |     case OP_LE: | 
| 565 |     case OP_LT: | 
| 566 |       Result = -Result; | 
| 567 |       break; | 
| 568 |     } // endswitch Opc | 
| 569 |  | 
| 570 |   if (trace(1)) | 
| 571 |     htrc("BlockEval: op=%d n=%d rc=%d\n" , Opc, n, Result); | 
| 572 |  | 
| 573 |   return Result; | 
| 574 |   } // end of BlockEval | 
| 575 |  | 
| 576 | /* ------------------------ Class BLKFILIN --------------------------- */ | 
| 577 |  | 
| 578 | /***********************************************************************/ | 
| 579 | /*  BLKFILIN constructor.                                              */ | 
| 580 | /***********************************************************************/ | 
| 581 | BLKFILIN::BLKFILIN(PGLOBAL g, PTDBDOS tdbp, int op, int opm, PXOB *xp) | 
| 582 |         : BLOCKFILTER(tdbp, op) | 
| 583 |   { | 
| 584 |   if (op == OP_IN) { | 
| 585 |     Opc = OP_EQ; | 
| 586 |     Opm = 1; | 
| 587 |   } else { | 
| 588 |     Opc = op; | 
| 589 |     Opm = opm; | 
| 590 |   } // endif op | 
| 591 |  | 
| 592 |   Colp = (PDOSCOL)xp[0]; | 
| 593 |   Arap = (PARRAY)xp[1]; | 
| 594 |   Type = Arap->GetResultType(); | 
| 595 |  | 
| 596 |   if (Colp->GetResultType() != Type) { | 
| 597 |     sprintf(g->Message, "BLKFILIN: %s" , MSG(VALTYPE_NOMATCH)); | 
| 598 | 		throw g->Message; | 
| 599 | 	} else if (Colp->GetValue()->IsCi()) | 
| 600 |     Arap->SetPrecision(g, 1);        // Case insensitive | 
| 601 |  | 
| 602 |   Sorted = Colp->IsSorted() > 0; | 
| 603 |   } // end of BLKFILIN constructor | 
| 604 |  | 
| 605 | /***********************************************************************/ | 
| 606 | /*  Reset: have the sorted array reset its Bot value to -1 (bottom).   */ | 
| 607 | /***********************************************************************/ | 
| 608 | void BLKFILIN::Reset(PGLOBAL) | 
| 609 |   { | 
| 610 |   Arap->Reset(); | 
| 611 | //  MakeValueBitmap();      // Does nothing for class BLKFILIN | 
| 612 |   } // end of Reset | 
| 613 |  | 
| 614 | /***********************************************************************/ | 
| 615 | /*  Evaluate block filter for a IN operator on a constant array.       */ | 
| 616 | /*  Note: here we need to use the GetValPtrEx function to get a zero   */ | 
| 617 | /*  ended string in case of string argument. This is because the ARRAY */ | 
| 618 | /*  can have a different width than the char column.                   */ | 
| 619 | /***********************************************************************/ | 
| 620 | int BLKFILIN::BlockEval(PGLOBAL g) | 
| 621 |   { | 
| 622 |   int   n = ((PTDBDOS)Colp->GetTo_Tdb())->GetCurBlk(); | 
| 623 |   void *minp = Colp->GetMin()->GetValPtrEx(n); | 
| 624 |   void *maxp = Colp->GetMax()->GetValPtrEx(n); | 
| 625 |  | 
| 626 |   Result = Arap->BlockTest(g, Opc, Opm, minp, maxp, Sorted); | 
| 627 |   return Result; | 
| 628 |   } // end of BlockEval | 
| 629 |  | 
| 630 | /* ------------------------ Class BLKFILIN2 -------------------------- */ | 
| 631 |  | 
| 632 | /***********************************************************************/ | 
| 633 | /*  BLKFILIN2 constructor.                                             */ | 
| 634 | /*  New version that takes care of all operators and modificators.     */ | 
| 635 | /*  It is also ready to handle the case of correlated sub-selects.     */ | 
| 636 | /***********************************************************************/ | 
| 637 | BLKFILIN2::BLKFILIN2(PGLOBAL g, PTDBDOS tdbp, int op, int opm, PXOB *xp) | 
| 638 |          : BLKFILIN(g, tdbp, op, opm, xp) | 
| 639 |   { | 
| 640 |   Nbm = Colp->GetNbm(); | 
| 641 |   Valp = AllocateValue(g, Colp->GetValue()); | 
| 642 |   Invert = (Opc == OP_NE || Opc == OP_GE || Opc ==OP_GT); | 
| 643 |   Bmp = (uint*)PlugSubAlloc(g, NULL, Nbm * sizeof(uint)); | 
| 644 |   Bxp = (uint*)PlugSubAlloc(g, NULL, Nbm * sizeof(uint)); | 
| 645 |   MakeValueBitmap(); | 
| 646 |   } // end of BLKFILIN2 constructor | 
| 647 |  | 
| 648 | /***********************************************************************/ | 
| 649 | /*  MakeValueBitmap: Set the constant values bit map. It can be void   */ | 
| 650 | /*  if the constant values are not in the column distinct values list. */ | 
| 651 | /*  The bitmaps are prepared for the EQ, LE, and LT operators and      */ | 
| 652 | /*  takes care of the ALL and ANY modificators. If the operators are   */ | 
| 653 | /*  NE, GE, or GT the modificator is inverted and the result will be.  */ | 
| 654 | /***********************************************************************/ | 
| 655 | void BLKFILIN2::MakeValueBitmap(void) | 
| 656 |   { | 
| 657 |   int   i, k, n, ndv = Colp->GetNdv(); | 
| 658 |   bool  found, noteq = !(Opc == OP_EQ || Opc == OP_NE); | 
| 659 |   bool  all = (!Invert) ? (Opm == 2) : (Opm != 2); | 
| 660 |   uint  btp; | 
| 661 |   PVBLK dval = Colp->GetDval(); | 
| 662 |  | 
| 663 |   N = -1; | 
| 664 |  | 
| 665 |   // Take care of special cases | 
| 666 |   if (!(n = Arap->GetNval())) { | 
| 667 |     // Return TRUE for ALL because it means that there are no item that | 
| 668 |     // does not verify the condition, which is true indeed. | 
| 669 |     // Return FALSE for ANY because TRUE means that there is at least | 
| 670 |     // one item that verifies the condition, which is false. | 
| 671 |     Result = (Opm == 2) ? 2 : -2; | 
| 672 |     return; | 
| 673 |   } else if (!noteq && all && n > 1) { | 
| 674 |     // An item cannot be equal to all different values | 
| 675 |     // or an item is always unequal to any different values | 
| 676 |     Result = (Opc == OP_EQ) ? -2 : 2; | 
| 677 |     return; | 
| 678 |   } // endif's | 
| 679 |  | 
| 680 |   for (i = 0; i < Nbm; i++) | 
| 681 |     Bmp[i] = Bxp[i] = 0; | 
| 682 |  | 
| 683 |   for (k = 0; k < n; k++) { | 
| 684 |     Arap->GetNthValue(Valp, k); | 
| 685 |     found = dval->Locate(Valp, i); | 
| 686 |     N = i / MAXBMP; | 
| 687 |     btp = 1 << (i % MAXBMP); | 
| 688 |  | 
| 689 |     if (found) | 
| 690 |       Bmp[N] |= btp; | 
| 691 |  | 
| 692 |     // For LT and LE if ALL the condition applies to the smallest item | 
| 693 |     // if ANY it applies to the largest item. In the case of EQ we come | 
| 694 |     // here only if ANY or if n == 1, so it does applies to the largest. | 
| 695 |     if ((!k && all) || (k == n - 1 && !all)) { | 
| 696 |       Bxp[N] = btp - 1; | 
| 697 |  | 
| 698 |       if (found && Opc != OP_LT && Opc != OP_GE) | 
| 699 |         Bxp[N] |= btp;     // Found value must be included | 
| 700 |  | 
| 701 |       } // endif k, opm | 
| 702 |  | 
| 703 |     } // endfor k | 
| 704 |  | 
| 705 |   if (noteq) | 
| 706 |     Bmp[N] = Bxp[N]; | 
| 707 |  | 
| 708 |   Void = !Bmp[N];          // There are no good values in the file | 
| 709 |  | 
| 710 |   for (i = 0; i < N; i++) { | 
| 711 |     Bxp[i] = ~0; | 
| 712 |  | 
| 713 |     if (noteq) { | 
| 714 |       Bmp[i] = Bxp[i]; | 
| 715 |       Void = FALSE; | 
| 716 |       } // endif noteq | 
| 717 |  | 
| 718 |     } // endfor i | 
| 719 |  | 
| 720 |   if (!Bmp[N] && !Bxp[N]) { | 
| 721 |     if (--N < 0) | 
| 722 |       // All array values are smaller than block values | 
| 723 |       Result = (Invert) ? 2 : -2; | 
| 724 |  | 
| 725 |   } else if (N == Nbm - 1 && (signed)Bmp[N] == (1 << (ndv % MAXBMP)) - 1) { | 
| 726 |     // Condition will be always TRUE or FALSE for the whole file | 
| 727 |     Result = (Invert) ? -2 : 2; | 
| 728 |     N = -1; | 
| 729 |   } // endif's | 
| 730 |  | 
| 731 |   } // end of MakeValueBitmap | 
| 732 |  | 
| 733 | /***********************************************************************/ | 
| 734 | /*  Evaluate block filter for set operators on a constant array.       */ | 
| 735 | /*  Note: here we need to use the GetValPtrEx function to get a zero   */ | 
| 736 | /*  ended string in case of string argument. This is because the ARRAY */ | 
| 737 | /*  can have a different width than the char column.                   */ | 
| 738 | /***********************************************************************/ | 
| 739 | int BLKFILIN2::BlockEval(PGLOBAL) | 
| 740 |   { | 
| 741 |   if (N < 0) | 
| 742 |     return Result;                  // Was set in MakeValueBitmap | 
| 743 |  | 
| 744 |   int    i, n = ((PTDBDOS)Colp->GetTo_Tdb())->GetCurBlk(); | 
| 745 |   bool   fnd = FALSE, all = TRUE, gt = TRUE; | 
| 746 |   uint   bres; | 
| 747 |   uint  *bkmp = (uint*)Colp->GetBmap()->GetValPtr(n * Nbm); | 
| 748 |  | 
| 749 |   // Set result as if Opc were OP_EQ, OP_LT, or OP_LE | 
| 750 |   // The difference between ALL or ANY was handled in MakeValueBitmap | 
| 751 |   for (i = 0; i < Nbm; i++) | 
| 752 |     if (i <= N) { | 
| 753 |       if ((bres = Bmp[i] & bkmp[i])) | 
| 754 |         fnd = TRUE; | 
| 755 |  | 
| 756 |       if (bres != bkmp[i]) | 
| 757 |         all = FALSE; | 
| 758 |  | 
| 759 |       if (Bxp[i] & bkmp[i]) | 
| 760 |         gt = FALSE; | 
| 761 |  | 
| 762 |     } else if (bkmp[i]) { | 
| 763 |       all = FALSE; | 
| 764 |       break; | 
| 765 |     } // endif's | 
| 766 |  | 
| 767 |   if (!fnd) { | 
| 768 |     if (Void || (Sorted && gt)) | 
| 769 |       Result = -2;              // No more good block in file | 
| 770 |     else | 
| 771 |       Result = -1;              // No good values in this block | 
| 772 |  | 
| 773 |   } else if (all) | 
| 774 |     Result = 1;                 // All block values are good | 
| 775 |   else | 
| 776 |     Result = 0;                 // Block contains some good values | 
| 777 |  | 
| 778 |   // For OP_NE, OP_GE, and OP_GT the result must be inverted. | 
| 779 |   switch (Opc) { | 
| 780 |     case OP_NE: | 
| 781 |     case OP_GE: | 
| 782 |     case OP_GT: | 
| 783 |       Result = -Result; | 
| 784 |       break; | 
| 785 |     } // endswitch Opc | 
| 786 |  | 
| 787 |   return Result; | 
| 788 |   } // end of BlockEval | 
| 789 |  | 
| 790 | #if 0 | 
| 791 | /***********************************************************************/ | 
| 792 | /*  BLKFILIN2 constructor.                                             */ | 
| 793 | /***********************************************************************/ | 
| 794 | BLKFILIN2::BLKFILIN2(PGLOBAL g, PTDBDOS tdbp, int op, int opm, PXOB *xp) | 
| 795 |          : BLKFILIN(g, tdbp, op, opm, xp) | 
| 796 |   { | 
| 797 |   // Currently, bitmap matching is only implemented for the IN operator | 
| 798 |   if (!(Bitmap = (op == OP_IN || (op == OP_EQ && opm != 2)))) { | 
| 799 |     Nbm = Colp->GetNbm(); | 
| 800 |     N = 0; | 
| 801 |     return;           // Revert to standard minmax method | 
| 802 |     } // endif minmax | 
| 803 |  | 
| 804 |   int   i, n; | 
| 805 |   ULONG btp; | 
| 806 |   PVAL  valp = AllocateValue(g, Colp->GetValue()); | 
| 807 |   PVBLK dval = Colp->GetDval(); | 
| 808 |  | 
| 809 |   Nbm = Colp->GetNbm(); | 
| 810 |   N = -1; | 
| 811 |   Bmp = (PULONG)PlugSubAlloc(g, NULL, Nbm * sizeof(ULONG)); | 
| 812 |   Bxp = (PULONG)PlugSubAlloc(g, NULL, Nbm * sizeof(ULONG)); | 
| 813 |  | 
| 814 |   for (i = 0; i < Nbm; i++) | 
| 815 |     Bmp[i] = Bxp[i] = 0; | 
| 816 |  | 
| 817 |   for (n = 0; n < Arap->GetNval(); n++) { | 
| 818 |     Arap->GetNthValue(valp, n); | 
| 819 |  | 
| 820 |     if ((i = dval->Find(valp)) >= 0) | 
| 821 |       Bmp[i / MAXBMP] |= 1 << (i % MAXBMP); | 
| 822 |  | 
| 823 |     } // endfor n | 
| 824 |  | 
| 825 |   for (i = Nbm - 1; i >= 0; i--) | 
| 826 |     if (Bmp[i]) { | 
| 827 |       for (btp = Bmp[i]; btp; btp >>= 1) | 
| 828 |         Bxp[i] |= btp; | 
| 829 |  | 
| 830 |       for (N = i--; i >= 0; i--) | 
| 831 |         Bxp[i] = ~0; | 
| 832 |  | 
| 833 |       break; | 
| 834 |       } // endif Bmp | 
| 835 |  | 
| 836 |   } // end of BLKFILIN2 constructor | 
| 837 |  | 
| 838 | /***********************************************************************/ | 
| 839 | /*  Evaluate block filter for a IN operator on a constant array.       */ | 
| 840 | /*  Note: here we need to use the GetValPtrEx function to get a zero   */ | 
| 841 | /*  ended string in case of string argument. This is because the ARRAY */ | 
| 842 | /*  can have a different width than the char column.                   */ | 
| 843 | /***********************************************************************/ | 
| 844 | int BLKFILIN2::BlockEval(PGLOBAL g) | 
| 845 |   { | 
| 846 |   if (N < 0) | 
| 847 |     return -2;                  // IN list contains no good values | 
| 848 |  | 
| 849 |   int    i, n = ((PTDBDOS)Colp->GetTo_Tdb())->GetCurBlk(); | 
| 850 |   bool   fnd = FALSE, all = TRUE, gt = TRUE; | 
| 851 |   ULONG  bres; | 
| 852 |   PULONG bkmp = (PULONG)Colp->GetBmap()->GetValPtr(n * Nbm); | 
| 853 |  | 
| 854 |   if (Bitmap) { | 
| 855 |     // For IN operator use the bitmap method | 
| 856 |     for (i = 0; i < Nbm; i++) | 
| 857 |       if (i <= N) { | 
| 858 |         if ((bres = Bmp[i] & bkmp[i])) | 
| 859 |           fnd = TRUE; | 
| 860 |  | 
| 861 |         if (bres != bkmp[i]) | 
| 862 |           all = FALSE; | 
| 863 |  | 
| 864 |         if (Bxp[i] & bkmp[i]) | 
| 865 |           gt = FALSE; | 
| 866 |  | 
| 867 |       } else if (bkmp[i]) { | 
| 868 |         all = FALSE; | 
| 869 |         break; | 
| 870 |       } // endif's | 
| 871 |  | 
| 872 |     if (!fnd) { | 
| 873 |       if (Sorted && gt) | 
| 874 |         Result = -2;              // No more good block in file | 
| 875 |       else | 
| 876 |         Result = -1;              // No good values in this block | 
| 877 |  | 
| 878 |     } else if (all) | 
| 879 |       Result = 1;                 // All block values are good | 
| 880 |     else | 
| 881 |       Result = 0;                 // Block contains some good values | 
| 882 |  | 
| 883 |   } else { | 
| 884 |     // For other than IN operators, revert to standard minmax method | 
| 885 |     int   n = 0, ndv = Colp->GetNdv(); | 
| 886 |     void *minp = NULL; | 
| 887 |     void *maxp = NULL; | 
| 888 |     ULONG btp; | 
| 889 |     PVBLK dval = Colp->GetDval(); | 
| 890 |  | 
| 891 |     for (i = 0; i < Nbm; i++) | 
| 892 |       for (btp = 1; btp && n < ndv; btp <<= 1, n++) | 
| 893 |         if (btp & bkmp[i]) { | 
| 894 |           if (!minp) | 
| 895 |             minp = dval->GetValPtrEx(n); | 
| 896 |  | 
| 897 |           maxp = dval->GetValPtrEx(n); | 
| 898 |           } // endif btp | 
| 899 |  | 
| 900 |     Result = Arap->BlockTest(g, Opc, Opm, minp, maxp, Colp->IsSorted()); | 
| 901 |   } // endif Bitmap | 
| 902 |  | 
| 903 |   return Result; | 
| 904 |   } // end of BlockEval | 
| 905 | #endif // 0 | 
| 906 |  | 
| 907 | /* ------------------------ Class BLKSPCIN --------------------------- */ | 
| 908 |  | 
| 909 | /***********************************************************************/ | 
| 910 | /*  BLKSPCIN constructor.                                              */ | 
| 911 | /***********************************************************************/ | 
| 912 | BLKSPCIN::BLKSPCIN(PGLOBAL, PTDBDOS tdbp, int op, int opm, | 
| 913 |                    PXOB *xp, int bsize) | 
| 914 |         : BLOCKFILTER(tdbp, op) | 
| 915 |   { | 
| 916 |   if (op == OP_IN) { | 
| 917 |     Opc = OP_EQ; | 
| 918 |     Opm = 1; | 
| 919 |   } else | 
| 920 |     Opm = opm; | 
| 921 |  | 
| 922 |   Arap = (PARRAY)xp[1]; | 
| 923 | #if defined(_DEBUG) | 
| 924 |   assert (Opm); | 
| 925 |   assert (Arap->GetResultType() == TYPE_INT); | 
| 926 | #endif | 
| 927 |   Bsize = bsize; | 
| 928 |   } // end of BLKSPCIN constructor | 
| 929 |  | 
| 930 | /***********************************************************************/ | 
| 931 | /*  Reset: have the sorted array reset its Bot value to -1 (bottom).   */ | 
| 932 | /***********************************************************************/ | 
| 933 | void BLKSPCIN::Reset(PGLOBAL) | 
| 934 |   { | 
| 935 |   Arap->Reset(); | 
| 936 |   } // end of Reset | 
| 937 |  | 
| 938 | /***********************************************************************/ | 
| 939 | /*  Evaluate block filter for a IN operator on a constant array.       */ | 
| 940 | /***********************************************************************/ | 
| 941 | int BLKSPCIN::BlockEval(PGLOBAL g) | 
| 942 |   { | 
| 943 |   int  n = Tdbp->GetCurBlk(); | 
| 944 |   int minrow = n * Bsize + 1;   // Minimum Rowid value for this block | 
| 945 |   int maxrow = (n + 1) * Bsize; // Maximum Rowid value for this block | 
| 946 |  | 
| 947 |   Result = Arap->BlockTest(g, Opc, Opm, &minrow, &maxrow, TRUE); | 
| 948 |   return Result; | 
| 949 |   } // end of BlockEval | 
| 950 |  | 
| 951 | /* ------------------------------------------------------------------- */ | 
| 952 |  | 
| 953 | #if 0 | 
| 954 | /***********************************************************************/ | 
| 955 | /*  Implementation of the BLOCKINDEX class.                            */ | 
| 956 | /***********************************************************************/ | 
| 957 | BLOCKINDEX::BLOCKINDEX(PBX nx, PDOSCOL cp, PKXBASE kp) | 
| 958 |   { | 
| 959 |   Next = nx; | 
| 960 |   Tdbp = (cp) ? (PTDBDOS)cp->GetTo_Tdb() : NULL; | 
| 961 |   Colp = cp; | 
| 962 |   Kxp = kp; | 
| 963 |   Type = (cp) ? cp->GetResultType() : TYPE_ERROR; | 
| 964 |   Sorted = (cp) ? cp->IsSorted() > 0 : FALSE; | 
| 965 |   Result = 0; | 
| 966 |   } // end of BLOCKINDEX constructor | 
| 967 |  | 
| 968 | /***********************************************************************/ | 
| 969 | /*  Reset Bot and Top values of optimized Kindex blocks.               */ | 
| 970 | /***********************************************************************/ | 
| 971 | void BLOCKINDEX::Reset(void) | 
| 972 |   { | 
| 973 |   if (Next) | 
| 974 |     Next->Reset(); | 
| 975 |  | 
| 976 |   Kxp->Reset(); | 
| 977 |   } // end of Reset | 
| 978 |  | 
| 979 | /***********************************************************************/ | 
| 980 | /*  Evaluate block indexing test.                                      */ | 
| 981 | /***********************************************************************/ | 
| 982 | int BLOCKINDEX::BlockEval(PGLOBAL g) | 
| 983 |   { | 
| 984 | #if defined(_DEBUG) | 
| 985 |   assert (Tdbp && Colp); | 
| 986 | #endif | 
| 987 |   int   n = Tdbp->GetCurBlk(); | 
| 988 |   void *minp = Colp->GetMin()->GetValPtr(n); | 
| 989 |   void *maxp = Colp->GetMax()->GetValPtr(n); | 
| 990 |  | 
| 991 |   Result = Kxp->BlockTest(g, minp, maxp, Type, Sorted); | 
| 992 |   return Result; | 
| 993 |   } // end of BlockEval | 
| 994 |  | 
| 995 | /***********************************************************************/ | 
| 996 | /*  Make file output of BLOCKINDEX contents.                           */ | 
| 997 | /***********************************************************************/ | 
| 998 | void BLOCKINDEX::Printf(PGLOBAL g, FILE *f, UINT n) | 
| 999 |   { | 
| 1000 |   char m[64]; | 
| 1001 |  | 
| 1002 |   memset(m, ' ', n);                    // Make margin string | 
| 1003 |   m[n] = '\0'; | 
| 1004 |  | 
| 1005 |   fprintf(f, "%sBLOCKINDEX: at %p next=%p col=%s kxp=%p result=%d\n" , | 
| 1006 |     m, this, Next, (Colp) ? Colp->GetName() : "Rowid" , Kxp, Result); | 
| 1007 |  | 
| 1008 |   if (Next) | 
| 1009 |     Next->Printf(g, f, n); | 
| 1010 |  | 
| 1011 |   } // end of Printf | 
| 1012 |  | 
| 1013 | /***********************************************************************/ | 
| 1014 | /*  Make string output of BLOCKINDEX contents.                         */ | 
| 1015 | /***********************************************************************/ | 
| 1016 | void BLOCKINDEX::Prints(PGLOBAL g, char *ps, UINT z) | 
| 1017 |   { | 
| 1018 |   strncat(ps, "BlockIndex(es)" , z); | 
| 1019 |   } // end of Prints | 
| 1020 |  | 
| 1021 | /* ------------------------------------------------------------------- */ | 
| 1022 |  | 
| 1023 | /***********************************************************************/ | 
| 1024 | /*  Implementation of the BLOCKINDX2 class.                            */ | 
| 1025 | /***********************************************************************/ | 
| 1026 | BLOCKINDX2::BLOCKINDX2(PBX nx, PDOSCOL cp, PKXBASE kp) | 
| 1027 |           : BLOCKINDEX(nx, cp, kp) | 
| 1028 |   { | 
| 1029 |   Nbm = Colp->GetNbm(); | 
| 1030 |   Dval = Colp->GetDval(); | 
| 1031 |   Bmap = Colp->GetBmap(); | 
| 1032 | #if defined(_DEBUG) | 
| 1033 |   assert(Dval && Bmap); | 
| 1034 | #endif | 
| 1035 |   } // end of BLOCKINDX2 constructor | 
| 1036 |  | 
| 1037 | /***********************************************************************/ | 
| 1038 | /*  Evaluate block indexing test.                                      */ | 
| 1039 | /***********************************************************************/ | 
| 1040 | int BLOCKINDX2::BlockEval(PGLOBAL g) | 
| 1041 |   { | 
| 1042 |   int   n = Tdbp->GetCurBlk(); | 
| 1043 |   PUINT bmp = (PUINT)Bmap->GetValPtr(n * Nbm); | 
| 1044 |  | 
| 1045 |   Result = Kxp->BlockTst2(g, Dval, bmp, Nbm, Type, Sorted); | 
| 1046 |   return Result; | 
| 1047 |   } // end of BlockEval | 
| 1048 |  | 
| 1049 | /* ------------------------------------------------------------------- */ | 
| 1050 |  | 
| 1051 | /***********************************************************************/ | 
| 1052 | /*  Implementation of the BLKSPCINDX class.                            */ | 
| 1053 | /***********************************************************************/ | 
| 1054 | BLKSPCINDX::BLKSPCINDX(PBX nx, PTDBDOS tp, PKXBASE kp, int bsize) | 
| 1055 |           : BLOCKINDEX(nx, NULL, kp) | 
| 1056 |   { | 
| 1057 |   Tdbp = tp; | 
| 1058 |   Bsize = bsize; | 
| 1059 |   Type = TYPE_INT; | 
| 1060 |   Sorted = TRUE; | 
| 1061 |   } // end of BLKSPCINDX constructor | 
| 1062 |  | 
| 1063 | /***********************************************************************/ | 
| 1064 | /*  Evaluate block indexing test.                                      */ | 
| 1065 | /***********************************************************************/ | 
| 1066 | int BLKSPCINDX::BlockEval(PGLOBAL g) | 
| 1067 |   { | 
| 1068 |   int  n = Tdbp->GetCurBlk(); | 
| 1069 |   int minrow = n * Bsize + 1;   // Minimum Rowid value for this block | 
| 1070 |   int maxrow = (n + 1) * Bsize; // Maximum Rowid value for this block | 
| 1071 |  | 
| 1072 |   Result = Kxp->BlockTest(g, &minrow, &maxrow, TYPE_INT, TRUE); | 
| 1073 |   return Result; | 
| 1074 |   } // end of BlockEval | 
| 1075 | #endif // 0 | 
| 1076 |  |