summaryrefslogtreecommitdiff
path: root/storage/connect/xindex.cpp
diff options
context:
space:
mode:
authorSergei Golubchik <serg@mariadb.org>2014-10-15 12:59:13 +0200
committerSergei Golubchik <serg@mariadb.org>2014-10-15 12:59:13 +0200
commitf62c12b405ba7ec80b8e2490856b83c6f5899211 (patch)
tree010605c7f145da6ea6ac14b39abc4cf700d619b1 /storage/connect/xindex.cpp
parentf947f73b2b6d2bd246b81a9038224d2a85777520 (diff)
parentf1afc003eefe0aafd3e070c7453d9e029d8445a8 (diff)
downloadmariadb-git-f62c12b405ba7ec80b8e2490856b83c6f5899211.tar.gz
Merge 10.0.14 into 10.1
Diffstat (limited to 'storage/connect/xindex.cpp')
-rwxr-xr-xstorage/connect/xindex.cpp480
1 files changed, 318 insertions, 162 deletions
diff --git a/storage/connect/xindex.cpp b/storage/connect/xindex.cpp
index fad7495fa82..7cc52580760 100755
--- a/storage/connect/xindex.cpp
+++ b/storage/connect/xindex.cpp
@@ -1,7 +1,7 @@
/***************** Xindex C++ Class Xindex Code (.CPP) *****************/
-/* Name: XINDEX.CPP Version 2.8 */
+/* Name: XINDEX.CPP Version 2.9 */
/* */
-/* (C) Copyright to the author Olivier BERTRAND 2004-2013 */
+/* (C) Copyright to the author Olivier BERTRAND 2004-2014 */
/* */
/* This file contains the class XINDEX implementation code. */
/***********************************************************************/
@@ -45,11 +45,12 @@
//nclude "array.h"
#include "filamtxt.h"
#include "tabdos.h"
+#include "tabvct.h"
/***********************************************************************/
/* Macro or external routine definition */
/***********************************************************************/
-#define NZ 7
+#define NZ 8
#define NW 5
#define MAX_INDX 10
#ifndef INVALID_SET_FILE_POINTER
@@ -112,6 +113,8 @@ INDEXDEF::INDEXDEF(char *name, bool uniq, int n)
Unique = uniq;
Invalid = false;
AutoInc = false;
+ Dynamic = false;
+ Mapped = false;
Nparts = 0;
ID = n;
//Offset = 0;
@@ -165,6 +168,8 @@ XXBASE::XXBASE(PTDBDOS tbxp, bool b) : CSORT(b),
Op = OP_EQ;
To_KeyCol = NULL;
Mul = false;
+ Srtd = false;
+ Dynamic = false;
Val_K = -1;
Nblk = Sblk = 0;
Thresh = 7;
@@ -237,25 +242,27 @@ void XINDEX::Reset(void)
/***********************************************************************/
/* XINDEX Close: terminate index and free all allocated data. */
-/* Do not reset other values that are used at return to make. */
+/* Do not reset values that are used at return to make. */
/***********************************************************************/
void XINDEX::Close(void)
{
// Close file or view of file
- X->Close();
+ if (X)
+ X->Close();
// De-allocate data
PlgDBfree(Record);
PlgDBfree(Index);
PlgDBfree(Offset);
- // De-allocate Key data
- for (PXCOL kcp = To_KeyCol; kcp; kcp = kcp->Next)
- kcp->FreeData();
+ for (PXCOL kcp = To_KeyCol; kcp; kcp = kcp->Next) {
+ // Column values cannot be retrieved from key anymore
+ if (kcp->Colp)
+ kcp->Colp->SetKcol(NULL);
- // Column values cannot be retrieved from key anymore
- for (int k = 0; k < Nk; k++)
- To_Cols[k]->SetKcol(NULL);
+ // De-allocate Key data
+ kcp->FreeData();
+ } // endfor kcp
} // end of Close
@@ -276,6 +283,25 @@ int XINDEX::Qcompare(int *i1, int *i2)
} // end of Qcompare
/***********************************************************************/
+/* AddColumns: here we try to determine whether it is worthwhile to */
+/* add to the keys the values of the columns selected for this table. */
+/* Sure enough, it is done while records are read and permit to avoid */
+/* reading the table while doing the join (Dynamic index only) */
+/***********************************************************************/
+bool XINDEX::AddColumns(PIXDEF xdp)
+ {
+ if (!Dynamic)
+ return false; // Not applying to static index
+ else if (IsMul())
+ return false; // Not done yet for multiple index
+ else if (Tbxp->GetAmType() == TYPE_AM_VCT && ((PTDBVCT)Tbxp)->IsSplit())
+ return false; // This would require to read additional files
+ else
+ return true;
+
+ } // end of AddColumns
+
+/***********************************************************************/
/* Make: Make and index on key column(s). */
/***********************************************************************/
bool XINDEX::Make(PGLOBAL g, PIXDEF sxp)
@@ -283,13 +309,18 @@ bool XINDEX::Make(PGLOBAL g, PIXDEF sxp)
/*********************************************************************/
/* Table can be accessed through an index. */
/*********************************************************************/
- int k, rc = RC_OK;
+ int k, nk = Nk, rc = RC_OK;
int *bof, i, j, n, ndf, nkey;
PKPDEF kdfp = Xdp->GetToKeyParts();
- bool brc = true;
+ bool brc = false;
PCOL colp;
- PXCOL kp, prev = NULL, kcp = NULL;
- PDBUSER dup = (PDBUSER)g->Activityp->Aptr;
+ PFIL filp = Tdbp->GetFilter();
+ PXCOL kp, addcolp, prev = NULL, kcp = NULL;
+//PDBUSER dup = (PDBUSER)g->Activityp->Aptr;
+
+#if defined(_DEBUG)
+ assert(X || Nk == 1);
+#endif // _DEBUG
/*********************************************************************/
/* Allocate the storage that will contain the keys and the file */
@@ -347,6 +378,51 @@ bool XINDEX::Make(PGLOBAL g, PIXDEF sxp)
To_LastCol = prev;
+ if (AddColumns(sxp)) {
+ PCOL kolp = To_Cols[0]; // Temporary while imposing Nk = 1
+
+ i = 0;
+
+ // Allocate the accompanying
+ for (colp = Tbxp->GetColumns(); colp; colp = colp->GetNext()) {
+ // Count how many columns to add
+// for (k = 0; k < Nk; k++)
+// if (colp == To_Cols[k])
+// break;
+
+// if (k == nk)
+ if (colp != kolp)
+ i++;
+
+ } // endfor colp
+
+ if (i && i < 10) // Should be a parameter
+ for (colp = Tbxp->GetColumns(); colp; colp = colp->GetNext()) {
+// for (k = 0; k < Nk; k++)
+// if (colp == To_Cols[k])
+// break;
+
+// if (k < nk)
+ if (colp == kolp)
+ continue; // This is a key column
+
+ kcp = new(g) KXYCOL(this);
+
+ if (kcp->Init(g, colp, n, true, 0))
+ return true;
+
+ if (trace)
+ htrc("Adding colp=%p Buf_Type=%d size=%d\n",
+ colp, colp->GetResultType(), n);
+
+ nk++;
+ prev->Next = kcp;
+ prev = kcp;
+ } // endfor colp
+
+ } // endif AddColumns
+
+#if 0
/*********************************************************************/
/* Get the starting information for progress. */
/*********************************************************************/
@@ -354,18 +430,19 @@ bool XINDEX::Make(PGLOBAL g, PIXDEF sxp)
sprintf((char*)dup->Step, MSG(BUILD_INDEX), Xdp->GetName(), Tdbp->Name);
dup->ProgMax = Tdbp->GetProgMax(g);
dup->ProgCur = 0;
+#endif // 0
/*********************************************************************/
/* Standard init: read the file and construct the index table. */
/* Note: reading will be sequential as To_Kindex is not set. */
/*********************************************************************/
- for (i = nkey = 0; i < n && rc != RC_EF; i++) {
-#if defined(THREAD)
+ for (i = nkey = 0; rc != RC_EF; i++) {
+#if 0
if (!dup->Step) {
strcpy(g->Message, MSG(QUERY_CANCELLED));
longjmp(g->jumper[g->jump_level], 99);
} // endif Step
-#endif // THREAD
+#endif // 0
/*******************************************************************/
/* Read a valid record from table file. */
@@ -373,16 +450,19 @@ bool XINDEX::Make(PGLOBAL g, PIXDEF sxp)
rc = Tdbp->ReadDB(g);
// Update progress information
- dup->ProgCur = Tdbp->GetProgCur();
+// dup->ProgCur = Tdbp->GetProgCur();
// Check return code and do whatever must be done according to it
switch (rc) {
case RC_OK:
- break;
- case RC_EF:
- goto end_of_file;
+ if (ApplyFilter(g, filp))
+ break;
+
+ // passthru
case RC_NF:
continue;
+ case RC_EF:
+ goto end_of_file;
default:
sprintf(g->Message, MSG(RC_READING), rc, Tdbp->Name);
goto err;
@@ -392,20 +472,25 @@ bool XINDEX::Make(PGLOBAL g, PIXDEF sxp)
/* Get and Store the file position of the last read record for */
/* future direct access. */
/*******************************************************************/
- To_Rec[nkey] = Tdbp->GetRecpos();
+ if (nkey == n) {
+ sprintf(g->Message, MSG(TOO_MANY_KEYS), nkey);
+ return true;
+ } else
+ To_Rec[nkey] = Tdbp->GetRecpos();
/*******************************************************************/
/* Get the keys and place them in the key blocks. */
/*******************************************************************/
for (k = 0, kcp = To_KeyCol;
- k < Nk && kcp;
+ k < nk && kcp;
k++, kcp = kcp->Next) {
- colp = To_Cols[k];
- colp->Reset();
+// colp = To_Cols[k];
+ colp = kcp->Colp;
- colp->ReadColumn(g);
-// if (colp->ReadColumn(g))
-// goto err;
+ if (!colp->GetStatus(BUF_READ))
+ colp->ReadColumn(g);
+ else
+ colp->Reset();
kcp->SetValue(colp, nkey);
} // endfor k
@@ -416,7 +501,7 @@ bool XINDEX::Make(PGLOBAL g, PIXDEF sxp)
end_of_file:
// Update progress information
- dup->ProgCur = Tdbp->GetProgMax(g);
+//dup->ProgCur = Tdbp->GetProgMax(g);
/*********************************************************************/
/* Record the Index size and eventually resize memory allocation. */
@@ -451,18 +536,30 @@ bool XINDEX::Make(PGLOBAL g, PIXDEF sxp)
goto err; // Error
} // endif alloc
+ // We must separate keys and added columns before sorting
+ addcolp = To_LastCol->Next;
+ To_LastCol->Next = NULL;
+
// Call the sort program, it returns the number of distinct values
if ((Ndif = Qsort(g, Num_K)) < 0)
goto err; // Error during sort
+ if (trace)
+ htrc("Make: Nk=%d n=%d Num_K=%d Ndif=%d addcolp=%p BlkFil=%p X=%p\n",
+ Nk, n, Num_K, Ndif, addcolp, Tdbp->To_BlkFil, X);
+
// Check whether the unique index is unique indeed
if (!Mul)
if (Ndif < Num_K) {
strcpy(g->Message, MSG(INDEX_NOT_UNIQ));
+ brc = true;
goto err;
} else
PlgDBfree(Offset); // Not used anymore
+ // Restore kcp list
+ To_LastCol->Next = addcolp;
+
// Use the index to physically reorder the xindex
Srtd = Reorder(g);
@@ -487,7 +584,7 @@ bool XINDEX::Make(PGLOBAL g, PIXDEF sxp)
} else {
Mul = false; // Current index is unique
PlgDBfree(Offset); // Not used anymore
- MaxSame = 1; // Reset it when remaking an index
+ MaxSame = 1; // Reset it when remaking an index
} // endif Ndif
/*********************************************************************/
@@ -502,7 +599,7 @@ bool XINDEX::Make(PGLOBAL g, PIXDEF sxp)
/* except if the subset originally contains unique values. */
/*********************************************************************/
// Update progress information
- dup->Step = STEP(REDUCE_INDEX);
+//dup->Step = STEP(REDUCE_INDEX);
ndf = Ndif;
To_LastCol->Mxs = MaxSame;
@@ -550,9 +647,11 @@ bool XINDEX::Make(PGLOBAL g, PIXDEF sxp)
/*********************************************************************/
/* For sorted columns and fixed record size, file position can be */
/* calculated, so the Record array can be discarted. */
+ /* Not true for DBF tables because of eventual soft deleted lines. */
/* Note: for Num_K = 1 any non null value is Ok. */
/*********************************************************************/
- if (Srtd && Tdbp->Ftype != RECFM_VAR) {
+ if (Srtd && !filp && Tdbp->Ftype != RECFM_VAR
+ && Tdbp->Txfp->GetAmType() != TYPE_AM_DBF) {
Incr = (Num_K > 1) ? To_Rec[1] : Num_K;
PlgDBfree(Record);
} // endif Srtd
@@ -579,14 +678,24 @@ bool XINDEX::Make(PGLOBAL g, PIXDEF sxp)
Cur_K = Num_K;
/*********************************************************************/
- /* Save the index so it has not to be recalculated. */
+ /* Save the xindex so it has not to be recalculated. */
/*********************************************************************/
- if (!SaveIndex(g, sxp))
- brc = false;
+ if (X) {
+ if (SaveIndex(g, sxp))
+ brc = true;
+
+ } else { // Dynamic index
+ // Indicate that key column values can be found from KEYCOL's
+ for (kcp = To_KeyCol; kcp; kcp = kcp->Next)
+ kcp->Colp->SetKcol(kcp);
+
+ Tdbp->SetFilter(NULL); // Not used anymore
+ } // endif X
err:
// We don't need the index anymore
- Close();
+ if (X || brc)
+ Close();
if (brc)
printf("%s\n", g->Message);
@@ -630,6 +739,7 @@ bool XINDEX::Reorder(PGLOBAL g)
register int i, j, k, n;
bool sorted = true;
PXCOL kcp;
+#if 0
PDBUSER dup = (PDBUSER)g->Activityp->Aptr;
if (Num_K > 500000) {
@@ -639,6 +749,7 @@ bool XINDEX::Reorder(PGLOBAL g)
dup->ProgCur = 0;
} else
dup = NULL;
+#endif // 0
if (!Pex)
return Srtd;
@@ -647,8 +758,8 @@ bool XINDEX::Reorder(PGLOBAL g)
if (Pex[i] == Num_K) { // Already moved
continue;
} else if (Pex[i] == i) { // Already placed
- if (dup)
- dup->ProgCur++;
+// if (dup)
+// dup->ProgCur++;
continue;
} // endif's Pex
@@ -677,8 +788,8 @@ bool XINDEX::Reorder(PGLOBAL g)
To_Rec[j] = To_Rec[k];
} // endif k
- if (dup)
- dup->ProgCur++;
+// if (dup)
+// dup->ProgCur++;
} // endfor j
@@ -706,11 +817,11 @@ bool XINDEX::SaveIndex(PGLOBAL g, PIXDEF sxp)
bool sep, rc = false;
PXCOL kcp = To_KeyCol;
PDOSDEF defp = (PDOSDEF)Tdbp->To_Def;
- PDBUSER dup = PlgGetUser(g);
+//PDBUSER dup = PlgGetUser(g);
- dup->Step = STEP(SAVING_INDEX);
- dup->ProgMax = 15 + 16 * Nk;
- dup->ProgCur = 0;
+//dup->Step = STEP(SAVING_INDEX);
+//dup->ProgMax = 15 + 16 * Nk;
+//dup->ProgCur = 0;
switch (Tdbp->Ftype) {
case RECFM_VAR: ftype = ".dnx"; break;
@@ -755,31 +866,32 @@ bool XINDEX::SaveIndex(PGLOBAL g, PIXDEF sxp)
/*********************************************************************/
/* Write the index values on the index file. */
/*********************************************************************/
- n[0] = ID; // To check validity
+ n[0] = ID + MAX_INDX; // To check validity
n[1] = Nk; // The number of indexed columns
n[2] = nof; // The offset array size or 0
n[3] = Num_K; // The index size
n[4] = Incr; // Increment of record positions
n[5] = Nblk; n[6] = Sblk;
+ n[7] = Srtd ? 1 : 0; // Values are sorted in the file
-#if defined(TRACE)
- printf("Saving index %s\n", Xdp->GetName());
- printf("ID=%d Nk=%d nof=%d Num_K=%d Incr=%d Nblk=%d Sblk=%d\n",
- ID, Nk, nof, Num_K, Incr, Nblk, Sblk);
-#endif // TRACE
+ if (trace) {
+ htrc("Saving index %s\n", Xdp->GetName());
+ htrc("ID=%d Nk=%d nof=%d Num_K=%d Incr=%d Nblk=%d Sblk=%d Srtd=%d\n",
+ ID, Nk, nof, Num_K, Incr, Nblk, Sblk, Srtd);
+ } // endif trace
size = X->Write(g, n, NZ, sizeof(int), rc);
- dup->ProgCur = 1;
+//dup->ProgCur = 1;
if (Mul) // Write the offset array
size += X->Write(g, Pof, nof, sizeof(int), rc);
- dup->ProgCur = 5;
+//dup->ProgCur = 5;
if (!Incr) // Write the record position array(s)
size += X->Write(g, To_Rec, Num_K, sizeof(int), rc);
- dup->ProgCur = 15;
+//dup->ProgCur = 15;
for (; kcp; kcp = kcp->Next) {
n[0] = kcp->Ndf; // Number of distinct sub-values
@@ -789,25 +901,24 @@ bool XINDEX::SaveIndex(PGLOBAL g, PIXDEF sxp)
n[4] = kcp->Type; // To be checked later
size += X->Write(g, n, NW, sizeof(int), rc);
- dup->ProgCur += 1;
+// dup->ProgCur += 1;
if (n[2])
size += X->Write(g, kcp->To_Bkeys, Nblk, kcp->Klen, rc);
- dup->ProgCur += 5;
+// dup->ProgCur += 5;
size += X->Write(g, kcp->To_Keys, n[0], kcp->Klen, rc);
- dup->ProgCur += 5;
+// dup->ProgCur += 5;
if (n[1])
size += X->Write(g, kcp->Kof, n[1], sizeof(int), rc);
- dup->ProgCur += 5;
+// dup->ProgCur += 5;
} // endfor kcp
-#if defined(TRACE)
- printf("Index %s saved, Size=%d\n", Xdp->GetName(), Size);
-#endif // TRACE
+ if (trace)
+ htrc("Index %s saved, Size=%d\n", Xdp->GetName(), size);
end:
X->Close(fn, id);
@@ -896,9 +1007,8 @@ bool XINDEX::Init(PGLOBAL g)
PlugSetPath(fn, fn, Tdbp->GetPath());
-#if defined(TRACE)
- printf("Index %s file: %s\n", Xdp->GetName(), fn);
-#endif // TRACE
+ if (trace)
+ htrc("Index %s file: %s\n", Xdp->GetName(), fn);
/*********************************************************************/
/* Open the index file and check its validity. */
@@ -907,21 +1017,31 @@ bool XINDEX::Init(PGLOBAL g)
goto err; // No saved values
// Now start the reading process.
- if (X->Read(g, nv, NZ, sizeof(int)))
+ if (X->Read(g, nv, NZ - 1, sizeof(int)))
goto err;
-#if defined(TRACE)
- printf("nv=%d %d %d %d %d %d %d\n",
- nv[0], nv[1], nv[2], nv[3], nv[4], nv[5], nv[6]);
-#endif // TRACE
+ if (nv[0] >= MAX_INDX) {
+ // New index format
+ if (X->Read(g, nv + 7, 1, sizeof(int)))
+ goto err;
+
+ Srtd = nv[7] != 0;
+ nv[0] -= MAX_INDX;
+ } else
+ Srtd = false;
+
+ if (trace)
+ htrc("nv=%d %d %d %d %d %d %d (%d)\n",
+ nv[0], nv[1], nv[2], nv[3], nv[4], nv[5], nv[6], Srtd);
// The test on ID was suppressed because MariaDB can change an index ID
- // when other indexes are added or deleted
+ // when other indexes are added or deleted
if (/*nv[0] != ID ||*/ nv[1] != Nk) {
sprintf(g->Message, MSG(BAD_INDEX_FILE), fn);
-#if defined(TRACE)
- printf("nv[0]=%d ID=%d nv[1]=%d Nk=%d\n", nv[0], ID, nv[1], Nk);
-#endif // TRACE
+
+ if (trace)
+ htrc("nv[0]=%d ID=%d nv[1]=%d Nk=%d\n", nv[0], ID, nv[1], Nk);
+
goto err;
} // endif
@@ -1140,9 +1260,8 @@ bool XINDEX::MapInit(PGLOBAL g)
PlugSetPath(fn, fn, Tdbp->GetPath());
-#if defined(TRACE)
- printf("Index %s file: %s\n", Xdp->GetName(), fn);
-#endif // TRACE
+ if (trace)
+ htrc("Index %s file: %s\n", Xdp->GetName(), fn);
/*********************************************************************/
/* Get a view on the part of the index file containing this index. */
@@ -1157,24 +1276,33 @@ bool XINDEX::MapInit(PGLOBAL g)
// Position the memory base at the offset of this index
mbase += noff[id].Low;
} // endif id
-
+
// Now start the mapping process.
nv = (int*)mbase;
- mbase += NZ * sizeof(int);
-#if defined(TRACE)
- printf("nv=%d %d %d %d %d %d %d\n",
- nv[0], nv[1], nv[2], nv[3], nv[4], nv[5], nv[6]);
-#endif // TRACE
+ if (nv[0] >= MAX_INDX) {
+ // New index format
+ Srtd = nv[7] != 0;
+ nv[0] -= MAX_INDX;
+ mbase += NZ * sizeof(int);
+ } else {
+ Srtd = false;
+ mbase += (NZ - 1) * sizeof(int);
+ } // endif nv
+
+ if (trace)
+ htrc("nv=%d %d %d %d %d %d %d %d\n",
+ nv[0], nv[1], nv[2], nv[3], nv[4], nv[5], nv[6], Srtd);
// The test on ID was suppressed because MariaDB can change an index ID
- // when other indexes are added or deleted
+ // when other indexes are added or deleted
if (/*nv[0] != ID ||*/ nv[1] != Nk) {
// Not this index
sprintf(g->Message, MSG(BAD_INDEX_FILE), fn);
-#if defined(TRACE)
- printf("nv[0]=%d ID=%d nv[1]=%d Nk=%d\n", nv[0], ID, nv[1], Nk);
-#endif // TRACE
+
+ if (trace)
+ htrc("nv[0]=%d ID=%d nv[1]=%d Nk=%d\n", nv[0], ID, nv[1], Nk);
+
goto err;
} // endif nv
@@ -1272,16 +1400,19 @@ err:
/***********************************************************************/
/* Get Ndif and Num_K from the index file. */
/***********************************************************************/
-bool XINDEX::GetAllSizes(PGLOBAL g, int &ndif, int &numk)
+bool XINDEX::GetAllSizes(PGLOBAL g,/* int &ndif,*/ int &numk)
{
char *ftype;
char fn[_MAX_PATH];
- int n, nv[NZ], id = -1;
- bool estim = false;
+ int nv[NZ], id = -1; // n
+//bool estim = false;
+ bool rc = true;
PDOSDEF defp = (PDOSDEF)Tdbp->To_Def;
- ndif = numk = 0;
+// ndif = numk = 0;
+ numk = 0;
+#if 0
/*********************************************************************/
/* Get the estimated table size. */
/* Note: for fixed tables we must use cardinality to avoid the call */
@@ -1309,6 +1440,7 @@ bool XINDEX::GetAllSizes(PGLOBAL g, int &ndif, int &numk)
strcpy(g->Message, MSG(NO_KEY_COL));
return true; // Error
} // endif Nk
+#endif // 0
switch (Tdbp->Ftype) {
case RECFM_VAR: ftype = ".dnx"; break;
@@ -1341,9 +1473,8 @@ bool XINDEX::GetAllSizes(PGLOBAL g, int &ndif, int &numk)
PlugSetPath(fn, fn, Tdbp->GetPath());
-#if defined(TRACE)
- printf("Index %s file: %s\n", Xdp->GetName(), fn);
-#endif // TRACE
+ if (trace)
+ htrc("Index %s file: %s\n", Xdp->GetName(), fn);
/*********************************************************************/
/* Open the index file and check its validity. */
@@ -1359,20 +1490,21 @@ bool XINDEX::GetAllSizes(PGLOBAL g, int &ndif, int &numk)
if (X->Read(g, nv, NZ, sizeof(int)))
goto err;
-#if defined(TRACE)
- printf("nv=%d %d %d %d\n", nv[0], nv[1], nv[2], nv[3]);
-#endif // TRACE
+ if (trace)
+ htrc("nv=%d %d %d %d\n", nv[0], nv[1], nv[2], nv[3]);
// The test on ID was suppressed because MariaDB can change an index ID
- // when other indexes are added or deleted
+ // when other indexes are added or deleted
if (/*nv[0] != ID ||*/ nv[1] != Nk) {
sprintf(g->Message, MSG(BAD_INDEX_FILE), fn);
-#if defined(TRACE)
- printf("nv[0]=%d ID=%d nv[1]=%d Nk=%d\n", nv[0], ID, nv[1], Nk);
-#endif // TRACE
+
+ if (trace)
+ htrc("nv[0]=%d ID=%d nv[1]=%d Nk=%d\n", nv[0], ID, nv[1], Nk);
+
goto err;
} // endif
+#if 0
if (nv[2]) {
Mul = true;
Ndif = nv[2] - 1; // nv[2] is offset size, equal to Ndif + 1
@@ -1388,9 +1520,11 @@ bool XINDEX::GetAllSizes(PGLOBAL g, int &ndif, int &numk)
sprintf(g->Message, MSG(OPT_NOT_MATCH), fn);
goto err;
} // endif
+#endif // 0
Num_K = nv[3];
+#if 0
if (Nk > 1) {
if (nv[2] && X->Seek(g, nv[2] * sizeof(int), 0, SEEK_CUR))
goto err;
@@ -1411,17 +1545,18 @@ bool XINDEX::GetAllSizes(PGLOBAL g, int &ndif, int &numk)
Ndif = nv[0];
} // endif Nk
+#endif // 0
/*********************************************************************/
/* Set size values. */
/*********************************************************************/
- ndif = Ndif;
+//ndif = Ndif;
numk = Num_K;
- return false;
+ rc = false;
err:
X->Close();
- return true;
+ return rc;
} // end of GetAllSizes
/***********************************************************************/
@@ -1455,7 +1590,7 @@ int XINDEX::Range(PGLOBAL g, int limit, bool incl)
n = k;
// if (limit)
// n = (Mul) ? k : kp->Val_K;
-// else
+// else
// n = (Mul) ? Pof[kp->Val_K + 1] - k : 1;
} else {
@@ -1642,9 +1777,8 @@ int XINDEX::Fetch(PGLOBAL g)
break;
case OP_SAME: // Read next same
// Logically the key values should be the same as before
-#if defined(TRACE)
- printf("looking for next same value\n");
-#endif // TRACE
+ if (trace > 1)
+ htrc("looking for next same value\n");
if (NextVal(true)) {
Op = OP_EQ;
@@ -1690,9 +1824,9 @@ int XINDEX::Fetch(PGLOBAL g)
Nth++;
-#if defined(TRACE)
- printf("Fetch: Looking for new value\n");
-#endif // TRACE
+ if (trace > 1)
+ htrc("Fetch: Looking for new value\n");
+
Cur_K = FastFind(Nval);
if (Cur_K >= Num_K)
@@ -1848,8 +1982,7 @@ int XINDEX::FastFind(int nv)
XINDXS::XINDXS(PTDBDOS tdbp, PIXDEF xdp, PXLOAD pxp, PCOL *cp, PXOB *xp)
: XINDEX(tdbp, xdp, pxp, cp, xp)
{
-//Srtd = To_Cols[0]->GetOpt() < 0; // ?????
- Srtd = false;
+ Srtd = To_Cols[0]->GetOpt() == 2;
} // end of XINDXS constructor
/***********************************************************************/
@@ -1891,7 +2024,7 @@ int XINDXS::Range(PGLOBAL g, int limit, bool incl)
if (k < Num_K || Op != OP_EQ)
if (limit)
n = (Mul) ? k : kp->Val_K;
- else
+ else
n = (Mul) ? Pof[kp->Val_K + 1] - k : 1;
} else {
@@ -1987,10 +2120,9 @@ int XINDXS::Fetch(PGLOBAL g)
To_KeyCol->Val_K = Cur_K = 0;
Op = OP_NEXT;
break;
- case OP_SAME: // Read next same
-#if defined(TRACE)
-// printf("looking for next same value\n");
-#endif // TRACE
+ case OP_SAME: // Read next same
+ if (trace > 1)
+ htrc("looking for next same value\n");
if (!Mul || NextVal(true)) {
Op = OP_EQ;
@@ -2023,18 +2155,17 @@ int XINDXS::Fetch(PGLOBAL g)
/* Look for the first key equal to the link column values */
/* and return its rank whithin the index table. */
/*****************************************************************/
- if (To_KeyCol->InitFind(g, To_Vals[0]))
- return -1; // No more constant values
- else
- Nth++;
-
-#if defined(TRACE)
- printf("Fetch: Looking for new value\n");
-#endif // TRACE
-
- Cur_K = FastFind(1);
-
- if (Cur_K >= Num_K)
+ if (To_KeyCol->InitFind(g, To_Vals[0]))
+ return -1; // No more constant values
+ else
+ Nth++;
+
+ if (trace > 1)
+ htrc("Fetch: Looking for new value\n");
+
+ Cur_K = FastFind(1);
+
+ if (Cur_K >= Num_K)
// Rank not whithin index table, signal record not found
return -2;
else if (Mul)
@@ -2119,7 +2250,10 @@ int XINDXS::FastFind(int nk)
n = 0;
} // endif sup
- kcp->Val_K = i; // Used by FillValue
+ // Loop on kcp because of dynamic indexing
+ for (; kcp; kcp = kcp->Next)
+ kcp->Val_K = i; // Used by FillValue
+
return ((n) ? Num_K : (Mul) ? Pof[i] : i);
} // end of FastFind
@@ -2195,7 +2329,7 @@ bool XFILE::Open(PGLOBAL g, char *filename, int id, MODE mode)
sprintf(g->Message, MSG(FUNC_ERRNO), errno, "Xseek");
return true;
} // endif
-
+
NewOff.Low = (int)ftell(Xfile);
} else if (mode == MODE_WRITE) {
if (id >= 0) {
@@ -2218,7 +2352,7 @@ bool XFILE::Open(PGLOBAL g, char *filename, int id, MODE mode)
sprintf(g->Message, MSG(FUNC_ERRNO), errno, "Xseek");
return true;
} // endif
-
+
} // endif mode
return false;
@@ -2336,7 +2470,7 @@ void *XFILE::FileView(PGLOBAL g, char *fn)
/***********************************************************************/
bool XHUGE::Open(PGLOBAL g, char *filename, int id, MODE mode)
{
- IOFF noff[MAX_INDX];
+ IOFF noff[MAX_INDX];
if (Hfile != INVALID_HANDLE_VALUE) {
sprintf(g->Message, MSG(FILE_OPEN_YET), filename);
@@ -2344,7 +2478,7 @@ bool XHUGE::Open(PGLOBAL g, char *filename, int id, MODE mode)
} // endif
if (trace)
- htrc(" Xopen: filename=%s mode=%d\n", filename, mode);
+ htrc(" Xopen: filename=%s id=%d mode=%d\n", filename, id, mode);
#if defined(WIN32)
LONG high = 0;
@@ -2424,19 +2558,19 @@ bool XHUGE::Open(PGLOBAL g, char *filename, int id, MODE mode)
} // endif rc
// Position the cursor at the offset of this index
- rc = SetFilePointer(Hfile, noff[id].Low,
+ rc = SetFilePointer(Hfile, noff[id].Low,
(PLONG)&noff[id].High, FILE_BEGIN);
if (rc == INVALID_SET_FILE_POINTER) {
sprintf(g->Message, MSG(FUNC_ERRNO), GetLastError(), "SetFilePointer");
return true;
} // endif
-
+
} // endif Mode
#else // UNIX
int oflag = O_LARGEFILE; // Enable file size > 2G
- mode_t pmod = 0;
+ mode_t pmod = S_IRUSR | S_IWUSR | S_IRGRP | S_IWGRP | S_IROTH | S_IWOTH;
/*********************************************************************/
/* Create the file object according to access mode */
@@ -2447,7 +2581,7 @@ bool XHUGE::Open(PGLOBAL g, char *filename, int id, MODE mode)
break;
case MODE_WRITE:
oflag |= O_WRONLY | O_CREAT | O_TRUNC;
- pmod = S_IREAD | S_IWRITE;
+// pmod = S_IREAD | S_IWRITE;
break;
case MODE_INSERT:
oflag |= (O_WRONLY | O_APPEND);
@@ -2479,7 +2613,10 @@ bool XHUGE::Open(PGLOBAL g, char *filename, int id, MODE mode)
sprintf(g->Message, MSG(FUNC_ERRNO), errno, "Seek");
return true;
} // endif
-
+
+ if (trace)
+ htrc("INSERT: NewOff=%lld\n", NewOff.Val);
+
} else if (mode == MODE_WRITE) {
if (id >= 0) {
// New not sep index file. Write the header.
@@ -2487,19 +2624,27 @@ bool XHUGE::Open(PGLOBAL g, char *filename, int id, MODE mode)
NewOff.Low = write(Hfile, &noff, sizeof(noff));
} // endif id
+ if (trace)
+ htrc("WRITE: NewOff=%lld\n", NewOff.Val);
+
} else if (mode == MODE_READ && id >= 0) {
// Get offset from the header
if (read(Hfile, noff, sizeof(noff)) != sizeof(noff)) {
sprintf(g->Message, MSG(READ_ERROR), "Index file", strerror(errno));
return true;
- } // endif MAX_INDX
+ } // endif read
+
+ if (trace)
+ htrc("noff[%d]=%lld\n", id, noff[id].Val);
// Position the cursor at the offset of this index
- if (!lseek64(Hfile, noff[id].Val, SEEK_SET)) {
- sprintf(g->Message, MSG(FUNC_ERRNO), errno, "Hseek");
+ if (lseek64(Hfile, noff[id].Val, SEEK_SET) < 0) {
+ sprintf(g->Message, "(XHUGE)lseek64: %s (%lld)", strerror(errno), noff[id].Val);
+ printf("%s\n", g->Message);
+// sprintf(g->Message, MSG(FUNC_ERRNO), errno, "Hseek");
return true;
- } // endif
-
+ } // endif lseek64
+
} // endif mode
#endif // UNIX
@@ -2526,15 +2671,15 @@ bool XHUGE::Seek(PGLOBAL g, int low, int high, int origin)
if (lseek64(Hfile, pos, origin) < 0) {
sprintf(g->Message, MSG(ERROR_IN_LSK), errno);
-#if defined(TRACE)
- printf("lseek64 error %d\n", errno);
-#endif // TRACE
+
+ if (trace)
+ htrc("lseek64 error %d\n", errno);
+
return true;
} // endif lseek64
-#if defined(TRACE)
- printf("Seek: low=%d high=%d\n", low, high);
-#endif // TRACE
+ if (trace)
+ htrc("Seek: low=%d high=%d\n", low, high);
#endif // UNIX
return false;
@@ -2632,12 +2777,15 @@ int XHUGE::Write(PGLOBAL g, void *buf, int n, int size, bool& rc)
/***********************************************************************/
void XHUGE::Close(char *fn, int id)
{
+ if (trace)
+ htrc("XHUGE::Close: fn=%s id=%d NewOff=%lld\n", fn, id, NewOff.Val);
+
#if defined(WIN32)
if (id >= 0 && fn) {
CloseFileHandle(Hfile);
Hfile = CreateFile(fn, GENERIC_READ | GENERIC_WRITE, 0, NULL,
OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL);
-
+
if (Hfile != INVALID_HANDLE_VALUE)
if (SetFilePointer(Hfile, id * sizeof(IOFF), NULL, FILE_BEGIN)
!= INVALID_SET_FILE_POINTER) {
@@ -2649,10 +2797,18 @@ void XHUGE::Close(char *fn, int id)
} // endif id
#else // !WIN32
if (id >= 0 && fn) {
- fcntl(Hfile, F_SETFD, O_WRONLY);
-
- if (lseek(Hfile, id * sizeof(IOFF), SEEK_SET))
- write(Hfile, &NewOff, sizeof(IOFF));
+ if (Hfile != INVALID_HANDLE_VALUE) {
+ if (lseek64(Hfile, id * sizeof(IOFF), SEEK_SET) >= 0) {
+ ssize_t nbw = write(Hfile, &NewOff, sizeof(IOFF));
+
+ if (nbw != (signed)sizeof(IOFF))
+ htrc("Error writing index file header: %s\n", strerror(errno));
+
+ } else
+ htrc("(XHUGE::Close)lseek64: %s (%d)\n", strerror(errno), id);
+
+ } else
+ htrc("(XHUGE)error reopening %s: %s\n", fn, strerror(errno));
} // endif id
#endif // !WIN32
@@ -2678,6 +2834,7 @@ void *XHUGE::FileView(PGLOBAL g, char *fn)
/***********************************************************************/
XXROW::XXROW(PTDBDOS tdbp) : XXBASE(tdbp, false)
{
+ Srtd = true;
Tdbp = tdbp;
Valp = NULL;
} // end of XXROW constructor
@@ -2788,7 +2945,7 @@ int XXROW::FastFind(int nk)
/***********************************************************************/
/* KXYCOL public constructor. */
/***********************************************************************/
-KXYCOL::KXYCOL(PKXBASE kp) : To_Keys(Keys.Memp),
+KXYCOL::KXYCOL(PKXBASE kp) : To_Keys(Keys.Memp),
To_Bkeys(Bkeys.Memp), Kof((CPINT&)Koff.Memp)
{
Next = NULL;
@@ -2821,7 +2978,7 @@ bool KXYCOL::Init(PGLOBAL g, PCOL colp, int n, bool sm, int kln)
int len = colp->GetLength(), prec = colp->GetScale();
// Currently no indexing on NULL columns
- if (colp->IsNullable()) {
+ if (colp->IsNullable() && kln) {
sprintf(g->Message, "Cannot index nullable column %s", colp->GetName());
return true;
} // endif nullable
@@ -2860,8 +3017,7 @@ bool KXYCOL::Init(PGLOBAL g, PCOL colp, int n, bool sm, int kln)
// Store this information to avoid sorting when already done
if (Asc)
-// IsSorted = colp->GetOpt() == 2;
- IsSorted = false;
+ IsSorted = colp->GetOpt() == 2;
//SetNulls(colp->IsNullable()); for when null columns will be indexable
Colp = colp;
@@ -2885,9 +3041,9 @@ BYTE* KXYCOL::MapInit(PGLOBAL g, PCOL colp, int *n, BYTE *m)
Type = colp->GetResultType();
- if (trace)
- htrc("MapInit(%p): colp=%p type=%d n=%d len=%d m=%p\n",
- this, colp, Type, n[0], len, m);
+ if (trace)
+ htrc("MapInit(%p): colp=%p type=%d n=%d len=%d m=%p\n",
+ this, colp, Type, n[0], len, m);
// Allocate the Value object used when moving items
Valp = AllocateValue(g, Type, len, prec, colp->IsUnsigned());