diff options
author | Sergei Golubchik <serg@mariadb.org> | 2014-10-15 12:59:13 +0200 |
---|---|---|
committer | Sergei Golubchik <serg@mariadb.org> | 2014-10-15 12:59:13 +0200 |
commit | f62c12b405ba7ec80b8e2490856b83c6f5899211 (patch) | |
tree | 010605c7f145da6ea6ac14b39abc4cf700d619b1 /storage/connect/xindex.cpp | |
parent | f947f73b2b6d2bd246b81a9038224d2a85777520 (diff) | |
parent | f1afc003eefe0aafd3e070c7453d9e029d8445a8 (diff) | |
download | mariadb-git-f62c12b405ba7ec80b8e2490856b83c6f5899211.tar.gz |
Merge 10.0.14 into 10.1
Diffstat (limited to 'storage/connect/xindex.cpp')
-rwxr-xr-x | storage/connect/xindex.cpp | 480 |
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()); |