summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--storage/connect/catalog.h1
-rw-r--r--storage/connect/colblk.cpp2
-rw-r--r--storage/connect/colblk.h7
-rw-r--r--storage/connect/connect.cc19
-rw-r--r--storage/connect/filamap.cpp69
-rw-r--r--storage/connect/filamfix.cpp34
-rw-r--r--storage/connect/filamfix.h20
-rw-r--r--storage/connect/filamtxt.cpp62
-rwxr-xr-xstorage/connect/filamvct.cpp29
-rw-r--r--storage/connect/filamzip.cpp611
-rw-r--r--storage/connect/filamzip.h4
-rw-r--r--storage/connect/ha_connect.cc402
-rw-r--r--storage/connect/ha_connect.h5
-rw-r--r--storage/connect/plgdbsem.h55
-rw-r--r--storage/connect/plgdbutl.cpp4
-rw-r--r--storage/connect/reldef.cpp21
-rw-r--r--storage/connect/reldef.h32
-rw-r--r--storage/connect/tabdos.cpp1571
-rw-r--r--storage/connect/tabdos.h121
-rw-r--r--storage/connect/tabfix.cpp75
-rw-r--r--storage/connect/tabfix.h2
-rw-r--r--storage/connect/tabfmt.cpp7
-rw-r--r--storage/connect/tabfmt.h2
-rw-r--r--storage/connect/table.cpp39
-rw-r--r--storage/connect/tabmac.h2
-rw-r--r--storage/connect/tabmul.h2
-rw-r--r--storage/connect/tabmysql.cpp12
-rw-r--r--storage/connect/tabodbc.cpp14
-rw-r--r--storage/connect/tabsys.cpp2
-rw-r--r--storage/connect/tabsys.h2
-rw-r--r--storage/connect/tabtbl.cpp23
-rw-r--r--storage/connect/tabtbl.h4
-rw-r--r--storage/connect/tabvct.cpp19
-rw-r--r--storage/connect/tabvct.h2
-rw-r--r--storage/connect/tabwmi.cpp20
-rw-r--r--storage/connect/tabwmi.h2
-rw-r--r--storage/connect/tabxml.cpp2
-rw-r--r--storage/connect/tabxml.h2
-rw-r--r--storage/connect/valblk.cpp143
-rw-r--r--storage/connect/valblk.h48
-rw-r--r--storage/connect/value.cpp118
-rw-r--r--storage/connect/value.h21
-rw-r--r--storage/connect/xobject.cpp4
-rw-r--r--storage/connect/xobject.h8
-rw-r--r--storage/connect/xtable.h75
45 files changed, 3329 insertions, 390 deletions
diff --git a/storage/connect/catalog.h b/storage/connect/catalog.h
index a61b1a53653..86d973e0036 100644
--- a/storage/connect/catalog.h
+++ b/storage/connect/catalog.h
@@ -44,6 +44,7 @@ typedef struct _colinfo {
int Precision;
int Scale;
int Opt;
+ int Freq;
char *Remark;
char *Datefmt;
char *Fieldfmt;
diff --git a/storage/connect/colblk.cpp b/storage/connect/colblk.cpp
index bce26e25387..364628bfca6 100644
--- a/storage/connect/colblk.cpp
+++ b/storage/connect/colblk.cpp
@@ -39,6 +39,7 @@ COLBLK::COLBLK(PCOLDEF cdp, PTDB tdbp, int i)
Opt = cdp->Opt;
Long = cdp->Long;
Precision = cdp->Precision;
+ Freq = cdp->Freq;
Buf_Type = cdp->Buf_Type;
ColUse |= cdp->Flags; // Used by CONNECT
Nullable = !!(cdp->Flags & U_NULLS);
@@ -49,6 +50,7 @@ COLBLK::COLBLK(PCOLDEF cdp, PTDB tdbp, int i)
Opt = 0;
Long = 0;
Precision = 0;
+ Freq = 0;
Buf_Type = TYPE_ERROR;
Nullable = false;
Unsigned = false;
diff --git a/storage/connect/colblk.h b/storage/connect/colblk.h
index 7b84d237bd2..1204c4623f7 100644
--- a/storage/connect/colblk.h
+++ b/storage/connect/colblk.h
@@ -36,6 +36,10 @@ class DllExport COLBLK : public XOBJECT {
virtual int GetAmType() {return TYPE_AM_ERROR;}
virtual void SetOk(void) {Status |= BUF_EMPTY;}
virtual PTDB GetTo_Tdb(void) {return To_Tdb;}
+#if defined(BLK_INDX)
+ virtual int GetClustered(void) {return 0;}
+ virtual int IsClustered(void) {return FALSE;}
+#endif // BLK_INDX
PCOL GetNext(void) {return Next;}
PSZ GetName(void) {return Name;}
int GetIndex(void) {return Index;}
@@ -76,7 +80,9 @@ class DllExport COLBLK : public XOBJECT {
virtual void WriteColumn(PGLOBAL g);
virtual void Print(PGLOBAL g, FILE *, uint);
virtual void Print(PGLOBAL g, char *, uint);
+#if defined(BLK_INDX)
virtual bool VarSize(void) {return false;}
+#endif // BLK_INDX
virtual bool IsColInside(PCOL colp) {return this == colp;}
bool InitValue(PGLOBAL g);
@@ -94,6 +100,7 @@ class DllExport COLBLK : public XOBJECT {
int Buf_Type; // Data type
int Long; // Internal length in table
int Precision; // Column length (as for ODBC)
+ int Freq; // Evaluated ceiling of distinct values
FORMAT Format; // Output format
ushort ColUse; // Column usage
ushort Status; // Column read status
diff --git a/storage/connect/connect.cc b/storage/connect/connect.cc
index d111ff07044..f6d25b47ce7 100644
--- a/storage/connect/connect.cc
+++ b/storage/connect/connect.cc
@@ -433,7 +433,7 @@ RCODE EvalColumns(PGLOBAL g, PTDB tdbp, bool mrr)
/***********************************************************************/
/* ReadNext: Read next record sequentially. */
/***********************************************************************/
-RCODE CntReadNext(PGLOBAL g, PTDB tdbp)
+RCODE CntReadNext(PGLOBAL g, PTDB tdbp)
{
RCODE rc;
@@ -449,8 +449,21 @@ RCODE CntReadNext(PGLOBAL g, PTDB tdbp)
((PTDBASE)tdbp)->SetKindex(NULL);
} // endif index
+ // Save stack and allocation environment and prepare error return
+ if (g->jump_level == MAX_JUMP) {
+ strcpy(g->Message, MSG(TOO_MANY_JUMPS));
+ return RC_FX;
+ } // endif jump_level
+
+ if ((setjmp(g->jumper[++g->jump_level])) != 0) {
+ rc= RC_FX;
+ goto err;
+ } // endif rc
+
while ((rc= (RCODE)tdbp->ReadDB(g)) == RC_NF) ;
-
+
+ err:
+ g->jump_level--;
return (rc != RC_OK) ? rc : EvalColumns(g, tdbp);
} // end of CntReadNext
@@ -578,7 +591,7 @@ int CntCloseTable(PGLOBAL g, PTDB tdbp)
tbxp= (TDBDOX*)tdbp;
tbxp->SetKindex(NULL);
tbxp->To_Key_Col= NULL;
- rc= tbxp->ResetTableOpt(g, ((PTDBASE)tdbp)->GetDef()->Indexable());
+ rc= tbxp->ResetTableOpt(g, false, ((PTDBASE)tdbp)->GetDef()->Indexable());
err:
if (xtrace > 1)
diff --git a/storage/connect/filamap.cpp b/storage/connect/filamap.cpp
index 5a67c5d2dd2..64e9ed15f40 100644
--- a/storage/connect/filamap.cpp
+++ b/storage/connect/filamap.cpp
@@ -1,11 +1,11 @@
/*********** File AM Map C++ Program Source Code File (.CPP) ***********/
/* PROGRAM NAME: FILAMAP */
/* ------------- */
-/* Version 1.4 */
+/* Version 1.5 */
/* */
/* COPYRIGHT: */
/* ---------- */
-/* (C) Copyright to the author Olivier BERTRAND 2005-2013 */
+/* (C) Copyright to the author Olivier BERTRAND 2005-2014 */
/* */
/* WHAT THIS PROGRAM DOES: */
/* ----------------------- */
@@ -322,8 +322,30 @@ int MAPFAM::ReadBuffer(PGLOBAL g)
/*******************************************************************/
/* Record file position in case of UPDATE or DELETE. */
/*******************************************************************/
- Fpos = Mempos;
- CurBlk = (int)Rows++;
+#if defined(BLK_INDX)
+ int rc;
+
+ next:
+#endif // BLK_INDX
+ Fpos = Mempos;
+ CurBlk = (int)Rows++;
+
+#if defined(BLK_INDX)
+ /*******************************************************************/
+ /* Check whether optimization on ROWID */
+ /* can be done, as well as for join as for local filtering. */
+ /*******************************************************************/
+ switch (Tdbp->TestBlock(g)) {
+ case RC_EF:
+ return RC_EF;
+ case RC_NF:
+ // Skip this record
+ if ((rc = SkipRecord(g, FALSE)) != RC_OK)
+ return rc;
+
+ goto next;
+ } // endswitch rc
+#endif // BLK_INDX
} else
Placed = false;
@@ -491,7 +513,11 @@ MBKFAM::MBKFAM(PDOSDEF tdp) : MAPFAM(tdp)
Block = tdp->GetBlock();
Last = tdp->GetLast();
Nrec = tdp->GetElemt();
+#if defined(BLK_INDX)
BlkPos = tdp->GetTo_Pos();
+#else // !BLK_INDX
+ BlkPos = NULL;
+#endif // !BLK_INDX
CurNum = Nrec;
} // end of MBKFAM standard constructor
@@ -537,6 +563,7 @@ int MBKFAM::GetRowID(void)
/***********************************************************************/
int MBKFAM::ReadBuffer(PGLOBAL g)
{
+#if defined(BLK_INDX)
int len;
/*********************************************************************/
@@ -554,9 +581,21 @@ int MBKFAM::ReadBuffer(PGLOBAL g)
/*******************************************************************/
CurNum = 0;
+ next:
if (++CurBlk >= Block)
return RC_EF;
+ /*******************************************************************/
+ /* Before reading a new block, check whether block optimization */
+ /* can be done, as well as for join as for local filtering. */
+ /*******************************************************************/
+ switch (Tdbp->TestBlock(g)) {
+ case RC_EF:
+ return RC_EF;
+ case RC_NF:
+ goto next;
+ } // endswitch rc
+
Fpos = Mempos = Memory + BlkPos[CurBlk];
} // endif's
@@ -568,6 +607,10 @@ int MBKFAM::ReadBuffer(PGLOBAL g)
memcpy(Tdbp->GetLine(), Fpos, len);
Tdbp->GetLine()[len] = '\0';
return RC_OK;
+#else // !BLK_POS
+ strcpy(g->Message, "This AM cannot be used in this version");
+ return RC_FX;
+#endif // !BLK_POS
} // end of ReadBuffer
/***********************************************************************/
@@ -657,10 +700,26 @@ int MPXFAM::ReadBuffer(PGLOBAL g)
/* New block. */
/*******************************************************************/
CurNum = 0;
-
+
+#if defined(BLK_INDX)
+ next:
+#endif // BLK_INDX
if (++CurBlk >= Block)
return RC_EF;
+#if defined(BLK_INDX)
+ /*******************************************************************/
+ /* Before reading a new block, check whether block optimization */
+ /* can be done, as well as for join as for local filtering. */
+ /*******************************************************************/
+ switch (Tdbp->TestBlock(g)) {
+ case RC_EF:
+ return RC_EF;
+ case RC_NF:
+ goto next;
+ } // endswitch rc
+#endif // BLK_INDX
+
Fpos = Mempos = Headlen + Memory + CurBlk * Blksize;
} // endif's
diff --git a/storage/connect/filamfix.cpp b/storage/connect/filamfix.cpp
index a92d9766933..295c281a478 100644
--- a/storage/connect/filamfix.cpp
+++ b/storage/connect/filamfix.cpp
@@ -1,11 +1,11 @@
/*********** File AM Fix C++ Program Source Code File (.CPP) ***********/
/* PROGRAM NAME: FILAMFIX */
/* ------------- */
-/* Version 1.4 */
+/* Version 1.5 */
/* */
/* COPYRIGHT: */
/* ---------- */
-/* (C) Copyright to the author Olivier BERTRAND 2005-2013 */
+/* (C) Copyright to the author Olivier BERTRAND 2005-2014 */
/* */
/* WHAT THIS PROGRAM DOES: */
/* ----------------------- */
@@ -168,9 +168,24 @@ int FIXFAM::ReadBuffer(PGLOBAL g)
CurNum = 0;
Tdbp->SetLine(To_Buf);
+#if defined(BLK_INDX)
+ next:
+#endif // BLK_INDX
if (++CurBlk >= Block)
return RC_EF;
+#if defined(BLK_INDX)
+ /*****************************************************************/
+ /* Before reading a new block, check whether block indexing */
+ /* can be done, as well as for join as for local filtering. */
+ /*****************************************************************/
+ switch (Tdbp->TestBlock(g)) {
+ case RC_EF:
+ return RC_EF;
+ case RC_NF:
+ goto next;
+ } // endswitch rc
+#endif // BLK_INDX
} // endif's
if (OldBlk == CurBlk) {
@@ -1028,9 +1043,24 @@ int BGXFAM::ReadBuffer(PGLOBAL g)
CurNum = 0;
Tdbp->SetLine(To_Buf);
+#if defined(BLK_INDX)
+ next:
+#endif // BLK_INDX
if (++CurBlk >= Block)
return RC_EF;
+#if defined(BLK_INDX)
+ /*****************************************************************/
+ /* Before reading a new block, check whether block optimization */
+ /* can be done, as well as for join as for local filtering. */
+ /*****************************************************************/
+ switch (Tdbp->TestBlock(g)) {
+ case RC_EF:
+ return RC_EF;
+ case RC_NF:
+ goto next;
+ } // endswitch rc
+#endif // BLK_INDX
} // endif's
if (OldBlk == CurBlk) {
diff --git a/storage/connect/filamfix.h b/storage/connect/filamfix.h
index 758d891bf2c..b2c5019c635 100644
--- a/storage/connect/filamfix.h
+++ b/storage/connect/filamfix.h
@@ -33,16 +33,16 @@ class DllExport FIXFAM : public BLKFAM {
virtual int Cardinality(PGLOBAL g) {return TXTFAM::Cardinality(g);}
virtual int MaxBlkSize(PGLOBAL g, int s)
{return TXTFAM::MaxBlkSize(g, s);}
- virtual bool AllocateBuffer(PGLOBAL g);
- virtual void ResetBuffer(PGLOBAL g);
- virtual int ReadBuffer(PGLOBAL g);
- virtual int WriteBuffer(PGLOBAL g);
- virtual int DeleteRecords(PGLOBAL g, int irc);
- virtual void CloseTableFile(PGLOBAL g);
+ virtual bool AllocateBuffer(PGLOBAL g);
+ virtual void ResetBuffer(PGLOBAL g);
+ virtual int ReadBuffer(PGLOBAL g);
+ virtual int WriteBuffer(PGLOBAL g);
+ virtual int DeleteRecords(PGLOBAL g, int irc);
+ virtual void CloseTableFile(PGLOBAL g);
protected:
- virtual bool CopyHeader(PGLOBAL g) {return false;}
- virtual bool MoveIntermediateLines(PGLOBAL g, bool *b);
+ virtual bool CopyHeader(PGLOBAL g) {return false;}
+ virtual bool MoveIntermediateLines(PGLOBAL g, bool *b);
// No additional members
}; // end of class FIXFAM
@@ -69,7 +69,7 @@ class BGXFAM : public FIXFAM {
virtual bool OpenTableFile(PGLOBAL g);
virtual int ReadBuffer(PGLOBAL g);
virtual int WriteBuffer(PGLOBAL g);
- virtual int DeleteRecords(PGLOBAL g, int irc);
+ virtual int DeleteRecords(PGLOBAL g, int irc);
virtual void CloseTableFile(PGLOBAL g);
virtual void Rewind(void);
@@ -78,7 +78,7 @@ class BGXFAM : public FIXFAM {
, int org = FILE_BEGIN);
int BigRead(PGLOBAL g, HANDLE h, void *inbuf, int req);
bool BigWrite(PGLOBAL g, HANDLE h, void *inbuf, int req);
- virtual bool OpenTempFile(PGLOBAL g);
+ virtual bool OpenTempFile(PGLOBAL g);
virtual bool MoveIntermediateLines(PGLOBAL g, bool *b = NULL);
// Members
diff --git a/storage/connect/filamtxt.cpp b/storage/connect/filamtxt.cpp
index 1d3f17e2228..d7310f34e6b 100644
--- a/storage/connect/filamtxt.cpp
+++ b/storage/connect/filamtxt.cpp
@@ -1,11 +1,11 @@
/*********** File AM Txt C++ Program Source Code File (.CPP) ***********/
/* PROGRAM NAME: FILAMTXT */
/* ------------- */
-/* Version 1.4 */
+/* Version 1.5 */
/* */
/* COPYRIGHT: */
/* ---------- */
-/* (C) Copyright to the author Olivier BERTRAND 2005-2013 */
+/* (C) Copyright to the author Olivier BERTRAND 2005-2014 */
/* */
/* WHAT THIS PROGRAM DOES: */
/* ----------------------- */
@@ -235,13 +235,20 @@ int TXTFAM::Cardinality(PGLOBAL g)
/***********************************************************************/
int TXTFAM::MaxBlkSize(PGLOBAL g, int s)
{
- int savcur = CurBlk, blm1 = Block - 1;
+ int rc = RC_OK, savcur = CurBlk, blm1 = Block - 1;
int size, last = s - blm1 * Nrec;
// Roughly estimate the table size as the sum of blocks
// that can contain good rows
for (size = 0, CurBlk = 0; CurBlk < Block; CurBlk++)
+#if defined(BLK_INDX)
+ if ((rc = Tdbp->TestBlock(g)) == RC_OK)
+ size += (CurBlk == blm1) ? last : Nrec;
+ else if (rc == RC_EF)
+ break;
+#else // !BLK_INDX
size += (CurBlk == blm1) ? last : Nrec;
+#endif // !BLK_INDX
CurBlk = savcur;
return size;
@@ -543,6 +550,9 @@ int DOSFAM::ReadBuffer(PGLOBAL g)
/*******************************************************************/
/* Record file position in case of UPDATE or DELETE. */
/*******************************************************************/
+#if defined(BLK_INDX)
+ next:
+#endif // BLK_INDX
if (RecordPos(g))
return RC_FX;
@@ -551,6 +561,22 @@ int DOSFAM::ReadBuffer(PGLOBAL g)
if (trace > 1)
htrc("ReadBuffer: CurBlk=%d\n", CurBlk);
+#if defined(BLK_INDX)
+ /*******************************************************************/
+ /* Check whether optimization on ROWID */
+ /* can be done, as well as for join as for local filtering. */
+ /*******************************************************************/
+ switch (Tdbp->TestBlock(g)) {
+ case RC_EF:
+ return RC_EF;
+ case RC_NF:
+ // Skip this record
+ if ((rc = SkipRecord(g, FALSE)) != RC_OK)
+ return rc;
+
+ goto next;
+ } // endswitch rc
+#endif // BLK_INDX
} else
Placed = false;
@@ -993,7 +1019,11 @@ BLKFAM::BLKFAM(PDOSDEF tdp) : DOSFAM(tdp)
Last = tdp->GetLast();
Nrec = tdp->GetElemt();
Closing = false;
+#if defined(BLK_INDX)
BlkPos = tdp->GetTo_Pos();
+#else // !BLK_INDX
+ BlkPos = NULL;
+#endif // !BLK_INDX
CurLine = NULL;
NxtLine = NULL;
OutBuf = NULL;
@@ -1033,13 +1063,20 @@ int BLKFAM::Cardinality(PGLOBAL g)
/***********************************************************************/
int BLKFAM::MaxBlkSize(PGLOBAL g, int s)
{
- int savcur = CurBlk;
+ int rc = RC_OK, savcur = CurBlk;
int size;
// Roughly estimate the table size as the sum of blocks
// that can contain good rows
for (size = 0, CurBlk = 0; CurBlk < Block; CurBlk++)
+#if defined(BLK_INDX)
+ if ((rc = Tdbp->TestBlock(g)) == RC_OK)
+ size += (CurBlk == Block - 1) ? Last : Nrec;
+ else if (rc == RC_EF)
+ break;
+#else // !BLK_INDX
size += (CurBlk == Block - 1) ? Last : Nrec;
+#endif // !BLK_INDX
CurBlk = savcur;
return size;
@@ -1150,6 +1187,7 @@ int BLKFAM::SkipRecord(PGLOBAL g, bool header)
/***********************************************************************/
int BLKFAM::ReadBuffer(PGLOBAL g)
{
+#if defined(BLK_INDX)
int i, n, rc = RC_OK;
/*********************************************************************/
@@ -1176,9 +1214,21 @@ int BLKFAM::ReadBuffer(PGLOBAL g)
/*******************************************************************/
CurNum = 0;
+ next:
if (++CurBlk >= Block)
return RC_EF;
+ /*******************************************************************/
+ /* Before reading a new block, check whether block optimization */
+ /* can be done, as well as for join as for local filtering. */
+ /*******************************************************************/
+ switch (Tdbp->TestBlock(g)) {
+ case RC_EF:
+ return RC_EF;
+ case RC_NF:
+ goto next;
+ } // endswitch rc
+
} // endif's
if (OldBlk == CurBlk)
@@ -1241,6 +1291,10 @@ int BLKFAM::ReadBuffer(PGLOBAL g)
// Store the current record file position for Delete and Update
Fpos = BlkPos[CurBlk] + CurLine - To_Buf;
return rc;
+#else // !BLK_POS
+ strcpy(g->Message, "This AM cannot be used in this version");
+ return RC_FX;
+#endif // !BLK_POS
} // end of ReadBuffer
/***********************************************************************/
diff --git a/storage/connect/filamvct.cpp b/storage/connect/filamvct.cpp
index 11c9ac69d4d..4887d7e52fd 100755
--- a/storage/connect/filamvct.cpp
+++ b/storage/connect/filamvct.cpp
@@ -1,11 +1,11 @@
/*********** File AM Vct C++ Program Source Code File (.CPP) ***********/
/* PROGRAM NAME: FILAMVCT */
/* ------------- */
-/* Version 2.4 */
+/* Version 2.5 */
/* */
/* COPYRIGHT: */
/* ---------- */
-/* (C) Copyright to the author Olivier BERTRAND 2005-2013 */
+/* (C) Copyright to the author Olivier BERTRAND 2005-2014 */
/* */
/* WHAT THIS PROGRAM DOES: */
/* ----------------------- */
@@ -249,13 +249,20 @@ bool VCTFAM::SetBlockInfo(PGLOBAL g)
/***********************************************************************/
int VCTFAM::MaxBlkSize(PGLOBAL g, int s)
{
- int savcur = CurBlk;
+ int rc = RC_OK, savcur = CurBlk;
int size;
// Roughly estimate the table size as the sum of blocks
// that can contain good rows
for (size = 0, CurBlk = 0; CurBlk < Block; CurBlk++)
+#if defined(BLK_INDX)
+ if ((rc = Tdbp->TestBlock(g)) == RC_OK)
+ size += (CurBlk == Block - 1) ? Last : Nrec;
+ else if (rc == RC_EF)
+ break;
+#else // !BLK_INDX
size += (CurBlk == Block - 1) ? Last : Nrec;
+#endif // !BLK_INDX
CurBlk = savcur;
return size;
@@ -572,9 +579,25 @@ int VCTFAM::ReadBuffer(PGLOBAL g)
/*******************************************************************/
CurNum = 0;
+#if defined(BLK_INDX)
+ next:
+#endif // BLK_INDX
if (++CurBlk == Block)
return RC_EF; // End of file
+#if defined(BLK_INDX)
+ /*******************************************************************/
+ /* Before reading a new block, check whether block optimizing */
+ /* can be done, as well as for join as for local filtering. */
+ /*******************************************************************/
+ switch (Tdbp->TestBlock(g)) {
+ case RC_EF:
+ return RC_EF;
+ case RC_NF:
+ goto next;
+ } // endswitch rc
+#endif // BLK_INDX
+
num_there++;
} // endif CurNum
diff --git a/storage/connect/filamzip.cpp b/storage/connect/filamzip.cpp
index 4f1a02d8257..04184bdda71 100644
--- a/storage/connect/filamzip.cpp
+++ b/storage/connect/filamzip.cpp
@@ -306,10 +306,30 @@ int ZIPFAM::ReadBuffer(PGLOBAL g)
/*******************************************************************/
/* Record file position in case of UPDATE or DELETE. */
/*******************************************************************/
+#if defined(BLK_INDX)
+ next:
+#endif // BLK_INDX
if (RecordPos(g))
return RC_FX;
CurBlk = Rows++; // Update RowID
+
+#if defined(BLK_INDX)
+ /*******************************************************************/
+ /* Check whether optimization on ROWID */
+ /* can be done, as well as for join as for local filtering. */
+ /*******************************************************************/
+ switch (Tdbp->TestBlock(g)) {
+ case RC_EF:
+ return RC_EF;
+ case RC_NF:
+ // Skip this record
+ if ((rc = SkipRecord(g, FALSE)) != RC_OK)
+ return rc;
+
+ goto next;
+ } // endswitch rc
+#endif // BLK_INDX
} else
Placed = false;
@@ -403,7 +423,11 @@ ZBKFAM::ZBKFAM(PDOSDEF tdp) : ZIPFAM(tdp)
CurLine = NULL;
NxtLine = NULL;
Closing = false;
+#if defined(BLK_INDX)
BlkPos = tdp->GetTo_Pos();
+#else // !BLK_INDX
+ BlkPos = NULL;
+#endif // !BLK_INDX
} // end of ZBKFAM standard constructor
ZBKFAM::ZBKFAM(PZBKFAM txfp) : ZIPFAM(txfp)
@@ -418,13 +442,20 @@ ZBKFAM::ZBKFAM(PZBKFAM txfp) : ZIPFAM(txfp)
/***********************************************************************/
int ZBKFAM::MaxBlkSize(PGLOBAL g, int s)
{
- int savcur = CurBlk;
+ int rc = RC_OK, savcur = CurBlk;
int size;
// Roughly estimate the table size as the sum of blocks
// that can contain good rows
for (size = 0, CurBlk = 0; CurBlk < Block; CurBlk++)
+#if defined(BLK_INDX)
+ if ((rc = Tdbp->TestBlock(g)) == RC_OK)
+ size += (CurBlk == Block - 1) ? Last : Nrec;
+ else if (rc == RC_EF)
+ break;
+#else // !BLK_INDX
size += (CurBlk == Block - 1) ? Last : Nrec;
+#endif // !BLK_INDX
CurBlk = savcur;
return size;
@@ -509,7 +540,8 @@ int ZBKFAM::SkipRecord(PGLOBAL g, bool header)
/***********************************************************************/
int ZBKFAM::ReadBuffer(PGLOBAL g)
{
- int n, rc = RC_OK;
+#if defined(BLK_INDX)
+ int n, skip, rc = RC_OK;
/*********************************************************************/
/* Sequential reading when Placed is not true. */
@@ -532,10 +564,34 @@ int ZBKFAM::ReadBuffer(PGLOBAL g)
/* New block. */
/*********************************************************************/
CurNum = 0;
+ skip = 0;
+ next:
if (++CurBlk >= Block)
return RC_EF;
+ /*********************************************************************/
+ /* Before using the new block, check whether block optimization */
+ /* can be done, as well as for join as for local filtering. */
+ /*********************************************************************/
+ switch (Tdbp->TestBlock(g)) {
+ case RC_EF:
+ return RC_EF;
+ case RC_NF:
+ skip++;
+ goto next;
+ } // endswitch rc
+
+ if (skip)
+ // Skip blocks rejected by block optimization
+ for (int i = CurBlk - skip; i < CurBlk; i++) {
+ BlkLen = BlkPos[i + 1] - BlkPos[i];
+
+ if (gzseek(Zfile, (z_off_t)BlkLen, SEEK_CUR) < 0)
+ return Zerror(g);
+
+ } // endfor i
+
BlkLen = BlkPos[CurBlk + 1] - BlkPos[CurBlk];
if (!(n = gzread(Zfile, To_Buf, BlkLen))) {
@@ -559,6 +615,10 @@ int ZBKFAM::ReadBuffer(PGLOBAL g)
rc = Zerror(g);
return rc;
+#else // !BLK_POS
+ strcpy(g->Message, "This AM cannot be used in this version");
+ return RC_FX;
+#endif // !BLK_POS
} // end of ReadBuffer
/***********************************************************************/
@@ -770,8 +830,33 @@ int ZIXFAM::ReadBuffer(PGLOBAL g)
CurNum = 0;
Tdbp->SetLine(To_Buf);
-//if (++CurBlk >= Block)
-// return RC_EF;
+#if defined(BLK_INDX)
+ int skip = 0;
+
+ next:
+ if (++CurBlk >= Block)
+ return RC_EF;
+
+ /*********************************************************************/
+ /* Before using the new block, check whether block optimization */
+ /* can be done, as well as for join as for local filtering. */
+ /*********************************************************************/
+ switch (Tdbp->TestBlock(g)) {
+ case RC_EF:
+ return RC_EF;
+ case RC_NF:
+ skip++;
+ goto next;
+ } // endswitch rc
+
+ if (skip)
+ // Skip blocks rejected by block optimization
+ for (int i = 0; i < skip; i++) {
+ if (gzseek(Zfile, (z_off_t)Buflen, SEEK_CUR) < 0)
+ return Zerror(g);
+
+ } // endfor i
+#endif // BLK_INDX
if (!(n = gzread(Zfile, To_Buf, Buflen))) {
rc = RC_EF;
@@ -818,4 +903,522 @@ int ZIXFAM::WriteBuffer(PGLOBAL g)
return RC_OK;
} // end of WriteBuffer
+#if defined(BLK_INDX)
+/* --------------------------- Class ZLBFAM -------------------------- */
+
+/***********************************************************************/
+/* Constructors. */
+/***********************************************************************/
+ZLBFAM::ZLBFAM(PDOSDEF tdp) : BLKFAM(tdp)
+ {
+ Zstream = NULL;
+ Zbuffer = NULL;
+ Zlenp = NULL;
+ Optimized = tdp->IsOptimized();
+ } // end of ZLBFAM standard constructor
+
+ZLBFAM::ZLBFAM(PZLBFAM txfp) : BLKFAM(txfp)
+ {
+ Zstream = txfp->Zstream;
+ Zbuffer = txfp->Zbuffer;
+ Zlenp = txfp->Zlenp;
+ Optimized = txfp->Optimized;
+ } // end of ZLBFAM (dummy?) copy constructor
+
+/***********************************************************************/
+/* ZLB GetFileLength: returns an estimate of what would be the */
+/* uncompressed file size in number of bytes. */
+/***********************************************************************/
+int ZLBFAM::GetFileLength(PGLOBAL g)
+ {
+ int len = (Optimized) ? BlkPos[Block] : BLKFAM::GetFileLength(g);
+
+ if (len > 0)
+ // Estimate size reduction to a max of 5
+ len *= 5;
+
+ return len;
+ } // end of GetFileLength
+
+/***********************************************************************/
+/* Allocate the line buffer. For mode Delete a bigger buffer has to */
+/* be allocated because is it also used to move lines into the file. */
+/***********************************************************************/
+bool ZLBFAM::AllocateBuffer(PGLOBAL g)
+ {
+ char *msg;
+ int n, zrc;
+
+#if 0
+ if (!Optimized && Tdbp->NeedIndexing(g)) {
+ strcpy(g->Message, MSG(NOP_ZLIB_INDEX));
+ return TRUE;
+ } // endif indexing
+#endif // 0
+
+#if defined(NOLIB)
+ if (!zlib && LoadZlib()) {
+ sprintf(g->Message, MSG(DLL_LOAD_ERROR), GetLastError(), "zlib.dll");
+ return TRUE;
+ } // endif zlib
+#endif
+
+ BLKFAM::AllocateBuffer(g);
+//Buflen = Nrec * (Lrecl + 2);
+//Rbuf = Nrec;
+
+ // Allocate the compressed buffer
+ n = Buflen + 16; // ?????????????????????????????????
+ Zlenp = (int*)PlugSubAlloc(g, NULL, n);
+ Zbuffer = (Byte*)(Zlenp + 1);
+
+ // Allocate and initialize the Z stream
+ Zstream = (z_streamp)PlugSubAlloc(g, NULL, sizeof(z_stream));
+ Zstream->zalloc = (alloc_func)0;
+ Zstream->zfree = (free_func)0;
+ Zstream->opaque = (voidpf)0;
+ Zstream->next_in = NULL;
+ Zstream->avail_in = 0;
+
+ if (Tdbp->GetMode() == MODE_READ) {
+ msg = "inflateInit";
+ zrc = inflateInit(Zstream);
+ } else {
+ msg = "deflateInit";
+ zrc = deflateInit(Zstream, Z_DEFAULT_COMPRESSION);
+ } // endif Mode
+
+ if (zrc != Z_OK) {
+ if (Zstream->msg)
+ sprintf(g->Message, "%s error: %s", msg, Zstream->msg);
+ else
+ sprintf(g->Message, "%s error: %d", msg, zrc);
+
+ return TRUE;
+ } // endif zrc
+
+ if (Tdbp->GetMode() == MODE_INSERT) {
+ // Write the file header block
+ if (Last == Nrec) {
+ CurBlk = Block;
+ CurNum = 0;
+
+ if (!GetFileLength(g)) {
+ // Write the zlib header as an extra block
+ strcpy(To_Buf, "PlugDB");
+ BlkLen = strlen("PlugDB") + 1;
+
+ if (WriteCompressedBuffer(g))
+ return TRUE;
+
+ } // endif void file
+
+ } else {
+ // In mode insert, if Last != Nrec, last block must be updated
+ CurBlk = Block - 1;
+ CurNum = Last;
+
+ strcpy(g->Message, MSG(NO_PAR_BLK_INS));
+ return TRUE;
+ } // endif Last
+
+ } else { // MODE_READ
+ // First thing to do is to read the header block
+ void *rdbuf;
+
+ if (Optimized) {
+ BlkLen = BlkPos[0];
+ rdbuf = Zlenp;
+ } else {
+ // Get the stored length from the file itself
+ if (fread(Zlenp, sizeof(int), 1, Stream) != 1)
+ return FALSE; // Empty file
+
+ BlkLen = *Zlenp;
+ rdbuf = Zbuffer;
+ } // endif Optimized
+
+ switch (ReadCompressedBuffer(g, rdbuf)) {
+ case RC_EF:
+ return FALSE;
+ case RC_FX:
+#if defined(UNIX)
+ sprintf(g->Message, MSG(READ_ERROR), To_File, strerror(errno));
+#else
+ sprintf(g->Message, MSG(READ_ERROR), To_File, _strerror(NULL));
+#endif
+ case RC_NF:
+ return TRUE;
+ } // endswitch
+
+ // Some old tables can have PlugDB in their header
+ if (strcmp(To_Buf, "PlugDB")) {
+ sprintf(g->Message, MSG(BAD_HEADER), Tdbp->GetFile(g));
+ return TRUE;
+ } // endif strcmp
+
+ } // endif Mode
+
+ return FALSE;
+ } // end of AllocateBuffer
+
+/***********************************************************************/
+/* GetPos: return the position of last read record. */
+/***********************************************************************/
+int ZLBFAM::GetPos(void)
+ {
+ return (Optimized) ? (CurNum + Nrec * CurBlk) : Fpos;
+ } // end of GetPos
+
+/***********************************************************************/
+/* GetNextPos: should not be called for this class. */
+/***********************************************************************/
+int ZLBFAM::GetNextPos(void)
+ {
+ if (Optimized) {
+ assert(FALSE);
+ return 0;
+ } else
+ return ftell(Stream);
+
+ } // end of GetNextPos
+
+/***********************************************************************/
+/* ReadBuffer: Read one line for a text file. */
+/***********************************************************************/
+int ZLBFAM::ReadBuffer(PGLOBAL g)
+ {
+ int n;
+ void *rdbuf;
+
+ /*********************************************************************/
+ /* Sequential reading when Placed is not true. */
+ /*********************************************************************/
+ if (Placed) {
+ Placed = FALSE;
+ } else if (++CurNum < Rbuf) {
+ CurLine = NxtLine;
+
+ // Get the position of the next line in the buffer
+ if (Tdbp->GetFtype() == RECFM_VAR)
+ while (*NxtLine++ != '\n') ;
+ else
+ NxtLine += Lrecl;
+
+ // Set caller line buffer
+ n = NxtLine - CurLine - ((Tdbp->GetFtype() == RECFM_BIN) ? 0 : Ending);
+ memcpy(Tdbp->GetLine(), CurLine, n);
+ Tdbp->GetLine()[n] = '\0';
+ return RC_OK;
+ } else if (Rbuf < Nrec && CurBlk != -1) {
+ CurNum--; // To have a correct Last value when optimizing
+ return RC_EF;
+ } else {
+ /*******************************************************************/
+ /* New block. */
+ /*******************************************************************/
+ CurNum = 0;
+
+ next:
+ if (++CurBlk >= Block)
+ return RC_EF;
+
+ /*******************************************************************/
+ /* Before reading a new block, check whether block optimization */
+ /* can be done, as well as for join as for local filtering. */
+ /*******************************************************************/
+ if (Optimized) switch (Tdbp->TestBlock(g)) {
+ case RC_EF:
+ return RC_EF;
+ case RC_NF:
+ goto next;
+ } // endswitch rc
+
+ } // endif's
+
+ if (OldBlk == CurBlk)
+ goto ok; // Block is already there
+
+ if (Optimized) {
+ // Store the position of next block
+ Fpos = BlkPos[CurBlk];
+
+ // fseek is required only in non sequential reading
+ if (CurBlk != OldBlk + 1)
+ if (fseek(Stream, Fpos, SEEK_SET)) {
+ sprintf(g->Message, MSG(FSETPOS_ERROR), Fpos);
+ return RC_FX;
+ } // endif fseek
+
+ // Calculate the length of block to read
+ BlkLen = BlkPos[CurBlk + 1] - Fpos;
+ rdbuf = Zlenp;
+ } else { // !Optimized
+ if (CurBlk != OldBlk + 1) {
+ strcpy(g->Message, MSG(INV_RAND_ACC));
+ return RC_FX;
+ } else
+ Fpos = ftell(Stream); // Used when optimizing
+
+ // Get the stored length from the file itself
+ if (fread(Zlenp, sizeof(int), 1, Stream) != 1) {
+ if (feof(Stream))
+ return RC_EF;
+
+ goto err;
+ } // endif fread
+
+ BlkLen = *Zlenp;
+ rdbuf = Zbuffer;
+ } // endif Optimized
+
+ // Read the next block
+ switch (ReadCompressedBuffer(g, rdbuf)) {
+ case RC_FX: goto err;
+ case RC_NF: return RC_FX;
+ case RC_EF: return RC_EF;
+ default: Rbuf = (CurBlk == Block - 1) ? Last : Nrec;
+ } // endswitch ReadCompressedBuffer
+
+ ok:
+ if (Tdbp->GetFtype() == RECFM_VAR) {
+ int i;
+
+ // Get the position of the current line
+ for (i = 0, CurLine = To_Buf; i < CurNum; i++)
+ while (*CurLine++ != '\n') ; // What about Unix ???
+
+ // Now get the position of the next line
+ for (NxtLine = CurLine; *NxtLine++ != '\n';) ;
+
+ // Set caller line buffer
+ n = NxtLine - CurLine - Ending;
+ } else {
+ CurLine = To_Buf + CurNum * Lrecl;
+ NxtLine = CurLine + Lrecl;
+ n = Lrecl - ((Tdbp->GetFtype() == RECFM_BIN) ? 0 : Ending);
+ } // endif Ftype
+
+ memcpy(Tdbp->GetLine(), CurLine, n);
+ Tdbp->GetLine()[n] = '\0';
+
+ OldBlk = CurBlk; // Last block actually read
+ IsRead = TRUE; // Is read indeed
+ return RC_OK;
+
+ err:
+#if defined(UNIX)
+ sprintf(g->Message, MSG(READ_ERROR), To_File, strerror(errno));
+#else
+ sprintf(g->Message, MSG(READ_ERROR), To_File, _strerror(NULL));
+#endif
+ return RC_FX;
+ } // end of ReadBuffer
+
+/***********************************************************************/
+/* Read and decompress a block from the stream. */
+/***********************************************************************/
+int ZLBFAM::ReadCompressedBuffer(PGLOBAL g, void *rdbuf)
+ {
+ if (fread(rdbuf, 1, (size_t)BlkLen, Stream) == (unsigned)BlkLen) {
+ int zrc;
+
+ num_read++;
+
+ if (Optimized && BlkLen != signed(*Zlenp + sizeof(int))) {
+ sprintf(g->Message, MSG(BAD_BLK_SIZE), CurBlk + 1);
+ return RC_NF;
+ } // endif BlkLen
+
+ // HERE WE MUST INFLATE THE BLOCK
+ Zstream->next_in = Zbuffer;
+ Zstream->avail_in = (uInt)(*Zlenp);
+ Zstream->next_out = (Byte*)To_Buf;
+ Zstream->avail_out = Buflen;
+ zrc = inflate(Zstream, Z_SYNC_FLUSH);
+
+ if (zrc != Z_OK) {
+ if (Zstream->msg)
+ sprintf(g->Message, MSG(FUNC_ERR_S), "inflate", Zstream->msg);
+ else
+ sprintf(g->Message, MSG(FUNCTION_ERROR), "inflate", (int)zrc);
+
+ return RC_NF;
+ } // endif zrc
+
+ } else if (feof(Stream)) {
+ return RC_EF;
+ } else
+ return RC_FX;
+
+ return RC_OK;
+ } // end of ReadCompressedBuffer
+
+/***********************************************************************/
+/* WriteBuffer: File write routine for DOS access method. */
+/* Update is directly written back into the file, */
+/* with this (fast) method, record size cannot change. */
+/***********************************************************************/
+int ZLBFAM::WriteBuffer(PGLOBAL g)
+ {
+ assert (Tdbp->GetMode() == MODE_INSERT);
+
+ /*********************************************************************/
+ /* Prepare the write buffer. */
+ /*********************************************************************/
+ if (!Closing) {
+ if (Tdbp->GetFtype() == RECFM_BIN)
+ memcpy(CurLine, Tdbp->GetLine(), Lrecl);
+ else
+ strcat(strcpy(CurLine, Tdbp->GetLine()), CrLf);
+
+#if defined(_DEBUG)
+ if (Tdbp->GetFtype() == RECFM_FIX &&
+ (signed)strlen(CurLine) != Lrecl + (signed)strlen(CrLf)) {
+ strcpy(g->Message, MSG(BAD_LINE_LEN));
+ Closing = TRUE;
+ return RC_FX;
+ } // endif Lrecl
+#endif // _DEBUG
+ } // endif Closing
+
+ /*********************************************************************/
+ /* In Insert mode, blocs are added sequentialy to the file end. */
+ /*********************************************************************/
+ if (++CurNum != Rbuf) {
+ if (Tdbp->GetFtype() == RECFM_VAR)
+ CurLine += strlen(CurLine);
+ else
+ CurLine += Lrecl;
+
+ return RC_OK; // We write only full blocks
+ } // endif CurNum
+
+ // HERE WE MUST DEFLATE THE BLOCK
+ if (Tdbp->GetFtype() == RECFM_VAR)
+ NxtLine = CurLine + strlen(CurLine);
+ else
+ NxtLine = CurLine + Lrecl;
+
+ BlkLen = NxtLine - To_Buf;
+
+ if (WriteCompressedBuffer(g)) {
+ Closing = TRUE; // To tell CloseDB about a Write error
+ return RC_FX;
+ } // endif WriteCompressedBuffer
+
+ CurBlk++;
+ CurNum = 0;
+ CurLine = To_Buf;
+ return RC_OK;
+ } // end of WriteBuffer
+
+/***********************************************************************/
+/* Compress the buffer and write the deflated output to stream. */
+/***********************************************************************/
+bool ZLBFAM::WriteCompressedBuffer(PGLOBAL g)
+ {
+ int zrc;
+
+ Zstream->next_in = (Byte*)To_Buf;
+ Zstream->avail_in = (uInt)BlkLen;
+ Zstream->next_out = Zbuffer;
+ Zstream->avail_out = Buflen + 16;
+ Zstream->total_out = 0;
+ zrc = deflate(Zstream, Z_FULL_FLUSH);
+
+ if (zrc != Z_OK) {
+ if (Zstream->msg)
+ sprintf(g->Message, MSG(FUNC_ERR_S), "deflate", Zstream->msg);
+ else
+ sprintf(g->Message, MSG(FUNCTION_ERROR), "deflate", (int)zrc);
+
+ return TRUE;
+ } else
+ *Zlenp = Zstream->total_out;
+
+ // Now start the writing process.
+ BlkLen = *Zlenp + sizeof(int);
+
+ if (fwrite(Zlenp, 1, BlkLen, Stream) != (size_t)BlkLen) {
+ sprintf(g->Message, MSG(FWRITE_ERROR), strerror(errno));
+ return TRUE;
+ } // endif size
+
+ return FALSE;
+ } // end of WriteCompressedBuffer
+
+/***********************************************************************/
+/* Table file close routine for DOS access method. */
+/***********************************************************************/
+void ZLBFAM::CloseTableFile(PGLOBAL g)
+ {
+ int rc = RC_OK;
+
+ if (Tdbp->GetMode() == MODE_INSERT) {
+ PCATLG cat = PlgGetCatalog(g);
+ LPCSTR name = Tdbp->GetName();
+ PDOSDEF defp = (PDOSDEF)Tdbp->GetDef();
+
+ // Closing is True if last Write was in error
+ if (CurNum && !Closing) {
+ // Some more inserted lines remain to be written
+ Last = (Nrec - Rbuf) + CurNum;
+ Block = CurBlk + 1;
+ Rbuf = CurNum--;
+ Closing = TRUE;
+ rc = WriteBuffer(g);
+ } else if (Rbuf == Nrec) {
+ Last = Nrec;
+ Block = CurBlk;
+ } // endif CurNum
+
+ if (rc != RC_FX) {
+ defp->SetBlock(Block);
+ defp->SetLast(Last);
+ cat->SetIntCatInfo("Blocks", Block);
+ cat->SetIntCatInfo("Last", Last);
+ } // endif
+
+ fclose(Stream);
+ } else
+ rc = fclose(Stream);
+
+#ifdef DEBTRACE
+ htrc("ZLB CloseTableFile: closing %s mode=%d rc=%d\n",
+ To_File, Tdbp->GetMode(), rc);
+#endif
+
+ Stream = NULL; // So we can know whether table is open
+ To_Fb->Count = 0; // Avoid double closing by PlugCloseAll
+
+ if (Tdbp->GetMode() == MODE_READ)
+ rc = inflateEnd(Zstream);
+ else
+ rc = deflateEnd(Zstream);
+
+ } // end of CloseTableFile
+
+/***********************************************************************/
+/* Rewind routine for ZLIB access method. */
+/***********************************************************************/
+void ZLBFAM::Rewind(void)
+ {
+ // We must be positioned after the header block
+ if (CurBlk >= 0) { // Nothing to do if no block read yet
+ if (!Optimized) { // If optimized, fseek will be done in ReadBuffer
+ rewind(Stream);
+ fread(Zlenp, sizeof(int), 1, Stream);
+ fseek(Stream, *Zlenp + sizeof(int), SEEK_SET);
+ OldBlk = -1;
+ } // endif Optimized
+
+ CurBlk = -1;
+ CurNum = Rbuf;
+ } // endif CurBlk
+
+//OldBlk = -1;
+//Rbuf = 0; commented out in case we reuse last read block
+ } // end of Rewind
+#endif // BLK_INDX
/* ------------------------ End of ZipFam ---------------------------- */
diff --git a/storage/connect/filamzip.h b/storage/connect/filamzip.h
index f6f28ca5315..67d9553a4e6 100644
--- a/storage/connect/filamzip.h
+++ b/storage/connect/filamzip.h
@@ -122,7 +122,7 @@ class DllExport ZIXFAM : public ZBKFAM {
// No additional Members
}; // end of class ZIXFAM
-#ifdef NOT_USED
+#if defined(BLK_INDX)
/***********************************************************************/
/* This is the DOS/UNIX Access Method class declaration for PlugDB */
/* fixed/variable files compressed using the zlib library functions. */
@@ -166,6 +166,6 @@ class DllExport ZLBFAM : public BLKFAM {
int *Zlenp; // Pointer to block length
bool Optimized; // true when opt file is available
}; // end of class ZLBFAM
-#endif // NOT_USED
+#endif // BLK_INDX
#endif // __FILAMZIP_H
diff --git a/storage/connect/ha_connect.cc b/storage/connect/ha_connect.cc
index f19cac9da50..f301ed2dcae 100644
--- a/storage/connect/ha_connect.cc
+++ b/storage/connect/ha_connect.cc
@@ -252,8 +252,8 @@ ha_create_table_option connect_table_option_list[]=
ha_create_table_option connect_field_option_list[]=
{
HA_FOPTION_NUMBER("FLAG", offset, (ulonglong) -1, 0, INT_MAX32, 1),
- HA_FOPTION_NUMBER("FREQUENCY", freq, 0, 0, INT_MAX32, 1), // not used
- HA_FOPTION_NUMBER("OPT_VALUE", opt, 0, 0, 2, 1), // used for indexing
+ HA_FOPTION_NUMBER("MAX_DIST", freq, 0, 0, INT_MAX32, 1), // BLK_INDX
+ HA_FOPTION_NUMBER("DISTRIB", opt, 0, 0, 2, 1), // used for BLK_INDX
HA_FOPTION_NUMBER("FIELD_LENGTH", fldlen, 0, 0, INT_MAX32, 1),
HA_FOPTION_STRING("DATE_FORMAT", dateformat),
HA_FOPTION_STRING("FIELD_FORMAT", fieldformat),
@@ -331,11 +331,12 @@ DllExport LPCSTR PlugSetPath(LPSTR to, LPCSTR name, LPCSTR dir)
delete_table method in handler.cc
*/
static const char *ha_connect_exts[]= {
- ".dos", ".fix", ".csv",".bin", ".fmt", ".dbf", ".xml", ".ini", ".vec",
+ ".dos", ".fix", ".csv", ".bin", ".fmt", ".dbf", ".xml", ".ini", ".vec",
".dnx", ".fnx", ".bnx", ".vnx", ".dbx",
- NULL
-};
-
+#if defined(BLK_INDX)
+ ".dop", ".fop", ".bop", ".vop",
+#endif // BLK_INDX
+ NULL};
/**
@brief
@@ -453,7 +454,7 @@ static handler* connect_create_handler(handlerton *hton,
handler *h= new (mem_root) ha_connect(hton, table);
if (xtrace)
- printf("New CONNECT %p, table: %s\n",
+ htrc("New CONNECT %p, table: %s\n",
h, table ? table->table_name.str : "<null>");
return h;
@@ -500,7 +501,7 @@ ha_connect::ha_connect(handlerton *hton, TABLE_SHARE *table_arg)
ha_connect::~ha_connect(void)
{
if (xtrace)
- printf("Delete CONNECT %p, table: %s, xp=%p count=%d\n", this,
+ htrc("Delete CONNECT %p, table: %s, xp=%p count=%d\n", this,
table ? table->s->table_name.str : "<null>",
xp, xp ? xp->count : 0);
@@ -932,12 +933,12 @@ void *ha_connect::GetColumnOption(PGLOBAL g, void *field, PCOLINFO pcf)
if (fop) {
pcf->Offset= (int)fop->offset;
-// pcf->Freq= fop->freq;
+ pcf->Freq= (int)fop->freq;
pcf->Datefmt= (char*)fop->dateformat;
pcf->Fieldfmt= (char*)fop->fieldformat;
} else {
pcf->Offset= -1;
-// pcf->Freq= 0;
+ pcf->Freq= 0;
pcf->Datefmt= NULL;
pcf->Fieldfmt= NULL;
} // endif fop
@@ -1046,7 +1047,7 @@ PIXDEF ha_connect::GetIndexInfo(TABLE_SHARE *s)
for (int n= 0; (unsigned)n < s->keynames.count; n++) {
if (xtrace)
- printf("Getting created index %d info\n", n + 1);
+ htrc("Getting created index %d info\n", n + 1);
// Find the index to describe
kp= s->key_info[n];
@@ -1182,7 +1183,7 @@ PTDB ha_connect::GetTDB(PGLOBAL g)
valid_query_id= xp->last_query_id;
tp->SetMode(xmod);
} else
- printf("GetTDB: %s\n", g->Message);
+ htrc("GetTDB: %s\n", g->Message);
return tp;
} // end of GetTDB
@@ -1197,7 +1198,7 @@ int ha_connect::OpenTable(PGLOBAL g, bool del)
// Double test to be on the safe side
if (!g || !table) {
- printf("OpenTable logical error; g=%p table=%p\n", g, table);
+ htrc("OpenTable logical error; g=%p table=%p\n", g, table);
return HA_ERR_INITIALIZATION;
} // endif g
@@ -1278,9 +1279,8 @@ int ha_connect::OpenTable(PGLOBAL g, bool del)
PIXDEF oldpix= GetIndexInfo();
} // endif xmod
-// tdbp->SetOrig((PTBX)table); // used by CheckCond
} else
- printf("OpenTable: %s\n", g->Message);
+ htrc("OpenTable: %s\n", g->Message);
if (rc) {
tdbp= NULL;
@@ -1334,7 +1334,7 @@ int ha_connect::MakeRecord(char *buf)
DBUG_ENTER("ha_connect::MakeRecord");
if (xtrace > 1)
- printf("Maps: read=%08X write=%08X vcol=%08X defr=%08X defw=%08X\n",
+ htrc("Maps: read=%08X write=%08X vcol=%08X defr=%08X defw=%08X\n",
*table->read_set->bitmap, *table->write_set->bitmap,
*table->vcol_set->bitmap,
*table->def_read_set.bitmap, *table->def_write_set.bitmap);
@@ -1372,7 +1372,7 @@ int ha_connect::MakeRecord(char *buf)
if (mrr)
continue;
#endif // MRRBKA_SUPPORT
- printf("Column %s not found\n", fp->field_name);
+ htrc("Column %s not found\n", fp->field_name);
dbug_tmp_restore_column_map(table->write_set, org_bitmap);
DBUG_RETURN(HA_ERR_WRONG_IN_RECORD);
} // endif colp
@@ -1487,7 +1487,7 @@ int ha_connect::ScanRecord(PGLOBAL g, uchar *buf)
break;
if (!colp) {
- printf("Column %s not found\n", fp->field_name);
+ htrc("Column %s not found\n", fp->field_name);
rc= HA_ERR_WRONG_IN_RECORD;
goto err;
} else
@@ -1612,16 +1612,16 @@ const char *ha_connect::GetValStr(OPVAL vop, bool neg)
val= (neg) ? " NOT IN (" : " IN (";
break;
case OP_NULL:
- val= " IS NULL";
+ val= (neg) ? " IS NOT NULL" : " IS NULL";
break;
case OP_LIKE:
val= " LIKE ";
break;
case OP_XX:
- val= " BETWEEN ";
+ val= (neg) ? " NOT BETWEEN " : " BETWEEN ";
break;
case OP_EXIST:
- val= " EXISTS ";
+ val= (neg) ? " NOT EXISTS " : " EXISTS ";
break;
case OP_AND:
val= " AND ";
@@ -1656,22 +1656,204 @@ const char *ha_connect::GetValStr(OPVAL vop, bool neg)
} // end of GetValStr
+#if defined(BLK_INDX)
/***********************************************************************/
-/* Check the WHERE condition and return an ODBC/WQL filter. */
+/* Check the WHERE condition and return a CONNECT filter. */
/***********************************************************************/
-PFIL ha_connect::CheckCond(PGLOBAL g, PFIL filp, AMT tty, Item *cond)
+PFIL ha_connect::CondFilter(PGLOBAL g, Item *cond)
+{
+ unsigned int i;
+ bool ismul= false;
+ OPVAL vop= OP_XX;
+ PFIL filp= NULL;
+
+ if (!cond)
+ return NULL;
+
+ if (xtrace)
+ htrc("Cond type=%d\n", cond->type());
+
+ if (cond->type() == COND::COND_ITEM) {
+ PFIL fp;
+ Item_cond *cond_item= (Item_cond *)cond;
+
+ if (xtrace)
+ htrc("Cond: Ftype=%d name=%s\n", cond_item->functype(),
+ cond_item->func_name());
+
+ switch (cond_item->functype()) {
+ case Item_func::COND_AND_FUNC: vop= OP_AND; break;
+ case Item_func::COND_OR_FUNC: vop= OP_OR; break;
+ default: return NULL;
+ } // endswitch functype
+
+ List<Item>* arglist= cond_item->argument_list();
+ List_iterator<Item> li(*arglist);
+ Item *subitem;
+
+ for (i= 0; i < arglist->elements; i++)
+ if ((subitem= li++)) {
+ if (!(fp= CondFilter(g, subitem))) {
+ if (vop == OP_OR)
+ return NULL;
+ } else
+ filp= (filp) ? MakeFilter(g, filp, vop, fp) : fp;
+
+ } else
+ return NULL;
+
+ } else if (cond->type() == COND::FUNC_ITEM) {
+ unsigned int i;
+ bool iscol, neg= FALSE;
+ PCOL colp[2]= {NULL,NULL};
+ PPARM pfirst= NULL, pprec= NULL;
+ POPER pop;
+ Item_func *condf= (Item_func *)cond;
+ Item* *args= condf->arguments();
+
+ if (xtrace)
+ htrc("Func type=%d argnum=%d\n", condf->functype(),
+ condf->argument_count());
+
+ switch (condf->functype()) {
+ case Item_func::EQUAL_FUNC:
+ case Item_func::EQ_FUNC: vop= OP_EQ; break;
+ case Item_func::NE_FUNC: vop= OP_NE; break;
+ case Item_func::LT_FUNC: vop= OP_LT; break;
+ case Item_func::LE_FUNC: vop= OP_LE; break;
+ case Item_func::GE_FUNC: vop= OP_GE; break;
+ case Item_func::GT_FUNC: vop= OP_GT; break;
+ case Item_func::IN_FUNC: vop= OP_IN;
+ case Item_func::BETWEEN:
+ ismul= true;
+ neg= ((Item_func_opt_neg *)condf)->negated;
+ break;
+ default: return NULL;
+ } // endswitch functype
+
+ pop= (POPER)PlugSubAlloc(g, NULL, sizeof(OPER));
+ pop->Name= NULL;
+ pop->Val=vop;
+ pop->Mod= 0;
+
+ if (condf->argument_count() < 2)
+ return NULL;
+
+ for (i= 0; i < condf->argument_count(); i++) {
+ if (xtrace)
+ htrc("Argtype(%d)=%d\n", i, args[i]->type());
+
+ if (i >= 2 && !ismul) {
+ if (xtrace)
+ htrc("Unexpected arg for vop=%d\n", vop);
+
+ continue;
+ } // endif i
+
+ if ((iscol= args[i]->type() == COND::FIELD_ITEM)) {
+ Item_field *pField= (Item_field *)args[i];
+
+ // IN and BETWEEN clauses should be col VOP list
+ if (i && ismul)
+ return NULL;
+
+ if (pField->field->table != table ||
+ !(colp[i]= tdbp->ColDB(g, (PSZ)pField->field->field_name, 0)))
+ return NULL; // Column does not belong to this table
+
+ if (xtrace) {
+ htrc("Field index=%d\n", pField->field->field_index);
+ htrc("Field name=%s\n", pField->field->field_name);
+ } // endif xtrace
+
+ } else {
+ char buff[256];
+ String *res, tmp(buff, sizeof(buff), &my_charset_bin);
+ Item_basic_constant *pval= (Item_basic_constant *)args[i];
+ PPARM pp= (PPARM)PlugSubAlloc(g, NULL, sizeof(PARM));
+
+ // IN and BETWEEN clauses should be col VOP list
+ if (!i && (ismul))
+ return NULL;
+
+ if ((res= pval->val_str(&tmp)) == NULL)
+ return NULL; // To be clarified
+
+ switch (args[i]->real_type()) {
+ case COND::STRING_ITEM:
+ pp->Type= TYPE_STRING;
+ pp->Value= PlugSubAlloc(g, NULL, res->length() + 1);
+ strncpy((char*)pp->Value, res->ptr(), res->length() + 1);
+ break;
+ case COND::INT_ITEM:
+ pp->Type= TYPE_INT;
+ pp->Value= PlugSubAlloc(g, NULL, sizeof(int));
+ *((int*)pp->Value)= (int)pval->val_int();
+ break;
+ case COND::DATE_ITEM:
+ pp->Type= TYPE_DATE;
+ pp->Value= PlugSubAlloc(g, NULL, sizeof(int));
+ *((int*)pp->Value)= (int)pval->val_int_from_date();
+ break;
+ case COND::REAL_ITEM:
+ pp->Type= TYPE_DOUBLE;
+ pp->Value= PlugSubAlloc(g, NULL, sizeof(double));
+ *((double*)pp->Value)= pval->val_real();
+ break;
+ case COND::DECIMAL_ITEM:
+ pp->Type= TYPE_DOUBLE;
+ pp->Value= PlugSubAlloc(g, NULL, sizeof(double));
+ *((double*)pp->Value)= pval->val_real_from_decimal();
+ break;
+ case COND::CACHE_ITEM: // Possible ???
+ case COND::NULL_ITEM: // TODO: handle this
+ default:
+ return NULL;
+ } // endswitch type
+
+ if (xtrace)
+ htrc("Value=%.*s\n", res->length(), res->ptr());
+
+ // Append the value to the argument list
+ if (pprec)
+ pprec->Next= pp;
+ else
+ pfirst= pp;
+
+ pp->Domain= i;
+ pp->Next= NULL;
+ pprec= pp;
+ } // endif type
+
+ } // endfor i
+
+ filp= MakeFilter(g, colp, pop, pfirst, neg);
+ } else {
+ if (xtrace)
+ htrc("Unsupported condition\n");
+
+ return NULL;
+ } // endif's type
+
+ return filp;
+} // end of CondFilter
+#endif // BLK_INDX
+
+/***********************************************************************/
+/* Check the WHERE condition and return a MYSQL/ODBC/WQL filter. */
+/***********************************************************************/
+PCFIL ha_connect::CheckCond(PGLOBAL g, PCFIL filp, AMT tty, Item *cond)
{
char *body= filp->Body;
unsigned int i;
bool ismul= false, x= (tty == TYPE_AM_MYX || tty == TYPE_AM_XDBC);
- PPARM pfirst= NULL, pprec= NULL, pp[2]= {NULL, NULL};
OPVAL vop= OP_XX;
if (!cond)
return NULL;
if (xtrace)
- printf("Cond type=%d\n", cond->type());
+ htrc("Cond type=%d\n", cond->type());
if (cond->type() == COND::COND_ITEM) {
char *p1, *p2;
@@ -1681,7 +1863,7 @@ PFIL ha_connect::CheckCond(PGLOBAL g, PFIL filp, AMT tty, Item *cond)
return NULL;
if (xtrace)
- printf("Cond: Ftype=%d name=%s\n", cond_item->functype(),
+ htrc("Cond: Ftype=%d name=%s\n", cond_item->functype(),
cond_item->func_name());
switch (cond_item->functype()) {
@@ -1728,7 +1910,7 @@ PFIL ha_connect::CheckCond(PGLOBAL g, PFIL filp, AMT tty, Item *cond)
Item* *args= condf->arguments();
if (xtrace)
- printf("Func type=%d argnum=%d\n", condf->functype(),
+ htrc("Func type=%d argnum=%d\n", condf->functype(),
condf->argument_count());
// neg= condf->
@@ -1742,8 +1924,10 @@ PFIL ha_connect::CheckCond(PGLOBAL g, PFIL filp, AMT tty, Item *cond)
case Item_func::GE_FUNC: vop= OP_GE; break;
case Item_func::GT_FUNC: vop= OP_GT; break;
case Item_func::IN_FUNC: vop= OP_IN;
+ case Item_func::BETWEEN:
+ ismul= true;
neg= ((Item_func_opt_neg *)condf)->negated;
- case Item_func::BETWEEN: ismul= true; break;
+ break;
default: return NULL;
} // endswitch functype
@@ -1757,11 +1941,11 @@ PFIL ha_connect::CheckCond(PGLOBAL g, PFIL filp, AMT tty, Item *cond)
for (i= 0; i < condf->argument_count(); i++) {
if (xtrace)
- printf("Argtype(%d)=%d\n", i, args[i]->type());
+ htrc("Argtype(%d)=%d\n", i, args[i]->type());
if (i >= 2 && !ismul) {
if (xtrace)
- printf("Unexpected arg for vop=%d\n", vop);
+ htrc("Unexpected arg for vop=%d\n", vop);
continue;
} // endif i
@@ -1793,8 +1977,8 @@ PFIL ha_connect::CheckCond(PGLOBAL g, PFIL filp, AMT tty, Item *cond)
fnm= pField->field->field_name;
if (xtrace) {
- printf("Field index=%d\n", pField->field->field_index);
- printf("Field name=%s\n", pField->field->field_name);
+ htrc("Field index=%d\n", pField->field->field_index);
+ htrc("Field name=%s\n", pField->field->field_name);
} // endif xtrace
// IN and BETWEEN clauses should be col VOP list
@@ -1815,7 +1999,7 @@ PFIL ha_connect::CheckCond(PGLOBAL g, PFIL filp, AMT tty, Item *cond)
String *res, tmp(buff, sizeof(buff), &my_charset_bin);
Item_basic_constant *pval= (Item_basic_constant *)args[i];
- switch (args[i]->type()) {
+ switch (args[i]->real_type()) {
case COND::STRING_ITEM:
case COND::INT_ITEM:
case COND::REAL_ITEM:
@@ -1832,7 +2016,7 @@ PFIL ha_connect::CheckCond(PGLOBAL g, PFIL filp, AMT tty, Item *cond)
return NULL; // To be clarified
if (xtrace)
- printf("Value=%.*s\n", res->length(), res->ptr());
+ htrc("Value=%.*s\n", res->length(), res->ptr());
// IN and BETWEEN clauses should be col VOP list
if (!i && (x || ismul))
@@ -1877,7 +2061,7 @@ PFIL ha_connect::CheckCond(PGLOBAL g, PFIL filp, AMT tty, Item *cond)
} else {
if (xtrace)
- printf("Unsupported condition\n");
+ htrc("Unsupported condition\n");
return NULL;
} // endif's type
@@ -1912,32 +2096,45 @@ const COND *ha_connect::cond_push(const COND *cond)
if (tdbp) {
AMT tty= tdbp->GetAmType();
bool x= (tty == TYPE_AM_MYX || tty == TYPE_AM_XDBC);
-
- if (tty == TYPE_AM_WMI || tty == TYPE_AM_ODBC ||
- tty == TYPE_AM_TBL || tty == TYPE_AM_MYSQL ||
- tty == TYPE_AM_PLG || x) {
+ bool b= (tty == TYPE_AM_WMI || tty == TYPE_AM_ODBC ||
+ tty == TYPE_AM_TBL || tty == TYPE_AM_MYSQL ||
+ tty == TYPE_AM_PLG || x);
+#if defined(BLK_INDX)
+ bool go= true;
+#else // !BLK_INDX)
+ bool go= b;
+#endif // !BLK_INDX
+
+ if (go) {
PGLOBAL& g= xp->g;
- PFIL filp= (PFIL)PlugSubAlloc(g, NULL, sizeof(FILTER));
- filp->Body= (char*)PlugSubAlloc(g, NULL, (x) ? 128 : 0);
- *filp->Body= 0;
- filp->Op= OP_XX;
- filp->Cmds= NULL;
+ if (b) {
+ PCFIL filp= (PCFIL)PlugSubAlloc(g, NULL, sizeof(CONDFIL));
- if (CheckCond(g, filp, tty, (Item *)cond)) {
- if (xtrace)
- printf("cond_push: %s\n", filp->Body);
+ filp->Body= (char*)PlugSubAlloc(g, NULL, (x) ? 128 : 0);
+ *filp->Body= 0;
+ filp->Op= OP_XX;
+ filp->Cmds= NULL;
+
+ if (CheckCond(g, filp, tty, (Item *)cond)) {
+ if (xtrace)
+ htrc("cond_push: %s\n", filp->Body);
+
+ if (!x)
+ PlugSubAlloc(g, NULL, strlen(filp->Body) + 1);
+ else
+ cond= NULL; // Does this work?
+
+ tdbp->SetCondFil(filp);
+ } else if (x && cond)
+ tdbp->SetCondFil(filp); // Wrong filter
- if (!x)
- PlugSubAlloc(g, NULL, strlen(filp->Body) + 1);
+ } // endif b
+#if defined(BLK_INDX)
else
- cond= NULL; // Does this work?
-
- tdbp->SetFilter(filp);
- } else if (x && cond)
- tdbp->SetFilter(filp); // Wrong filter
-
- } // endif tty
+ tdbp->SetFilter(CondFilter(g, (Item *)cond));
+#endif // BLK_INDX
+ } // endif go
} // endif tdbp
@@ -2019,7 +2216,7 @@ int ha_connect::open(const char *name, int mode, uint test_if_locked)
DBUG_ENTER("ha_connect::open");
if (xtrace)
- printf("open: name=%s mode=%d test=%u\n", name, mode, test_if_locked);
+ htrc("open: name=%s mode=%d test=%u\n", name, mode, test_if_locked);
if (!(share= get_share()))
DBUG_RETURN(1);
@@ -2063,11 +2260,23 @@ int ha_connect::optimize(THD* thd, HA_CHECK_OPT* check_opt)
dup->Check |= CHK_OPT;
if (tdbp || (tdbp= GetTDB(g))) {
+#if defined(BLK_INDX)
+ bool b= ((PTDBASE)tdbp)->GetDef()->Indexable();
+
+ if ((rc= ((PTDBASE)tdbp)->ResetTableOpt(g, true, b))) {
+ if (rc == RC_INFO) {
+ push_warning(thd, Sql_condition::WARN_LEVEL_WARN, 0, g->Message);
+ rc= 0;
+ } else
+ rc= HA_ERR_INTERNAL_ERROR;
+
+ } // endif rc
+#else // !BLK_INDX
if (!((PTDBASE)tdbp)->GetDef()->Indexable()) {
sprintf(g->Message, "optimize: Table %s is not indexable", tdbp->GetName());
my_message(ER_INDEX_REBUILD, g->Message, MYF(0));
rc= HA_ERR_UNSUPPORTED;
- } else if ((rc= ((PTDBASE)tdbp)->ResetTableOpt(g, true))) {
+ } else if ((rc= ((PTDBASE)tdbp)->ResetTableOpt(g, false, true))) {
if (rc == RC_INFO) {
push_warning(thd, Sql_condition::WARN_LEVEL_WARN, 0, g->Message);
rc= 0;
@@ -2075,6 +2284,8 @@ int ha_connect::optimize(THD* thd, HA_CHECK_OPT* check_opt)
rc= HA_ERR_INTERNAL_ERROR;
} // endif's
+#endif // !BLK_INDX
+
} else
rc= HA_ERR_INTERNAL_ERROR;
@@ -2179,7 +2390,7 @@ int ha_connect::write_row(uchar *buf)
// Return result code from write operation
if (CntWriteRow(g, tdbp)) {
DBUG_PRINT("write_row", ("%s", g->Message));
- printf("write_row: %s\n", g->Message);
+ htrc("write_row: %s\n", g->Message);
rc= HA_ERR_INTERNAL_ERROR;
} // endif RC
@@ -2216,7 +2427,7 @@ int ha_connect::update_row(const uchar *old_data, uchar *new_data)
DBUG_ENTER("ha_connect::update_row");
if (xtrace > 1)
- printf("update_row: old=%s new=%s\n", old_data, new_data);
+ htrc("update_row: old=%s new=%s\n", old_data, new_data);
// Check values for possible change in indexed column
if ((rc= CheckRecord(g, old_data, new_data)))
@@ -2224,7 +2435,7 @@ int ha_connect::update_row(const uchar *old_data, uchar *new_data)
if (CntUpdateRow(g, tdbp)) {
DBUG_PRINT("update_row", ("%s", g->Message));
- printf("update_row CONNECT: %s\n", g->Message);
+ htrc("update_row CONNECT: %s\n", g->Message);
rc= HA_ERR_INTERNAL_ERROR;
} // endif RC
@@ -2258,7 +2469,7 @@ int ha_connect::delete_row(const uchar *buf)
if (CntDeleteRow(xp->g, tdbp, false)) {
rc= HA_ERR_INTERNAL_ERROR;
- printf("delete_row CONNECT: %s\n", xp->g->Message);
+ htrc("delete_row CONNECT: %s\n", xp->g->Message);
} // endif DeleteRow
DBUG_RETURN(rc);
@@ -2275,7 +2486,7 @@ int ha_connect::index_init(uint idx, bool sorted)
DBUG_ENTER("index_init");
if (xtrace)
- printf("index_init: this=%p idx=%u sorted=%d\n", this, idx, sorted);
+ htrc("index_init: this=%p idx=%u sorted=%d\n", this, idx, sorted);
if ((rc= rnd_init(0)))
return rc;
@@ -2291,7 +2502,7 @@ int ha_connect::index_init(uint idx, bool sorted)
if (indexing <= 0) {
DBUG_PRINT("index_init", ("%s", g->Message));
- printf("index_init CONNECT: %s\n", g->Message);
+ htrc("index_init CONNECT: %s\n", g->Message);
active_index= MAX_KEY;
rc= HA_ERR_INTERNAL_ERROR;
} else {
@@ -2307,7 +2518,7 @@ int ha_connect::index_init(uint idx, bool sorted)
} // endif indexing
if (xtrace)
- printf("index_init: rc=%d indexing=%d active_index=%d\n",
+ htrc("index_init: rc=%d indexing=%d active_index=%d\n",
rc, indexing, active_index);
DBUG_RETURN(rc);
@@ -2350,13 +2561,13 @@ int ha_connect::ReadIndexed(uchar *buf, OPVAL op, const uchar *key, uint key_len
break;
default: // Read error
DBUG_PRINT("ReadIndexed", ("%s", xp->g->Message));
- printf("ReadIndexed: %s\n", xp->g->Message);
+ htrc("ReadIndexed: %s\n", xp->g->Message);
rc= HA_ERR_INTERNAL_ERROR;
break;
} // endswitch RC
if (xtrace > 1)
- printf("ReadIndexed: op=%d rc=%d\n", op, rc);
+ htrc("ReadIndexed: op=%d rc=%d\n", op, rc);
table->status= (rc == RC_OK) ? 0 : STATUS_NOT_FOUND;
return rc;
@@ -2399,7 +2610,7 @@ int ha_connect::index_read(uchar * buf, const uchar * key, uint key_len,
} // endswitch find_flag
if (xtrace > 1)
- printf("%p index_read: op=%d\n", this, op);
+ htrc("%p index_read: op=%d\n", this, op);
if (indexing > 0)
rc= ReadIndexed(buf, op, key, key_len);
@@ -2542,7 +2753,7 @@ int ha_connect::rnd_init(bool scan)
} // endif xmod
if (xtrace)
- printf("rnd_init: this=%p scan=%d xmod=%d alter=%d\n",
+ htrc("rnd_init: this=%p scan=%d xmod=%d alter=%d\n",
this, scan, xmod, alter);
if (!g || !table || xmod == MODE_INSERT)
@@ -2637,22 +2848,23 @@ int ha_connect::rnd_next(uchar *buf)
rc= HA_ERR_RECORD_DELETED;
break;
default: // Read error
- printf("rnd_next CONNECT: %s\n", xp->g->Message);
+ htrc("rnd_next CONNECT: %s\n", xp->g->Message);
rc= (records()) ? HA_ERR_INTERNAL_ERROR : HA_ERR_END_OF_FILE;
break;
} // endswitch RC
-#ifndef DBUG_OFF
- if (rc || !(xp->nrd++ % 16384)) {
+ if (xtrace > 1 && (rc || !(xp->nrd++ % 16384))) {
ulonglong tb2= my_interval_timer();
double elapsed= (double) (tb2 - xp->tb1) / 1000000000ULL;
DBUG_PRINT("rnd_next", ("rc=%d nrd=%u fnd=%u nfd=%u sec=%.3lf\n",
rc, (uint)xp->nrd, (uint)xp->fnd,
(uint)xp->nfd, elapsed));
+ htrc("rnd_next: rc=%d nrd=%u fnd=%u nfd=%u sec=%.3lf\n",
+ rc, (uint)xp->nrd, (uint)xp->fnd,
+ (uint)xp->nfd, elapsed);
xp->tb1= tb2;
xp->fnd= xp->nfd= 0;
} // endif nrd
-#endif
table->status= (!rc) ? 0 : STATUS_NOT_FOUND;
DBUG_RETURN(rc);
@@ -2766,7 +2978,7 @@ int ha_connect::info(uint flag)
DBUG_ENTER("ha_connect::info");
if (xtrace)
- printf("%p In info: flag=%u valid_info=%d\n", this, flag, valid_info);
+ htrc("%p In info: flag=%u valid_info=%d\n", this, flag, valid_info);
if (!valid_info) {
// tdbp must be available to get updated info
@@ -2879,7 +3091,7 @@ int ha_connect::delete_all_rows()
if (!(rc= OpenTable(g))) {
if (CntDeleteRow(g, tdbp, true)) {
- printf("%s\n", g->Message);
+ htrc("%s\n", g->Message);
rc= HA_ERR_INTERNAL_ERROR;
} // endif
@@ -2989,8 +3201,8 @@ MODE ha_connect::CheckMode(PGLOBAL g, THD *thd,
{
if (xtrace) {
LEX_STRING *query_string= thd_query_string(thd);
- printf("%p check_mode: cmdtype=%d\n", this, thd_sql_command(thd));
- printf("Cmd=%.*s\n", (int) query_string->length, query_string->str);
+ htrc("%p check_mode: cmdtype=%d\n", this, thd_sql_command(thd));
+ htrc("Cmd=%.*s\n", (int) query_string->length, query_string->str);
} // endif xtrace
// Next code is temporarily replaced until sql_command is set
@@ -3040,7 +3252,7 @@ MODE ha_connect::CheckMode(PGLOBAL g, THD *thd,
newmode= MODE_ALTER;
break;
default:
- printf("Unsupported sql_command=%d", thd_sql_command(thd));
+ htrc("Unsupported sql_command=%d", thd_sql_command(thd));
strcpy(g->Message, "CONNECT Unsupported command");
my_message(ER_NOT_ALLOWED_COMMAND, g->Message, MYF(0));
newmode= MODE_ERROR;
@@ -3085,7 +3297,7 @@ MODE ha_connect::CheckMode(PGLOBAL g, THD *thd,
newmode= MODE_ALTER;
break;
default:
- printf("Unsupported sql_command=%d", thd_sql_command(thd));
+ htrc("Unsupported sql_command=%d", thd_sql_command(thd));
strcpy(g->Message, "CONNECT Unsupported command");
my_message(ER_NOT_ALLOWED_COMMAND, g->Message, MYF(0));
newmode= MODE_ERROR;
@@ -3095,7 +3307,7 @@ MODE ha_connect::CheckMode(PGLOBAL g, THD *thd,
} // endif's newmode
if (xtrace)
- printf("New mode=%d\n", newmode);
+ htrc("New mode=%d\n", newmode);
return newmode;
} // end of check_mode
@@ -3170,7 +3382,7 @@ int ha_connect::external_lock(THD *thd, int lock_type)
DBUG_ASSERT(thd == current_thd);
if (xtrace)
- printf("external_lock: this=%p thd=%p xp=%p g=%p lock_type=%d\n",
+ htrc("external_lock: this=%p thd=%p xp=%p g=%p lock_type=%d\n",
this, thd, xp, g, lock_type);
if (!g)
@@ -3309,7 +3521,7 @@ int ha_connect::external_lock(THD *thd, int lock_type)
if (check_privileges(thd, options, table->s->db.str)) {
strcpy(g->Message, "This operation requires the FILE privilege");
- printf("%s\n", g->Message);
+ htrc("%s\n", g->Message);
DBUG_RETURN(HA_ERR_INTERNAL_ERROR);
} // endif check_privileges
@@ -3343,18 +3555,18 @@ int ha_connect::external_lock(THD *thd, int lock_type)
if (xtrace) {
#if 0
- printf("xcheck=%d cras=%d\n", xcheck, cras);
+ htrc("xcheck=%d cras=%d\n", xcheck, cras);
if (xcheck)
- printf("oldsep=%d oldpix=%p\n",
+ htrc("oldsep=%d oldpix=%p\n",
((PCHK)g->Xchk)->oldsep, ((PCHK)g->Xchk)->oldpix);
#endif // 0
- printf("Calling CntCheckDB db=%s cras=%d\n", GetDBName(NULL), cras);
+ htrc("Calling CntCheckDB db=%s cras=%d\n", GetDBName(NULL), cras);
} // endif xtrace
// Set or reset the good database environment
if (CntCheckDB(g, this, GetDBName(NULL))) {
- printf("%p external_lock: %s\n", this, g->Message);
+ htrc("%p external_lock: %s\n", this, g->Message);
rc= HA_ERR_INTERNAL_ERROR;
// This can NOT be called without open called first, but
// the table can have been closed since then
@@ -3375,7 +3587,7 @@ int ha_connect::external_lock(THD *thd, int lock_type)
} // endif tdbp
if (xtrace)
- printf("external_lock: rc=%d\n", rc);
+ htrc("external_lock: rc=%d\n", rc);
DBUG_RETURN(rc);
} // end of external_lock
@@ -3517,10 +3729,10 @@ int ha_connect::delete_or_rename_table(const char *name, const char *to)
if (xtrace) {
if (to)
- printf("rename_table: this=%p thd=%p sqlcom=%d from=%s to=%s\n",
+ htrc("rename_table: this=%p thd=%p sqlcom=%d from=%s to=%s\n",
this, thd, sqlcom, name, to);
else
- printf("delete_table: this=%p thd=%p sqlcom=%d name=%s\n",
+ htrc("delete_table: this=%p thd=%p sqlcom=%d name=%s\n",
this, thd, sqlcom, name);
} // endif xtrace
@@ -3625,7 +3837,7 @@ ha_rows ha_connect::records_in_range(uint inx, key_range *min_key,
index_init(inx, false);
if (xtrace)
- printf("records_in_range: inx=%d indexing=%d\n", inx, indexing);
+ htrc("records_in_range: inx=%d indexing=%d\n", inx, indexing);
if (indexing > 0) {
int nval;
@@ -4626,7 +4838,7 @@ int ha_connect::create(const char *name, TABLE *table_arg,
table= table_arg; // Used by called functions
if (xtrace)
- printf("create: this=%p thd=%p xp=%p g=%p sqlcom=%d name=%s\n",
+ htrc("create: this=%p thd=%p xp=%p g=%p sqlcom=%d name=%s\n",
this, thd, xp, g, sqlcom, GetTableName());
// CONNECT engine specific table options:
@@ -4954,7 +5166,7 @@ int ha_connect::create(const char *name, TABLE *table_arg,
} // endif
if (xtrace)
- printf("xchk=%p createas=%d\n", g->Xchk, g->Createas);
+ htrc("xchk=%p createas=%d\n", g->Xchk, g->Createas);
// To check whether indices have to be made or remade
if (!g->Xchk) {
@@ -4985,7 +5197,7 @@ int ha_connect::create(const char *name, TABLE *table_arg,
cat->SetDataPath(g, table_arg->s->db.str);
if ((rc= optimize(table->in_use, NULL))) {
- printf("Create rc=%d %s\n", rc, g->Message);
+ htrc("Create rc=%d %s\n", rc, g->Message);
my_message(ER_UNKNOWN_ERROR, g->Message, MYF(0));
rc= HA_ERR_INTERNAL_ERROR;
} else
@@ -5025,7 +5237,7 @@ int ha_connect::create(const char *name, TABLE *table_arg,
g->Xchk= NULL;
if (xtrace && g->Xchk)
- printf("oldsep=%d newsep=%d oldpix=%p newpix=%p\n",
+ htrc("oldsep=%d newsep=%d oldpix=%p newpix=%p\n",
xcp->oldsep, xcp->newsep, xcp->oldpix, xcp->newpix);
// if (g->Xchk &&
@@ -5306,7 +5518,7 @@ ha_connect::check_if_supported_inplace_alter(TABLE *altered_table,
tshp= NULL;
if (xtrace && g->Xchk)
- printf(
+ htrc(
"oldsep=%d newsep=%d oldopn=%s newopn=%s oldpix=%p newpix=%p\n",
xcp->oldsep, xcp->newsep,
SVP(xcp->oldopn), SVP(xcp->newopn),
diff --git a/storage/connect/ha_connect.h b/storage/connect/ha_connect.h
index 1bd3991e907..a2d3c5d6801 100644
--- a/storage/connect/ha_connect.h
+++ b/storage/connect/ha_connect.h
@@ -334,8 +334,11 @@ public:
condition stack.
*/
virtual const COND *cond_push(const COND *cond);
-PFIL CheckCond(PGLOBAL g, PFIL filp, AMT tty, Item *cond);
+PCFIL CheckCond(PGLOBAL g, PCFIL filp, AMT tty, Item *cond);
const char *GetValStr(OPVAL vop, bool neg);
+#if defined(BLK_INDX)
+PFIL CondFilter(PGLOBAL g, Item *cond);
+#endif // BLK_INDX
/**
Number of rows in table. It will only be called if
diff --git a/storage/connect/plgdbsem.h b/storage/connect/plgdbsem.h
index e251ded13df..99e9fb8fb08 100644
--- a/storage/connect/plgdbsem.h
+++ b/storage/connect/plgdbsem.h
@@ -29,6 +29,10 @@ enum BLKTYP {TYPE_TABLE = 50, /* Table Name/Srcdef/... Block */
// TYPE_OPVAL = 52, /* Operator value (OPVAL) */
TYPE_TDB = 53, /* Table Description Block */
TYPE_COLBLK = 54, /* Column Description Block */
+#if defined(BLK_INDX)
+ TYPE_FILTER = 55, /* Filter Description Block */
+ TYPE_ARRAY = 63, /* General array type */
+#endif // BLK_INDX
TYPE_PSZ = 64, /* Pointer to String ended by 0 */
TYPE_SQL = 65, /* Pointer to SQL block */
TYPE_XOBJECT = 69, /* Extended DB object */
@@ -144,21 +148,19 @@ enum RECFM {RECFM_NAF = -2, /* Not a file */
RECFM_PLG = 5, /* Table accessed via PLGconn */
RECFM_DBF = 6}; /* DBase formatted file */
-#if 0
enum MISC {DB_TABNO = 1, /* DB routines in Utility Table */
MAX_MULT_KEY = 10, /* Max multiple key number */
NAM_LEN = 128, /* Length of col and tab names */
ARRAY_SIZE = 50, /* Default array block size */
- MAXRES = 500, /* Default maximum result lines */
- MAXLIN = 10000, /* Default maximum data lines */
+// MAXRES = 500, /* Default maximum result lines */
+// MAXLIN = 10000, /* Default maximum data lines */
MAXBMP = 32}; /* Default XDB2 max bitmap size */
+#if 0
enum ALGMOD {AMOD_AUTO = 0, /* PLG chooses best algorithm */
AMOD_SQL = 1, /* Use SQL algorithm */
AMOD_QRY = 2}; /* Use QUERY algorithm */
-#else // !0
-#define NAM_LEN 128
-#endif // !0
+#endif // 0
enum MODE {MODE_ERROR = -1, /* Invalid mode */
MODE_ANY = 0, /* Unspecified mode */
@@ -342,7 +344,7 @@ typedef class XTAB *PTABLE;
typedef class COLUMN *PCOLUMN;
typedef class XOBJECT *PXOB;
typedef class COLBLK *PCOL;
-typedef class TBX *PTBX;
+//pedef class TBX *PTBX;
typedef class TDB *PTDB;
typedef void *PSQL; // Not used
typedef class TDBASE *PTDBASE;
@@ -376,6 +378,9 @@ typedef class COLDEF *PCOLDEF;
typedef class CONSTANT *PCONST;
typedef class VALUE *PVAL;
typedef class VALBLK *PVBLK;
+#if defined(BLK_INDX)
+typedef class FILTER *PFIL;
+#endif // BLK_INDX
typedef struct _fblock *PFBLOCK;
typedef struct _mblock *PMBLOCK;
@@ -431,7 +436,9 @@ typedef struct { /* User application block */
//int Maxres; /* Result Max nb of lines */
//int Maxtmp; /* Intermediate tables Maxres */
//int Maxlin; /* Query Max nb of data lines */
-//int Maxbmp; /* Maximum XDB2 bitmap size */
+#if defined(BLK_INDX)
+ int Maxbmp; /* Maximum XDB2 bitmap size */
+#endif // BLK_INDX
int Check; /* General level of checking */
int Numlines; /* Number of lines involved */
//ALGMOD AlgChoice; /* Choice of algorithm mode */
@@ -481,6 +488,38 @@ typedef struct _tabs {
PTABADR P3;
} TABS;
+#if defined(BLK_INDX)
+/***********************************************************************/
+/* Argument of expression, function, filter etc. (Xobject) */
+/***********************************************************************/
+typedef struct _arg { /* Argument */
+ PXOB To_Obj; /* To the argument object */
+ PVAL Value; /* Argument value */
+ bool Conv; /* TRUE if conversion is required */
+ } ARGBLK, *PARG;
+
+typedef struct _oper { /* Operator */
+ PSZ Name; /* The input/output operator name */
+ OPVAL Val; /* Operator numeric value */
+ int Mod; /* The modificator */
+ } OPER, *POPER;
+
+#if 0
+/***********************************************************************/
+/* Definitions and table of Scalar Functions. */
+/***********************************************************************/
+typedef struct _sfdsc { /* Scalar function description block*/
+ char Name[16]; /* Scalar function name */
+ EVAL EvalType; /* Type of Init and Eval functions */
+ OPVAL Op; /* Equivalent operator number */
+ int R_Type; /* Result Type */
+ int R_Length; /* Result Length */
+ int R_Prec; /* Result Precision */
+ int Numarg; /* Number of arguments */
+ } SFDSC, *PSFDSC;
+#endif // 0
+#endif // BLK_INDX
+
/***********************************************************************/
/* Following definitions are used to define table fields (columns). */
/***********************************************************************/
diff --git a/storage/connect/plgdbutl.cpp b/storage/connect/plgdbutl.cpp
index c51100e0141..f52515e540b 100644
--- a/storage/connect/plgdbutl.cpp
+++ b/storage/connect/plgdbutl.cpp
@@ -382,7 +382,9 @@ PDBUSER PlgMakeUser(PGLOBAL g)
//#endif
//dbuserp->Maxres = MAXRES;
//dbuserp->Maxlin = MAXLIN;
-//dbuserp->Maxbmp = MAXBMP;
+#if defined(BLK_INDX)
+ dbuserp->Maxbmp = MAXBMP;
+#endif // BLK_INDX
//dbuserp->AlgChoice = AMOD_AUTO;
dbuserp->UseTemp = TMP_AUTO;
dbuserp->Check = CHK_ALL;
diff --git a/storage/connect/reldef.cpp b/storage/connect/reldef.cpp
index 81c9bf9faca..a36901a5d65 100644
--- a/storage/connect/reldef.cpp
+++ b/storage/connect/reldef.cpp
@@ -204,6 +204,7 @@ PTABDEF OEMDEF::GetXdef(PGLOBAL g)
return xdefp;
} // end of GetXdef
+#if 0
/***********************************************************************/
/* DeleteTableFile: Delete an OEM table file if applicable. */
/***********************************************************************/
@@ -214,6 +215,7 @@ bool OEMDEF::DeleteTableFile(PGLOBAL g)
return (Pxdef) ? Pxdef->DeleteTableFile(g) : true;
} // end of DeleteTableFile
+#endif // 0
/***********************************************************************/
/* Define: initialize the table definition block from XDB file. */
@@ -285,8 +287,11 @@ PTDB OEMDEF::GetTable(PGLOBAL g, MODE mode)
if (cmpr == 1)
txfp = new(g) ZIPFAM(defp);
else {
+#if defined(BLK_INDX)
+ txfp = new(g) ZLBFAM(defp);
+#else // !BLK_INDX
strcpy(g->Message, "Compress 2 not supported yet");
-// txfp = new(g) ZLBFAM(defp);
+#endif // !BLK_INDX
return NULL;
} // endelse
#else // !ZIP_SUPPORT
@@ -339,6 +344,7 @@ COLCRT::COLCRT(PSZ name)
Offset = -1;
Long = -1;
Precision = -1;
+ Freq = -1;
Key = -1;
Scale = -1;
Opt = -1;
@@ -355,6 +361,7 @@ COLCRT::COLCRT(void)
Offset = 0;
Long = 0;
Precision = 0;
+ Freq = 0;
Key = 0;
Scale = 0;
Opt = 0;
@@ -368,6 +375,16 @@ COLCRT::COLCRT(void)
/***********************************************************************/
COLDEF::COLDEF(void) : COLCRT()
{
+#if defined(BLK_INDX)
+ To_Min = NULL;
+ To_Max = NULL;
+ To_Pos = NULL;
+ Xdb2 = FALSE;
+ To_Bmap = NULL;
+ To_Dval = NULL;
+ Ndv = 0;
+ Nbm = 0;
+#endif // BLK_INDX
Buf_Type = TYPE_ERROR;
Clen = 0;
Poff = 0;
@@ -401,7 +418,7 @@ int COLDEF::Define(PGLOBAL g, void *memp, PCOLINFO cfp, int poff)
Long = cfp->Length;
Opt = cfp->Opt;
Key = cfp->Key;
-// Freq = cfp->Freq;
+ Freq = cfp->Freq;
if (cfp->Remark && *cfp->Remark) {
Desc = (PSZ)PlugSubAlloc(g, memp, strlen(cfp->Remark) + 1);
diff --git a/storage/connect/reldef.h b/storage/connect/reldef.h
index a877c8ee915..c54d81f30cb 100644
--- a/storage/connect/reldef.h
+++ b/storage/connect/reldef.h
@@ -38,7 +38,7 @@ class DllExport RELDEF : public BLOCK { // Relation definition block
void SetCat(PCATLG cat) { Cat=cat; }
// Methods
- virtual bool DeleteTableFile(PGLOBAL g) {return true;}
+//virtual bool DeleteTableFile(PGLOBAL g) {return true;}
virtual bool Indexable(void) {return false;}
virtual bool Define(PGLOBAL g, PCATLG cat, LPCSTR name, LPCSTR am) = 0;
virtual PTDB GetTable(PGLOBAL g, MODE mode) = 0;
@@ -116,7 +116,7 @@ class DllExport OEMDEF : public TABDEF { /* OEM table */
virtual AMT GetDefType(void) {return TYPE_AM_OEM;}
// Methods
- virtual bool DeleteTableFile(PGLOBAL g);
+//virtual bool DeleteTableFile(PGLOBAL g);
virtual bool DefineAM(PGLOBAL g, LPCSTR am, int poff);
virtual PTDB GetTable(PGLOBAL g, MODE mode);
@@ -148,6 +148,7 @@ class DllExport COLCRT : public BLOCK { /* Column description block
PSZ GetDecode(void) {return Decode;}
PSZ GetFmt(void) {return Fmt;}
int GetOpt(void) {return Opt;}
+ int GetFreq(void) {return Freq;}
int GetLong(void) {return Long;}
int GetPrecision(void) {return Precision;}
int GetOffset(void) {return Offset;}
@@ -165,6 +166,7 @@ class DllExport COLCRT : public BLOCK { /* Column description block
int Precision; /* Logical column length */
int Scale; /* Decimals for float/decimal values */
int Opt; /* 0:Not 1:clustered 2:sorted-asc 3:desc */
+ int Freq; /* Estimated number of different values */
char DataType; /* Internal data type (C, N, F, T) */
}; // end of COLCRT
@@ -188,10 +190,36 @@ class DllExport COLDEF : public COLCRT { /* Column description block
int GetClen(void) {return Clen;}
int GetType(void) {return Buf_Type;}
int GetPoff(void) {return Poff;}
+#if defined(BLK_INDX)
+ void *GetMin(void) {return To_Min;}
+ void SetMin(void *minp) {To_Min = minp;}
+ void *GetMax(void) {return To_Max;}
+ void SetMax(void *maxp) {To_Max = maxp;}
+ bool GetXdb2(void) {return Xdb2;}
+ void SetXdb2(bool b) {Xdb2 = b;}
+ void *GetBmap(void) {return To_Bmap;}
+ void SetBmap(void *bmp) {To_Bmap = bmp;}
+ void *GetDval(void) {return To_Dval;}
+ void SetDval(void *dvp) {To_Dval = dvp;}
+ int GetNdv(void) {return Ndv;}
+ void SetNdv(int ndv) {Ndv = ndv;}
+ int GetNbm(void) {return Nbm;}
+ void SetNbm(int nbm) {Nbm = nbm;}
+#endif // BLK_INDX
int Define(PGLOBAL g, void *memp, PCOLINFO cfp, int poff);
void Define(PGLOBAL g, PCOL colp);
protected:
+#if defined(BLK_INDX)
+ void *To_Min; /* Point to array of block min values */
+ void *To_Max; /* Point to array of block max values */
+ int *To_Pos; /* Point to array of block positions */
+ bool Xdb2; /* TRUE if to be optimized by XDB2 */
+ void *To_Bmap; /* To array of block bitmap values */
+ void *To_Dval; /* To array of column distinct values */
+ int Ndv; /* Number of distinct values */
+ int Nbm; /* Number of ULONG in bitmap (XDB2) */
+#endif // BLK_INDX
int Buf_Type; /* Internal data type */
int Clen; /* Internal data size in chars (bytes) */
int Poff; /* Calculated offset for Packed tables */
diff --git a/storage/connect/tabdos.cpp b/storage/connect/tabdos.cpp
index 15215dc0f01..c1da09080cb 100644
--- a/storage/connect/tabdos.cpp
+++ b/storage/connect/tabdos.cpp
@@ -1,11 +1,11 @@
/************* TabDos C++ Program Source Code File (.CPP) **************/
/* PROGRAM NAME: TABDOS */
/* ------------- */
-/* Version 4.8 */
+/* Version 4.9 */
/* */
/* COPYRIGHT: */
/* ---------- */
-/* (C) Copyright to the author Olivier BERTRAND 1998-2012 */
+/* (C) Copyright to the author Olivier BERTRAND 1998-2014 */
/* */
/* WHAT THIS PROGRAM DOES: */
/* ----------------------- */
@@ -57,27 +57,32 @@
#include "tabdos.h"
#include "tabfix.h"
#include "tabmul.h"
-
-#define PLGINI "plugdb.ini" // Configuration settings file
-
-#if defined(UNIX)
-#define _fileno fileno
-#define _O_RDONLY O_RDONLY
-#endif
+#if defined(BLK_INDX)
+#include "array.h"
+#include "blkfil.h"
+//nclude "token.h"
+//#include "scalfnc.h"
+#endif // BLK_INDX
/***********************************************************************/
/* DB static variables. */
/***********************************************************************/
int num_read, num_there, num_eq[2]; // Statistics
-extern "C" char plgini[_MAX_PATH];
extern "C" int trace;
+#if defined(BLK_INDX)
+/***********************************************************************/
+/* Size of optimize file header. */
+/***********************************************************************/
+#define NZ 4
+
/***********************************************************************/
-/* Min and Max blocks contains zero ended fields (blank = false). */
-/* No conversion of block values (check = true). */
+/* Min and Max blocks contains zero ended fields (blank = FALSE). */
+/* No conversion of block values (check = TRUE). */
/***********************************************************************/
PVBLK AllocValBlock(PGLOBAL, void *, int, int, int len = 0, int prec = 0,
- bool check = true, bool blank = false, bool un = false);
+ bool check = TRUE, bool blank = FALSE, bool un = FALSE);
+#endif // BLK_INDX
/* --------------------------- Class DOSDEF -------------------------- */
@@ -96,7 +101,11 @@ DOSDEF::DOSDEF(void)
Huge = false;
Accept = false;
Eof = false;
+#if defined(BLK_INDX)
To_Pos = NULL;
+ Optimized = 0;
+ AllocBlks = 0;
+#endif // BLK_INDX
Compressed = 0;
Lrecl = 0;
AvgLen = 0;
@@ -110,6 +119,98 @@ DOSDEF::DOSDEF(void)
} // end of DOSDEF constructor
/***********************************************************************/
+/* DefineAM: define specific AM block values from XDB file. */
+/***********************************************************************/
+bool DOSDEF::DefineAM(PGLOBAL g, LPCSTR am, int poff)
+ {
+ char buf[8];
+ bool map = (am && (*am == 'M' || *am == 'm'));
+ LPCSTR dfm = (am && (*am == 'F' || *am == 'f')) ? "F"
+ : (am && (*am == 'B' || *am == 'b')) ? "B"
+ : (am && !stricmp(am, "DBF")) ? "D" : "V";
+
+ Desc = Fn = Cat->GetStringCatInfo(g, "Filename", NULL);
+ Ofn = Cat->GetStringCatInfo(g, "Optname", Fn);
+ Cat->GetCharCatInfo("Recfm", (PSZ)dfm, buf, sizeof(buf));
+ Recfm = (toupper(*buf) == 'F') ? RECFM_FIX :
+ (toupper(*buf) == 'B') ? RECFM_BIN :
+ (toupper(*buf) == 'D') ? RECFM_DBF : RECFM_VAR;
+ Lrecl = Cat->GetIntCatInfo("Lrecl", 0);
+
+ if (Recfm != RECFM_DBF)
+ Compressed = Cat->GetIntCatInfo("Compressed", 0);
+
+ Mapped = Cat->GetBoolCatInfo("Mapped", map);
+ Block = Cat->GetIntCatInfo("Blocks", 0);
+ Last = Cat->GetIntCatInfo("Last", 0);
+ Ending = Cat->GetIntCatInfo("Ending", CRLF);
+
+ if (Recfm == RECFM_FIX || Recfm == RECFM_BIN) {
+ Huge = Cat->GetBoolCatInfo("Huge", Cat->GetDefHuge());
+ Padded = Cat->GetBoolCatInfo("Padded", false);
+ Blksize = Cat->GetIntCatInfo("Blksize", 0);
+ Eof = (Cat->GetIntCatInfo("EOF", 0) != 0);
+ } else if (Recfm == RECFM_DBF) {
+ Maxerr = Cat->GetIntCatInfo("Maxerr", 0);
+ Accept = (Cat->GetIntCatInfo("Accept", 0) != 0);
+ ReadMode = Cat->GetIntCatInfo("Readmode", 0);
+ } else // (Recfm == RECFM_VAR)
+ AvgLen = Cat->GetIntCatInfo("Avglen", 0);
+
+ // Ignore wrong Index definitions for catalog commands
+ return (Cat->GetIndexInfo(g, this) /*&& !Cat->GetCatFnc()*/);
+ } // end of DefineAM
+
+#if 0
+#if defined(BLK_INDX)
+/***********************************************************************/
+/* DeleteTableFile: Delete DOS/UNIX table files using platform API. */
+/* If the table file is protected (declared as read/only) we still */
+/* erase the the eventual optimize and index files but return TRUE. */
+/***********************************************************************/
+bool DOSDEF::DeleteTableFile(PGLOBAL g)
+ {
+ char filename[_MAX_PATH];
+ bool rc, irc, orc = FALSE;
+ PIXDEF pxd;
+ PCOLDEF cdp = NULL;
+
+ /*********************************************************************/
+ /* Check for potential optimization. These tests are done */
+ /* because Optimized is set to 1 only after the first use of an */
+ /* optimized table and can be 0 if it has not been used yet. */
+ /*********************************************************************/
+ if (!Optimized)
+ for (cdp = To_Cols; cdp; cdp = cdp->GetNext())
+ if (cdp->GetOpt())
+ break;
+
+ if (IsOptimized() || cdp || (Recfm == RECFM_VAR && Elemt > 1 && Block))
+ if (!GetOptFileName(g, filename))
+#if defined(WIN32)
+ orc = !DeleteFile(filename);
+#else // UNIX
+ orc = remove(filename);
+#endif // WIN32
+
+ // Now delete the table file itself if not protected
+ if (!IsReadOnly()) {
+ rc = Erase(filename);
+ } else
+ rc = true;
+
+ // Delete eventual index file(s)
+ if ((pxd = To_Indx)) {
+ To_Indx = NULL; // So file can be erase
+ irc = DeleteIndexFile(g, pxd);
+ } else
+ irc = false;
+
+ return rc || orc || irc; // Return TRUE if error
+ } // end of DeleteTableFile
+
+#else // !BLK_INDX
+/***********************************************************************/
/* DeleteTableFile: Delete DOS/UNIX table files using platform API. */
/* If the table file is protected (declared as read/only) we still */
/* erase the the eventual optimize and index files but return true. */
@@ -127,6 +228,7 @@ bool DOSDEF::DeleteTableFile(PGLOBAL g)
return rc; // Return true if error
} // end of DeleteTableFile
+#endif // !BLK_INDX
/***********************************************************************/
/* Erase: This was made a separate routine because a strange thing */
@@ -147,6 +249,66 @@ bool DOSDEF::Erase(char *filename)
return rc; // Return true if error
} // end of Erase
+#endif // 0
+
+#if defined(BLK_INDX)
+/***********************************************************************/
+/* Get the full path/name of the optization file. */
+/***********************************************************************/
+bool DOSDEF::GetOptFileName(PGLOBAL g, char *filename)
+ {
+ char *ftype;
+
+ switch (Recfm) {
+ case RECFM_VAR: ftype = ".dop"; break;
+ case RECFM_FIX: ftype = ".fop"; break;
+ case RECFM_BIN: ftype = ".bop"; break;
+ case RECFM_VCT: ftype = ".vop"; break;
+ case RECFM_DBF: ftype = ".dbp"; break;
+ default:
+ sprintf(g->Message, MSG(INVALID_FTYPE), Recfm);
+ return TRUE;
+ } // endswitch Ftype
+
+ PlugSetPath(filename, Ofn, GetPath());
+ strcat(PlugRemoveType(filename, filename), ftype);
+ return FALSE;
+ } // end of GetOptFileName
+
+/***********************************************************************/
+/* After an optimize error occured, remove all set optimize values. */
+/***********************************************************************/
+void DOSDEF::RemoveOptValues(PGLOBAL g)
+ {
+ char filename[_MAX_PATH];
+ PCOLDEF cdp;
+
+ // Delete settings of optimized columns
+ for (cdp = To_Cols; cdp; cdp = cdp->GetNext())
+ if (cdp->GetOpt()) {
+ cdp->SetMin(NULL);
+ cdp->SetMax(NULL);
+ cdp->SetNdv(0);
+ cdp->SetNbm(0);
+ cdp->SetDval(NULL);
+ cdp->SetBmap(NULL);
+ } // endif Opt
+
+ // Delete block position setting for not fixed tables
+ To_Pos = NULL;
+ AllocBlks = 0;
+
+ // Delete any eventually ill formed non matching optimization file
+ if (!GetOptFileName(g, filename))
+#if defined(WIN32)
+ DeleteFile(filename);
+#else // UNIX
+ remove(filename);
+#endif // WIN32
+
+ Optimized = 0;
+ } // end of RemoveOptValues
+#endif // BLK_INDX
/***********************************************************************/
/* DeleteIndexFile: Delete DOS/UNIX index file(s) using platform API. */
@@ -222,49 +384,6 @@ bool DOSDEF::DeleteIndexFile(PGLOBAL g, PIXDEF pxdf)
} // end of DeleteIndexFile
/***********************************************************************/
-/* DefineAM: define specific AM block values from XDB file. */
-/***********************************************************************/
-bool DOSDEF::DefineAM(PGLOBAL g, LPCSTR am, int poff)
- {
- char buf[8];
- bool map = (am && (*am == 'M' || *am == 'm'));
- LPCSTR dfm = (am && (*am == 'F' || *am == 'f')) ? "F"
- : (am && (*am == 'B' || *am == 'b')) ? "B"
- : (am && !stricmp(am, "DBF")) ? "D" : "V";
-
- Desc = Fn = Cat->GetStringCatInfo(g, "Filename", NULL);
- Ofn = Cat->GetStringCatInfo(g, "Optname", Fn);
- Cat->GetCharCatInfo("Recfm", (PSZ)dfm, buf, sizeof(buf));
- Recfm = (toupper(*buf) == 'F') ? RECFM_FIX :
- (toupper(*buf) == 'B') ? RECFM_BIN :
- (toupper(*buf) == 'D') ? RECFM_DBF : RECFM_VAR;
- Lrecl = Cat->GetIntCatInfo("Lrecl", 0);
-
- if (Recfm != RECFM_DBF)
- Compressed = Cat->GetIntCatInfo("Compressed", 0);
-
- Mapped = Cat->GetBoolCatInfo("Mapped", map);
- Block = Cat->GetIntCatInfo("Blocks", 0);
- Last = Cat->GetIntCatInfo("Last", 0);
- Ending = Cat->GetIntCatInfo("Ending", CRLF);
-
- if (Recfm == RECFM_FIX || Recfm == RECFM_BIN) {
- Huge = Cat->GetBoolCatInfo("Huge", Cat->GetDefHuge());
- Padded = Cat->GetBoolCatInfo("Padded", false);
- Blksize = Cat->GetIntCatInfo("Blksize", 0);
- Eof = (Cat->GetIntCatInfo("EOF", 0) != 0);
- } else if (Recfm == RECFM_DBF) {
- Maxerr = Cat->GetIntCatInfo("Maxerr", 0);
- Accept = (Cat->GetIntCatInfo("Accept", 0) != 0);
- ReadMode = Cat->GetIntCatInfo("Readmode", 0);
- } else // (Recfm == RECFM_VAR)
- AvgLen = Cat->GetIntCatInfo("Avglen", 0);
-
- // Ignore wrong Index definitions for catalog commands
- return (Cat->GetIndexInfo(g, this) /*&& !Cat->GetCatFnc()*/);
- } // end of DefineAM
-
-/***********************************************************************/
/* InvalidateIndex: mark all indexes as invalid. */
/***********************************************************************/
bool DOSDEF::InvalidateIndex(PGLOBAL g)
@@ -311,28 +430,35 @@ PTDB DOSDEF::GetTable(PGLOBAL g, MODE mode)
txfp = new(g) BGXFAM(this);
else if (map)
txfp = new(g) MPXFAM(this);
+ else if (Compressed) {
#if defined(ZIP_SUPPORT)
- else if (Compressed)
txfp = new(g) ZIXFAM(this);
-#endif // ZIP_SUPPORT
- else
+#else // !ZIP_SUPPORT
+ sprintf(g->Message, MSG(NO_FEAT_SUPPORT), "ZIP");
+ return NULL;
+#endif // !ZIP_SUPPORT
+ } else
txfp = new(g) FIXFAM(this);
tdbp = new(g) TDBFIX(this, txfp);
} else {
-#if defined(ZIP_SUPPORT)
if (Compressed) {
+#if defined(ZIP_SUPPORT)
if (Compressed == 1)
txfp = new(g) ZIPFAM(this);
else {
+#if defined(BLK_INDX)
+ txfp = new(g) ZLBFAM(this);
+#else // !BLK_INDX
strcpy(g->Message, "Compress 2 not supported yet");
-// txfp = new(g) ZLBFAM(defp);
return NULL;
+#endif // !BLK_INDX
} // endelse
-
- } else
-#endif // ZIP_SUPPORT
- if (map)
+#else // !ZIP_SUPPORT
+ sprintf(g->Message, MSG(NO_FEAT_SUPPORT), "ZIP");
+ return NULL;
+#endif // !ZIP_SUPPORT
+ } else if (map)
txfp = new(g) MAPFAM(this);
else
txfp = new(g) DOSFAM(this);
@@ -344,6 +470,38 @@ PTDB DOSDEF::GetTable(PGLOBAL g, MODE mode)
if (Multiple)
tdbp = new(g) TDBMUL(tdbp);
+#if defined(BLK_INDX)
+ else
+ /*******************************************************************/
+ /* For block tables, get eventually saved optimization values. */
+ /*******************************************************************/
+ if (tdbp->GetBlockValues(g)) {
+ PushWarning(g, tdbp);
+// return NULL; // causes a crash when deleting index
+ } else if (Recfm == RECFM_VAR || Compressed > 1) {
+ if (IsOptimized()) {
+ if (map) {
+ txfp = new(g) MBKFAM(this);
+ } else if (Compressed) {
+#if defined(ZIP_SUPPORT)
+ if (Compressed == 1)
+ txfp = new(g) ZBKFAM(this);
+ else {
+ txfp->SetBlkPos(To_Pos);
+ ((PZLBFAM)txfp)->SetOptimized(To_Pos != NULL);
+ } // endelse
+#else
+ sprintf(g->Message, MSG(NO_FEAT_SUPPORT), "ZIP");
+ return NULL;
+#endif
+ } else
+ txfp = new(g) BLKFAM(this);
+
+ ((PTDBDOS)tdbp)->SetTxfp(txfp);
+ } // endif Optimized
+
+ } // endif Recfm
+#endif // BLK_INDX
return tdbp;
} // end of GetTable
@@ -364,6 +522,13 @@ TDBDOS::TDBDOS(PDOSDEF tdp, PTXF txfp) : TDBASE(tdp)
Ftype = tdp->Recfm;
To_Line = NULL;
Cardinal = -1;
+#if defined(BLK_INDX)
+//To_BlkIdx = NULL;
+ To_BlkFil = NULL;
+ SavFil = NULL;
+//Xeval = 0;
+ Beval = 0;
+#endif // BLK_INDX
} // end of TDBDOS standard constructor
TDBDOS::TDBDOS(PGLOBAL g, PTDBDOS tdbp) : TDBASE(tdbp)
@@ -374,6 +539,13 @@ TDBDOS::TDBDOS(PGLOBAL g, PTDBDOS tdbp) : TDBASE(tdbp)
Ftype = tdbp->Ftype;
To_Line = tdbp->To_Line;
Cardinal = tdbp->Cardinal;
+#if defined(BLK_INDX)
+//To_BlkIdx = tdbp->To_BlkIdx;
+ To_BlkFil = tdbp->To_BlkFil;
+ SavFil = tdbp->SavFil;
+//Xeval = tdbp->Xeval;
+ Beval = tdbp->Beval;
+#endif // BLK_INDX
} // end of TDBDOS copy constructor
// Method
@@ -416,14 +588,49 @@ void TDBDOS::PrintAM(FILE *f, char *m)
/***********************************************************************/
/* Remake the indexes after the table was modified. */
/***********************************************************************/
-int TDBDOS::ResetTableOpt(PGLOBAL g, bool dox)
+int TDBDOS::ResetTableOpt(PGLOBAL g, bool dop, bool dox)
{
- int rc = RC_OK;
+ int prc = RC_OK, rc = RC_OK;
MaxSize = -1; // Size must be recalculated
Cardinal = -1; // as well as Cardinality
- if (dox) {
+#if defined(BLK_INDX)
+ PTXF xp = Txfp;
+
+ To_Filter = NULL; // Disable filtering
+//To_BlkIdx = NULL; // and index filtering
+ To_BlkFil = NULL; // and block filtering
+
+ if (dop) {
+ Columns = NULL; // Not used anymore
+
+ if (Txfp->Blocked) {
+ // MakeBlockValues must be executed in non blocked mode
+ // except for ZLIB access method.
+ if (Txfp->GetAmType() == TYPE_AM_MAP) {
+ Txfp = new(g) MAPFAM((PDOSDEF)To_Def);
+#if defined(ZIP_SUPPORT)
+ } else if (Txfp->GetAmType() == TYPE_AM_ZIP) {
+ Txfp = new(g) ZIPFAM((PDOSDEF)To_Def);
+ } else if (Txfp->GetAmType() == TYPE_AM_ZLIB) {
+ Txfp->Reset();
+ ((PZLBFAM)Txfp)->SetOptimized(FALSE);
+#endif // ZIP_SUPPORT
+ } else // (Txfp->GetAmType() == TYPE_AM_BLK)
+ Txfp = new(g) DOSFAM((PDOSDEF)To_Def);
+
+ Txfp->SetTdbp(this);
+ } else
+ Txfp->Reset();
+
+ Use = USE_READY; // So the table can be reopened
+ Mode = MODE_ANY; // Just to be clean
+ rc = MakeBlockValues(g); // Redo optimization
+ } // endif dop
+#endif // BLK_INDX
+
+ if (dox && (rc == RC_OK || rc == RC_INFO)) {
// Remake eventual indexes
if (Mode != MODE_UPDATE)
To_SetCols = NULL; // Only used on Update
@@ -432,6 +639,7 @@ int TDBDOS::ResetTableOpt(PGLOBAL g, bool dox)
Txfp->Reset(); // New start
Use = USE_READY; // So the table can be reopened
Mode = MODE_READ; // New mode
+ prc = rc;
if (!(PlgGetUser(g)->Check & CHK_OPT)) {
// After the table was modified the indexes
@@ -441,11 +649,1020 @@ int TDBDOS::ResetTableOpt(PGLOBAL g, bool dox)
// ... or we should remake them.
rc = MakeIndex(g, NULL, false);
+#if defined(BLK_INDX)
+ rc = (rc == RC_INFO) ? prc : rc;
+#endif // BLK_INDX
} // endif dox
return rc;
} // end of ResetTableOpt
+#if defined(BLK_INDX)
+/***********************************************************************/
+/* Calculate the block sizes so block I/O can be used and also the */
+/* Min/Max values for clustered/sorted table columns. */
+/***********************************************************************/
+int TDBDOS::MakeBlockValues(PGLOBAL g)
+ {
+ int i, lg, nrec, rc;
+ int curnum, curblk, block, last, savndv, savnbm;
+ void *savmin, *savmax;
+ bool blocked, xdb2 = FALSE;
+//POOLHEADER save;
+ PCOLDEF cdp;
+ PDOSDEF defp = (PDOSDEF)To_Def;
+ PDOSCOL colp = NULL;
+ PDBUSER dup = PlgGetUser(g);
+ PCATLG cat = defp->GetCat();
+//void *memp = cat->GetDescp();
+
+ if ((nrec = defp->GetElemt()) < 2) {
+ strcpy(g->Message, MSG(TABLE_NOT_OPT));
+ return RC_INFO; // Not to be optimized
+ } else if (GetMaxSize(g) == 0 || !(dup->Check & CHK_OPT)) {
+ // Suppress the opt file firstly if the table is void,
+ // secondly when it was modified with OPTIMIZATION unchecked
+ // because it is no more valid.
+ defp->RemoveOptValues(g); // Erase opt file
+ return RC_OK; // void table
+ } else if (MaxSize < 0)
+ return RC_FX;
+
+ defp->SetOptimized(0);
+
+ // Estimate the number of needed blocks
+ block = (int)((MaxSize + (int)nrec - 1) / (int)nrec);
+
+ // We have to use local variables because Txfp->CurBlk is set
+ // to Rows+1 by unblocked variable length table access methods.
+ curblk = -1;
+ curnum = nrec - 1;
+ last = 0;
+ Txfp->Block = block; // This is useful mainly for
+ Txfp->CurBlk = curblk; // blocked tables (ZLBFAM), for
+ Txfp->CurNum = curnum; // others it is just to be clean.
+
+ /*********************************************************************/
+ /* Allocate the array of block starting positions. */
+ /*********************************************************************/
+//if (memp)
+// save = *(PPOOLHEADER)memp;
+
+ Txfp->BlkPos = (int*)PlugSubAlloc(g, NULL, (block + 1) * sizeof(int));
+
+ /*********************************************************************/
+ /* Allocate the blocks for clustered columns. */
+ /*********************************************************************/
+ blocked = Txfp->Blocked; // Save
+ Txfp->Blocked = TRUE; // So column block can be allocated
+
+ for (cdp = defp->GetCols(), i = 1; cdp; cdp = cdp->GetNext(), i++)
+ if (cdp->GetOpt()) {
+ lg = cdp->GetClen();
+
+ if (cdp->GetFreq() && cdp->GetFreq() <= dup->Maxbmp) {
+ cdp->SetXdb2(TRUE);
+ savndv = cdp->GetNdv();
+ cdp->SetNdv(0); // Reset Dval number of values
+ xdb2 = TRUE;
+ savmax = cdp->GetDval();
+ cdp->SetDval(PlugSubAlloc(g, NULL, cdp->GetFreq() * lg));
+ savnbm = cdp->GetNbm();
+ cdp->SetNbm(0); // Prevent Bmap allocation
+// savmin = cdp->GetBmap();
+// cdp->SetBmap(PlugSubAlloc(g, NULL, block * sizeof(int)));
+
+ if (trace)
+ htrc("Dval(%p) Bmap(%p) col(%d) %s Block=%d lg=%d\n",
+ cdp->GetDval(), cdp->GetBmap(), i, cdp->GetName(), block, lg);
+
+ // colp will be initialized with proper Dval VALBLK
+ colp = (PDOSCOL)MakeCol(g, cdp, colp, i);
+ colp->InitValue(g); // Allocate column value buffer
+ cdp->SetNbm(savnbm);
+// cdp->SetBmap(savmin); // Can be reused if the new size
+ cdp->SetDval(savmax); // is not greater than this one.
+ cdp->SetNdv(savndv);
+ } else {
+ cdp->SetXdb2(FALSE); // Maxbmp may have been reset
+ savmin = cdp->GetMin();
+ savmax = cdp->GetMax();
+ cdp->SetMin(PlugSubAlloc(g, NULL, block * lg));
+ cdp->SetMax(PlugSubAlloc(g, NULL, block * lg));
+
+ if (trace)
+ htrc("min(%p) max(%p) col(%d) %s Block=%d lg=%d\n",
+ cdp->GetMin(), cdp->GetMax(), i, cdp->GetName(), block, lg);
+
+ // colp will be initialized with proper opt VALBLK's
+ colp = (PDOSCOL)MakeCol(g, cdp, colp, i);
+ colp->InitValue(g); // Allocate column value buffer
+ cdp->SetMin(savmin); // Can be reused if the number
+ cdp->SetMax(savmax); // of blocks does not change.
+ } // endif Freq
+
+ } // endif Clustered
+
+//if (!colp)
+// return RC_INFO;
+
+ Txfp->Blocked = blocked;
+
+ /*********************************************************************/
+ /* Now do calculate the optimization values. */
+ /*********************************************************************/
+ Mode = MODE_READ;
+
+ if (OpenDB(g))
+ return RC_FX;
+
+ if (xdb2) {
+ /*********************************************************************/
+ /* Retrieve the distinct values of XDB2 columns. */
+ /*********************************************************************/
+ if (GetDistinctColumnValues(g, nrec))
+ return RC_FX;
+
+ OpenDB(g); // Rewind the table file
+ } // endif xdb2
+
+#if defined(PROG_INFO)
+ /*********************************************************************/
+ /* Initialize progress information */
+ /*********************************************************************/
+ char *p = (char *)PlugSubAlloc(g, NULL, 24 + strlen(Name));
+
+ dup->Step = strcat(strcpy(p, MSG(OPTIMIZING)), Name);
+ dup->ProgMax = GetProgMax(g);
+ dup->ProgCur = 0;
+#endif // SOCKET_MODE || THREAD
+
+ /*********************************************************************/
+ /* Make block starting pos and min/max values of cluster columns. */
+ /*********************************************************************/
+ while ((rc = ReadDB(g)) == RC_OK) {
+ if (blocked) {
+ // A blocked FAM class handles CurNum and CurBlk (ZLBFAM)
+ if (!Txfp->CurNum)
+ Txfp->BlkPos[Txfp->CurBlk] = Txfp->GetPos();
+
+ } else {
+ if (++curnum >= nrec) {
+ if (++curblk >= block) {
+ strcpy(g->Message, MSG(BAD_BLK_ESTIM));
+ goto err;
+ } else
+ curnum = 0;
+
+ // Get block starting position
+ Txfp->BlkPos[curblk] = Txfp->GetPos();
+ } // endif CurNum
+
+ last = curnum + 1; // curnum is zero based
+ Txfp->CurBlk = curblk; // Used in COLDOS::SetMinMax
+ Txfp->CurNum = curnum; // Used in COLDOS::SetMinMax
+ } // endif blocked
+
+ /*******************************************************************/
+ /* Now calculate the min and max values for the cluster columns. */
+ /*******************************************************************/
+ for (colp = (PDOSCOL)Columns; colp; colp = (PDOSCOL)colp->GetNext())
+ if (colp->Clustered == 2) {
+ if (colp->SetBitMap(g))
+ goto err;
+
+ } else
+ if (colp->SetMinMax(g))
+ goto err; // Currently: column is not sorted
+
+#if defined(SOCKET_MODE) || defined(THREAD)
+#if defined(SOCKET_MODE)
+ if (SendProgress(dup)) {
+ strcpy(g->Message, MSG(OPT_CANCELLED));
+ goto err;
+ } else
+#elif defined(THREAD)
+ if (!dup->Step) {
+ strcpy(g->Message, MSG(OPT_CANCELLED));
+ goto err;
+ } else
+#endif // THREAD
+ dup->ProgCur = GetProgCur();
+#endif // SOCKET_MODE || THREAD
+
+ } // endwhile
+
+ if (rc == RC_EF) {
+ Txfp->Nrec = nrec;
+
+ if (blocked) {
+ Txfp->Block = Txfp->CurBlk + 1;
+ Txfp->Last = (Txfp->CurNum) ? Txfp->CurNum + 1 : nrec;
+ } else {
+ Txfp->Block = curblk + 1;
+ Txfp->Last = last;
+ } // endif blocked
+
+ // This is needed to be able to calculate the last block size
+ Txfp->BlkPos[Txfp->Block] = Txfp->GetNextPos();
+ } else
+ goto err;
+
+ /*********************************************************************/
+ /* Save the optimization values for this table. */
+ /*********************************************************************/
+ if (!SaveBlockValues(g)) {
+ PCATLG cat = PlgGetCatalog(g);
+
+ defp->Block = Txfp->Block;
+ defp->Last = Txfp->Last;
+ CloseDB(g);
+ cat->SetIntCatInfo("Blocks", Txfp->Block);
+ cat->SetIntCatInfo("Last", Txfp->Last);
+ return RC_OK;
+ } // endif SaveBlockValues
+
+ err:
+ // Restore Desc memory suballocation
+//if (memp)
+// *(PPOOLHEADER)memp = save;
+
+ defp->RemoveOptValues(g);
+ CloseDB(g);
+ return RC_FX;
+ } // end of MakeBlockValues
+
+/***********************************************************************/
+/* Save the block and Min/Max values for this table. */
+/* The problem here is to avoid name duplication, because more than */
+/* one data file can have the same name (but different types) and/or */
+/* the same data file can be used with different block sizes. This is */
+/* why we use Ofn that defaults to the file name but can be set to a */
+/* different name if necessary. */
+/***********************************************************************/
+bool TDBDOS::SaveBlockValues(PGLOBAL g)
+ {
+ char filename[_MAX_PATH];
+ int lg, n[NZ + 2];
+ size_t nbk, ndv, nbm, block = Txfp->Block;
+ bool rc = FALSE;
+ FILE *opfile;
+ PDOSCOL colp;
+ PDOSDEF defp = (PDOSDEF)To_Def;
+
+ if (defp->GetOptFileName(g, filename))
+ return TRUE;
+
+ if (!(opfile = fopen(filename, "wb"))) {
+ sprintf(g->Message, MSG(OPEN_MODE_ERROR),
+ "wb", (int)errno, filename);
+ strcat(strcat(g->Message, ": "), strerror(errno));
+
+ if (trace)
+ htrc("%s\n", g->Message);
+
+ return TRUE;
+ } // endif opfile
+
+ if (Ftype == RECFM_VAR || defp->Compressed == 2) {
+ /*******************************************************************/
+ /* Write block starting positions into the opt file. */
+ /*******************************************************************/
+ block++;
+ lg = sizeof(int);
+ n[0] = Txfp->Last; n[1] = lg; n[2] = Txfp->Nrec; n[3] = Txfp->Block;
+
+ if (fwrite(n, sizeof(int), NZ, opfile) != NZ) {
+ sprintf(g->Message, MSG(OPT_HEAD_WR_ERR), strerror(errno));
+ rc = TRUE;
+ } // endif size
+
+ if (fwrite(Txfp->BlkPos, lg, block, opfile) != block) {
+ sprintf(g->Message, MSG(OPTBLK_WR_ERR), strerror(errno));
+ rc = TRUE;
+ } // endif size
+
+ block--; // = Txfp->Block;
+ } // endif Ftype
+
+ /*********************************************************************/
+ /* Write the Min/Max values into the opt file. */
+ /*********************************************************************/
+ for (colp = (PDOSCOL)Columns; colp; colp = (PDOSCOL)colp->Next) {
+ lg = colp->Value->GetClen();
+
+ // Now start the writing process
+ if (colp->Clustered == 2) {
+ // New XDB2 block optimization. Will be recognized when reading
+ // because the column index is negated.
+ ndv = colp->Ndv; nbm = colp->Nbm;
+ nbk = nbm * block;
+ n[0] = -colp->Index; n[1] = lg; n[2] = Txfp->Nrec; n[3] = block;
+ n[4] = ndv; n[5] = nbm;
+
+ if (fwrite(n, sizeof(int), NZ + 2, opfile) != NZ + 2) {
+ sprintf(g->Message, MSG(OPT_HEAD_WR_ERR), strerror(errno));
+ rc = TRUE;
+ } // endif size
+
+ if (fwrite(colp->Dval->GetValPointer(), lg, ndv, opfile) != ndv) {
+ sprintf(g->Message, MSG(OPT_DVAL_WR_ERR), strerror(errno));
+ rc = TRUE;
+ } // endif size
+
+ if (fwrite(colp->Bmap->GetValPointer(), sizeof(int), nbk, opfile) != nbk) {
+ sprintf(g->Message, MSG(OPT_BMAP_WR_ERR), strerror(errno));
+ rc = TRUE;
+ } // endif size
+
+ } else {
+ n[0] = colp->Index; n[1] = lg; n[2] = Txfp->Nrec; n[3] = block;
+
+ if (fwrite(n, sizeof(int), NZ, opfile) != NZ) {
+ sprintf(g->Message, MSG(OPT_HEAD_WR_ERR), strerror(errno));
+ rc = TRUE;
+ } // endif size
+
+ if (fwrite(colp->Min->GetValPointer(), lg, block, opfile) != block) {
+ sprintf(g->Message, MSG(OPT_MIN_WR_ERR), strerror(errno));
+ rc = TRUE;
+ } // endif size
+
+ if (fwrite(colp->Max->GetValPointer(), lg, block, opfile) != block) {
+ sprintf(g->Message, MSG(OPT_MAX_WR_ERR), strerror(errno));
+ rc = TRUE;
+ } // endif size
+
+ } // endif Clustered
+
+ } // endfor colp
+
+ fclose(opfile);
+ return rc;
+ } // end of SaveBlockValues
+
+/***********************************************************************/
+/* Read the Min/Max values for this table. */
+/* The problem here is to avoid name duplication, because more than */
+/* one data file can have the same name (but different types) and/or */
+/* the same data file can be used with different block sizes. This is */
+/* why we use Ofn that defaults to the file name but can be set to a */
+/* different name if necessary. */
+/***********************************************************************/
+bool TDBDOS::GetBlockValues(PGLOBAL g)
+ {
+ char filename[_MAX_PATH];
+ int i, lg, n[NZ];
+ int nrec, block, last = 0, allocblk = 0;
+ int len;
+ bool newblk = FALSE;
+ size_t ndv, nbm, nbk, blk;
+ FILE *opfile;
+ PCOLDEF cdp;
+ PDOSDEF defp = (PDOSDEF)To_Def;
+ PCATLG cat = defp->GetCat();
+
+ if (defp->Optimized)
+ return FALSE; // Already done or to be redone
+
+ if (Ftype == RECFM_VAR || defp->Compressed == 2) {
+ /*******************************************************************/
+ /* Variable length file that can be read by block. */
+ /*******************************************************************/
+ block = defp->GetBlock();
+ nrec = (defp->GetElemt()) ? defp->GetElemt() : 1;
+ last = defp->GetLast();
+
+ if (nrec > 1 && block)
+ len = (int)((block - 1) * nrec + last);
+ else
+ len = 0;
+
+ if (!len) {
+ if (nrec > 1) {
+ // The table can be declared optimized if it is void.
+ // This is useful to handle Insert in optimized mode.
+ char filename[_MAX_PATH];
+ int h;
+ int flen = -1;
+
+ PlugSetPath(filename, defp->Fn, GetPath());
+ h = open(filename, _O_RDONLY);
+ flen = (h == -1 && errno == ENOENT) ? 0 : _filelength(h);
+ defp->SetOptimized((flen) ? 0 : 1);
+
+ if (h != -1)
+ close(h);
+
+ } // endif nrec
+
+ return FALSE; // Opt file does not exist yet
+ } else if (len < 0)
+ return TRUE; // Table error
+
+ cdp = defp->GetCols();
+ i = 1;
+ } else {
+ /*******************************************************************/
+ /* Fixed length file. Opt file exists only for clustered columns. */
+ /*******************************************************************/
+ // Check for existence of clustered columns
+ for (cdp = defp->GetCols(), i = 1; cdp; cdp = cdp->GetNext(), i++)
+ if (cdp->GetOpt())
+ break;
+
+ if (!cdp)
+ return FALSE; // No optimization needed
+
+ if ((len = Cardinality(g)) < 0)
+ return TRUE; // Table error
+ else if (!len)
+ return FALSE; // File does not exist yet
+
+ block = Txfp->Block; // Was set in Cardinality
+ nrec = Txfp->Nrec;
+ } // endif Ftype
+
+ if (defp->GetOptFileName(g, filename))
+ return TRUE;
+
+ if (!(opfile = fopen(filename, "rb")))
+ return FALSE; // No saved values
+
+//if (memp) {
+// save = *(PPOOLHEADER)memp;
+// allocblk = defp->GetAllocBlks();
+// } // endif memp
+
+ if (block > allocblk)
+ newblk = TRUE; // Current allocation is too small
+
+ if (Ftype == RECFM_VAR || defp->Compressed == 2) {
+ /*******************************************************************/
+ /* Read block starting positions from the opt file. */
+ /*******************************************************************/
+ blk = block + 1;
+ lg = sizeof(int);
+
+ if (fread(n, sizeof(int), NZ, opfile) != NZ) {
+ sprintf(g->Message, MSG(OPT_HEAD_RD_ERR), strerror(errno));
+ goto err;
+ } // endif size
+
+ if (n[0] != last || n[1] != lg || n[2] != nrec || n[3] != block) {
+ sprintf(g->Message, MSG(OPT_NOT_MATCH), filename);
+ goto err;
+ } // endif
+
+ if (newblk)
+ defp->To_Pos = (int*)PlugSubAlloc(g, NULL, blk * lg);
+
+ if (fread(defp->To_Pos, lg, blk, opfile) != blk) {
+ sprintf(g->Message, MSG(OPTBLK_RD_ERR), strerror(errno));
+ goto err;
+ } // endif size
+
+ } // endif Ftype
+
+ /*********************************************************************/
+ /* Read the Min/Max values from the opt file. */
+ /*********************************************************************/
+ for (; cdp; cdp = cdp->GetNext(), i++)
+ if (cdp->GetOpt()) {
+ lg = cdp->GetClen();
+ blk = block;
+
+ // Now start the reading process.
+ if (fread(n, sizeof(int), NZ, opfile) != NZ) {
+ sprintf(g->Message, MSG(OPT_HEAD_RD_ERR), strerror(errno));
+ goto err;
+ } // endif size
+
+ if (n[0] == -i) {
+ // Read the XDB2 opt values from the opt file
+ if (n[1] != lg || n[2] != nrec || n[3] != block) {
+ sprintf(g->Message, MSG(OPT_NOT_MATCH), filename);
+ goto err;
+ } // endif
+
+ if (fread(n, sizeof(int), 2, opfile) != 2) {
+ sprintf(g->Message, MSG(OPT_HEAD_RD_ERR), strerror(errno));
+ goto err;
+ } // endif fread
+
+ ndv = n[0]; nbm = n[1]; nbk = nbm * blk;
+
+ if (cdp->GetNdv() < (int)ndv || !cdp->GetDval())
+ cdp->SetDval(PlugSubAlloc(g, NULL, ndv * lg));
+
+ cdp->SetNdv((int)ndv);
+
+ if (fread(cdp->GetDval(), lg, ndv, opfile) != ndv) {
+ sprintf(g->Message, MSG(OPT_DVAL_RD_ERR), strerror(errno));
+ goto err;
+ } // endif size
+
+ if (newblk || cdp->GetNbm() < (int)nbm || !cdp->GetBmap())
+ cdp->SetBmap(PlugSubAlloc(g, NULL, nbk * sizeof(int)));
+
+ cdp->SetNbm((int)nbm);
+
+ if (fread(cdp->GetBmap(), sizeof(int), nbk, opfile) != nbk) {
+ sprintf(g->Message, MSG(OPT_BMAP_RD_ERR), strerror(errno));
+ goto err;
+ } // endif size
+
+ cdp->SetXdb2(TRUE);
+ } else {
+ // Read the Min/Max values from the opt file
+ if (n[0] != i || n[1] != lg || n[2] != nrec || n[3] != block) {
+ sprintf(g->Message, MSG(OPT_NOT_MATCH), filename);
+ goto err;
+ } // endif
+
+ if (newblk || !cdp->GetMin())
+ cdp->SetMin(PlugSubAlloc(g, NULL, blk * lg));
+
+ if (fread(cdp->GetMin(), lg, blk, opfile) != blk) {
+ sprintf(g->Message, MSG(OPT_MIN_RD_ERR), strerror(errno));
+ goto err;
+ } // endif size
+
+ if (newblk || !cdp->GetMax())
+ cdp->SetMax(PlugSubAlloc(g, NULL, blk * lg));
+
+ if (fread(cdp->GetMax(), lg, blk, opfile) != blk) {
+ sprintf(g->Message, MSG(OPT_MAX_RD_ERR), strerror(errno));
+ goto err;
+ } // endif size
+
+ cdp->SetXdb2(FALSE);
+ } // endif n[0] (XDB2)
+
+ } // endif Clustered
+
+ defp->SetBlock(block);
+
+ if (newblk)
+ defp->SetAllocBlks(block);
+
+ defp->SetOptimized(1);
+ fclose(opfile);
+ MaxSize = -1; // Can be refined later
+ return FALSE;
+
+ err:
+ defp->RemoveOptValues(g);
+ fclose(opfile);
+//return TRUE;
+ // Ignore error if not in mode CHK_OPT
+ return (PlgGetUser(g)->Check & CHK_OPT) != 0;
+ } // end of GetBlockValues
+
+/***********************************************************************/
+/* This fonction is used while making XDB2 block optimization. */
+/* It constructs for each elligible columns, the sorted list of the */
+/* distinct values existing in the column. This function uses an */
+/* algorithm that permit to get several sets of distinct values by */
+/* reading the table only once, which cannot be done using a standard */
+/* SQL query. */
+/***********************************************************************/
+bool TDBDOS::GetDistinctColumnValues(PGLOBAL g, int nrec)
+ {
+ char *p;
+ int rc, blk, n = 0;
+ PDOSCOL colp;
+ PDBUSER dup = PlgGetUser(g);
+
+ /*********************************************************************/
+ /* Initialize progress information */
+ /*********************************************************************/
+ p = (char *)PlugSubAlloc(g, NULL, 48 + strlen(Name));
+ dup->Step = strcat(strcpy(p, MSG(GET_DIST_VALS)), Name);
+ dup->ProgMax = GetProgMax(g);
+ dup->ProgCur = 0;
+
+ while ((rc = ReadDB(g)) == RC_OK) {
+ for (colp = (PDOSCOL)Columns; colp; colp = (PDOSCOL)colp->Next)
+ if (colp->Clustered == 2)
+ if (colp->AddDistinctValue(g))
+ return TRUE; // Too many distinct values
+
+#if defined(SOCKET_MODE)
+ if (SendProgress(dup)) {
+ strcpy(g->Message, MSG(OPT_CANCELLED));
+ return TRUE;
+ } else
+#elif defined(THREAD)
+ if (!dup->Step) {
+ strcpy(g->Message, MSG(OPT_CANCELLED));
+ return TRUE;
+ } else
+#endif // THREAD
+ dup->ProgCur = GetProgCur();
+
+ n++;
+ } // endwhile
+
+ if (rc != RC_EF)
+ return TRUE;
+
+ // Reset the number of table blocks
+//nrec = ((PDOSDEF)To_Def)->GetElemt(); (or default value)
+ blk = (n + nrec - 1) / nrec;
+ Txfp->Block = blk; // Useful mainly for ZLBFAM ???
+
+ // Set Nbm, Bmap for XDB2 columns
+ for (colp = (PDOSCOL)Columns; colp; colp = (PDOSCOL)colp->Next)
+ if (colp->Clustered == 2) {
+// colp->Cdp->SetNdv(colp->Ndv);
+ colp->Nbm = (colp->Ndv + MAXBMP - 1) / MAXBMP;
+ colp->Bmap = AllocValBlock(g, NULL, TYPE_INT, colp->Nbm * blk);
+ } // endif Clustered
+
+ return FALSE;
+ } // end of GetDistinctColumnValues
+
+/***********************************************************************/
+/* Analyze the filter and construct the Block Evaluation Filter. */
+/* This is possible when a filter contains predicates implying a */
+/* column marked as "clustered" or "sorted" matched to a constant */
+/* argument. It is then possible by comparison against the smallest */
+/* and largest column values in each block to determine whether the */
+/* filter condition will be always true or always false for the block.*/
+/***********************************************************************/
+PBF TDBDOS::InitBlockFilter(PGLOBAL g, PFIL filp)
+ {
+ bool blk = Txfp->Blocked;
+
+ if (To_BlkFil)
+ return To_BlkFil; // Already done
+ else if (!filp)
+ return NULL;
+ else if (blk) {
+ if (Txfp->GetAmType() == TYPE_AM_DBF)
+ /*****************************************************************/
+ /* If RowID is used in this query, block optimization cannot be */
+ /* used because currently the file must be read sequentially. */
+ /*****************************************************************/
+ for (PCOL cp = Columns; cp; cp = cp->GetNext())
+ if (cp->GetAmType() == TYPE_AM_ROWID && !((RIDBLK*)cp)->GetRnm())
+ return NULL;
+
+ } // endif blk
+
+ int i, op = filp->GetOpc(), opm = filp->GetOpm(), n = 0;
+ bool cnv[2];
+ PCOL colp;
+ PXOB arg[2] = {NULL,NULL};
+ PBF *fp = NULL, bfp = NULL;
+
+ switch (op) {
+ case OP_EQ:
+ case OP_NE:
+ case OP_GT:
+ case OP_GE:
+ case OP_LT:
+ case OP_LE:
+ if (! opm) {
+ for (i = 0; i < 2; i++) {
+ arg[i] = filp->Arg(i);
+ cnv[i] = filp->Conv(i);
+ } // endfor i
+
+ bfp = CheckBlockFilari(g, arg, op, cnv);
+ break;
+ } // endif !opm
+
+ // if opm, pass thru
+ case OP_IN:
+ if (filp->GetArgType(0) == TYPE_COLBLK &&
+ filp->GetArgType(1) == TYPE_ARRAY) {
+ arg[0] = filp->Arg(0);
+ arg[1] = filp->Arg(1);
+ colp = (PCOL)arg[0];
+
+ if (colp->GetTo_Tdb() == this) {
+ // Block evaluation is possible for...
+ if (colp->GetAmType() == TYPE_AM_ROWID) {
+ // Special column ROWID and constant array, but
+ // currently we don't know how to retrieve a RowID
+ // from a DBF table that is not sequentially read.
+// if (Txfp->GetAmType() != TYPE_AM_DBF ||
+// ((RIDBLK*)arg[0])->GetRnm())
+ bfp = new(g) BLKSPCIN(g, this, op, opm, arg, Txfp->Nrec);
+
+ } else if (blk && Txfp->Nrec > 1 && colp->IsClustered())
+ // Clustered column and constant array
+ if (colp->GetClustered() == 2)
+ bfp = new(g) BLKFILIN2(g, this, op, opm, arg);
+ else
+ bfp = new(g) BLKFILIN(g, this, op, opm, arg);
+
+ } // endif this
+
+#if 0
+ } else if (filp->GetArgType(0) == TYPE_SCALF &&
+ filp->GetArgType(1) == TYPE_ARRAY) {
+ arg[0] = filp->Arg(0);
+ arg[1] = filp->Arg(1);
+
+ if (((PSCALF)arg[0])->GetOp() == OP_ROW &&
+ arg[1]->GetResultType() == TYPE_LIST) {
+ PARRAY par = (PARRAY)arg[1];
+ LSTVAL *vlp = (LSTVAL*)par->GetValue();
+
+ ((SFROW*)arg[0])->GetParms(n);
+
+ if (n != vlp->GetN())
+ return NULL;
+ else
+ n = par->GetNval();
+
+ arg[1] = new(g) CONSTANT(vlp);
+ fp = (PBF*)PlugSubAlloc(g, NULL, n * sizeof(PBF));
+ cnv[0] = cnv[1] = FALSE;
+
+ if (op == OP_IN)
+ op = OP_EQ;
+
+ for (i = 0; i < n; i++) {
+ par->GetNthValue(vlp, i);
+
+ if (!(fp[i] = CheckBlockFilari(g, arg, op, cnv)))
+ return NULL;
+
+ } // endfor i
+
+ bfp = new(g) BLKFILLOG(this, (opm == 2 ? OP_AND : OP_OR), fp, n);
+ } // endif ROW
+#endif // 0
+
+ } // endif Type
+
+ break;
+ case OP_AND:
+ case OP_OR:
+ fp = (PBF*)PlugSubAlloc(g, NULL, 2 * sizeof(PBF));
+ fp[0] = InitBlockFilter(g, (PFIL)(filp->Arg(0)));
+ fp[1] = InitBlockFilter(g, (PFIL)(filp->Arg(1)));
+
+ if (fp[0] || fp[1])
+ bfp = new(g) BLKFILLOG(this, op, fp, 2);
+
+ break;
+ case OP_NOT:
+ fp = (PBF*)PlugSubAlloc(g, NULL, sizeof(PBF));
+
+ if ((*fp = InitBlockFilter(g, (PFIL)(filp->Arg(0)))))
+ bfp = new(g) BLKFILLOG(this, op, fp, 1);
+
+ break;
+ case OP_LIKE:
+ default:
+ break;
+ } // endswitch op
+
+ return bfp;
+ } // end of InitBlockFilter
+
+/***********************************************************************/
+/* Analyze the passed arguments and construct the Block Filter. */
+/***********************************************************************/
+PBF TDBDOS::CheckBlockFilari(PGLOBAL g, PXOB *arg, int op, bool *cnv)
+ {
+//int i, n1, n2, ctype = TYPE_ERROR, n = 0, type[2] = {0,0};
+//bool conv = FALSE, xdb2 = FALSE, ok = FALSE, b[2];
+//PXOB *xarg1, *xarg2 = NULL, xp[2];
+ int i, ctype = TYPE_ERROR, n = 0, type[2] = {0,0};
+ bool conv = FALSE, xdb2 = FALSE, ok = FALSE;
+ PXOB *xarg2 = NULL, xp[2];
+ PCOL colp;
+//LSTVAL *vlp = NULL;
+//SFROW *sfr[2];
+ PBF *fp = NULL, bfp = NULL;
+
+ for (i = 0; i < 2; i++) {
+ switch (arg[i]->GetType()) {
+ case TYPE_CONST:
+ type[i] = 1;
+ ctype = arg[i]->GetResultType();
+ break;
+ case TYPE_COLBLK:
+ conv = cnv[i];
+ colp = (PCOL)arg[i];
+
+ if (colp->GetTo_Tdb() == this) {
+ if (colp->GetAmType() == TYPE_AM_ROWID) {
+ // Currently we don't know how to retrieve a RowID
+ // from a DBF table that is not sequentially read.
+// if (Txfp->GetAmType() != TYPE_AM_DBF ||
+// ((RIDBLK*)arg[i])->GetRnm())
+ type[i] = 5;
+
+ } else if (Txfp->Blocked && Txfp->Nrec > 1 &&
+ colp->IsClustered()) {
+ type[i] = 2;
+ xdb2 = colp->GetClustered() == 2;
+ } // endif Clustered
+
+ } else if (colp->GetColUse(U_CORREL)) {
+ // This is a column pointing to the outer query of a
+ // correlated subquery, it has a constant value during
+ // each execution of the subquery.
+ type[i] = 1;
+ ctype = arg[i]->GetResultType();
+ } // endif this
+
+ break;
+// case TYPE_SCALF:
+// if (((PSCALF)arg[i])->GetOp() == OP_ROW) {
+// sfr[i] = (SFROW*)arg[i];
+// type[i] = 7;
+// } // endif Op
+
+// break;
+ default:
+ break;
+ } // endswitch ArgType
+
+ if (!type[i])
+ break;
+
+ n += type[i];
+ } // endfor i
+
+ if (n == 3 || n == 6) {
+ if (conv) {
+ // The constant has not the good type and will not match
+ // the block min/max values. What we can do here is either
+ // abort with an error message or simply not do the block
+ // optimization (as column values can be converted when
+ // evaluating the filter.) Currently we prefer aborting
+ // because the user may count on the performance enhancing
+ // and silently not doing it is probably worse than just
+ // telling him to fix his query.
+ sprintf(g->Message, "Block opt: %s", MSG(VALTYPE_NOMATCH));
+ longjmp(g->jumper[g->jump_level], 99);
+ } // endif Conv
+
+ if (type[0] == 1) {
+ // Make it always as Column-op-Value
+ *xp = arg[0];
+ arg[0] = arg[1];
+ arg[1] = *xp;
+
+ switch (op) {
+ case OP_GT: op = OP_LT; break;
+ case OP_GE: op = OP_LE; break;
+ case OP_LT: op = OP_GT; break;
+ case OP_LE: op = OP_GE; break;
+ } // endswitch op
+
+ } // endif
+
+#if defined(_DEBUG)
+// assert(arg[0]->GetResultType() == ctype);
+#endif
+
+ if (n == 3) {
+ if (xdb2) {
+ if (((PDOSCOL)arg[0])->GetNbm() == 1)
+ bfp = new(g) BLKFILAR2(g, this, op, arg);
+ else // Multiple bitmap made of several ULONG's
+ bfp = new(g) BLKFILMR2(g, this, op, arg);
+ } else
+ bfp = new(g) BLKFILARI(g, this, op, arg);
+
+ } else // n = 6
+ bfp = new(g) BLKSPCARI(this, op, arg, Txfp->Nrec);
+
+#if 0
+ } else if (n == 8 || n == 14) {
+ if (n == 8 && ctype != TYPE_LIST) {
+ // Should never happen
+ strcpy(g->Message, "Block opt: bad constant");
+ longjmp(g->jumper[g->jump_level], 99);
+ } // endif Conv
+
+ if (type[0] == 1) {
+ // Make it always as Column-op-Value
+ sfr[0] = sfr[1];
+ arg[1] = arg[0];
+
+ switch (op) {
+ case OP_GT: op = OP_LT; break;
+ case OP_GE: op = OP_LE; break;
+ case OP_LT: op = OP_GT; break;
+ case OP_LE: op = OP_GE; break;
+ } // endswitch op
+
+ } // endif
+
+ xarg1 = sfr[0]->GetParms(n1);
+
+ if (n == 8) {
+ vlp = (LSTVAL*)arg[1]->GetValue();
+ n2 = vlp->GetN();
+ xp[1] = new(g) CONSTANT((PVAL)NULL);
+ } else
+ xarg2 = sfr[1]->GetParms(n2);
+
+ if (n1 != n2)
+ return NULL; // Should we flag an error ?
+
+ fp = (PBF*)PlugSubAlloc(g, NULL, n1 * sizeof(PBF));
+
+ for (i = 0; i < n1; i++) {
+ xp[0] = xarg1[i];
+
+ if (n == 8)
+ ((CONSTANT*)xp[1])->SetValue(vlp->GetSubVal(i));
+ else
+ xp[1] = xarg2[i];
+
+ b[0] = b[1] = (xp[0]->GetResultType() != xp[1]->GetResultType());
+ ok |= ((fp[i] = CheckBlockFilari(g, xp, op, b)) != NULL);
+ } // endfor i
+
+ if (ok)
+ bfp = new(g) BLKFILLOG(this, OP_AND, fp, n1);
+#endif // 0
+
+ } // endif n
+
+ return bfp;
+ } // end of CheckBlockFilari
+
+/***********************************************************************/
+/* ResetBlkFil: reset the block filter and restore filtering. */
+/***********************************************************************/
+void TDBDOS::ResetBlockFilter(PGLOBAL g)
+ {
+ if (!To_BlkFil)
+ return;
+
+ To_BlkFil->Reset(g);
+
+ if (SavFil && !To_Filter) {
+ // Restore filter if it was disabled by optimization
+ To_Filter = SavFil;
+ SavFil = NULL;
+ } // endif
+
+ Beval = 0;
+ } // end of ResetBlockFilter
+
+/***********************************************************************/
+/* Block optimization: evaluate the block index filter against */
+/* the min and max values of this block and return: */
+/* RC_OK: if some records in the block can meet filter criteria. */
+/* RC_NF: if no record in the block can meet filter criteria. */
+/* RC_EF: if no record in the remaining file can meet filter criteria.*/
+/* In addition, temporarily supress filtering if all the records in */
+/* the block meet filter criteria. */
+/***********************************************************************/
+int TDBDOS::TestBlock(PGLOBAL g)
+ {
+ int rc = RC_OK;
+
+ if (To_BlkFil && Beval != 2) {
+ // Check for block filtering evaluation
+ if (Beval == 1) {
+ // Filter was removed for last block, restore it
+ To_Filter = SavFil;
+ SavFil = NULL;
+ } // endif Beval
+
+ // Check for valid records in new block
+ switch (Beval = To_BlkFil->BlockEval(g)) {
+ case -2: // No more valid values in file
+ rc = RC_EF;
+ break;
+ case -1: // No valid values in block
+ rc = RC_NF;
+ break;
+ case 1: // All block values are valid
+ case 2: // All subsequent file values are Ok
+ // Before suppressing the filter for the block(s) it is
+ // necessary to reset the filtered columns to NOT_READ
+ // so their new values are retrieved by the SELECT list.
+ if (To_Filter) // Can be NULL when externally called (XDB)
+ To_Filter->Reset();
+
+ SavFil = To_Filter;
+ To_Filter = NULL; // So remove filter
+ } // endswitch Beval
+
+ if (trace)
+ htrc("BF Eval Beval=%d\n", Beval);
+
+ } // endif To_BlkFil
+
+ return rc;
+ } // end of TestBlock
+#endif // BLK_INDX
+
/***********************************************************************/
/* Check whether we have to create/update permanent indexes. */
/***********************************************************************/
@@ -730,11 +1947,21 @@ bool TDBDOS::OpenDB(PGLOBAL g)
/*******************************************************************/
/* Table already open, just replace it at its beginning. */
/*******************************************************************/
- Txfp->Rewind(); // see comment in Work.log
+ if (!To_Kindex) {
+ Txfp->Rewind(); // see comment in Work.log
- if (SkipHeader(g))
- return true;
+ if (SkipHeader(g))
+ return TRUE;
+
+ } else
+ /*****************************************************************/
+ /* Table is to be accessed through a sorted index table. */
+ /*****************************************************************/
+ To_Kindex->Reset();
+#if defined(BLK_INDX)
+ ResetBlockFilter(g);
+#endif // BLK_INDX
return false;
} // endif use
@@ -770,6 +1997,13 @@ bool TDBDOS::OpenDB(PGLOBAL g)
Use = USE_OPEN; // Do it now in case we are recursively called
+#if defined(BLK_INDX)
+ /*********************************************************************/
+ /* Allocate the block filter tree if evaluation is possible. */
+ /*********************************************************************/
+ To_BlkFil = InitBlockFilter(g, To_Filter);
+#endif // BLK_INDX
+
/*********************************************************************/
/* Allocate the line buffer plus a null character. */
/*********************************************************************/
@@ -928,6 +2162,42 @@ DOSCOL::DOSCOL(PGLOBAL g, PCOLDEF cdp, PTDB tp, PCOL cp, int i, PSZ am)
Long = cdp->GetLong();
To_Val = NULL;
+#if defined(BLK_INDX)
+ Clustered = 0;
+ Sorted = 0;
+ Ndv = 0; // Currently used only for XDB2
+ Nbm = 0; // Currently used only for XDB2
+ Min = NULL;
+ Max = NULL;
+ Bmap = NULL;
+ Dval = NULL;
+ Buf = NULL;
+
+ if (txfp->Blocked && Opt && (cdp->GetMin() || cdp->GetDval())) {
+ int nblk = txfp->GetBlock();
+
+ Clustered = (cdp->GetXdb2()) ? 2 : 1;
+ Sorted = (cdp->GetOpt() > 1) ? 1 : 0; // Currently ascending only
+
+ if (Clustered == 1) {
+ Min = AllocValBlock(g, cdp->GetMin(), Buf_Type, nblk, Long, prec);
+ Max = AllocValBlock(g, cdp->GetMax(), Buf_Type, nblk, Long, prec);
+ } else { // Clustered == 2
+ // Ndv is the number of distinct values in Dval. Ndv and Nbm
+ // may be 0 when optimizing because Ndval is not filled yet,
+ // but the size of the passed Dval memory block is Ok.
+ Ndv = cdp->GetNdv();
+ Dval = AllocValBlock(g, cdp->GetDval(), Buf_Type, Ndv, Long, prec);
+
+ // Bmap cannot be allocated when optimizing, we must know Nbm first
+ if ((Nbm = cdp->GetNbm()))
+ Bmap = AllocValBlock(g, cdp->GetBmap(), TYPE_INT, Nbm * nblk);
+
+ } // endif Clustered
+
+ } // endif Opt
+#endif // BLK_INDX
+
OldVal = NULL; // Currently used only in MinMax
Ldz = false;
Nod = false;
@@ -969,8 +2239,19 @@ DOSCOL::DOSCOL(DOSCOL *col1, PTDB tdbp) : COLBLK(col1, tdbp)
Dcm = col1->Dcm;
OldVal = col1->OldVal;
Buf = col1->Buf;
+#if defined(BLK_INDX)
+ Clustered = col1->Clustered;
+ Sorted = col1->Sorted;
+ Min = col1->Min;
+ Max = col1->Max;
+ Bmap = col1->Bmap;
+ Dval = col1->Dval;
+ Ndv = col1->Ndv;
+ Nbm = col1->Nbm;
+#endif // BLK_INDX
} // end of DOSCOL copy constructor
+#if defined(BLK_INDX)
/***********************************************************************/
/* VarSize: This function tells UpdateDB whether or not the block */
/* optimization file must be redone if this column is updated, even */
@@ -992,6 +2273,7 @@ bool DOSCOL::VarSize(void)
return false;
} // end VarSize
+#endif // BLK_INDX
/***********************************************************************/
/* SetBuffer: prepare a column block for write operation. */
@@ -1151,6 +2433,13 @@ void DOSCOL::WriteColumn(PGLOBAL g)
htrc("Lrecl=%d deplac=%d int=%d\n", tdbp->Lrecl, Deplac, Long);
field = Long;
+ len = (signed)strlen(tdbp->To_Line);
+
+ if (tdbp->GetAmType() == TYPE_AM_DOS && len > tdbp->Lrecl) {
+ sprintf(g->Message, "Line size %d is bigger than lrecl %d",
+ len, tdbp->Lrecl);
+ longjmp(g->jumper[g->jump_level], 32);
+ } // endif
if (tdbp->Ftype == RECFM_VAR && tdbp->Mode == MODE_UPDATE) {
len = (signed)strlen(tdbp->To_Line);
@@ -1269,6 +2558,146 @@ void DOSCOL::WriteColumn(PGLOBAL g)
} // end of WriteColumn
+#if defined(BLK_INDX)
+/***********************************************************************/
+/* SetMinMax: Calculate minimum and maximum values for one block. */
+/* Note: TYPE_STRING is stored and processed with zero ended strings */
+/* to be matching the way the FILTER Eval function processes them. */
+/***********************************************************************/
+bool DOSCOL::SetMinMax(PGLOBAL g)
+ {
+ PTDBDOS tp = (PTDBDOS)To_Tdb;
+
+ ReadColumn(g); // Extract column value from current line
+
+ if (CheckSorted(g))
+ return TRUE;
+
+ if (!tp->Txfp->CurNum) {
+ Min->SetValue(Value, tp->Txfp->CurBlk);
+ Max->SetValue(Value, tp->Txfp->CurBlk);
+ } else {
+ Min->SetMin(Value, tp->Txfp->CurBlk);
+ Max->SetMax(Value, tp->Txfp->CurBlk);
+ } // endif CurNum
+
+ return FALSE;
+ } // end of SetMinMax
+
+/***********************************************************************/
+/* SetBitMap: Calculate the bit map of existing values in one block. */
+/* Note: TYPE_STRING is processed with zero ended strings */
+/* to be matching the way the FILTER Eval function processes them. */
+/***********************************************************************/
+bool DOSCOL::SetBitMap(PGLOBAL g)
+ {
+ int i, m, n;
+ PULONG bmp;
+ PTDBDOS tp = (PTDBDOS)To_Tdb;
+ PDBUSER dup = PlgGetUser(g);
+
+ n = tp->Txfp->CurNum;
+ bmp = (PULONG)Bmap->GetValPtr(Nbm * tp->Txfp->CurBlk);
+
+ // Extract column value from current line
+ ReadColumn(g);
+
+ if (CheckSorted(g))
+ return TRUE;
+
+ if (!n) // New block
+ for (m = 0; m < Nbm; m++)
+ bmp[m] = 0; // Reset the new bit map
+
+ if ((i = Dval->Find(Value)) < 0) {
+ char buf[32];
+
+ sprintf(g->Message, MSG(DVAL_NOTIN_LIST),
+ Value->GetCharString(buf), Name);
+ return TRUE;
+ } else if (i >= dup->Maxbmp) {
+ sprintf(g->Message, MSG(OPT_LOGIC_ERR), i);
+ return TRUE;
+ } else {
+ m = i / MAXBMP;
+#if defined(_DEBUG)
+ assert (m < Nbm);
+#endif // _DEBUG
+ bmp[m] |= (1 << (i % MAXBMP));
+ } // endif's i
+
+ return FALSE;
+ } // end of SetBitMap
+
+/***********************************************************************/
+/* Checks whether a column declared as sorted is sorted indeed. */
+/***********************************************************************/
+bool DOSCOL::CheckSorted(PGLOBAL g)
+ {
+ if (Sorted)
+ if (OldVal) {
+ // Verify whether this column is sorted all right
+ if (OldVal->CompareValue(Value) > 0) {
+ // Column is no more in ascending order
+ sprintf(g->Message, MSG(COL_NOT_SORTED), Name, To_Tdb->GetName());
+ Sorted = FALSE;
+ return TRUE;
+ } else
+ OldVal->SetValue_pval(Value);
+
+ } else
+ OldVal = AllocateValue(g, Value);
+
+ return FALSE;
+ } // end of CheckSorted
+
+/***********************************************************************/
+/* AddDistinctValue: Check whether this value already exist in the */
+/* list and if not add it to the distinct values list. */
+/***********************************************************************/
+bool DOSCOL::AddDistinctValue(PGLOBAL g)
+ {
+ bool found = FALSE;
+ int i, m, n;
+
+ ReadColumn(g); // Extract column value from current line
+
+ // Perhaps a better algorithm can be used when Ndv gets bigger
+ // Here we cannot use Find because we must get the index of where
+ // to insert a new value if it is not found in the array.
+ for (n = 0; n < Ndv; n++) {
+ m = Dval->CompVal(Value, n);
+
+ if (m > 0)
+ continue;
+ else if (!m)
+ found = TRUE; // Already there
+
+ break;
+ } // endfor n
+
+ if (!found) {
+ // Check whether we have room for an additional value
+ if (Ndv == Freq) {
+ // Too many values because of wrong Freq setting
+ sprintf(g->Message, MSG(BAD_FREQ_SET), Name);
+ return TRUE;
+ } // endif Ndv
+
+ // New value, add it to the list before the nth value
+ Dval->SetNval(Ndv + 1);
+
+ for (i = Ndv; i > n; i--)
+ Dval->Move(i - 1, i);
+
+ Dval->SetValue(Value, n);
+ Ndv++;
+ } // endif found
+
+ return FALSE;
+ } // end of AddDistinctValue
+#endif // BLK_INDX
+
/***********************************************************************/
/* Make file output of a Dos column descriptor block. */
/***********************************************************************/
diff --git a/storage/connect/tabdos.h b/storage/connect/tabdos.h
index 5f67ffad92f..52bb1450c29 100644
--- a/storage/connect/tabdos.h
+++ b/storage/connect/tabdos.h
@@ -1,7 +1,7 @@
/*************** TabDos H Declares Source Code File (.H) ***************/
-/* Name: TABDOS.H Version 3.2 */
+/* Name: TABDOS.H Version 3.3 */
/* */
-/* (C) Copyright to the author Olivier BERTRAND 1999-2012 */
+/* (C) Copyright to the author Olivier BERTRAND 1999-2014 */
/* */
/* This file contains the DOS classes declares. */
/***********************************************************************/
@@ -12,9 +12,16 @@
#include "xtable.h" // Table base class declares
#include "colblk.h" // Column base class declares
#include "xindex.h"
+#if defined(BLK_INDX)
+#include "filter.h"
+#endif // BLK_INDX
//pedef struct _tabdesc *PTABD; // For friend setting
typedef class TXTFAM *PTXF;
+#if defined(BLK_INDX)
+typedef class BLOCKFILTER *PBF;
+typedef class BLOCKINDEX *PBX;
+#endif // BLK_INDX
/***********************************************************************/
/* DOS table. */
@@ -34,6 +41,7 @@ class DllExport DOSDEF : public TABDEF { /* Logical table description */
virtual const char *GetType(void) {return "DOS";}
virtual PIXDEF GetIndx(void) {return To_Indx;}
virtual void SetIndx(PIXDEF xdp) {To_Indx = xdp;}
+ virtual bool IsHuge(void) {return Huge;}
PSZ GetFn(void) {return Fn;}
PSZ GetOfn(void) {return Ofn;}
void SetBlock(int block) {Block = block;}
@@ -46,19 +54,28 @@ class DllExport DOSDEF : public TABDEF { /* Logical table description */
bool GetEof(void) {return Eof;}
int GetBlksize(void) {return Blksize;}
int GetEnding(void) {return Ending;}
+#if defined(BLK_INDX)
+ bool IsOptimized(void) {return (Optimized == 1);}
+ void SetOptimized(int opt) {Optimized = opt;}
+ void SetAllocBlks(int blks) {AllocBlks = blks;}
+ int GetAllocBlks(void) {return AllocBlks;}
int *GetTo_Pos(void) {return To_Pos;}
- virtual bool IsHuge(void) {return Huge;}
+#endif // BLK_INDX
// Methods
- virtual bool DeleteTableFile(PGLOBAL g);
+//virtual bool DeleteTableFile(PGLOBAL g);
virtual bool Indexable(void) {return Compressed != 1;}
virtual bool DeleteIndexFile(PGLOBAL g, PIXDEF pxdf);
virtual bool DefineAM(PGLOBAL g, LPCSTR am, int poff);
virtual PTDB GetTable(PGLOBAL g, MODE mode);
bool InvalidateIndex(PGLOBAL g);
+#if defined(BLK_INDX)
+ bool GetOptFileName(PGLOBAL g, char *filename);
+ void RemoveOptValues(PGLOBAL g);
+#endif // BLK_INDX
protected:
- virtual bool Erase(char *filename);
+//virtual bool Erase(char *filename);
// Members
PSZ Fn; /* Path/Name of corresponding file */
@@ -70,7 +87,11 @@ class DllExport DOSDEF : public TABDEF { /* Logical table description */
bool Huge; /* true for files larger than 2GB */
bool Accept; /* true if wrong lines are accepted (DBF)*/
bool Eof; /* true if an EOF (0xA) character exists */
- int *To_Pos; /* To array of block starting positions */
+#if defined(BLK_INDX)
+ int *To_Pos; /* To array of block starting positions */
+ int Optimized; /* 0: No, 1:Yes, 2:Redo optimization */
+ int AllocBlks; /* Number of suballocated opt blocks */
+#endif // BLK_INDX
int Compressed; /* 0: No, 1: gz, 2:zlib compressed file */
int Lrecl; /* Size of biggest record */
int AvgLen; /* Average size of records */
@@ -129,13 +150,15 @@ class DllExport TDBDOS : public TDBASE {
virtual bool IsUsingTemp(PGLOBAL g);
//virtual bool NeedIndexing(PGLOBAL g);
virtual void ResetSize(void) {MaxSize = Cardinal = -1;}
- virtual int ResetTableOpt(PGLOBAL g, bool dox);
-//virtual int MakeBlockValues(PGLOBAL g);
-//virtual bool SaveBlockValues(PGLOBAL g);
-//virtual bool GetBlockValues(PGLOBAL g);
-//virtual PBF InitBlockFilter(PGLOBAL g, PFIL filp);
+ virtual int ResetTableOpt(PGLOBAL g, bool dop, bool dox);
+#if defined(BLK_INDX)
+ virtual int MakeBlockValues(PGLOBAL g);
+ virtual bool SaveBlockValues(PGLOBAL g);
+ virtual bool GetBlockValues(PGLOBAL g);
+ virtual PBF InitBlockFilter(PGLOBAL g, PFIL filp);
//virtual PBX InitBlockIndex(PGLOBAL g);
-//virtual int TestBlock(PGLOBAL g);
+ virtual int TestBlock(PGLOBAL g);
+#endif // BLK_INDX
virtual void PrintAM(FILE *f, char *m);
// Database routines
@@ -162,25 +185,31 @@ class DllExport TDBDOS : public TDBASE {
virtual int EstimatedLength(PGLOBAL g);
// Optimization routines
-// void ResetBlockFilter(PGLOBAL g);
- int MakeIndex(PGLOBAL g, PIXDEF pxdf, bool add);
-// bool GetDistinctColumnValues(PGLOBAL g, int nrec);
+ int MakeIndex(PGLOBAL g, PIXDEF pxdf, bool add);
+#if defined(BLK_INDX)
+ void ResetBlockFilter(PGLOBAL g);
+ bool GetDistinctColumnValues(PGLOBAL g, int nrec);
protected:
-// PBF CheckBlockFilari(PGLOBAL g, PXOB *arg, int op, bool *cnv);
+ PBF CheckBlockFilari(PGLOBAL g, PXOB *arg, int op, bool *cnv);
+#endif // BLK_INDX
// Members
PTXF Txfp; // To the File access method class
+#if defined(BLK_INDX)
//PBX To_BlkIdx; // To index test block
-//PBF To_BlkFil; // To evaluation block filter
-//PFIL SavFil; // Saved hidden filter
+ PBF To_BlkFil; // To evaluation block filter
+ PFIL SavFil; // Saved hidden filter
+#endif // BLK_INDX
char *To_Line; // Points to current processed line
int Cardinal; // Table Cardinality
RECFM Ftype; // File type: 0-var 1-fixed 2-binary (VCT)
int Lrecl; // Logical Record Length
int AvgLen; // Logical Record Average Length
+#if defined(BLK_INDX)
//int Xeval; // BlockTest return value
-//int Beval; // BlockEval return value
+ int Beval; // BlockEval return value
+#endif // BLK_INDX
}; // end of class TDBDOS
/***********************************************************************/
@@ -198,50 +227,60 @@ class DllExport DOSCOL : public COLBLK {
// Implementation
virtual int GetAmType(void) {return TYPE_AM_DOS;}
-//virtual int GetClustered(void) {return Clustered;}
-//virtual int IsClustered(void) {return (Clustered &&
-// ((PDOSDEF)(((PTDBDOS)To_Tdb)->To_Def))->IsOptimized());}
-//virtual int IsSorted(void) {return Sorted;}
virtual void SetTo_Val(PVAL valp) {To_Val = valp;}
-//virtual PVBLK GetMin(void) {return Min;}
-//virtual PVBLK GetMax(void) {return Max;}
-//virtual int GetNdv(void) {return Ndv;}
-//virtual int GetNbm(void) {return Nbm;}
-//virtual PVBLK GetBmap(void) {return Bmap;}
-//virtual PVBLK GetDval(void) {return Dval;}
+#if defined(BLK_INDX)
+ virtual int GetClustered(void) {return Clustered;}
+ virtual int IsClustered(void) {return (Clustered &&
+ ((PDOSDEF)(((PTDBDOS)To_Tdb)->To_Def))->IsOptimized());}
+ virtual int IsSorted(void) {return Sorted;}
+ virtual PVBLK GetMin(void) {return Min;}
+ virtual PVBLK GetMax(void) {return Max;}
+ virtual int GetNdv(void) {return Ndv;}
+ virtual int GetNbm(void) {return Nbm;}
+ virtual PVBLK GetBmap(void) {return Bmap;}
+ virtual PVBLK GetDval(void) {return Dval;}
+#endif // BLK_INDX
// Methods
+#if defined(BLK_INDX)
virtual bool VarSize(void);
+#endif // BLK_INDX
virtual bool SetBuffer(PGLOBAL g, PVAL value, bool ok, bool check);
virtual void ReadColumn(PGLOBAL g);
virtual void WriteColumn(PGLOBAL g);
virtual void Print(PGLOBAL g, FILE *, uint);
protected:
-//virtual bool SetMinMax(PGLOBAL g);
-//virtual bool SetBitMap(PGLOBAL g);
-// bool CheckSorted(PGLOBAL g);
-// bool AddDistinctValue(PGLOBAL g);
+#if defined(BLK_INDX)
+ virtual bool SetMinMax(PGLOBAL g);
+ virtual bool SetBitMap(PGLOBAL g);
+ bool CheckSorted(PGLOBAL g);
+ bool AddDistinctValue(PGLOBAL g);
+#endif // BLK_INDX
// Default constructor not to be used
DOSCOL(void) {}
// Members
-//PVBLK Min; // Array of block min values
-//PVBLK Max; // Array of block max values
-//PVBLK Bmap; // Array of block bitmap values
-//PVBLK Dval; // Array of column distinct values
+#if defined(BLK_INDX)
+ PVBLK Min; // Array of block min values
+ PVBLK Max; // Array of block max values
+ PVBLK Bmap; // Array of block bitmap values
+ PVBLK Dval; // Array of column distinct values
+#endif // BLK_INDX
PVAL To_Val; // To value used for Update/Insert
PVAL OldVal; // The previous value of the object.
char *Buf; // Buffer used in write operations
bool Ldz; // True if field contains leading zeros
bool Nod; // True if no decimal point
int Dcm; // Last Dcm digits are decimals
-//int Clustered; // 0:No 1:Yes
-//int Sorted; // 0:No 1:Asc (2:Desc - NIY)
int Deplac; // Offset in dos_buf
-//int Ndv; // Number of distinct values
-//int Nbm; // Number of uint in bitmap
+#if defined(BLK_INDX)
+ int Clustered; // 0:No 1:Yes
+ int Sorted; // 0:No 1:Asc (2:Desc - NIY)
+ int Ndv; // Number of distinct values
+ int Nbm; // Number of uint in bitmap
+#endif // BLK_INDX
}; // end of class DOSCOL
#endif // __TABDOS_H
diff --git a/storage/connect/tabfix.cpp b/storage/connect/tabfix.cpp
index 99063e86b57..cb95cebe7d1 100644
--- a/storage/connect/tabfix.cpp
+++ b/storage/connect/tabfix.cpp
@@ -1,11 +1,11 @@
/************* TabFix C++ Program Source Code File (.CPP) **************/
/* PROGRAM NAME: TABFIX */
/* ------------- */
-/* Version 4.8 */
+/* Version 4.9 */
/* */
/* COPYRIGHT: */
/* ---------- */
-/* (C) Copyright to the author Olivier BERTRAND 1998-2012 */
+/* (C) Copyright to the author Olivier BERTRAND 1998-2014 */
/* */
/* WHAT THIS PROGRAM DOES: */
/* ----------------------- */
@@ -45,6 +45,10 @@
#include "filamfix.h"
#include "filamdbf.h"
#include "tabfix.h" // TDBFIX, FIXCOL classes declares
+#if defined(BLK_INDX)
+#include "array.h"
+#include "blkfil.h"
+#endif // BLK_INDX
/***********************************************************************/
/* DB static variables. */
@@ -123,10 +127,52 @@ PCOL TDBFIX::MakeCol(PGLOBAL g, PCOLDEF cdp, PCOL cprec, int n)
/***********************************************************************/
/* Remake the indexes after the table was modified. */
/***********************************************************************/
-int TDBFIX::ResetTableOpt(PGLOBAL g, bool dox)
+int TDBFIX::ResetTableOpt(PGLOBAL g, bool dop, bool dox)
{
+#if defined(BLK_INDX)
+ int prc, rc = RC_OK;
+
+ To_Filter = NULL; // Disable filtering
+//To_BlkIdx = NULL; // and block filtering
+ To_BlkFil = NULL; // and index filtering
+ RestoreNrec(); // May have been modified
+ MaxSize = -1; // Size must be recalculated
+ Cardinal = -1; // as well as Cardinality
+
+ if (dop) {
+ Columns = NULL; // Not used anymore
+ Txfp->Reset();
+// OldBlk = CurBlk = -1;
+// ReadBlks = CurNum = Rbuf = Modif = 0;
+ Use = USE_READY; // So the table can be reopened
+ Mode = MODE_ANY; // Just to be clean
+ rc = MakeBlockValues(g); // Redo optimization
+ } // endif dop
+
+ if (dox && (rc == RC_OK || rc == RC_INFO)) {
+ // Remake eventual indexes
+ Columns = NULL; // Not used anymore
+ Txfp->Reset(); // New start
+ Use = USE_READY; // So the table can be reopened
+ Mode = MODE_READ; // New mode
+ prc = rc;
+
+ if (!(PlgGetUser(g)->Check & CHK_OPT)) {
+ // After the table was modified the indexes
+ // are invalid and we should mark them as such...
+ rc = ((PDOSDEF)To_Def)->InvalidateIndex(g);
+ } else
+ // ... or we should remake them.
+ rc = MakeIndex(g, NULL, FALSE);
+
+ rc = (rc == RC_INFO) ? prc : rc;
+ } // endif dox
+
+ return rc;
+#else // !BLK_INDX
RestoreNrec(); // May have been modified
- return TDBDOS::ResetTableOpt(g, dox);
+ return TDBDOS::ResetTableOpt(g, dop, dox);
+#endif // !BLK_INDX
} // end of ResetTableOpt
/***********************************************************************/
@@ -163,8 +209,17 @@ int TDBFIX::Cardinality(PGLOBAL g)
/***********************************************************************/
int TDBFIX::GetMaxSize(PGLOBAL g)
{
- if (MaxSize < 0)
+ if (MaxSize < 0) {
MaxSize = Cardinality(g);
+#if defined(BLK_INDX)
+ if (MaxSize > 0 && (To_BlkFil = InitBlockFilter(g, To_Filter))
+ && !To_BlkFil->Correlated()) {
+ // Use BlockTest to reduce the estimated size
+ MaxSize = Txfp->MaxBlkSize(g, MaxSize);
+ ResetBlockFilter(g);
+ } // endif To_BlkFil
+#endif // BLK_INDX
+ } // endif MaxSize
return MaxSize;
} // end of GetMaxSize
@@ -246,6 +301,9 @@ bool TDBFIX::OpenDB(PGLOBAL g)
else
Txfp->Rewind(); // see comment in Work.log
+#if defined(BLK_INDX)
+ ResetBlockFilter(g);
+#endif // BLK_INDX
return false;
} // endif use
@@ -277,6 +335,13 @@ bool TDBFIX::OpenDB(PGLOBAL g)
/*********************************************************************/
To_Line = Txfp->GetBuf(); // For WriteDB
+#if defined(BLK_INDX)
+ /*********************************************************************/
+ /* Allocate the block filter tree if evaluation is possible. */
+ /*********************************************************************/
+ To_BlkFil = InitBlockFilter(g, To_Filter);
+#endif // BLK_INDX
+
if (trace)
htrc("OpenDos: R%hd mode=%d\n", Tdb_No, Mode);
diff --git a/storage/connect/tabfix.h b/storage/connect/tabfix.h
index bcd171b37bb..5feb3589928 100644
--- a/storage/connect/tabfix.h
+++ b/storage/connect/tabfix.h
@@ -38,7 +38,7 @@ class DllExport TDBFIX : public TDBDOS {
virtual void ResetDB(void);
virtual bool IsUsingTemp(PGLOBAL g);
virtual int RowNumber(PGLOBAL g, bool b = false);
- virtual int ResetTableOpt(PGLOBAL g, bool dox);
+ virtual int ResetTableOpt(PGLOBAL g, bool dop, bool dox);
virtual void ResetSize(void);
virtual int GetBadLines(void) {return Txfp->GetNerr();}
diff --git a/storage/connect/tabfmt.cpp b/storage/connect/tabfmt.cpp
index 9a121b9ab9a..18ecaae430a 100644
--- a/storage/connect/tabfmt.cpp
+++ b/storage/connect/tabfmt.cpp
@@ -459,9 +459,12 @@ PTDB CSVDEF::GetTable(PGLOBAL g, MODE mode)
if (Compressed == 1)
txfp = new(g) ZIPFAM(this);
else {
+#if defined(BLK_INDX)
+ txfp = new(g) ZLBFAM(this);
+#else // !BLK_INDX
strcpy(g->Message, "Compress 2 not supported yet");
-// txfp = new(g) ZLBFAM(defp);
return NULL;
+#endif // !BLK_INDX
} // endelse
#else // !ZIP_SUPPORT
strcpy(g->Message, "Compress not supported");
@@ -1272,6 +1275,7 @@ CSVCOL::CSVCOL(CSVCOL *col1, PTDB tdbp) : DOSCOL(col1, tdbp)
Fldnum = col1->Fldnum;
} // end of CSVCOL copy constructor
+#if defined(BLK_INDX)
/***********************************************************************/
/* VarSize: This function tells UpdateDB whether or not the block */
/* optimization file must be redone if this column is updated, even */
@@ -1290,6 +1294,7 @@ bool CSVCOL::VarSize(void)
return false;
} // end VarSize
+#endif // BLK_INDX
/***********************************************************************/
/* ReadColumn: call DOSCOL::ReadColumn after having set the offet */
diff --git a/storage/connect/tabfmt.h b/storage/connect/tabfmt.h
index d4a7f4105d6..52b0094bfef 100644
--- a/storage/connect/tabfmt.h
+++ b/storage/connect/tabfmt.h
@@ -112,7 +112,9 @@ class CSVCOL : public DOSCOL {
virtual int GetAmType() {return TYPE_AM_CSV;}
// Methods
+#if defined(BLK_INDX)
virtual bool VarSize(void);
+#endif // BLK_INDX
virtual void ReadColumn(PGLOBAL g);
virtual void WriteColumn(PGLOBAL g);
// void Print(FILE *, uint);
diff --git a/storage/connect/table.cpp b/storage/connect/table.cpp
index 37035ed752d..d23740394b4 100644
--- a/storage/connect/table.cpp
+++ b/storage/connect/table.cpp
@@ -36,27 +36,6 @@ extern "C" int trace; // The general trace value
void NewPointer(PTABS, void *, void *);
void AddPointer(PTABS, void *);
-/* ---------------------------- class TBX ---------------------------- */
-
-/***********************************************************************/
-/* TBX public constructors. */
-/***********************************************************************/
-TBX::TBX(void)
- {
- Use = USE_NO;
- To_Orig = NULL;
- To_Filter = NULL;
- } // end of TBX constructor
-
-TBX::TBX(PTBX txp)
- {
- Use = txp->Use;
- To_Orig = txp;
- To_Filter = NULL;
- } // end of TBX copy constructor
-
-// Methods
-
/* ---------------------------- class TDB ---------------------------- */
/***********************************************************************/
@@ -64,6 +43,12 @@ TBX::TBX(PTBX txp)
/***********************************************************************/
TDB::TDB(PTABDEF tdp) : Tdb_No(++Tnum)
{
+ Use = USE_NO;
+ To_Orig = NULL;
+#if defined(BLK_INDX)
+ To_Filter = NULL;
+#endif // BLK_FILTER
+ To_CondFil = NULL;
Next = NULL;
Name = (tdp) ? tdp->GetName() : NULL;
To_Table = NULL;
@@ -72,8 +57,14 @@ TDB::TDB(PTABDEF tdp) : Tdb_No(++Tnum)
Mode = MODE_READ;
} // end of TDB standard constructor
-TDB::TDB(PTDB tdbp) : TBX(tdbp), Tdb_No(++Tnum)
+TDB::TDB(PTDB tdbp) : Tdb_No(++Tnum)
{
+ Use = tdbp->Use;
+ To_Orig = tdbp;
+#if defined(BLK_INDX)
+ To_Filter = NULL;
+#endif // BLK_FILTER
+ To_CondFil = NULL;
Next = NULL;
Name = tdbp->Name;
To_Table = tdbp->To_Table;
@@ -179,7 +170,7 @@ int TDB::RowNumber(PGLOBAL g, bool b)
return 0;
} // end of RowNumber
-PTBX TDB::Copy(PTABS t)
+PTDB TDB::Copy(PTABS t)
{
PTDB tp, tdb1, tdb2 = NULL, outp = NULL;
//PGLOBAL g = t->G; // Is this really useful ???
@@ -398,7 +389,7 @@ PCOL TDBASE::InsertSpcBlk(PGLOBAL g, PCOLDEF cdp)
/***********************************************************************/
/* ResetTableOpt: Wrong for this table type. */
/***********************************************************************/
-int TDBASE::ResetTableOpt(PGLOBAL g, bool dox)
+int TDBASE::ResetTableOpt(PGLOBAL g, bool dop, bool dox)
{
strcpy(g->Message, "This table is not indexable");
return RC_INFO;
diff --git a/storage/connect/tabmac.h b/storage/connect/tabmac.h
index cfdf842cdc8..eb115b18049 100644
--- a/storage/connect/tabmac.h
+++ b/storage/connect/tabmac.h
@@ -31,7 +31,7 @@ class DllExport MACDEF : public TABDEF { /* Logical table description */
// Methods
virtual bool DefineAM(PGLOBAL g, LPCSTR am, int poff);
virtual PTDB GetTable(PGLOBAL g, MODE m);
- virtual bool DeleteTableFile(PGLOBAL g) {return true;}
+//virtual bool DeleteTableFile(PGLOBAL g) {return true;}
protected:
// Members
diff --git a/storage/connect/tabmul.h b/storage/connect/tabmul.h
index 052b4e7d33e..379e8f88e93 100644
--- a/storage/connect/tabmul.h
+++ b/storage/connect/tabmul.h
@@ -38,7 +38,7 @@ class DllExport TDBMUL : public TDBASE {
// Methods
virtual void ResetDB(void);
virtual PTDB CopyOne(PTABS t);
- virtual bool IsSame(PTBX tp) {return tp == (PTBX)Tdbp;}
+ virtual bool IsSame(PTDB tp) {return tp == (PTDB)Tdbp;}
virtual PSZ GetFile(PGLOBAL g) {return Tdbp->GetFile(g);}
virtual int GetRecpos(void) {return 0;}
virtual PCOL ColDB(PGLOBAL g, PSZ name, int num);
diff --git a/storage/connect/tabmysql.cpp b/storage/connect/tabmysql.cpp
index 9b4f0dbe3ce..ce41a8429be 100644
--- a/storage/connect/tabmysql.cpp
+++ b/storage/connect/tabmysql.cpp
@@ -527,8 +527,8 @@ bool TDBMYSQL::MakeSelect(PGLOBAL g)
strcat(strcat(strcat(strcat(Query, " FROM "), tk), Tabname), tk);
- if (To_Filter)
- strcat(strcat(Query, " WHERE "), To_Filter->Body);
+ if (To_CondFil)
+ strcat(strcat(Query, " WHERE "), To_CondFil->Body);
if (trace)
htrc("Query=%s\n", Query);
@@ -1395,11 +1395,11 @@ PCMD TDBMYEXC::MakeCMD(PGLOBAL g)
{
PCMD xcmd = NULL;
- if (To_Filter) {
+ if (To_CondFil) {
if (Cmdcol) {
- if (!stricmp(Cmdcol, To_Filter->Body) &&
- (To_Filter->Op == OP_EQ || To_Filter->Op == OP_IN)) {
- xcmd = To_Filter->Cmds;
+ if (!stricmp(Cmdcol, To_CondFil->Body) &&
+ (To_CondFil->Op == OP_EQ || To_CondFil->Op == OP_IN)) {
+ xcmd = To_CondFil->Cmds;
} else
strcpy(g->Message, "Invalid command specification filter");
diff --git a/storage/connect/tabodbc.cpp b/storage/connect/tabodbc.cpp
index 1fb71e33646..c7513601979 100644
--- a/storage/connect/tabodbc.cpp
+++ b/storage/connect/tabodbc.cpp
@@ -408,7 +408,7 @@ char *TDBODBC::MakeSQL(PGLOBAL g, bool cnt)
// Below 14 is length of 'select ' + length of ' from ' + 1
len = (strlen(colist) + strlen(buf) + 14);
- len += (To_Filter ? strlen(To_Filter->Body) + 7 : 0);
+ len += (To_CondFil ? strlen(To_CondFil->Body) + 7 : 0);
if (Catalog && *Catalog)
catp = Catalog;
@@ -441,8 +441,8 @@ char *TDBODBC::MakeSQL(PGLOBAL g, bool cnt)
strcat(sql, tabname);
- if (To_Filter)
- strcat(strcat(sql, " WHERE "), To_Filter->Body);
+ if (To_CondFil)
+ strcat(strcat(sql, " WHERE "), To_CondFil->Body);
return sql;
} // end of MakeSQL
@@ -1229,11 +1229,11 @@ PCMD TDBXDBC::MakeCMD(PGLOBAL g)
{
PCMD xcmd = NULL;
- if (To_Filter) {
+ if (To_CondFil) {
if (Cmdcol) {
- if (!stricmp(Cmdcol, To_Filter->Body) &&
- (To_Filter->Op == OP_EQ || To_Filter->Op == OP_IN)) {
- xcmd = To_Filter->Cmds;
+ if (!stricmp(Cmdcol, To_CondFil->Body) &&
+ (To_CondFil->Op == OP_EQ || To_CondFil->Op == OP_IN)) {
+ xcmd = To_CondFil->Cmds;
} else
strcpy(g->Message, "Invalid command specification filter");
diff --git a/storage/connect/tabsys.cpp b/storage/connect/tabsys.cpp
index 2bb5532cea0..409352fdee6 100644
--- a/storage/connect/tabsys.cpp
+++ b/storage/connect/tabsys.cpp
@@ -113,6 +113,7 @@ PTDB INIDEF::GetTable(PGLOBAL g, MODE m)
return tdbp;
} // end of GetTable
+#if 0
/***********************************************************************/
/* DeleteTableFile: Delete INI table files using platform API. */
/***********************************************************************/
@@ -134,6 +135,7 @@ bool INIDEF::DeleteTableFile(PGLOBAL g)
return rc; // Return true if error
} // end of DeleteTableFile
+#endif // 0
/* ------------------------------------------------------------------- */
diff --git a/storage/connect/tabsys.h b/storage/connect/tabsys.h
index 2780eb3ca98..714f2475873 100644
--- a/storage/connect/tabsys.h
+++ b/storage/connect/tabsys.h
@@ -32,7 +32,7 @@ class DllExport INIDEF : public TABDEF { /* INI table description */
// Methods
virtual bool DefineAM(PGLOBAL g, LPCSTR am, int poff);
virtual PTDB GetTable(PGLOBAL g, MODE m);
- virtual bool DeleteTableFile(PGLOBAL g);
+//virtual bool DeleteTableFile(PGLOBAL g);
protected:
// Members
diff --git a/storage/connect/tabtbl.cpp b/storage/connect/tabtbl.cpp
index 56305871c69..c78c62af9cc 100644
--- a/storage/connect/tabtbl.cpp
+++ b/storage/connect/tabtbl.cpp
@@ -1,11 +1,11 @@
/************* TabTbl C++ Program Source Code File (.CPP) **************/
/* PROGRAM NAME: TABTBL */
/* ------------- */
-/* Version 1.6 */
+/* Version 1.7 */
/* */
/* COPYRIGHT: */
/* ---------- */
-/* (C) Copyright to PlugDB Software Development 2008-2013 */
+/* (C) Copyright to PlugDB Software Development 2008-2014 */
/* Author: Olivier BERTRAND */
/* */
/* WHAT THIS PROGRAM DOES: */
@@ -66,7 +66,6 @@
#include "global.h" // global declarations
#include "plgdbsem.h" // DB application declarations
#include "reldef.h" // DB definition declares
-//#include "filter.h" // FILTER classes dcls
#include "filamtxt.h"
#include "tabcol.h"
#include "tabdos.h" // TDBDOS and DOSCOL class dcls
@@ -245,7 +244,7 @@ bool TDBTBL::InitTableList(PGLOBAL g)
// PlugSetPath(filename, Tdbp->GetFile(g), Tdbp->GetPath());
for (n = 0, tp = tdp->Tablep; tp; tp = tp->GetNext()) {
- if (TestFil(g, To_Filter, tp)) {
+ if (TestFil(g, To_CondFil, tp)) {
tabp = new(g) XTAB(tp);
if (tabp->GetSrc()) {
@@ -286,14 +285,14 @@ bool TDBTBL::InitTableList(PGLOBAL g)
hc->get_table()->s->connect_string.length = sln;
//NumTables = n;
- To_Filter = NULL; // To avoid doing it several times
+ To_CondFil = NULL; // To avoid doing it several times
return FALSE;
} // end of InitTableList
/***********************************************************************/
/* Test the tablename against the pseudo "local" filter. */
/***********************************************************************/
-bool TDBTBL::TestFil(PGLOBAL g, PFIL filp, PTABLE tabp)
+bool TDBTBL::TestFil(PGLOBAL g, PCFIL filp, PTABLE tabp)
{
char *body, *fil, op[8], tn[NAME_LEN];
bool neg;
@@ -421,12 +420,12 @@ bool TDBTBL::OpenDB(PGLOBAL g)
} // endif use
/*********************************************************************/
- /* When GetMaxsize was called, To_Filter was not set yet. */
+ /* When GetMaxsize was called, To_CondFil was not set yet. */
/*********************************************************************/
- if (To_Filter && Tablist) {
+ if (To_CondFil && Tablist) {
Tablist = NULL;
Nbc = 0;
- } // endif To_Filter
+ } // endif To_CondFil
/*********************************************************************/
/* Open the first table of the list. */
@@ -661,12 +660,12 @@ bool TDBTBM::OpenDB(PGLOBAL g)
#if 0
/*********************************************************************/
- /* When GetMaxsize was called, To_Filter was not set yet. */
+ /* When GetMaxsize was called, To_CondFil was not set yet. */
/*********************************************************************/
- if (To_Filter && Tablist) {
+ if (To_CondFil && Tablist) {
Tablist = NULL;
Nbc = 0;
- } // endif To_Filter
+ } // endif To_CondFil
#endif // 0
/*********************************************************************/
diff --git a/storage/connect/tabtbl.h b/storage/connect/tabtbl.h
index 48371e40ade..0ff6c37eaed 100644
--- a/storage/connect/tabtbl.h
+++ b/storage/connect/tabtbl.h
@@ -87,7 +87,7 @@ class DllExport TDBTBL : public TDBPRX {
protected:
// Internal functions
bool InitTableList(PGLOBAL g);
- bool TestFil(PGLOBAL g, PFIL filp, PTABLE tabp);
+ bool TestFil(PGLOBAL g, PCFIL filp, PTABLE tabp);
// Members
PTABLE Tablist; // Points to the table list
@@ -152,7 +152,7 @@ class DllExport TDBTBM : public TDBTBL {
protected:
// Internal functions
//bool InitTableList(PGLOBAL g);
-//bool TestFil(PGLOBAL g, PFIL filp, PTABLE tabp);
+//bool TestFil(PGLOBAL g, PCFIL filp, PTABLE tabp);
bool OpenTables(PGLOBAL g);
int ReadNextRemote(PGLOBAL g);
diff --git a/storage/connect/tabvct.cpp b/storage/connect/tabvct.cpp
index 8b7d8ba91eb..cb5e6f3200c 100644
--- a/storage/connect/tabvct.cpp
+++ b/storage/connect/tabvct.cpp
@@ -1,11 +1,11 @@
/************* TabVct C++ Program Source Code File (.CPP) **************/
/* PROGRAM NAME: TABVCT */
/* ------------- */
-/* Version 3.7 */
+/* Version 3.8 */
/* */
/* COPYRIGHT: */
/* ---------- */
-/* (C) Copyright to the author Olivier BERTRAND 1999-2012 */
+/* (C) Copyright to the author Olivier BERTRAND 1999-2014 */
/* */
/* WHAT THIS PROGRAM DOES: */
/* ----------------------- */
@@ -118,6 +118,7 @@ bool VCTDEF::DefineAM(PGLOBAL g, LPCSTR am, int poff)
return false;
} // end of DefineAM
+#if 0
/***********************************************************************/
/* Erase: This was made a separate routine because a strange thing */
/* happened when DeleteTablefile was defined for the VCTDEF class: */
@@ -157,6 +158,7 @@ bool VCTDEF::Erase(char *filename)
return rc; // Return true if error
} // end of Erase
+#endif // 0
/***********************************************************************/
/* Prepare the column file name pattern for a split table. */
@@ -231,7 +233,8 @@ PTDB VCTDEF::GetTable(PGLOBAL g, MODE mode)
/*********************************************************************/
if (mode != MODE_INSERT)
if (tdbp->GetBlockValues(g))
- return NULL;
+ PushWarning(g, (PTDBASE)tdbp);
+// return NULL; // causes a crash when deleting index
return tdbp;
} // end of GetTable
@@ -298,6 +301,9 @@ bool TDBVCT::OpenDB(PGLOBAL g)
To_Kindex->Reset();
Txfp->Rewind();
+#if defined(BLK_INDX)
+ ResetBlockFilter(g);
+#endif // BLK_INDX
return false;
} // endif Use
@@ -319,6 +325,13 @@ bool TDBVCT::OpenDB(PGLOBAL g)
// This was not done in previous version
Use = USE_OPEN; // Do it now in case we are recursively called
+#if defined(BLK_INDX)
+ /*********************************************************************/
+ /* Allocate the block filter tree if evaluation is possible. */
+ /*********************************************************************/
+ To_BlkFil = InitBlockFilter(g, To_Filter);
+#endif // BLK_INDX
+
/*********************************************************************/
/* Reset buffer access according to indexing and to mode. */
/*********************************************************************/
diff --git a/storage/connect/tabvct.h b/storage/connect/tabvct.h
index 4049b4f7683..f1c0a8a3a98 100644
--- a/storage/connect/tabvct.h
+++ b/storage/connect/tabvct.h
@@ -37,7 +37,7 @@ class DllExport VCTDEF : public DOSDEF { /* Logical table description */
protected:
// Specific file erase routine for vertical tables
- virtual bool Erase(char *filename);
+//virtual bool Erase(char *filename);
int MakeFnPattern(char *fpat);
// Members
diff --git a/storage/connect/tabwmi.cpp b/storage/connect/tabwmi.cpp
index 8f91d9b3ed8..5052268b9e2 100644
--- a/storage/connect/tabwmi.cpp
+++ b/storage/connect/tabwmi.cpp
@@ -14,7 +14,7 @@
#include "reldef.h"
#include "xtable.h"
#include "colblk.h"
-#include "filter.h"
+//#include "filter.h"
//#include "xindex.h"
#include "tabwmi.h"
#include "valblk.h"
@@ -480,8 +480,8 @@ bool TDBWMI::Initialize(PGLOBAL g)
/***********************************************************************/
void TDBWMI::DoubleSlash(PGLOBAL g)
{
- if (To_Filter && strchr(To_Filter->Body, '\\')) {
- char *body = To_Filter->Body;
+ if (To_CondFil && strchr(To_CondFil->Body, '\\')) {
+ char *body = To_CondFil->Body;
char *buf = (char*)PlugSubAlloc(g, NULL, strlen(body) * 2);
int i = 0, k = 0;
@@ -492,8 +492,8 @@ void TDBWMI::DoubleSlash(PGLOBAL g)
buf[k++] = body[i];
} while (body[i++]);
- To_Filter->Body = buf;
- } // endif To_Filter
+ To_CondFil->Body = buf;
+ } // endif To_CondFil
} // end of DoubleSlash
@@ -540,13 +540,13 @@ char *TDBWMI::MakeWQL(PGLOBAL g)
// Below 14 is length of 'select ' + length of ' from ' + 1
len = (strlen(colist) + strlen(Wclass) + 14);
- len += (To_Filter ? strlen(To_Filter->Body) + 7 : 0);
+ len += (To_CondFil ? strlen(To_CondFil->Body) + 7 : 0);
wql = (char*)PlugSubAlloc(g, NULL, len);
strcat(strcat(strcpy(wql, "SELECT "), colist), " FROM ");
strcat(wql, Wclass);
- if (To_Filter)
- strcat(strcat(wql, " WHERE "), To_Filter->Body);
+ if (To_CondFil)
+ strcat(strcat(wql, " WHERE "), To_CondFil->Body);
return wql;
} // end of MakeWQL
@@ -659,8 +659,8 @@ bool TDBWMI::OpenDB(PGLOBAL g)
return true;
} // endif Mode
- if (!To_Filter && !stricmp(Wclass, "CIM_Datafile")
- && !stricmp(Nspace, "root\\cimv2")) {
+ if (!To_CondFil && !stricmp(Wclass, "CIM_Datafile")
+ && !stricmp(Nspace, "root\\cimv2")) {
strcpy(g->Message,
"Would last forever when not filtered, use DIR table instead");
return true;
diff --git a/storage/connect/tabwmi.h b/storage/connect/tabwmi.h
index 9df57e7c579..558e527773e 100644
--- a/storage/connect/tabwmi.h
+++ b/storage/connect/tabwmi.h
@@ -48,7 +48,7 @@ class WMIDEF : public TABDEF { /* Logical table description */
// Methods
virtual bool DefineAM(PGLOBAL g, LPCSTR am, int poff);
virtual PTDB GetTable(PGLOBAL g, MODE m);
- virtual bool DeleteTableFile(PGLOBAL g) {return true;}
+//virtual bool DeleteTableFile(PGLOBAL g) {return true;}
protected:
// Members
diff --git a/storage/connect/tabxml.cpp b/storage/connect/tabxml.cpp
index 7e4ee3453ae..7a2c0169c2b 100644
--- a/storage/connect/tabxml.cpp
+++ b/storage/connect/tabxml.cpp
@@ -187,6 +187,7 @@ PTDB XMLDEF::GetTable(PGLOBAL g, MODE m)
return tdbp;
} // end of GetTable
+#if 0
/***********************************************************************/
/* DeleteTableFile: Delete XML table files using platform API. */
/***********************************************************************/
@@ -208,6 +209,7 @@ bool XMLDEF::DeleteTableFile(PGLOBAL g)
return rc; // Return true if error
} // end of DeleteTableFile
+#endif // 0
/* ------------------------- TDBXML Class ---------------------------- */
diff --git a/storage/connect/tabxml.h b/storage/connect/tabxml.h
index 817bea45b3b..20998589967 100644
--- a/storage/connect/tabxml.h
+++ b/storage/connect/tabxml.h
@@ -30,7 +30,7 @@ class DllExport XMLDEF : public TABDEF { /* Logical table description */
// Methods
virtual bool DefineAM(PGLOBAL g, LPCSTR am, int poff);
virtual PTDB GetTable(PGLOBAL g, MODE m);
- virtual bool DeleteTableFile(PGLOBAL g);
+//virtual bool DeleteTableFile(PGLOBAL g);
protected:
// Members
diff --git a/storage/connect/valblk.cpp b/storage/connect/valblk.cpp
index c0127072896..e8da2044a47 100644
--- a/storage/connect/valblk.cpp
+++ b/storage/connect/valblk.cpp
@@ -40,7 +40,8 @@
#include "plgdbsem.h"
#include "valblk.h"
-#define CheckBlanks assert(!Blanks);
+#define CheckBlanks assert(!Blanks);
+#define CheckParms(V, N) ChkIndx(N); ChkTyp(V);
/***********************************************************************/
/* AllocValBlock: allocate a VALBLK according to type. */
@@ -447,6 +448,38 @@ template <>
uchar TYPBLK<uchar>::GetTypedValue(PVBLK blk, int n)
{return blk->GetUTinyValue(n);}
+#if defined(BLK_INDX)
+/***********************************************************************/
+/* Set one value in a block if val is less than the current value. */
+/***********************************************************************/
+template <class TYPE>
+void TYPBLK<TYPE>::SetMin(PVAL valp, int n)
+ {
+ CheckParms(valp, n)
+ TYPE tval = GetTypedValue(valp);
+ TYPE& tmin = Typp[n];
+
+ if (tval < tmin)
+ tmin = tval;
+
+ } // end of SetMin
+
+/***********************************************************************/
+/* Set one value in a block if val is greater than the current value. */
+/***********************************************************************/
+template <class TYPE>
+void TYPBLK<TYPE>::SetMax(PVAL valp, int n)
+ {
+ CheckParms(valp, n)
+ TYPE tval = GetTypedValue(valp);
+ TYPE& tmin = Typp[n];
+
+ if (tval > tmin)
+ tmin = tval;
+
+ } // end of SetMax
+#endif // BLK_INDX
+
#if 0
/***********************************************************************/
/* Set many values in a block from values in another block. */
@@ -779,6 +812,38 @@ void CHRBLK::SetValue(PVBLK pv, int n1, int n2)
SetNull(n1, b);
} // end of SetValue
+#if defined(BLK_INDX)
+/***********************************************************************/
+/* Set one value in a block if val is less than the current value. */
+/***********************************************************************/
+void CHRBLK::SetMin(PVAL valp, int n)
+ {
+ CheckParms(valp, n)
+ CheckBlanks
+ char *vp = valp->GetCharValue();
+ char *bp = Chrp + n * Long;
+
+ if (((Ci) ? strnicmp(vp, bp, Long) : strncmp(vp, bp, Long)) < 0)
+ memcpy(bp, vp, Long);
+
+ } // end of SetMin
+
+/***********************************************************************/
+/* Set one value in a block if val is greater than the current value. */
+/***********************************************************************/
+void CHRBLK::SetMax(PVAL valp, int n)
+ {
+ CheckParms(valp, n)
+ CheckBlanks
+ char *vp = valp->GetCharValue();
+ char *bp = Chrp + n * Long;
+
+ if (((Ci) ? strnicmp(vp, bp, Long) : strncmp(vp, bp, Long)) > 0)
+ memcpy(bp, vp, Long);
+
+ } // end of SetMax
+#endif // BLK_INDX
+
#if 0
/***********************************************************************/
/* Set many values in a block from values in another block. */
@@ -1101,6 +1166,36 @@ void STRBLK::SetValue(char *sp, uint len, int n)
Strp[n] = p;
} // end of SetValue
+#if defined(BLK_INDX)
+/***********************************************************************/
+/* Set one value in a block if val is less than the current value. */
+/***********************************************************************/
+void STRBLK::SetMin(PVAL valp, int n)
+ {
+ CheckParms(valp, n)
+ char *vp = valp->GetCharValue();
+ char *bp = Strp[n];
+
+ if (strcmp(vp, bp) < 0)
+ SetValue(valp, n);
+
+ } // end of SetMin
+
+/***********************************************************************/
+/* Set one value in a block if val is greater than the current value. */
+/***********************************************************************/
+void STRBLK::SetMax(PVAL valp, int n)
+ {
+ CheckParms(valp, n)
+ char *vp = valp->GetCharValue();
+ char *bp = Strp[n];
+
+ if (strcmp(vp, bp) > 0)
+ SetValue(valp, n);
+
+ } // end of SetMax
+#endif // BLK_INDX
+
/***********************************************************************/
/* Move one value from i to j. */
/***********************************************************************/
@@ -1240,5 +1335,51 @@ void DATBLK::SetValue(PSZ p, int n)
} // end of SetValue
+#if defined(BLK_INDX)
+/* -------------------------- Class MBVALS --------------------------- */
+
+/***********************************************************************/
+/* Allocate a value block according to type,len, and nb of values. */
+/***********************************************************************/
+PVBLK MBVALS::Allocate(PGLOBAL g, int type, int len, int prec,
+ int n, bool sub)
+ {
+ Mblk.Sub = sub;
+ Mblk.Size = n * GetTypeSize(type, len);
+
+ if (!PlgDBalloc(g, NULL, Mblk)) {
+ sprintf(g->Message, MSG(ALLOC_ERROR), "MBVALS::Allocate");
+ return NULL;
+ } else
+ Vblk = AllocValBlock(g, Mblk.Memp, type, n, len, prec,
+ TRUE, TRUE, FALSE);
+
+ return Vblk;
+ } // end of Allocate
+
+/***********************************************************************/
+/* Reallocate the value block according to the new size. */
+/***********************************************************************/
+bool MBVALS::ReAllocate(PGLOBAL g, int n)
+ {
+ if (!PlgDBrealloc(g, NULL, Mblk, n * Vblk->GetVlen())) {
+ sprintf(g->Message, MSG(ALLOC_ERROR), "MBVALS::ReAllocate");
+ return TRUE;
+ } else
+ Vblk->ReAlloc(Mblk.Memp, n);
+
+ return FALSE;
+ } // end of ReAllocate
+
+/***********************************************************************/
+/* Free the value block. */
+/***********************************************************************/
+void MBVALS::Free(void)
+ {
+ PlgDBfree(Mblk);
+ Vblk = NULL;
+ } // end of Free
+#endif // BLK_INDX
+
/* ------------------------- End of Valblk --------------------------- */
diff --git a/storage/connect/valblk.h b/storage/connect/valblk.h
index 1edfe7f76b4..6b427512332 100644
--- a/storage/connect/valblk.h
+++ b/storage/connect/valblk.h
@@ -22,6 +22,38 @@ DllExport PVBLK AllocValBlock(PGLOBAL, void*, int, int, int, int,
bool, bool, bool);
const char *GetFmt(int type, bool un = false);
+#if defined(BLK_INDX)
+/***********************************************************************/
+/* DB static external variables. */
+/***********************************************************************/
+extern MBLOCK Nmblk; /* Used to initialize MBLOCK's */
+
+/***********************************************************************/
+/* Class MBVALS is a utility class for (re)allocating VALBLK's. */
+/***********************************************************************/
+class MBVALS : public BLOCK {
+//friend class LSTBLK;
+ friend class ARRAY;
+ public:
+ // Constructors
+ MBVALS(void) {Vblk = NULL; Mblk = Nmblk;}
+
+ // Methods
+ void *GetMemp(void) {return Mblk.Memp;}
+ PVBLK Allocate(PGLOBAL g, int type, int len, int prec,
+ int n, bool sub = FALSE);
+ bool ReAllocate(PGLOBAL g, int n);
+ void Free(void);
+
+ protected:
+ // Members
+ PVBLK Vblk; // Pointer to VALBLK
+ MBLOCK Mblk; // The memory block
+ }; // end of class MBVALS
+
+typedef class MBVALS *PMBV;
+#endif // BLK_INDX
+
/***********************************************************************/
/* Class VALBLK represent a base class for variable blocks. */
/***********************************************************************/
@@ -79,9 +111,11 @@ class VALBLK : public BLOCK {
virtual void SetValue(char *sp, uint len, int n) {assert(false);}
virtual void SetValue(PVAL valp, int n) = 0;
virtual void SetValue(PVBLK pv, int n1, int n2) = 0;
-#if 0
+#if defined(BLK_INDX)
virtual void SetMin(PVAL valp, int n) = 0;
virtual void SetMax(PVAL valp, int n) = 0;
+#endif // BLK_INDX
+#if 0
virtual void SetValues(PVBLK pv, int i, int n) = 0;
virtual void AddMinus1(PVBLK pv, int n1, int n2) {assert(false);}
#endif // 0
@@ -161,6 +195,10 @@ class TYPBLK : public VALBLK {
virtual void SetValue(PVAL valp, int n);
virtual void SetValue(PVBLK pv, int n1, int n2);
//virtual void SetValues(PVBLK pv, int k, int n);
+#if defined(BLK_INDX)
+ virtual void SetMin(PVAL valp, int n);
+ virtual void SetMax(PVAL valp, int n);
+#endif // BLK_INDX
virtual void Move(int i, int j);
virtual int CompVal(PVAL vp, int n);
virtual int CompVal(int i1, int i2);
@@ -212,6 +250,10 @@ class CHRBLK : public VALBLK {
virtual void SetValue(PVAL valp, int n);
virtual void SetValue(PVBLK pv, int n1, int n2);
//virtual void SetValues(PVBLK pv, int k, int n);
+#if defined(BLK_INDX)
+ virtual void SetMin(PVAL valp, int n);
+ virtual void SetMax(PVAL valp, int n);
+#endif // BLK_INDX
virtual void Move(int i, int j);
virtual int CompVal(PVAL vp, int n);
virtual int CompVal(int i1, int i2);
@@ -264,6 +306,10 @@ class STRBLK : public VALBLK {
virtual void SetValue(PVAL valp, int n);
virtual void SetValue(PVBLK pv, int n1, int n2);
//virtual void SetValues(PVBLK pv, int k, int n);
+#if defined(BLK_INDX)
+ virtual void SetMin(PVAL valp, int n);
+ virtual void SetMax(PVAL valp, int n);
+#endif // BLK_INDX
virtual void Move(int i, int j);
virtual int CompVal(PVAL vp, int n);
virtual int CompVal(int i1, int i2);
diff --git a/storage/connect/value.cpp b/storage/connect/value.cpp
index c818070b970..7653b222a41 100644
--- a/storage/connect/value.cpp
+++ b/storage/connect/value.cpp
@@ -83,6 +83,7 @@ int DTVAL::Shift = 0;
/* Routines called externally. */
/***********************************************************************/
bool PlugEvalLike(PGLOBAL, LPCSTR, LPCSTR, bool);
+
#if !defined(WIN32)
extern "C" {
PSZ strupr(PSZ s);
@@ -90,6 +91,34 @@ PSZ strlwr(PSZ s);
}
#endif // !WIN32
+#if defined(BLK_INDX)
+/***********************************************************************/
+/* Returns the bitmap representing the conditions that must not be */
+/* met when returning from TestValue for a given operator. */
+/* Bit one is EQ, bit 2 is LT, and bit 3 is GT. */
+/***********************************************************************/
+BYTE OpBmp(PGLOBAL g, OPVAL opc)
+ {
+ BYTE bt;
+
+ switch (opc) {
+ case OP_IN:
+ case OP_EQ: bt = 0x06; break;
+ case OP_NE: bt = 0x01; break;
+ case OP_GT: bt = 0x03; break;
+ case OP_GE: bt = 0x02; break;
+ case OP_LT: bt = 0x05; break;
+ case OP_LE: bt = 0x04; break;
+ case OP_EXIST: bt = 0x00; break;
+ default:
+ sprintf(g->Message, MSG(BAD_FILTER_OP), opc);
+ longjmp(g->jumper[g->jump_level], TYPE_ARRAY);
+ } // endswitch opc
+
+ return bt;
+ } // end of OpBmp
+#endif // BLK_INDX
+
/***********************************************************************/
/* Get a long long number from its character representation. */
/* IN p: Pointer to the numeric string */
@@ -277,7 +306,7 @@ const char *GetFmt(int type, bool un)
return fmt;
} // end of GetFmt
-#if 0
+#if defined(BLK_INDX)
/***********************************************************************/
/* ConvertType: what this function does is to determine the type to */
/* which should be converted a value so no precision would be lost. */
@@ -324,7 +353,7 @@ int ConvertType(int target, int type, CONV kind, bool match)
} // endswitch kind
} // end of ConvertType
-#endif // 0
+#endif // BLK_INDX
/***********************************************************************/
/* AllocateConstant: allocates a constant Value. */
@@ -422,7 +451,7 @@ PVAL AllocateValue(PGLOBAL g, int type, int len, int prec,
return valp;
} // end of AllocateValue
-#if 0
+#if defined(BLK_INDX)
/***********************************************************************/
/* Allocate a constant Value converted to newtype. */
/* Can also be used to copy a Value eventually converted. */
@@ -490,7 +519,7 @@ PVAL AllocateValue(PGLOBAL g, PVAL valp, int newtype, int uns)
valp->SetGlobal(g);
return valp;
} // end of AllocateValue
-#endif // 0
+#endif // BLK_INDX
/* -------------------------- Class VALUE ---------------------------- */
@@ -527,6 +556,20 @@ const char *VALUE::GetXfmt(void)
return fmt;
} // end of GetFmt
+#if defined(BLK_INDX)
+/***********************************************************************/
+/* Returns a BYTE indicating the comparison between two values. */
+/* Bit 1 indicates equality, Bit 2 less than, and Bit3 greater than. */
+/* More than 1 bit can be set only in the case of TYPE_LIST. */
+/***********************************************************************/
+BYTE VALUE::TestValue(PVAL vp)
+ {
+ int n = CompareValue(vp);
+
+ return (n > 0) ? 0x04 : (n < 0) ? 0x02 : 0x01;
+ } // end of TestValue
+#endif // BLK_INDX
+
/* -------------------------- Class TYPVAL ---------------------------- */
/***********************************************************************/
@@ -897,6 +940,26 @@ bool TYPVAL<TYPE>::IsEqual(PVAL vp, bool chktype)
} // end of IsEqual
+#if defined(BLK_INDX)
+/***********************************************************************/
+/* Compare values and returns 1, 0 or -1 according to comparison. */
+/* This function is used for evaluation of numeric filters. */
+/***********************************************************************/
+template <class TYPE>
+int TYPVAL<TYPE>::CompareValue(PVAL vp)
+ {
+//assert(vp->GetType() == Type);
+
+ // Process filtering on numeric values.
+ TYPE n = GetTypedValue(vp);
+
+//if (trace)
+// htrc(" Comparing: val=%d,%d\n", Tval, n);
+
+ return (Tval > n) ? 1 : (Tval < n) ? (-1) : 0;
+ } // end of CompareValue
+#endif // BLK_INDX
+
/***********************************************************************/
/* FormatValue: This function set vp (a STRING value) to the string */
/* constructed from its own value formated using the fmt format. */
@@ -1347,6 +1410,34 @@ bool TYPVAL<PSZ>::IsEqual(PVAL vp, bool chktype)
} // end of IsEqual
+#if defined(BLK_INDX)
+/***********************************************************************/
+/* Compare values and returns 1, 0 or -1 according to comparison. */
+/* This function is used for evaluation of numeric filters. */
+/***********************************************************************/
+int TYPVAL<PSZ>::CompareValue(PVAL vp)
+ {
+ int n;
+//assert(vp->GetType() == Type);
+
+ if (trace)
+ htrc(" Comparing: val='%s','%s'\n", Strp, vp->GetCharValue());
+
+ // Process filtering on character strings.
+ if (Ci || vp->IsCi())
+ n = stricmp(Strp, vp->GetCharValue());
+ else
+ n = strcmp(Strp, vp->GetCharValue());
+
+#if defined(WIN32)
+ if (n == _NLSCMPERROR)
+ return n; // Here we should raise an error
+#endif // WIN32
+
+ return (n > 0) ? 1 : (n < 0) ? -1 : 0;
+ } // end of CompareValue
+#endif // BLK_INDX
+
/***********************************************************************/
/* FormatValue: This function set vp (a STRING value) to the string */
/* constructed from its own value formated using the fmt format. */
@@ -1573,6 +1664,25 @@ bool DECVAL::IsEqual(PVAL vp, bool chktype)
return !strcmp(Strp, vp->GetCharString(buf));
} // end of IsEqual
+#if defined(BLK_INDX)
+/***********************************************************************/
+/* Compare values and returns 1, 0 or -1 according to comparison. */
+/* This function is used for evaluation of numeric filters. */
+/***********************************************************************/
+int DECVAL::CompareValue(PVAL vp)
+ {
+//assert(vp->GetType() == Type);
+
+ // Process filtering on numeric values.
+ double f = atof(Strp), n = vp->GetFloatValue();
+
+//if (trace)
+// htrc(" Comparing: val=%d,%d\n", f, n);
+
+ return (f > n) ? 1 : (f < n) ? (-1) : 0;
+ } // end of CompareValue
+#endif // BLK_INDX
+
#if 0
/***********************************************************************/
/* FormatValue: This function set vp (a STRING value) to the string */
diff --git a/storage/connect/value.h b/storage/connect/value.h
index f8e89ba55fd..39fee7f73bb 100644
--- a/storage/connect/value.h
+++ b/storage/connect/value.h
@@ -46,8 +46,10 @@ DllExport char *GetFormatType(int);
DllExport int GetFormatType(char);
DllExport bool IsTypeChar(int type);
DllExport bool IsTypeNum(int type);
-//lExport int ConvertType(int, int, CONV, bool match = false);
-//lExport PVAL AllocateValue(PGLOBAL, PVAL, int = TYPE_VOID, int = 0);
+#if defined(BLK_INDX)
+DllExport int ConvertType(int, int, CONV, bool match = false);
+DllExport PVAL AllocateValue(PGLOBAL, PVAL, int = TYPE_VOID, int = 0);
+#endif // BLK_INDX
DllExport PVAL AllocateValue(PGLOBAL, int, int len = 0, int prec = 0,
bool uns = false, PSZ fmt = NULL);
DllExport ulonglong CharToNumber(char *, int, ulonglong, bool,
@@ -95,6 +97,11 @@ class DllExport VALUE : public BLOCK {
virtual bool SetValue_pval(PVAL valp, bool chktype = false) = 0;
virtual bool SetValue_char(char *p, int n) = 0;
virtual void SetValue_psz(PSZ s) = 0;
+#if defined(BLK_INDX)
+ virtual void SetValue_bool(bool b) {assert(FALSE);}
+ virtual int CompareValue(PVAL vp) = 0;
+ virtual BYTE TestValue(PVAL vp);
+#endif // BLK_INDX
virtual void SetValue(char c) {assert(false);}
virtual void SetValue(uchar c) {assert(false);}
virtual void SetValue(short i) {assert(false);}
@@ -163,6 +170,10 @@ class DllExport TYPVAL : public VALUE {
virtual bool SetValue_pval(PVAL valp, bool chktype);
virtual bool SetValue_char(char *p, int n);
virtual void SetValue_psz(PSZ s);
+#if defined(BLK_INDX)
+ virtual void SetValue_bool(bool b) {Tval = (b) ? 1 : 0;}
+ virtual int CompareValue(PVAL vp);
+#endif // BLK_INDX
virtual void SetValue(char c) {Tval = (TYPE)c; Null = false;}
virtual void SetValue(uchar c) {Tval = (TYPE)c; Null = false;}
virtual void SetValue(short i) {Tval = (TYPE)i; Null = false;}
@@ -242,6 +253,9 @@ class DllExport TYPVAL<PSZ>: public VALUE {
virtual void SetValue(ulonglong n);
virtual void SetValue(double f);
virtual void SetBinValue(void *p);
+#if defined(BLK_INDX)
+ virtual int CompareValue(PVAL vp);
+#endif // BLK_INDX
virtual bool GetBinValue(void *buf, int buflen, bool go);
virtual char *ShowValue(char *buf, int);
virtual char *GetCharString(char *p);
@@ -280,6 +294,9 @@ class DllExport DECVAL: public TYPVAL<PSZ> {
virtual char *ShowValue(char *buf, int);
//virtual char *GetCharString(char *p);
virtual bool IsEqual(PVAL vp, bool chktype);
+#if defined(BLK_INDX)
+ virtual int CompareValue(PVAL vp);
+#endif // BLK_INDX
//virtual bool FormatValue(PVAL vp, char *fmt);
//virtual bool SetConstFormat(PGLOBAL, FORMAT&);
diff --git a/storage/connect/xobject.cpp b/storage/connect/xobject.cpp
index aa87517bd2e..4050fd520fa 100644
--- a/storage/connect/xobject.cpp
+++ b/storage/connect/xobject.cpp
@@ -109,7 +109,7 @@ int CONSTANT::GetLengthEx(void)
return Value->GetValLen();
} // end of GetLengthEx
-#if 0
+#if defined(BLK_INDX)
/***********************************************************************/
/* Convert a constant to the given type. */
/***********************************************************************/
@@ -120,7 +120,7 @@ void CONSTANT::Convert(PGLOBAL g, int newtype)
longjmp(g->jumper[g->jump_level], TYPE_CONST);
} // end of Convert
-#endif // 0
+#endif // BLK_INDX
/***********************************************************************/
/* Compare: returns true if this object is equivalent to xp. */
diff --git a/storage/connect/xobject.h b/storage/connect/xobject.h
index b7869be96b2..793a08ddb9e 100644
--- a/storage/connect/xobject.h
+++ b/storage/connect/xobject.h
@@ -68,7 +68,7 @@ class DllExport XOBJECT : public BLOCK {
virtual bool CheckLocal(PTDB) {return true;}
virtual int CheckSpcCol(PTDB, int) {return 2;}
virtual bool CheckSort(PTDB) {return false;}
- virtual bool VerifyColumn(PTBX txp) {return false;}
+ virtual bool VerifyColumn(PTDB txp) {return false;}
virtual bool VerifyTdb(PTDB& tdbp) {return false;}
virtual bool IsColInside(PCOL colp) {return false;}
@@ -123,10 +123,12 @@ class DllExport CONSTANT : public XOBJECT {
virtual bool SetFormat(PGLOBAL g, FORMAT& fmt)
{return Value->SetConstFormat(g, fmt);}
virtual int CheckSpcCol(PTDB, int) {return 1;}
-// void Convert(PGLOBAL g, int newtype);
+#if defined(BLK_INDX)
+ void Convert(PGLOBAL g, int newtype);
+#endif // BLK_INDX
// bool Rephrase(PGLOBAL g, PSZ work);
void SetValue(PVAL vp) {Value = vp;}
- virtual bool VerifyColumn(PTBX txp) {return true;}
+ virtual bool VerifyColumn(PTDB txp) {return true;}
virtual bool VerifyTdb(PTDB& tdbp) {return true;}
virtual void Print(PGLOBAL g, FILE *, uint);
virtual void Print(PGLOBAL g, char *, uint);
diff --git a/storage/connect/xtable.h b/storage/connect/xtable.h
index 8884860cb5b..79b343e8a6d 100644
--- a/storage/connect/xtable.h
+++ b/storage/connect/xtable.h
@@ -33,58 +33,20 @@ class CMD : public BLOCK {
char *Cmd;
}; // end of class CMD
-// Filter passed all tables
-typedef struct _filter {
+// Condition filter structure
+typedef struct _cond_filter {
char *Body;
OPVAL Op;
PCMD Cmds;
-} FILTER, *PFIL;
+} CONDFIL, *PCFIL;
typedef class TDBCAT *PTDBCAT;
typedef class CATCOL *PCATCOL;
/***********************************************************************/
-/* Definition of class TBX (pure virtual class for TDB and OPJOIN) */
-/***********************************************************************/
-class DllExport TBX: public BLOCK { // Base class for OPJOIN and TDB classes.
- public:
- // Constructors
- TBX(void);
- TBX(PTBX txp);
-
- // Implementation
- inline PTBX GetOrig(void) {return To_Orig;}
- inline TUSE GetUse(void) {return Use;}
- inline void SetUse(TUSE n) {Use = n;}
- inline PFIL GetFilter(void) {return To_Filter;}
- inline void SetOrig(PTBX txp) {To_Orig = txp;}
- inline void SetFilter(PFIL fp) {To_Filter = fp;}
-
- // Methods
- virtual bool IsSame(PTBX tp) {return tp == this;}
- virtual int GetTdb_No(void) = 0; // Convenience during conversion
- virtual PTDB GetNext(void) = 0;
- virtual int Cardinality(PGLOBAL) = 0;
- virtual int GetMaxSize(PGLOBAL) = 0;
- virtual int GetProgMax(PGLOBAL) = 0;
- virtual int GetProgCur(void) = 0;
- virtual int GetBadLines(void) {return 0;}
- virtual PTBX Copy(PTABS t) = 0;
-
- protected:
-//virtual void PrepareFilters(PGLOBAL g) = 0;
-
- protected:
- // Members
- PTBX To_Orig; // Pointer to original if it is a copy
- PFIL To_Filter;
- TUSE Use;
- }; // end of class TBX
-
-/***********************************************************************/
/* Definition of class TDB with all its method functions. */
/***********************************************************************/
-class DllExport TDB: public TBX { // Table Descriptor Block.
+class DllExport TDB: public BLOCK { // Table Descriptor Block.
public:
// Constructors
TDB(PTABDEF tdp = NULL);
@@ -92,11 +54,21 @@ class DllExport TDB: public TBX { // Table Descriptor Block.
// Implementation
static void SetTnum(int n) {Tnum = n;}
+ inline PTDB GetOrig(void) {return To_Orig;}
+ inline TUSE GetUse(void) {return Use;}
+ inline PCFIL GetCondFil(void) {return To_CondFil;}
inline LPCSTR GetName(void) {return Name;}
inline PTABLE GetTable(void) {return To_Table;}
inline PCOL GetColumns(void) {return Columns;}
inline int GetDegree(void) {return Degree;}
inline MODE GetMode(void) {return Mode;}
+#if defined(BLK_INDX)
+ inline PFIL GetFilter(void) {return To_Filter;}
+ inline void SetFilter(PFIL fp) {To_Filter = fp;}
+#endif // BLK_INDX
+ inline void SetOrig(PTDB txp) {To_Orig = txp;}
+ inline void SetUse(TUSE n) {Use = n;}
+ inline void SetCondFil(PCFIL cfp) {To_CondFil = cfp;}
inline void SetNext(PTDB tdbp) {Next = tdbp;}
inline void SetName(LPCSTR name) {Name = name;}
inline void SetTable(PTABLE tablep) {To_Table = tablep;}
@@ -105,25 +77,30 @@ class DllExport TDB: public TBX { // Table Descriptor Block.
inline void SetMode(MODE mode) {Mode = mode;}
//Properties
+ virtual AMT GetAmType(void) {return TYPE_AM_ERROR;}
virtual int GetTdb_No(void) {return Tdb_No;}
virtual PTDB GetNext(void) {return Next;}
virtual PCATLG GetCat(void) {return NULL;}
// Methods
- virtual AMT GetAmType(void) {return TYPE_AM_ERROR;}
+ virtual bool IsSame(PTDB tp) {return tp == this;}
virtual bool GetBlockValues(PGLOBAL g) {return false;}
virtual int Cardinality(PGLOBAL g) {return (g) ? -1 : 0;}
+ virtual int GetMaxSize(PGLOBAL) = 0;
+ virtual int GetProgMax(PGLOBAL) = 0;
+ virtual int GetProgCur(void) = 0;
virtual int RowNumber(PGLOBAL g, bool b = false);
virtual bool IsReadOnly(void) {return true;}
- virtual const CHARSET_INFO *data_charset() { return NULL; }
+ virtual const CHARSET_INFO *data_charset() {return NULL;}
virtual PTDB Duplicate(PGLOBAL g) {return NULL;}
virtual PTDB CopyOne(PTABS t) {return this;}
- virtual PTBX Copy(PTABS t);
+ virtual PTDB Copy(PTABS t);
virtual void PrintAM(FILE *f, char *m)
{fprintf(f, "%s AM(%d)\n", m, GetAmType());}
virtual void Print(PGLOBAL g, FILE *f, uint n);
virtual void Print(PGLOBAL g, char *ps, uint z);
virtual PSZ GetServer(void) = 0;
+ virtual int GetBadLines(void) {return 0;}
// Database pure virtual routines
virtual PCOL ColDB(PGLOBAL g, PSZ name, int num) = 0;
@@ -141,6 +118,12 @@ class DllExport TDB: public TBX { // Table Descriptor Block.
protected:
// Members
+ PTDB To_Orig; // Pointer to original if it is a copy
+ TUSE Use;
+#if defined(BLK_INDX)
+ PFIL To_Filter;
+#endif // BLK_INDX
+ PCFIL To_CondFil; // To condition filter structure
static int Tnum; // Used to generate Tdb_no's
const int Tdb_No; // GetTdb_No() is always 0 for OPJOIN
PTDB Next; // Next in linearized queries
@@ -194,7 +177,7 @@ class DllExport TDBASE : public TDB {
virtual void ResetDB(void) {}
virtual void ResetSize(void) {MaxSize = -1;}
virtual void RestoreNrec(void) {}
- virtual int ResetTableOpt(PGLOBAL g, bool dox);
+ virtual int ResetTableOpt(PGLOBAL g, bool dop, bool dox);
virtual PSZ GetServer(void) {return "Current";}
// Database routines