mirror of
https://github.com/MariaDB/server.git
synced 2025-01-17 20:42:30 +01:00
5f64276fb2
modified: storage/connect/array.cpp modified: storage/connect/blkfil.cpp modified: storage/connect/block.h modified: storage/connect/bson.cpp modified: storage/connect/cmgoconn.cpp modified: storage/connect/colblk.cpp modified: storage/connect/domdoc.cpp modified: storage/connect/filamap.cpp modified: storage/connect/filamdbf.cpp modified: storage/connect/filamfix.cpp modified: storage/connect/filamgz.cpp modified: storage/connect/filamtxt.cpp modified: storage/connect/filamvct.cpp modified: storage/connect/filamzip.cpp modified: storage/connect/filter.cpp modified: storage/connect/filter.h modified: storage/connect/fmdlex.c modified: storage/connect/global.h modified: storage/connect/ha_connect.cc modified: storage/connect/javaconn.cpp modified: storage/connect/javaconn.h modified: storage/connect/jdbconn.cpp modified: storage/connect/jmgfam.cpp modified: storage/connect/json.cpp modified: storage/connect/macutil.cpp modified: storage/connect/macutil.h modified: storage/connect/maputil.cpp modified: storage/connect/mycat.cc modified: storage/connect/myconn.cpp modified: storage/connect/myconn.h modified: storage/connect/myutil.cpp modified: storage/connect/odbconn.cpp modified: storage/connect/odbconn.h modified: storage/connect/os.h modified: storage/connect/osutil.c modified: storage/connect/plgdbsem.h modified: storage/connect/plgdbutl.cpp modified: storage/connect/plugutil.cpp modified: storage/connect/rcmsg.c modified: storage/connect/reldef.cpp modified: storage/connect/reldef.h modified: storage/connect/tabdos.cpp modified: storage/connect/tabext.cpp modified: storage/connect/tabfix.cpp modified: storage/connect/tabfmt.cpp modified: storage/connect/tabjdbc.cpp modified: storage/connect/tabmac.cpp modified: storage/connect/tabmac.h modified: storage/connect/tabmul.cpp modified: storage/connect/tabmul.h modified: storage/connect/tabmysql.cpp modified: storage/connect/taboccur.cpp modified: storage/connect/tabodbc.cpp modified: storage/connect/tabpivot.cpp modified: storage/connect/tabrest.cpp modified: storage/connect/tabrest.h modified: storage/connect/tabsys.cpp modified: storage/connect/tabtbl.cpp modified: storage/connect/tabutil.cpp modified: storage/connect/tabvct.cpp modified: storage/connect/tabwmi.cpp modified: storage/connect/tabxcl.cpp modified: storage/connect/tabxml.cpp modified: storage/connect/valblk.cpp modified: storage/connect/value.cpp modified: storage/connect/xindex.cpp modified: storage/connect/xindex.h - Fix Date errors and SSL warnings modified: storage/connect/mysql-test/connect/r/jdbc.result modified: storage/connect/mysql-test/connect/r/jdbc_new.result modified: storage/connect/mysql-test/connect/t/jdbc.test modified: storage/connect/mysql-test/connect/t/jdbc_new.test - Update java source files modified: storage/connect/Mongo2Interface.java modified: storage/connect/Mongo3Interface.java added: storage/connect/Client2.java added: storage/connect/Client3.java added: storage/connect/TestInsert2.java added: storage/connect/TestInsert3.java
1075 lines
35 KiB
C++
1075 lines
35 KiB
C++
/************* 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) {
|
|
sprintf(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
|