summaryrefslogtreecommitdiffstats
path: root/storage/connect/blkfil.cpp
diff options
context:
space:
mode:
Diffstat (limited to '')
-rw-r--r--storage/connect/blkfil.cpp1075
1 files changed, 1075 insertions, 0 deletions
diff --git a/storage/connect/blkfil.cpp b/storage/connect/blkfil.cpp
new file mode 100644
index 00000000..692ef98a
--- /dev/null
+++ b/storage/connect/blkfil.cpp
@@ -0,0 +1,1075 @@
+/************* BlkFil C++ Program Source Code File (.CPP) **************/
+/* PROGRAM NAME: BLKFIL */
+/* ------------- */
+/* Version 2.6 */
+/* */
+/* COPYRIGHT: */
+/* ---------- */
+/* (C) Copyright to the author Olivier BERTRAND 2004-2017 */
+/* */
+/* WHAT THIS PROGRAM DOES: */
+/* ----------------------- */
+/* This program is the implementation of block indexing classes. */
+/* */
+/***********************************************************************/
+
+/***********************************************************************/
+/* Include relevant MariaDB header file. */
+/***********************************************************************/
+#include "my_global.h"
+#include "sql_class.h"
+//#include "sql_time.h"
+
+#if defined(_WIN32)
+//#include <windows.h>
+#else // !_WIN32
+#include <string.h>
+#include <sys/types.h>
+#include <sys/stat.h>
+#endif // !_WIN32
+
+/***********************************************************************/
+/* Include application header files: */
+/***********************************************************************/
+#include "global.h" // global declarations
+#include "plgdbsem.h" // DB application declarations
+#include "xindex.h" // Key Index class declarations
+#include "filamtxt.h" // File access method dcls
+#include "tabdos.h" // TDBDOS and DOSCOL class dcls
+#include "array.h" // ARRAY classes dcls
+#include "blkfil.h" // Block Filter classes dcls
+
+/* ------------------------ Class BLOCKFILTER ------------------------ */
+
+/***********************************************************************/
+/* BLOCKFILTER constructor. */
+/***********************************************************************/
+BLOCKFILTER::BLOCKFILTER(PTDBDOS tdbp, int op)
+ {
+ Tdbp = tdbp;
+ Correl = FALSE;
+ Opc = op;
+ Opm = 0;
+ Result = 0;
+ } // end of BLOCKFILTER constructor
+
+/***********************************************************************/
+/* Make file output of BLOCKFILTER contents. */
+/***********************************************************************/
+void BLOCKFILTER::Printf(PGLOBAL, FILE *f, uint n)
+ {
+ char m[64];
+
+ memset(m, ' ', n); // Make margin string
+ m[n] = '\0';
+
+ fprintf(f, "%sBLOCKFILTER: at %p opc=%d opm=%d result=%d\n",
+ m, this, Opc, Opm, Result);
+ } // end of Printf
+
+/***********************************************************************/
+/* Make string output of BLOCKFILTER contents. */
+/***********************************************************************/
+void BLOCKFILTER::Prints(PGLOBAL, char *ps, uint z)
+ {
+ strncat(ps, "BlockFilter(s)", z);
+ } // end of Prints
+
+
+/* ---------------------- Class BLKFILLOG ---------------------------- */
+
+/***********************************************************************/
+/* BLKFILLOG constructor. */
+/***********************************************************************/
+BLKFILLOG::BLKFILLOG(PTDBDOS tdbp, int op, PBF *bfp, int n)
+ : BLOCKFILTER(tdbp, op)
+ {
+ N = n;
+ Fil = bfp;
+
+ for (int i = 0; i < N; i++)
+ if (Fil[i])
+ Correl |= Fil[i]->Correl;
+
+ } // end of BLKFILLOG constructor
+
+/***********************************************************************/
+/* Reset: this function is used only to check the existence of a */
+/* BLKFILIN block and have it reset its Bot value for sorted columns. */
+/***********************************************************************/
+void BLKFILLOG::Reset(PGLOBAL g)
+ {
+ for (int i = 0; i < N; i++)
+ if (Fil[i])
+ Fil[i]->Reset(g);
+
+ } // end of Reset
+
+/***********************************************************************/
+/* This function is used for block filter evaluation. We use here a */
+/* fuzzy logic between the values returned by evaluation blocks: */
+/* -2: the condition will be always false for the rest of the file. */
+/* -1: the condition will be false for the whole group. */
+/* 0: the condition may be true for some of the group values. */
+/* 1: the condition will be true for the whole group. */
+/* 2: the condition will be always true for the rest of the file. */
+/***********************************************************************/
+int BLKFILLOG::BlockEval(PGLOBAL g)
+ {
+ int i, rc;
+
+ for (i = 0; i < N; i++) {
+ // 0: Means some block filter value may be True
+ rc = (Fil[i]) ? Fil[i]->BlockEval(g) : 0;
+
+ if (!i)
+ Result = (Opc == OP_NOT) ? -rc : rc;
+ else switch (Opc) {
+ case OP_AND:
+ Result = MY_MIN(Result, rc);
+ break;
+ case OP_OR:
+ Result = MY_MAX(Result, rc);
+ break;
+ default:
+ // Should never happen
+ Result = 0;
+ return Result;
+ } // endswitch Opc
+
+ } // endfor i
+
+ return Result;
+ } // end of BlockEval
+
+/* ---------------------- Class BLKFILARI----------------------------- */
+
+/***********************************************************************/
+/* BLKFILARI constructor. */
+/***********************************************************************/
+BLKFILARI::BLKFILARI(PGLOBAL g, PTDBDOS tdbp, int op, PXOB *xp)
+ : BLOCKFILTER(tdbp, op)
+ {
+ Colp = (PDOSCOL)xp[0];
+
+ if (xp[1]->GetType() == TYPE_COLBLK) {
+ Cpx = (PCOL)xp[1]; // Subquery pseudo constant column
+ Correl = TRUE;
+ } else
+ Cpx = NULL;
+
+ Sorted = Colp->IsSorted() > 0;
+
+ // Don't remember why this was changed. Anyway it is no good for
+ // correlated subqueries because the Value must reflect changes
+ if (Cpx)
+ Valp = xp[1]->GetValue();
+ else
+ Valp = AllocateValue(g, xp[1]->GetValue());
+
+ } // end of BLKFILARI constructor
+
+/***********************************************************************/
+/* Reset: re-eval the constant value in the case of pseudo constant */
+/* column use in a correlated subquery. */
+/***********************************************************************/
+void BLKFILARI::Reset(PGLOBAL g)
+ {
+ if (Cpx) {
+ Cpx->Reset();
+ Cpx->Eval(g);
+ MakeValueBitmap(); // Does nothing for class BLKFILARI
+ } // endif Cpx
+
+ } // end of Reset
+
+/***********************************************************************/
+/* Evaluate block filter for arithmetic operators. */
+/***********************************************************************/
+int BLKFILARI::BlockEval(PGLOBAL)
+ {
+ int mincmp, maxcmp, n;
+
+#if defined(_DEBUG)
+ assert (Colp->IsClustered());
+#endif
+
+ n = ((PTDBDOS)Colp->GetTo_Tdb())->GetCurBlk();
+ mincmp = Colp->GetMin()->CompVal(Valp, n);
+ maxcmp = Colp->GetMax()->CompVal(Valp, n);
+
+ switch (Opc) {
+ case OP_EQ:
+ case OP_NE:
+ if (mincmp < 0) // Means minval > Val
+ Result = (Sorted) ? -2 : -1;
+ else if (maxcmp > 0) // Means maxval < Val
+ Result = -1;
+ else if (!mincmp && !maxcmp) // minval = maxval = val
+ Result = 1;
+ else
+ Result = 0;
+
+ break;
+ case OP_GT:
+ case OP_LE:
+ if (mincmp < 0) // minval > Val
+ Result = (Sorted) ? 2 : 1;
+ else if (maxcmp < 0) // maxval > Val
+ Result = 0;
+ else // maxval <= Val
+ Result = -1;
+
+ break;
+ case OP_GE:
+ case OP_LT:
+ if (mincmp <= 0) // minval >= Val
+ Result = (Sorted) ? 2 : 1;
+ else if (maxcmp <= 0) // Maxval >= Val
+ Result = 0;
+ else // Maxval < Val
+ Result = -1;
+
+ break;
+ } // endswitch Opc
+
+ switch (Opc) {
+ case OP_NE:
+ case OP_LE:
+ case OP_LT:
+ Result = -Result;
+ break;
+ } // endswitch Opc
+
+ if (trace(1))
+ htrc("BlockEval: op=%d n=%d rc=%d\n", Opc, n, Result);
+
+ return Result;
+ } // end of BlockEval
+
+/* ---------------------- Class BLKFILAR2----------------------------- */
+
+/***********************************************************************/
+/* BLKFILAR2 constructor. */
+/***********************************************************************/
+BLKFILAR2::BLKFILAR2(PGLOBAL g, PTDBDOS tdbp, int op, PXOB *xp)
+ : BLKFILARI(g, tdbp, op, xp)
+ {
+ MakeValueBitmap();
+ } // end of BLKFILAR2 constructor
+
+/***********************************************************************/
+/* MakeValueBitmap: Set the constant value bit map. It can be void */
+/* if the constant value is not in the column distinct values list. */
+/***********************************************************************/
+void BLKFILAR2::MakeValueBitmap(void)
+ {
+ int i; // ndv = Colp->GetNdv();
+ bool found = FALSE;
+ PVBLK dval = Colp->GetDval();
+
+ assert(dval);
+
+ /*********************************************************************/
+ /* Here we cannot use Find because we must get the index */
+ /* of where to put the value if it is not found in the array. */
+ /* This is needed by operators other than OP_EQ or OP_NE. */
+ /*********************************************************************/
+ found = dval->Locate(Valp, i);
+
+ /*********************************************************************/
+ /* Set the constant value bitmap. The bitmaps are really matching */
+ /* the OP_EQ, OP_LE, and OP_LT operator but are also used for the */
+ /* other operators for which the Result will be inverted. */
+ /* The reason the bitmaps are not directly complemented for them is */
+ /* to be able to test easily the cases of sorted columns with Bxp, */
+ /* and the case of a void bitmap, which happens if the constant */
+ /* value is not in the column distinct values list. */
+ /*********************************************************************/
+ if (found) {
+ Bmp = 1 << i; // Bit of the found value
+ Bxp = Bmp - 1; // All smaller values
+
+ if (Opc != OP_LT && Opc != OP_GE)
+ Bxp |= Bmp; // Found value must be included
+
+ } else {
+ Bmp = 0;
+ Bxp = (1 << i) - 1;
+ } // endif found
+
+ if (!(Opc == OP_EQ || Opc == OP_NE))
+ Bmp = Bxp;
+
+ } // end of MakeValueBitmap
+
+/***********************************************************************/
+/* Evaluate XDB2 block filter for arithmetic operators. */
+/***********************************************************************/
+int BLKFILAR2::BlockEval(PGLOBAL)
+ {
+#if defined(_DEBUG)
+ assert (Colp->IsClustered());
+#endif
+
+ int n = ((PTDBDOS)Colp->GetTo_Tdb())->GetCurBlk();
+ uint bkmp = *(uint*)Colp->GetBmap()->GetValPtr(n);
+ uint bres = Bmp & bkmp;
+
+ // Set result as if Opc were OP_EQ, OP_LT, or OP_LE
+ if (!bres) {
+ if (!Bmp)
+ Result = -2; // No good block in the table file
+ else if (!Sorted)
+ Result = -1; // No good values in this block
+ else // Sorted column, test for no more good blocks in file
+ Result = (Bxp & bkmp) ? -1 : -2;
+
+ } else
+ // Test whether all block values are good or only some ones
+ Result = (bres == bkmp) ? 1 : 0;
+
+ // For OP_NE, OP_GE, and OP_GT the result must be inverted.
+ switch (Opc) {
+ case OP_NE:
+ case OP_GE:
+ case OP_GT:
+ Result = -Result;
+ break;
+ } // endswitch Opc
+
+ if (trace(1))
+ htrc("BlockEval2: op=%d n=%d rc=%d\n", Opc, n, Result);
+
+ return Result;
+ } // end of BlockEval
+
+/* ---------------------- Class BLKFILMR2----------------------------- */
+
+/***********************************************************************/
+/* BLKFILMR2 constructor. */
+/***********************************************************************/
+BLKFILMR2::BLKFILMR2(PGLOBAL g, PTDBDOS tdbp, int op, PXOB *xp)
+ : BLKFILARI(g, tdbp, op, xp)
+ {
+ Nbm = Colp->GetNbm();
+ Bmp = (uint*)PlugSubAlloc(g, NULL, Nbm * sizeof(uint));
+ Bxp = (uint*)PlugSubAlloc(g, NULL, Nbm * sizeof(uint));
+ MakeValueBitmap();
+ } // end of BLKFILMR2 constructor
+
+/***********************************************************************/
+/* MakeValueBitmap: Set the constant value bit map. It can be void */
+/* if the constant value is not in the column distinct values list. */
+/***********************************************************************/
+void BLKFILMR2::MakeValueBitmap(void)
+ {
+ int i; // ndv = Colp->GetNdv();
+ bool found = FALSE, noteq = !(Opc == OP_EQ || Opc == OP_NE);
+ PVBLK dval = Colp->GetDval();
+
+ assert(dval);
+
+ for (i = 0; i < Nbm; i++)
+ Bmp[i] = Bxp[i] = 0;
+
+ /*********************************************************************/
+ /* Here we cannot use Find because we must get the index */
+ /* of where to put the value if it is not found in the array. */
+ /* This is needed by operators other than OP_EQ or OP_NE. */
+ /*********************************************************************/
+ found = dval->Locate(Valp, i);
+
+ /*********************************************************************/
+ /* For bitmaps larger than a ULONG, we must know where Bmp and Bxp */
+ /* are positioned in the ULONG bit map block array. */
+ /*********************************************************************/
+ N = i / MAXBMP;
+ i %= MAXBMP;
+
+ /*********************************************************************/
+ /* Set the constant value bitmaps. The bitmaps are really matching */
+ /* the OP_EQ, OP_LE, and OP_LT operator but are also used for the */
+ /* other operators for which the Result will be inverted. */
+ /* The reason the bitmaps are not directly complemented for them is */
+ /* to be able to easily test the cases of sorted columns with Bxp, */
+ /* and the case of a void bitmap, which happens if the constant */
+ /* value is not in the column distinct values list. */
+ /*********************************************************************/
+ if (found) {
+ Bmp[N] = 1 << i;
+ Bxp[N] = Bmp[N] - 1;
+
+ if (Opc != OP_LT && Opc != OP_GE)
+ Bxp[N] |= Bmp[N]; // Found value must be included
+
+ } else
+ Bxp[N] = (1 << i) - 1;
+
+ if (noteq)
+ Bmp[N] = Bxp[N];
+
+ Void = !Bmp[N]; // There are no good values in the file
+
+ for (i = 0; i < N; i++) {
+ Bxp[i] = ~0;
+
+ if (noteq)
+ Bmp[i] = Bxp[i];
+
+ Void = Void && !Bmp[i];
+ } // endfor i
+
+ if (!Bmp[N] && !Bxp[N])
+ N--;
+
+ } // end of MakeValueBitmap
+
+/***********************************************************************/
+/* Evaluate XDB2 block filter for arithmetic operators. */
+/***********************************************************************/
+int BLKFILMR2::BlockEval(PGLOBAL)
+ {
+#if defined(_DEBUG)
+ assert (Colp->IsClustered());
+#endif
+
+ int i, n = ((PTDBDOS)Colp->GetTo_Tdb())->GetCurBlk();
+ bool fnd = FALSE, all = TRUE, gt = TRUE;
+ uint bres;
+ uint *bkmp = (uint*)Colp->GetBmap()->GetValPtr(n * Nbm);
+
+ // Set result as if Opc were OP_EQ, OP_LT, or OP_LE
+ for (i = 0; i < Nbm; i++)
+ if (i <= N) {
+ if ((bres = Bmp[i] & bkmp[i]))
+ fnd = TRUE; // Some good value(s) found in the block
+
+ if (bres != bkmp[i])
+ all = FALSE; // Not all block values are good
+
+ if (Bxp[i] & bkmp[i])
+ gt = FALSE; // Not all block values are > good value(s)
+
+ } else if (bkmp[i]) {
+ all = FALSE;
+ break;
+ } // endif's
+
+ if (!fnd) {
+ if (Void || (gt && Sorted))
+ Result = -2; // No (more) good block in file
+ else
+ Result = -1; // No good values in this block
+
+ } else
+ Result = (all) ? 1 : 0; // All block values are good
+
+ // For OP_NE, OP_GE, and OP_GT the result must be inverted.
+ switch (Opc) {
+ case OP_NE:
+ case OP_GE:
+ case OP_GT:
+ Result = -Result;
+ break;
+ } // endswitch Opc
+
+ if (trace(1))
+ htrc("BlockEval2: op=%d n=%d rc=%d\n", Opc, n, Result);
+
+ return Result;
+ } // end of BlockEval
+
+/***********************************************************************/
+/* BLKSPCARI constructor. */
+/***********************************************************************/
+BLKSPCARI::BLKSPCARI(PTDBDOS tdbp, int op, PXOB *xp, int bsize)
+ : BLOCKFILTER(tdbp, op)
+ {
+ if (xp[1]->GetType() == TYPE_COLBLK) {
+ Cpx = (PCOL)xp[1]; // Subquery pseudo constant column
+ Correl = TRUE;
+ } else
+ Cpx = NULL;
+
+ Valp = xp[1]->GetValue();
+ Val = (int)xp[1]->GetValue()->GetIntValue();
+ Bsize = bsize;
+ } // end of BLKFILARI constructor
+
+/***********************************************************************/
+/* Reset: re-eval the constant value in the case of pseudo constant */
+/* column use in a correlated subquery. */
+/***********************************************************************/
+void BLKSPCARI::Reset(PGLOBAL g)
+ {
+ if (Cpx) {
+ Cpx->Reset();
+ Cpx->Eval(g);
+ Val = (int)Valp->GetIntValue();
+ } // endif Cpx
+
+ } // end of Reset
+
+/***********************************************************************/
+/* Evaluate block filter for arithmetic operators (ROWID) */
+/***********************************************************************/
+int BLKSPCARI::BlockEval(PGLOBAL)
+ {
+ int mincmp, maxcmp, n, m;
+
+ n = Tdbp->GetCurBlk();
+ m = n * Bsize + 1; // Minimum Rowid value for this block
+ mincmp = (Val > m) ? 1 : (Val < m) ? (-1) : 0;
+ m = (n + 1) * Bsize; // Maximum Rowid value for this block
+ maxcmp = (Val > m) ? 1 : (Val < m) ? (-1) : 0;
+
+ switch (Opc) {
+ case OP_EQ:
+ case OP_NE:
+ if (mincmp < 0) // Means minval > Val
+ Result = -2; // Always sorted
+ else if (maxcmp > 0) // Means maxval < Val
+ Result = -1;
+ else if (!mincmp && !maxcmp) // minval = maxval = val
+ Result = 1;
+ else
+ Result = 0;
+
+ break;
+ case OP_GT:
+ case OP_LE:
+ if (mincmp < 0) // minval > Val
+ Result = 2; // Always sorted
+ else if (maxcmp < 0) // maxval > Val
+ Result = 0;
+ else // maxval <= Val
+ Result = -1;
+
+ break;
+ case OP_GE:
+ case OP_LT:
+ if (mincmp <= 0) // minval >= Val
+ Result = 2; // Always sorted
+ else if (maxcmp <= 0) // Maxval >= Val
+ Result = 0;
+ else // Maxval < Val
+ Result = -1;
+
+ break;
+ } // endswitch Opc
+
+ switch (Opc) {
+ case OP_NE:
+ case OP_LE:
+ case OP_LT:
+ Result = -Result;
+ break;
+ } // endswitch Opc
+
+ if (trace(1))
+ htrc("BlockEval: op=%d n=%d rc=%d\n", Opc, n, Result);
+
+ return Result;
+ } // end of BlockEval
+
+/* ------------------------ Class BLKFILIN --------------------------- */
+
+/***********************************************************************/
+/* BLKFILIN constructor. */
+/***********************************************************************/
+BLKFILIN::BLKFILIN(PGLOBAL g, PTDBDOS tdbp, int op, int opm, PXOB *xp)
+ : BLOCKFILTER(tdbp, op)
+ {
+ if (op == OP_IN) {
+ Opc = OP_EQ;
+ Opm = 1;
+ } else {
+ Opc = op;
+ Opm = opm;
+ } // endif op
+
+ Colp = (PDOSCOL)xp[0];
+ Arap = (PARRAY)xp[1];
+ Type = Arap->GetResultType();
+
+ if (Colp->GetResultType() != Type) {
+ snprintf(g->Message, sizeof(g->Message), "BLKFILIN: %s", MSG(VALTYPE_NOMATCH));
+ throw g->Message;
+ } else if (Colp->GetValue()->IsCi())
+ Arap->SetPrecision(g, 1); // Case insensitive
+
+ Sorted = Colp->IsSorted() > 0;
+ } // end of BLKFILIN constructor
+
+/***********************************************************************/
+/* Reset: have the sorted array reset its Bot value to -1 (bottom). */
+/***********************************************************************/
+void BLKFILIN::Reset(PGLOBAL)
+ {
+ Arap->Reset();
+// MakeValueBitmap(); // Does nothing for class BLKFILIN
+ } // end of Reset
+
+/***********************************************************************/
+/* Evaluate block filter for a IN operator on a constant array. */
+/* Note: here we need to use the GetValPtrEx function to get a zero */
+/* ended string in case of string argument. This is because the ARRAY */
+/* can have a different width than the char column. */
+/***********************************************************************/
+int BLKFILIN::BlockEval(PGLOBAL g)
+ {
+ int n = ((PTDBDOS)Colp->GetTo_Tdb())->GetCurBlk();
+ void *minp = Colp->GetMin()->GetValPtrEx(n);
+ void *maxp = Colp->GetMax()->GetValPtrEx(n);
+
+ Result = Arap->BlockTest(g, Opc, Opm, minp, maxp, Sorted);
+ return Result;
+ } // end of BlockEval
+
+/* ------------------------ Class BLKFILIN2 -------------------------- */
+
+/***********************************************************************/
+/* BLKFILIN2 constructor. */
+/* New version that takes care of all operators and modificators. */
+/* It is also ready to handle the case of correlated sub-selects. */
+/***********************************************************************/
+BLKFILIN2::BLKFILIN2(PGLOBAL g, PTDBDOS tdbp, int op, int opm, PXOB *xp)
+ : BLKFILIN(g, tdbp, op, opm, xp)
+ {
+ Nbm = Colp->GetNbm();
+ Valp = AllocateValue(g, Colp->GetValue());
+ Invert = (Opc == OP_NE || Opc == OP_GE || Opc ==OP_GT);
+ Bmp = (uint*)PlugSubAlloc(g, NULL, Nbm * sizeof(uint));
+ Bxp = (uint*)PlugSubAlloc(g, NULL, Nbm * sizeof(uint));
+ MakeValueBitmap();
+ } // end of BLKFILIN2 constructor
+
+/***********************************************************************/
+/* MakeValueBitmap: Set the constant values bit map. It can be void */
+/* if the constant values are not in the column distinct values list. */
+/* The bitmaps are prepared for the EQ, LE, and LT operators and */
+/* takes care of the ALL and ANY modificators. If the operators are */
+/* NE, GE, or GT the modificator is inverted and the result will be. */
+/***********************************************************************/
+void BLKFILIN2::MakeValueBitmap(void)
+ {
+ int i, k, n, ndv = Colp->GetNdv();
+ bool found, noteq = !(Opc == OP_EQ || Opc == OP_NE);
+ bool all = (!Invert) ? (Opm == 2) : (Opm != 2);
+ uint btp;
+ PVBLK dval = Colp->GetDval();
+
+ N = -1;
+
+ // Take care of special cases
+ if (!(n = Arap->GetNval())) {
+ // Return TRUE for ALL because it means that there are no item that
+ // does not verify the condition, which is true indeed.
+ // Return FALSE for ANY because TRUE means that there is at least
+ // one item that verifies the condition, which is false.
+ Result = (Opm == 2) ? 2 : -2;
+ return;
+ } else if (!noteq && all && n > 1) {
+ // An item cannot be equal to all different values
+ // or an item is always unequal to any different values
+ Result = (Opc == OP_EQ) ? -2 : 2;
+ return;
+ } // endif's
+
+ for (i = 0; i < Nbm; i++)
+ Bmp[i] = Bxp[i] = 0;
+
+ for (k = 0; k < n; k++) {
+ Arap->GetNthValue(Valp, k);
+ found = dval->Locate(Valp, i);
+ N = i / MAXBMP;
+ btp = 1 << (i % MAXBMP);
+
+ if (found)
+ Bmp[N] |= btp;
+
+ // For LT and LE if ALL the condition applies to the smallest item
+ // if ANY it applies to the largest item. In the case of EQ we come
+ // here only if ANY or if n == 1, so it does applies to the largest.
+ if ((!k && all) || (k == n - 1 && !all)) {
+ Bxp[N] = btp - 1;
+
+ if (found && Opc != OP_LT && Opc != OP_GE)
+ Bxp[N] |= btp; // Found value must be included
+
+ } // endif k, opm
+
+ } // endfor k
+
+ if (noteq)
+ Bmp[N] = Bxp[N];
+
+ Void = !Bmp[N]; // There are no good values in the file
+
+ for (i = 0; i < N; i++) {
+ Bxp[i] = ~0;
+
+ if (noteq) {
+ Bmp[i] = Bxp[i];
+ Void = FALSE;
+ } // endif noteq
+
+ } // endfor i
+
+ if (!Bmp[N] && !Bxp[N]) {
+ if (--N < 0)
+ // All array values are smaller than block values
+ Result = (Invert) ? 2 : -2;
+
+ } else if (N == Nbm - 1 && (signed)Bmp[N] == (1 << (ndv % MAXBMP)) - 1) {
+ // Condition will be always TRUE or FALSE for the whole file
+ Result = (Invert) ? -2 : 2;
+ N = -1;
+ } // endif's
+
+ } // end of MakeValueBitmap
+
+/***********************************************************************/
+/* Evaluate block filter for set operators on a constant array. */
+/* Note: here we need to use the GetValPtrEx function to get a zero */
+/* ended string in case of string argument. This is because the ARRAY */
+/* can have a different width than the char column. */
+/***********************************************************************/
+int BLKFILIN2::BlockEval(PGLOBAL)
+ {
+ if (N < 0)
+ return Result; // Was set in MakeValueBitmap
+
+ int i, n = ((PTDBDOS)Colp->GetTo_Tdb())->GetCurBlk();
+ bool fnd = FALSE, all = TRUE, gt = TRUE;
+ uint bres;
+ uint *bkmp = (uint*)Colp->GetBmap()->GetValPtr(n * Nbm);
+
+ // Set result as if Opc were OP_EQ, OP_LT, or OP_LE
+ // The difference between ALL or ANY was handled in MakeValueBitmap
+ for (i = 0; i < Nbm; i++)
+ if (i <= N) {
+ if ((bres = Bmp[i] & bkmp[i]))
+ fnd = TRUE;
+
+ if (bres != bkmp[i])
+ all = FALSE;
+
+ if (Bxp[i] & bkmp[i])
+ gt = FALSE;
+
+ } else if (bkmp[i]) {
+ all = FALSE;
+ break;
+ } // endif's
+
+ if (!fnd) {
+ if (Void || (Sorted && gt))
+ Result = -2; // No more good block in file
+ else
+ Result = -1; // No good values in this block
+
+ } else if (all)
+ Result = 1; // All block values are good
+ else
+ Result = 0; // Block contains some good values
+
+ // For OP_NE, OP_GE, and OP_GT the result must be inverted.
+ switch (Opc) {
+ case OP_NE:
+ case OP_GE:
+ case OP_GT:
+ Result = -Result;
+ break;
+ } // endswitch Opc
+
+ return Result;
+ } // end of BlockEval
+
+#if 0
+/***********************************************************************/
+/* BLKFILIN2 constructor. */
+/***********************************************************************/
+BLKFILIN2::BLKFILIN2(PGLOBAL g, PTDBDOS tdbp, int op, int opm, PXOB *xp)
+ : BLKFILIN(g, tdbp, op, opm, xp)
+ {
+ // Currently, bitmap matching is only implemented for the IN operator
+ if (!(Bitmap = (op == OP_IN || (op == OP_EQ && opm != 2)))) {
+ Nbm = Colp->GetNbm();
+ N = 0;
+ return; // Revert to standard minmax method
+ } // endif minmax
+
+ int i, n;
+ ULONG btp;
+ PVAL valp = AllocateValue(g, Colp->GetValue());
+ PVBLK dval = Colp->GetDval();
+
+ Nbm = Colp->GetNbm();
+ N = -1;
+ Bmp = (PULONG)PlugSubAlloc(g, NULL, Nbm * sizeof(ULONG));
+ Bxp = (PULONG)PlugSubAlloc(g, NULL, Nbm * sizeof(ULONG));
+
+ for (i = 0; i < Nbm; i++)
+ Bmp[i] = Bxp[i] = 0;
+
+ for (n = 0; n < Arap->GetNval(); n++) {
+ Arap->GetNthValue(valp, n);
+
+ if ((i = dval->Find(valp)) >= 0)
+ Bmp[i / MAXBMP] |= 1 << (i % MAXBMP);
+
+ } // endfor n
+
+ for (i = Nbm - 1; i >= 0; i--)
+ if (Bmp[i]) {
+ for (btp = Bmp[i]; btp; btp >>= 1)
+ Bxp[i] |= btp;
+
+ for (N = i--; i >= 0; i--)
+ Bxp[i] = ~0;
+
+ break;
+ } // endif Bmp
+
+ } // end of BLKFILIN2 constructor
+
+/***********************************************************************/
+/* Evaluate block filter for a IN operator on a constant array. */
+/* Note: here we need to use the GetValPtrEx function to get a zero */
+/* ended string in case of string argument. This is because the ARRAY */
+/* can have a different width than the char column. */
+/***********************************************************************/
+int BLKFILIN2::BlockEval(PGLOBAL g)
+ {
+ if (N < 0)
+ return -2; // IN list contains no good values
+
+ int i, n = ((PTDBDOS)Colp->GetTo_Tdb())->GetCurBlk();
+ bool fnd = FALSE, all = TRUE, gt = TRUE;
+ ULONG bres;
+ PULONG bkmp = (PULONG)Colp->GetBmap()->GetValPtr(n * Nbm);
+
+ if (Bitmap) {
+ // For IN operator use the bitmap method
+ for (i = 0; i < Nbm; i++)
+ if (i <= N) {
+ if ((bres = Bmp[i] & bkmp[i]))
+ fnd = TRUE;
+
+ if (bres != bkmp[i])
+ all = FALSE;
+
+ if (Bxp[i] & bkmp[i])
+ gt = FALSE;
+
+ } else if (bkmp[i]) {
+ all = FALSE;
+ break;
+ } // endif's
+
+ if (!fnd) {
+ if (Sorted && gt)
+ Result = -2; // No more good block in file
+ else
+ Result = -1; // No good values in this block
+
+ } else if (all)
+ Result = 1; // All block values are good
+ else
+ Result = 0; // Block contains some good values
+
+ } else {
+ // For other than IN operators, revert to standard minmax method
+ int n = 0, ndv = Colp->GetNdv();
+ void *minp = NULL;
+ void *maxp = NULL;
+ ULONG btp;
+ PVBLK dval = Colp->GetDval();
+
+ for (i = 0; i < Nbm; i++)
+ for (btp = 1; btp && n < ndv; btp <<= 1, n++)
+ if (btp & bkmp[i]) {
+ if (!minp)
+ minp = dval->GetValPtrEx(n);
+
+ maxp = dval->GetValPtrEx(n);
+ } // endif btp
+
+ Result = Arap->BlockTest(g, Opc, Opm, minp, maxp, Colp->IsSorted());
+ } // endif Bitmap
+
+ return Result;
+ } // end of BlockEval
+#endif // 0
+
+/* ------------------------ Class BLKSPCIN --------------------------- */
+
+/***********************************************************************/
+/* BLKSPCIN constructor. */
+/***********************************************************************/
+BLKSPCIN::BLKSPCIN(PGLOBAL, PTDBDOS tdbp, int op, int opm,
+ PXOB *xp, int bsize)
+ : BLOCKFILTER(tdbp, op)
+ {
+ if (op == OP_IN) {
+ Opc = OP_EQ;
+ Opm = 1;
+ } else
+ Opm = opm;
+
+ Arap = (PARRAY)xp[1];
+#if defined(_DEBUG)
+ assert (Opm);
+ assert (Arap->GetResultType() == TYPE_INT);
+#endif
+ Bsize = bsize;
+ } // end of BLKSPCIN constructor
+
+/***********************************************************************/
+/* Reset: have the sorted array reset its Bot value to -1 (bottom). */
+/***********************************************************************/
+void BLKSPCIN::Reset(PGLOBAL)
+ {
+ Arap->Reset();
+ } // end of Reset
+
+/***********************************************************************/
+/* Evaluate block filter for a IN operator on a constant array. */
+/***********************************************************************/
+int BLKSPCIN::BlockEval(PGLOBAL g)
+ {
+ int n = Tdbp->GetCurBlk();
+ int minrow = n * Bsize + 1; // Minimum Rowid value for this block
+ int maxrow = (n + 1) * Bsize; // Maximum Rowid value for this block
+
+ Result = Arap->BlockTest(g, Opc, Opm, &minrow, &maxrow, TRUE);
+ return Result;
+ } // end of BlockEval
+
+/* ------------------------------------------------------------------- */
+
+#if 0
+/***********************************************************************/
+/* Implementation of the BLOCKINDEX class. */
+/***********************************************************************/
+BLOCKINDEX::BLOCKINDEX(PBX nx, PDOSCOL cp, PKXBASE kp)
+ {
+ Next = nx;
+ Tdbp = (cp) ? (PTDBDOS)cp->GetTo_Tdb() : NULL;
+ Colp = cp;
+ Kxp = kp;
+ Type = (cp) ? cp->GetResultType() : TYPE_ERROR;
+ Sorted = (cp) ? cp->IsSorted() > 0 : FALSE;
+ Result = 0;
+ } // end of BLOCKINDEX constructor
+
+/***********************************************************************/
+/* Reset Bot and Top values of optimized Kindex blocks. */
+/***********************************************************************/
+void BLOCKINDEX::Reset(void)
+ {
+ if (Next)
+ Next->Reset();
+
+ Kxp->Reset();
+ } // end of Reset
+
+/***********************************************************************/
+/* Evaluate block indexing test. */
+/***********************************************************************/
+int BLOCKINDEX::BlockEval(PGLOBAL g)
+ {
+#if defined(_DEBUG)
+ assert (Tdbp && Colp);
+#endif
+ int n = Tdbp->GetCurBlk();
+ void *minp = Colp->GetMin()->GetValPtr(n);
+ void *maxp = Colp->GetMax()->GetValPtr(n);
+
+ Result = Kxp->BlockTest(g, minp, maxp, Type, Sorted);
+ return Result;
+ } // end of BlockEval
+
+/***********************************************************************/
+/* Make file output of BLOCKINDEX contents. */
+/***********************************************************************/
+void BLOCKINDEX::Printf(PGLOBAL g, FILE *f, UINT n)
+ {
+ char m[64];
+
+ memset(m, ' ', n); // Make margin string
+ m[n] = '\0';
+
+ fprintf(f, "%sBLOCKINDEX: at %p next=%p col=%s kxp=%p result=%d\n",
+ m, this, Next, (Colp) ? Colp->GetName() : "Rowid", Kxp, Result);
+
+ if (Next)
+ Next->Printf(g, f, n);
+
+ } // end of Printf
+
+/***********************************************************************/
+/* Make string output of BLOCKINDEX contents. */
+/***********************************************************************/
+void BLOCKINDEX::Prints(PGLOBAL g, char *ps, UINT z)
+ {
+ strncat(ps, "BlockIndex(es)", z);
+ } // end of Prints
+
+/* ------------------------------------------------------------------- */
+
+/***********************************************************************/
+/* Implementation of the BLOCKINDX2 class. */
+/***********************************************************************/
+BLOCKINDX2::BLOCKINDX2(PBX nx, PDOSCOL cp, PKXBASE kp)
+ : BLOCKINDEX(nx, cp, kp)
+ {
+ Nbm = Colp->GetNbm();
+ Dval = Colp->GetDval();
+ Bmap = Colp->GetBmap();
+#if defined(_DEBUG)
+ assert(Dval && Bmap);
+#endif
+ } // end of BLOCKINDX2 constructor
+
+/***********************************************************************/
+/* Evaluate block indexing test. */
+/***********************************************************************/
+int BLOCKINDX2::BlockEval(PGLOBAL g)
+ {
+ int n = Tdbp->GetCurBlk();
+ PUINT bmp = (PUINT)Bmap->GetValPtr(n * Nbm);
+
+ Result = Kxp->BlockTst2(g, Dval, bmp, Nbm, Type, Sorted);
+ return Result;
+ } // end of BlockEval
+
+/* ------------------------------------------------------------------- */
+
+/***********************************************************************/
+/* Implementation of the BLKSPCINDX class. */
+/***********************************************************************/
+BLKSPCINDX::BLKSPCINDX(PBX nx, PTDBDOS tp, PKXBASE kp, int bsize)
+ : BLOCKINDEX(nx, NULL, kp)
+ {
+ Tdbp = tp;
+ Bsize = bsize;
+ Type = TYPE_INT;
+ Sorted = TRUE;
+ } // end of BLKSPCINDX constructor
+
+/***********************************************************************/
+/* Evaluate block indexing test. */
+/***********************************************************************/
+int BLKSPCINDX::BlockEval(PGLOBAL g)
+ {
+ int n = Tdbp->GetCurBlk();
+ int minrow = n * Bsize + 1; // Minimum Rowid value for this block
+ int maxrow = (n + 1) * Bsize; // Maximum Rowid value for this block
+
+ Result = Kxp->BlockTest(g, &minrow, &maxrow, TYPE_INT, TRUE);
+ return Result;
+ } // end of BlockEval
+#endif // 0