diff options
Diffstat (limited to 'storage/connect')
50 files changed, 4028 insertions, 1366 deletions
diff --git a/storage/connect/array.cpp b/storage/connect/array.cpp index 6cd175a0f0a..9815fbb6be6 100644 --- a/storage/connect/array.cpp +++ b/storage/connect/array.cpp @@ -127,6 +127,10 @@ PARRAY MakeValueArray(PGLOBAL g, PPARM pp) case TYPE_PCHAR: par->AddValue(g, parmp->Value); break; + case TYPE_VOID: + // Integer stored inside pp->Value + par->AddValue(g, (int)parmp->Value); + break; } // endswitch valtyp /*********************************************************************/ @@ -152,14 +156,17 @@ ARRAY::ARRAY(PGLOBAL g, int type, int size, int length, int prec) Xsize = -1; Len = 1; - switch ((Type = type)) { + switch (type) { case TYPE_STRING: Len = length; - break; case TYPE_SHORT: case TYPE_INT: case TYPE_DOUBLE: case TYPE_PCHAR: + Type = type; + break; + case TYPE_VOID: + Type = TYPE_INT; break; #if 0 case TYPE_TOKEN: @@ -578,7 +585,7 @@ bool ARRAY::CanBeShort(void) /***********************************************************************/ int ARRAY::Convert(PGLOBAL g, int k, PVAL vp) { - int i, prec = 0; + int i; bool b = FALSE; PMBV ovblk = Valblk; PVBLK ovblp = Vblp; @@ -588,7 +595,6 @@ int ARRAY::Convert(PGLOBAL g, int k, PVAL vp) switch (Type) { case TYPE_DOUBLE: - prec = 2; case TYPE_SHORT: case TYPE_INT: case TYPE_DATE: @@ -974,7 +980,7 @@ PSZ ARRAY::MakeArrayList(PGLOBAL g) size_t z, len = 2; if (Type == TYPE_LIST) - return "(???)"; // To be implemented + return "(?" "?" "?)"; // To be implemented z = MY_MAX(24, GetTypeSize(Type, Len) + 4); tp = (char*)PlugSubAlloc(g, NULL, z); diff --git a/storage/connect/catalog.h b/storage/connect/catalog.h index 411660431b9..5baab294737 100644 --- a/storage/connect/catalog.h +++ b/storage/connect/catalog.h @@ -1,7 +1,7 @@ /*************** Catalog H Declares Source Code File (.H) **************/ -/* Name: CATALOG.H Version 3.2 */ +/* Name: CATALOG.H Version 3.3 */ /* */ -/* (C) Copyright to the author Olivier BERTRAND 2000-2012 */ +/* (C) Copyright to the author Olivier BERTRAND 2000-2014 */ /* */ /* This file contains the CATALOG PlugDB classes definitions. */ /***********************************************************************/ @@ -68,11 +68,11 @@ class DllExport CATALOG { bool GetDefHuge(void) {return DefHuge;} void SetDefHuge(bool b) {DefHuge = b;} char *GetCbuf(void) {return Cbuf;} - char *GetDataPath(void) {return (char*)DataPath;} +//char *GetDataPath(void) {return (char*)DataPath;} // Methods virtual void Reset(void) {} - virtual void SetDataPath(PGLOBAL g, const char *path) {} +//virtual void SetDataPath(PGLOBAL g, const char *path) {} virtual bool CheckName(PGLOBAL g, char *name) {return true;} virtual bool ClearName(PGLOBAL g, PSZ name) {return true;} virtual PRELDEF MakeOneTableDesc(PGLOBAL g, LPCSTR name, LPCSTR am) {return NULL;} @@ -106,7 +106,7 @@ class DllExport CATALOG { int Cblen; /* Length of suballoc. buffer */ CURTAB Ctb; /* Used to enumerate tables */ bool DefHuge; /* true: tables default to huge */ - LPCSTR DataPath; /* Is the Path of DB data dir */ +//LPCSTR DataPath; /* Is the Path of DB data dir */ }; // end of class CATALOG #endif // __CATALOG__H diff --git a/storage/connect/checklvl.h b/storage/connect/checklvl.h index 5505534678d..d1e37afbc93 100644 --- a/storage/connect/checklvl.h +++ b/storage/connect/checklvl.h @@ -34,9 +34,10 @@ enum XMOD {XMOD_EXECUTE = 0, /* DOS execution mode */ /***********************************************************************/ /* Following definitions indicate the use of a temporay file. */ /***********************************************************************/ -enum USETEMP {TMP_AUTO = 0, /* Best choice */ - TMP_NO = 1, /* Never */ +enum USETEMP {TMP_NO = 0, /* Never */ + TMP_AUTO = 1, /* Best choice */ TMP_YES = 2, /* Always */ - TMP_FORCE = 3}; /* Forced for MAP tables */ + TMP_FORCE = 3, /* Forced for MAP tables */ + TMP_TEST = 4}; /* Testing value */ #endif // _CHKLVL_DEFINED_ diff --git a/storage/connect/connect.cc b/storage/connect/connect.cc index e495a0f62b9..381e437f9ec 100644 --- a/storage/connect/connect.cc +++ b/storage/connect/connect.cc @@ -122,9 +122,12 @@ bool CntCheckDB(PGLOBAL g, PHC handler, const char *pathname) (dbuserp->Catalog) ? ((MYCAT*)dbuserp->Catalog)->GetHandler() : NULL, handler); + // Set the database path for this table + handler->SetDataPath(g, pathname); + if (dbuserp->Catalog) { // ((MYCAT *)dbuserp->Catalog)->SetHandler(handler); done later - ((MYCAT *)dbuserp->Catalog)->SetDataPath(g, pathname); +// ((MYCAT *)dbuserp->Catalog)->SetDataPath(g, pathname); return false; // Nothing else to do } // endif Catalog @@ -141,8 +144,8 @@ bool CntCheckDB(PGLOBAL g, PHC handler, const char *pathname) if (!(dbuserp->Catalog= new MYCAT(handler))) return true; - ((MYCAT *)dbuserp->Catalog)->SetDataPath(g, pathname); - dbuserp->UseTemp= TMP_AUTO; +//((MYCAT *)dbuserp->Catalog)->SetDataPath(g, pathname); +//dbuserp->UseTemp= TMP_AUTO; /*********************************************************************/ /* All is correct. */ @@ -479,7 +482,7 @@ RCODE CntReadNext(PGLOBAL g, PTDB tdbp) /***********************************************************************/ RCODE CntWriteRow(PGLOBAL g, PTDB tdbp) { - RCODE rc; + RCODE rc; PCOL colp; PTDBASE tp= (PTDBASE)tdbp; @@ -503,11 +506,12 @@ RCODE CntWriteRow(PGLOBAL g, PTDB tdbp) if (!colp->GetColUse(U_VIRTUAL)) colp->WriteColumn(g); -// if (tdbp->GetMode() == MODE_INSERT) -// tbxp->SetModified(true); - - // Return result code from write operation - rc= (RCODE)tdbp->WriteDB(g); + if (tp->IsIndexed()) + // Index values must be sorted before updating + rc= (RCODE)((PTDBDOS)tp)->GetTxfp()->StoreValues(g, true); + else + // Return result code from write operation + rc= (RCODE)tdbp->WriteDB(g); err: g->jump_level--; @@ -517,7 +521,7 @@ RCODE CntWriteRow(PGLOBAL g, PTDB tdbp) /***********************************************************************/ /* UpdateRow: Update a row into a table. */ /***********************************************************************/ -RCODE CntUpdateRow(PGLOBAL g, PTDB tdbp) +RCODE CntUpdateRow(PGLOBAL g, PTDB tdbp) { if (!tdbp || tdbp->GetMode() != MODE_UPDATE) return RC_FX; @@ -531,19 +535,28 @@ RCODE CntUpdateRow(PGLOBAL g, PTDB tdbp) /***********************************************************************/ RCODE CntDeleteRow(PGLOBAL g, PTDB tdbp, bool all) { - RCODE rc; + RCODE rc; + PTDBASE tp= (PTDBASE)tdbp; if (!tdbp || tdbp->GetMode() != MODE_DELETE) return RC_FX; else if (tdbp->IsReadOnly()) return RC_NF; - if (((PTDBASE)tdbp)->GetDef()->Indexable() && all) - ((PTDBDOS)tdbp)->Cardinal= 0; + if (all) { + if (((PTDBASE)tdbp)->GetDef()->Indexable()) + ((PTDBDOS)tdbp)->Cardinal= 0; + + // Note: if all, this call will be done when closing the table + rc= (RCODE)tdbp->DeleteDB(g, RC_FX); +//} else if (tp->GetKindex() && !tp->GetKindex()->IsSorted() && +// tp->Txfp->GetAmType() != TYPE_AM_DBF) { + } else if(tp->IsIndexed()) { + // Index values must be sorted before updating + rc= (RCODE)((PTDBDOS)tp)->GetTxfp()->StoreValues(g, false); + } else // Return result code from delete operation + rc= (RCODE)tdbp->DeleteDB(g, RC_OK); - // Return result code from delete operation - // Note: if all, this call will be done when closing the table - rc= (RCODE)tdbp->DeleteDB(g, (all) ? RC_FX : RC_OK); return rc; } // end of CntDeleteRow @@ -553,7 +566,7 @@ RCODE CntDeleteRow(PGLOBAL g, PTDB tdbp, bool all) int CntCloseTable(PGLOBAL g, PTDB tdbp, bool nox, bool abort) { int rc= RC_OK; - TDBDOX *tbxp= NULL; + TDBASE *tbxp= (PTDBASE)tdbp; if (!tdbp) return rc; // Nothing to do @@ -568,8 +581,24 @@ int CntCloseTable(PGLOBAL g, PTDB tdbp, bool nox, bool abort) printf("CntCloseTable: tdbp=%p mode=%d nox=%d abort=%d\n", tdbp, tdbp->GetMode(), nox, abort); - if (tdbp->GetMode() == MODE_DELETE && tdbp->GetUse() == USE_OPEN) - rc= tdbp->DeleteDB(g, RC_EF); // Specific A.M. delete routine + if (tdbp->GetMode() == MODE_DELETE && tdbp->GetUse() == USE_OPEN) { + if (tbxp->IsIndexed()) + rc= ((PTDBDOS)tdbp)->GetTxfp()->DeleteSortedRows(g); + + if (!rc) + rc= tdbp->DeleteDB(g, RC_EF); // Specific A.M. delete routine + + } else if (tbxp->GetMode() == MODE_UPDATE && tbxp->IsIndexed()) + rc= ((PTDBDOX)tdbp)->Txfp->UpdateSortedRows(g); + + switch(rc) { + case RC_FX: + abort= true; + break; + case RC_INFO: + PushWarning(g, tbxp); + break; + } // endswitch rc // Prepare error return if (g->jump_level == MAX_JUMP) { @@ -606,9 +635,8 @@ int CntCloseTable(PGLOBAL g, PTDB tdbp, bool nox, bool abort) // Make all the eventual indexes tbxp= (TDBDOX*)tdbp; tbxp->ResetKindex(g, NULL); - tbxp->To_Key_Col= NULL; - rc= tbxp->ResetTableOpt(g, true, - ((PTDBASE)tdbp)->GetDef()->Indexable() == 1); + tbxp->SetKey_Col(NULL); + rc= tbxp->ResetTableOpt(g, true, tbxp->GetDef()->Indexable() == 1); err: if (trace > 1) @@ -622,7 +650,7 @@ int CntCloseTable(PGLOBAL g, PTDB tdbp, bool nox, bool abort) /* This is the condition(s) for doing indexing. */ /* Note: FIX table are not reset here to Nrec= 1. */ /***********************************************************************/ -int CntIndexInit(PGLOBAL g, PTDB ptdb, int id) +int CntIndexInit(PGLOBAL g, PTDB ptdb, int id, bool sorted) { PIXDEF xdp; PTDBDOX tdbp; @@ -674,7 +702,7 @@ int CntIndexInit(PGLOBAL g, PTDB ptdb, int id) #endif // 0 // Static indexes must be initialized now for records_in_range - if (tdbp->InitialyzeIndex(g, xdp)) + if (tdbp->InitialyzeIndex(g, xdp, sorted)) return 0; return (tdbp->To_Kindex->IsMul()) ? 2 : 1; @@ -721,7 +749,7 @@ RCODE CntIndexRead(PGLOBAL g, PTDB ptdb, OPVAL op, #if 0 } // endif !To_Xdp // Now it's time to make the dynamic index - if (tdbp->InitialyzeIndex(g, NULL)) { + if (tdbp->InitialyzeIndex(g, NULL, false)) { sprintf(g->Message, "Fail to make dynamic index %s", tdbp->To_Xdp->GetName()); return RC_FX; diff --git a/storage/connect/connect.h b/storage/connect/connect.h index 145991a3b74..fd8b7e9442f 100644 --- a/storage/connect/connect.h +++ b/storage/connect/connect.h @@ -34,7 +34,7 @@ PTDB CntGetTDB(PGLOBAL g, const char *name, MODE xmod, PHC); bool CntOpenTable(PGLOBAL g, PTDB tdbp, MODE, char *, char *, bool, PHC); bool CntRewindTable(PGLOBAL g, PTDB tdbp); int CntCloseTable(PGLOBAL g, PTDB tdbp, bool nox, bool abort); -int CntIndexInit(PGLOBAL g, PTDB tdbp, int id); +int CntIndexInit(PGLOBAL g, PTDB tdbp, int id, bool sorted); RCODE CntReadNext(PGLOBAL g, PTDB tdbp); RCODE CntIndexRead(PGLOBAL g, PTDB, OPVAL op, const void *k, int n, bool mrr); RCODE CntWriteRow(PGLOBAL g, PTDB tdbp); @@ -50,7 +50,7 @@ PGLOBAL CntExit(PGLOBAL g); /* These classes purpose is chiefly to access protected items! */ /***********************************************************************/ class DOXDEF: public DOSDEF { - friend int CntIndexInit(PGLOBAL, PTDB, int); + friend int CntIndexInit(PGLOBAL, PTDB, int, bool); }; // end of class DOXDEF /***********************************************************************/ @@ -59,7 +59,7 @@ class DOXDEF: public DOSDEF { class TDBDOX: public TDBDOS { friend int MakeIndex(PGLOBAL, PTDB, PIXDEF); friend int CntCloseTable(PGLOBAL, PTDB, bool, bool); - friend int CntIndexInit(PGLOBAL, PTDB, int); + friend int CntIndexInit(PGLOBAL, PTDB, int, bool); friend RCODE CntIndexRead(PGLOBAL, PTDB, OPVAL, const void*, int, bool); friend RCODE CntDeleteRow(PGLOBAL, PTDB, bool); friend int CntIndexRange(PGLOBAL, PTDB, const uchar**, uint*, @@ -70,7 +70,7 @@ class TDBDOX: public TDBDOS { class XKPDEF: public KPARTDEF { friend class TDBDOX; friend class ha_connect; - friend int CntIndexInit(PGLOBAL, PTDB, int); + friend int CntIndexInit(PGLOBAL, PTDB, int, bool); public: XKPDEF(const char *name, int n) : KPARTDEF((PSZ)name, n) {} }; // end of class XKPDEF diff --git a/storage/connect/filamap.cpp b/storage/connect/filamap.cpp index b5958c1a854..c0ca40f4c01 100644 --- a/storage/connect/filamap.cpp +++ b/storage/connect/filamap.cpp @@ -48,11 +48,6 @@ extern "C" int trace; -/***********************************************************************/ -/* Routine called externally by MAPFAM MakeDeletedFile function. */ -/***********************************************************************/ -PARRAY MakeValueArray(PGLOBAL g, PPARM pp); - /* --------------------------- Class MAPFAM -------------------------- */ /***********************************************************************/ @@ -134,9 +129,9 @@ bool MAPFAM::OpenTableFile(PGLOBAL g) && fp->Count && fp->Mode == mode) break; -#ifdef DEBTRACE - htrc("Mapping file, fp=%p\n", fp); -#endif + if (trace) + htrc("Mapping file, fp=%p\n", fp); + } else fp = NULL; @@ -291,6 +286,16 @@ bool MAPFAM::RecordPos(PGLOBAL g) } // end of RecordPos /***********************************************************************/ +/* Initialize Fpos and Mempos for indexed DELETE. */ +/***********************************************************************/ +int MAPFAM::InitDelete(PGLOBAL g, int fpos, int spos) + { + Fpos = Memory + fpos; + Mempos = Memory + spos; + return RC_OK; + } // end of InitDelete + +/***********************************************************************/ /* Skip one record in file. */ /***********************************************************************/ int MAPFAM::SkipRecord(PGLOBAL g, bool header) @@ -342,11 +347,12 @@ int MAPFAM::ReadBuffer(PGLOBAL g) return RC_EF; case RC_NF: // Skip this record - if ((rc = SkipRecord(g, FALSE)) != RC_OK) + if ((rc = SkipRecord(g, false)) != RC_OK) return rc; goto next; } // endswitch rc + } else Placed = false; @@ -409,17 +415,10 @@ int MAPFAM::DeleteRecords(PGLOBAL g, int irc) /* not required here, just setting of future Spos and Tpos. */ /*******************************************************************/ Tpos = Spos = Fpos; - Indxd = Tdbp->GetKindex() != NULL; - } // endif Tpos - - if (Indxd) { - // Moving will be done later, must be done in sequential order - (void)AddListValue(g, TYPE_PCHAR, Fpos, &To_Pos); - (void)AddListValue(g, TYPE_PCHAR, Mempos, &To_Sos); } else if ((n = Fpos - Spos) > 0) { - /*****************************************************************/ - /* Non consecutive line to delete. Move intermediate lines. */ - /*****************************************************************/ + /*******************************************************************/ + /* Non consecutive line to delete. Move intermediate lines. */ + /*******************************************************************/ memmove(Tpos, Spos, n); Tpos += n; @@ -437,10 +436,6 @@ int MAPFAM::DeleteRecords(PGLOBAL g, int irc) } else if (To_Fb) { // Can be NULL for deleted files /*******************************************************************/ /* Last call after EOF has been reached. */ - /*******************************************************************/ - Abort = (Indxd && MakeDeletedFile(g)); - - /*******************************************************************/ /* We must firstly Unmap the view and use the saved file handle */ /* to put an EOF at the end of the copied part of the file. */ /*******************************************************************/ @@ -496,55 +491,6 @@ int MAPFAM::DeleteRecords(PGLOBAL g, int irc) } // end of DeleteRecords /***********************************************************************/ -/* MakeDeletedFile. When deleting using indexing, the issue is that */ -/* record are not necessarily deleted in sequential order. Moving */ -/* intermediate lines cannot be done while deleting them. */ -/* What we do here is to reorder the deleted records and move the */ -/* intermediate files from the ordered deleted record positions. */ -/***********************************************************************/ -bool MAPFAM::MakeDeletedFile(PGLOBAL g) - { - int *ix, i, n; - - /*********************************************************************/ - /* Make and order the arrays from the saved values. */ - /*********************************************************************/ - if (!(Posar = MakeValueArray(g, To_Pos))) { - strcpy(g->Message, "Position array is null"); - goto err; - } else if (!(Sosar = MakeValueArray(g, To_Sos))) { - strcpy(g->Message, "Start position array is null"); - goto err; - } else if (!(ix = (int*)Posar->GetSortIndex(g))) { - strcpy(g->Message, "Error getting array sort index"); - goto err; - } // endif's - - for (i = 0; i < Posar->GetNval(); i++) { - Fpos = Posar->GetStringValue(ix[i]); - - if (!i) { - Tpos = Fpos; - } else if ((n = Fpos - Spos) >= 0) { - // Move all not deleted lines preceding this one - memmove(Tpos, Spos, n); - Tpos += n; - } // endif n - - // New start position - Spos = Sosar->GetStringValue(ix[i]); - } // endfor i - - return false; - -err: - if (trace) - htrc("%s\n", g->Message); - - return true; - } // end of MakeDeletedFile - -/***********************************************************************/ /* Table file close routine for MAP access method. */ /***********************************************************************/ void MAPFAM::CloseTableFile(PGLOBAL g, bool abort) @@ -735,6 +681,16 @@ bool MPXFAM::SetPos(PGLOBAL g, int pos) } // end of SetPos /***********************************************************************/ +/* Initialize CurBlk, CurNum, Mempos and Fpos for indexed DELETE. */ +/***********************************************************************/ +int MPXFAM::InitDelete(PGLOBAL g, int fpos, int spos) + { + Fpos = Memory + Headlen + fpos * Lrecl; + Mempos = Fpos + Lrecl; + return RC_OK; + } // end of InitDelete + +/***********************************************************************/ /* ReadBuffer: Read one line for a mapped Fix file. */ /***********************************************************************/ int MPXFAM::ReadBuffer(PGLOBAL g) diff --git a/storage/connect/filamap.h b/storage/connect/filamap.h index 7d3203d7ff2..1d85fa36155 100644 --- a/storage/connect/filamap.h +++ b/storage/connect/filamap.h @@ -47,7 +47,7 @@ class DllExport MAPFAM : public TXTFAM { virtual void Rewind(void); protected: - bool MakeDeletedFile(PGLOBAL g); + virtual int InitDelete(PGLOBAL g, int fpos, int spos); // Members char *Memory; // Pointer on file mapping view. @@ -104,11 +104,14 @@ class DllExport MPXFAM : public MBKFAM { virtual int MaxBlkSize(PGLOBAL g, int s) {return TXTFAM::MaxBlkSize(g, s);} virtual bool SetPos(PGLOBAL g, int recpos); + virtual int GetNextPos(void) {return (int)Fpos + Nrec;} virtual bool DeferReading(void) {return false;} virtual int ReadBuffer(PGLOBAL g); virtual int WriteBuffer(PGLOBAL g); protected: + virtual int InitDelete(PGLOBAL g, int fpos, int spos); + // No additional members }; // end of class MPXFAM diff --git a/storage/connect/filamdbf.cpp b/storage/connect/filamdbf.cpp index 5d01ee06df0..a214ab8acf2 100644 --- a/storage/connect/filamdbf.cpp +++ b/storage/connect/filamdbf.cpp @@ -176,7 +176,7 @@ static int dbfhead(PGLOBAL g, FILE *file, PSZ fn, DBFHEADER *buf) /* DBFColumns: constructs the result blocks containing the description */ /* of all the columns of a DBF file that will be retrieved by #GetData. */ /****************************************************************************/ -PQRYRES DBFColumns(PGLOBAL g, const char *fn, BOOL info) +PQRYRES DBFColumns(PGLOBAL g, char *dp, const char *fn, bool info) { int buftyp[] = {TYPE_STRING, TYPE_SHORT, TYPE_STRING, TYPE_INT, TYPE_INT, TYPE_SHORT}; @@ -186,7 +186,7 @@ PQRYRES DBFColumns(PGLOBAL g, const char *fn, BOOL info) char buf[2], filename[_MAX_PATH]; int ncol = sizeof(buftyp) / sizeof(int); int rc, type, len, field, fields; - BOOL bad; + bool bad; DBFHEADER mainhead; DESCRIPTOR thisfield; FILE *infile = NULL; @@ -205,7 +205,7 @@ PQRYRES DBFColumns(PGLOBAL g, const char *fn, BOOL info) /************************************************************************/ /* Open the input file. */ /************************************************************************/ - PlugSetPath(filename, fn, PlgGetDataPath(g)); + PlugSetPath(filename, fn, dp); if (!(infile= global_fopen(g, MSGID_CANNOT_OPEN, filename, "rb"))) return NULL; @@ -750,6 +750,36 @@ bool DBFFAM::CopyHeader(PGLOBAL g) return rc; } // end of CopyHeader +#if 0 // Not useful when UseTemp is false. +/***********************************************************************/ +/* Mark the line to delete with '*' (soft delete). */ +/* NOTE: this is not ready for UseTemp. */ +/***********************************************************************/ +int DBFFAM::InitDelete(PGLOBAL g, int fpos, int spos) + { + int rc = RC_FX; + size_t lrecl = (size_t)Lrecl; + + if (Nrec != 1) + strcpy(g->Message, "Cannot delete in block mode"); + else if (fseek(Stream, Headlen + fpos * Lrecl, SEEK_SET)) + sprintf(g->Message, MSG(FSETPOS_ERROR), 0); + else if (fread(To_Buf, 1, lrecl, Stream) != lrecl) + sprintf(g->Message, MSG(READ_ERROR), To_File, strerror(errno)); + else + *To_Buf = '*'; + + if (fseek(Stream, Headlen + fpos * Lrecl, SEEK_SET)) + sprintf(g->Message, MSG(FSETPOS_ERROR), 0); + else if (fwrite(To_Buf, 1, lrecl, Stream) != lrecl) + sprintf(g->Message, MSG(FWRITE_ERROR), strerror(errno)); + else + rc = RC_NF; // Ok, Nothing else to do + + return rc; + } // end of InitDelete +#endif // 0 + /***********************************************************************/ /* Data Base delete line routine for DBF access methods. */ /* Deleted lines are just flagged in the first buffer character. */ @@ -760,16 +790,12 @@ int DBFFAM::DeleteRecords(PGLOBAL g, int irc) // T_Stream is the temporary stream or the table file stream itself if (!T_Stream) if (UseTemp) { - if ((Indxd = Tdbp->GetKindex() != NULL)) { - strcpy(g->Message, "DBF indexed udate using temp file NIY"); - return RC_FX; - } else if (OpenTempFile(g)) + if (OpenTempFile(g)) return RC_FX; if (CopyHeader(g)) // For DBF tables return RC_FX; -// Indxd = Tdbp->GetKindex() != NULL; } else T_Stream = Stream; @@ -809,7 +835,7 @@ void DBFFAM::CloseTableFile(PGLOBAL g, bool abort) if (Modif && !Closing) { // Last updated block remains to be written Closing = true; - wrc = ReadBuffer(g); + wrc = WriteModifiedBlock(g); } // endif Modif if (UseTemp && T_Stream && wrc == RC_OK) { diff --git a/storage/connect/filamdbf.h b/storage/connect/filamdbf.h index 0345c0338e8..da84d7685a8 100644 --- a/storage/connect/filamdbf.h +++ b/storage/connect/filamdbf.h @@ -1,7 +1,7 @@ /***************** FilAmDbf H Declares Source Code File (.H) ****************/ -/* Name: filamdbf.h Version 1.3 */ +/* Name: filamdbf.h Version 1.4 */ /* */ -/* (C) Copyright to the author Olivier BERTRAND 2005-2012 */ +/* (C) Copyright to the author Olivier BERTRAND 2005-2014 */ /* */ /* This file contains the DBF file access method classes declares. */ /****************************************************************************/ @@ -19,7 +19,7 @@ typedef class DBMFAM *PDBMFAM; /****************************************************************************/ /* Functions used externally. */ /****************************************************************************/ -PQRYRES DBFColumns(PGLOBAL g, const char *fn, BOOL info); +PQRYRES DBFColumns(PGLOBAL g, char *dp, const char *fn, bool info); /****************************************************************************/ /* This is the base class for dBASE file access methods. */ @@ -40,8 +40,8 @@ class DllExport DBFBASE { // Members int Records; /* records in the file */ bool Accept; /* true if bad lines are accepted */ - int Nerr; /* Number of bad records */ - int Maxerr; /* Maximum number of bad records */ + int Nerr; /* Number of bad records */ + int Maxerr; /* Maximum number of bad records */ int ReadMode; /* 1: ALL 2: DEL 0: NOT DEL */ }; // end of class DBFBASE @@ -72,6 +72,7 @@ class DllExport DBFFAM : public FIXFAM, public DBFBASE { protected: virtual bool CopyHeader(PGLOBAL g); +//virtual int InitDelete(PGLOBAL g, int fpos, int spos); // Members }; // end of class DBFFAM diff --git a/storage/connect/filamfix.cpp b/storage/connect/filamfix.cpp index d6c3906dac3..1fa72d52746 100644 --- a/storage/connect/filamfix.cpp +++ b/storage/connect/filamfix.cpp @@ -55,11 +55,6 @@ extern "C" int trace; extern int num_read, num_there, num_eq[2]; // Statistics -/***********************************************************************/ -/* Routine called externally by BGXFAM MakeDeletedFile function. */ -/***********************************************************************/ -PARRAY MakeValueArray(PGLOBAL g, PPARM pp); - /* --------------------------- Class FIXFAM -------------------------- */ /***********************************************************************/ @@ -106,6 +101,16 @@ bool FIXFAM::SetPos(PGLOBAL g, int pos) } // end of SetPos /***********************************************************************/ +/* Initialize CurBlk and CurNum for indexed DELETE. */ +/***********************************************************************/ +int FIXFAM::InitDelete(PGLOBAL g, int fpos, int spos) + { + CurBlk = fpos / Nrec; + CurNum = fpos % Nrec; + return RC_OK; + } // end of InitDelete + +/***********************************************************************/ /* Allocate the block buffer for the table. */ /***********************************************************************/ bool FIXFAM::AllocateBuffer(PGLOBAL g) @@ -167,90 +172,93 @@ void FIXFAM::ResetBuffer(PGLOBAL g) } // end of ResetBuffer /***********************************************************************/ +/* WriteModifiedBlock: Used when updating. */ +/***********************************************************************/ +int FIXFAM::WriteModifiedBlock(PGLOBAL g) + { + /*********************************************************************/ + /* The old block was modified in Update mode. */ + /* In Update mode we simply rewrite the old block on itself. */ + /*********************************************************************/ + int rc = RC_OK; + bool moved = false; + + // Using temp copy any intermediate lines. + if (UseTemp && MoveIntermediateLines(g, &moved)) + rc = RC_FX; + + // Fpos is last position, Headlen is DBF file header length + else if (!moved && fseek(Stream, Headlen + Fpos * Lrecl, SEEK_SET)) { + sprintf(g->Message, MSG(FSETPOS_ERROR), 0); + rc = RC_FX; + } else if (fwrite(To_Buf, Lrecl, Rbuf, T_Stream) != (size_t)Rbuf) { + sprintf(g->Message, MSG(FWRITE_ERROR), strerror(errno)); + rc = RC_FX; + } else + Spos = Fpos + Nrec; // + Rbuf ??? + + if (Closing || rc != RC_OK) { // Error or called from CloseDB + Closing = true; // To tell CloseDB about error + return rc; + } // endif Closing + + // NOTE: Next line was added to avoid a very strange fread bug. + // When the fseek is not executed (even the file has the good + // pointer position) the next read can happen anywhere in the file. + OldBlk = CurBlk; // This will force fseek to be executed + Modif = 0; + return rc; + } // end of WriteModifiedBlock + +/***********************************************************************/ /* ReadBuffer: Read one line for a FIX file. */ /***********************************************************************/ int FIXFAM::ReadBuffer(PGLOBAL g) { int n, rc = RC_OK; - if (!Closing) { + /*********************************************************************/ + /* Sequential reading when Placed is not true. */ + /*********************************************************************/ + if (Placed) { + Tdbp->SetLine(To_Buf + CurNum * Lrecl); + Placed = false; + } else if (++CurNum < Rbuf) { + Tdbp->IncLine(Lrecl); // Used by DOSCOL functions + return RC_OK; + } else if (Rbuf < Nrec && CurBlk != -1) { + return RC_EF; + } else { /*******************************************************************/ - /* Sequential reading when Placed is not true. */ + /* New block. */ /*******************************************************************/ - if (Placed) { - Tdbp->SetLine(To_Buf + CurNum * Lrecl); - Placed = false; - } else if (++CurNum < Rbuf) { - Tdbp->IncLine(Lrecl); // Used by DOSCOL functions - return RC_OK; - } else if (Rbuf < Nrec && CurBlk != -1) { - return RC_EF; - } else { - /*****************************************************************/ - /* New block. */ - /*****************************************************************/ - CurNum = 0; - Tdbp->SetLine(To_Buf); + CurNum = 0; + Tdbp->SetLine(To_Buf); - next: - if (++CurBlk >= Block) - return RC_EF; + next: + if (++CurBlk >= Block) + return RC_EF; - /*****************************************************************/ - /* 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's - - if (OldBlk == CurBlk) { - IsRead = true; // Was read indeed - return RC_OK; // Block is already there - } // endif OldBlk - - } // endif !Closing - - if (Modif) { /*******************************************************************/ - /* The old block was modified in Update mode. */ - /* In Update mode we simply rewrite the old block on itself. */ + /* Before reading a new block, check whether block indexing */ + /* can be done, as well as for join as for local filtering. */ /*******************************************************************/ - bool moved = false; + switch (Tdbp->TestBlock(g)) { + case RC_EF: + return RC_EF; + case RC_NF: + goto next; + } // endswitch rc + } // endif's - if (UseTemp) // Copy any intermediate lines. - if (MoveIntermediateLines(g, &moved)) - rc = RC_FX; + if (OldBlk == CurBlk) { + IsRead = true; // Was read indeed + return RC_OK; // Block is already there + } // endif OldBlk - if (rc == RC_OK) { - // Fpos is last position, Headlen is DBF file header length - if (!moved && fseek(Stream, Headlen + Fpos * Lrecl, SEEK_SET)) { - sprintf(g->Message, MSG(FSETPOS_ERROR), 0); - rc = RC_FX; - } else if (fwrite(To_Buf, Lrecl, Rbuf, T_Stream) != (size_t)Rbuf) { - sprintf(g->Message, MSG(FWRITE_ERROR), strerror(errno)); - rc = RC_FX; - } // endif fwrite - - Spos = Fpos + Nrec; // + Rbuf ??? - } // endif rc - - if (Closing || rc != RC_OK) { // Error or called from CloseDB - Closing = true; // To tell CloseDB about error - return rc; - } // endif Closing - - // NOTE: Next line was added to avoid a very strange fread bug. - // When the fseek is not executed (even the file has the good - // pointer position) the next read can happen anywhere in the file. - OldBlk = CurBlk; // This will force fseek to be executed - Modif = 0; -// Spos = Fpos + Nrec; done above - } // endif Mode + // Write modified block in mode UPDATE + if (Modif && (rc = WriteModifiedBlock(g)) != RC_OK) + return rc; // This could be done only for new block. However note that FPOS // is used as block position when updating and as line position @@ -268,8 +276,6 @@ int FIXFAM::ReadBuffer(PGLOBAL g) if (trace > 1) htrc("File position is now %d\n", ftell(Stream)); -//long tell = ftell(Stream); not used - if (Padded) n = fread(To_Buf, (size_t)Blksize, 1, Stream); else @@ -340,21 +346,21 @@ int FIXFAM::WriteBuffer(PGLOBAL g) // T_Stream is the temporary stream or the table file stream itself if (!T_Stream) { if (UseTemp) { - if ((Indxd = Tdbp->GetKindex() != NULL)) { - strcpy(g->Message, "FIX indexed udate using temp file NIY"); - return RC_FX; - } else if (OpenTempFile(g)) + if (OpenTempFile(g)) return RC_FX; else if (CopyHeader(g)) // For DBF tables return RC_FX; -// Indxd = Tdbp->GetKindex() != NULL; } else T_Stream = Stream; } // endif T_Stream - Modif++; // Modified line in Update mode + if (Nrec > 1) + Modif++; // Modified line in blocked mode + else if (WriteModifiedBlock(g)) // Indexed update + return RC_FX; + } // endif Mode return RC_OK; @@ -413,17 +419,12 @@ int FIXFAM::DeleteRecords(PGLOBAL g, int irc) Spos = Tpos = Fpos; } // endif UseTemp - Indxd = Tdbp->GetKindex() != NULL; } // endif Tpos == Spos /*********************************************************************/ /* Move any intermediate lines. */ /*********************************************************************/ - if (Indxd) { - // Moving will be done later, must be done in sequential order - (void)AddListValue(g, TYPE_INT, &Fpos, &To_Pos); - moved = false; - } else if (MoveIntermediateLines(g, &moved)) + if (MoveIntermediateLines(g, &moved)) return RC_FX; if (irc == RC_OK) { @@ -456,9 +457,6 @@ int FIXFAM::DeleteRecords(PGLOBAL g, int irc) return RC_FX; } else { - if (Indxd && (Abort = MakeDeletedFile(g))) - return RC_FX; - /*****************************************************************/ /* Because the chsize functionality is only accessible with a */ /* system call we must close the file and reopen it with the */ @@ -560,59 +558,6 @@ bool FIXFAM::MoveIntermediateLines(PGLOBAL g, bool *b) } // end of MoveIntermediate Lines /***********************************************************************/ -/* MakeDeletedFile. When deleting using indexing, the issue is that */ -/* record are not necessarily deleted in sequential order. Moving */ -/* intermediate lines cannot be done while deleing them because */ -/* this can cause extra wrong records to be included in the new file. */ -/* What we do here is to reorder the deleted record and make the new */ -/* deleted file from the ordered deleted records. */ -/***********************************************************************/ -bool FIXFAM::MakeDeletedFile(PGLOBAL g) - { - const char *crlf = "\n", *mode = UseTemp ? "rb" : "r+b"; - int *ix, i; - bool moved; - - /*********************************************************************/ - /* Open the temporary file, Spos is at the beginning of file. */ - /*********************************************************************/ - if (!(Posar = MakeValueArray(g, To_Pos))) { - strcpy(g->Message, "Position array is null"); - goto err; - } else if (!(ix = (int*)Posar->GetSortIndex(g))) { - strcpy(g->Message, "Error getting array sort index"); - goto err; - } // endif's - - Spos = 0; - - for (i = 0; i < Posar->GetNval(); i++) { - Fpos = Posar->GetIntValue(ix[i]); - - if (i || UseTemp) { - // Copy all not updated lines preceding this one - if (MoveIntermediateLines(g, &moved)) - goto err; - - } else - Tpos = Fpos; - - // New start position - Spos = Fpos + 1; - } // endfor i - - if (!PlugCloseFile(g, To_Fbt) && !PlugCloseFile(g, To_Fb)) - return false; - -err: - if (trace) - htrc("%s\n", g->Message); - - PlugCloseFile(g, To_Fbt); - return true; - } // end of MakeDeletedFile - -/***********************************************************************/ /* Table file close routine for FIX access method. */ /***********************************************************************/ void FIXFAM::CloseTableFile(PGLOBAL g, bool abort) @@ -626,13 +571,12 @@ void FIXFAM::CloseTableFile(PGLOBAL g, bool abort) if (mode == MODE_INSERT && CurNum && !Closing) { // Some more inserted lines remain to be written Rbuf = CurNum--; -// Closing = true; wrc = WriteBuffer(g); } else if (mode == MODE_UPDATE) { if (Modif && !Closing) { // Last updated block remains to be written - Closing = true; - wrc = ReadBuffer(g); + Closing = true; // ??? + wrc = WriteModifiedBlock(g); } // endif Modif if (UseTemp && T_Stream && wrc == RC_OK) { @@ -640,7 +584,6 @@ void FIXFAM::CloseTableFile(PGLOBAL g, bool abort) // Copy any remaining lines bool b; - // Note: Indxd is not implemented yet Fpos = Tdbp->Cardinality(g); Abort = MoveIntermediateLines(g, &b) != RC_OK; } // endif Abort @@ -704,7 +647,9 @@ bool BGXFAM::BigSeek(PGLOBAL g, HANDLE h, BIGINT pos, int org) } // endif #else // !WIN32 if (lseek64(h, pos, org) < 0) { - sprintf(g->Message, MSG(ERROR_IN_LSK), errno); +// sprintf(g->Message, MSG(ERROR_IN_LSK), errno); + sprintf(g->Message, "lseek64: %s", strerror(errno)); + printf("%s\n", g->Message); return true; } // endif #endif // !WIN32 @@ -906,7 +851,7 @@ bool BGXFAM::OpenTableFile(PGLOBAL g) #else // UNIX int rc = 0; int oflag = O_LARGEFILE; // Enable file size > 2G - mode_t tmode = 0; + mode_t tmode = S_IRUSR | S_IWUSR | S_IRGRP | S_IWGRP | S_IROTH | S_IWOTH; /*********************************************************************/ /* Create the file object according to access mode */ @@ -931,7 +876,7 @@ bool BGXFAM::OpenTableFile(PGLOBAL g) break; case MODE_INSERT: oflag |= (O_WRONLY | O_CREAT | O_APPEND); - tmode = S_IREAD | S_IWRITE; + // tmode = S_IREAD | S_IWRITE; break; default: sprintf(g->Message, MSG(BAD_OPEN_MODE), mode); @@ -1090,85 +1035,92 @@ int BGXFAM::Cardinality(PGLOBAL g) } // end of Cardinality /***********************************************************************/ +/* WriteModifiedBlock: Used when updating. */ +/***********************************************************************/ +int BGXFAM::WriteModifiedBlock(PGLOBAL g) + { + /*********************************************************************/ + /* The old block was modified in Update mode. */ + /* In Update mode we simply rewrite the old block on itself. */ + /*********************************************************************/ + int rc = RC_OK; + bool moved = false; + + if (UseTemp) // Copy any intermediate lines. + if (MoveIntermediateLines(g, &moved)) + rc = RC_FX; + + if (rc == RC_OK) { + // Set file position to OldBlk position (Fpos) + if (!moved && BigSeek(g, Hfile, (BIGINT)Fpos * (BIGINT)Lrecl)) + rc = RC_FX; + else if (BigWrite(g, Tfile, To_Buf, Lrecl * Rbuf)) + rc = RC_FX; + + Spos = Fpos + Nrec; // + Rbuf ??? + } // endif rc + + if (Closing || rc != RC_OK) // Error or called from CloseDB + return rc; + + // NOTE: Next line was added to avoid a very strange fread bug. + // When the fseek is not executed (even the file has the good + // pointer position) the next read can happen anywhere in the file. + OldBlk = CurBlk; // This will force fseek to be executed + Modif = 0; + return rc; + } // end of WriteModifiedBlock + +/***********************************************************************/ /* ReadBuffer: Read Nrec lines for a big fixed/binary file. */ /***********************************************************************/ int BGXFAM::ReadBuffer(PGLOBAL g) { int nbr, rc = RC_OK; - if (!Closing) { + /*********************************************************************/ + /* Sequential reading when Placed is not true. */ + /*********************************************************************/ + if (Placed) { + Tdbp->SetLine(To_Buf + CurNum * Lrecl); + Placed = false; + } else if (++CurNum < Rbuf) { + Tdbp->IncLine(Lrecl); // Used by DOSCOL functions + return RC_OK; + } else if (Rbuf < Nrec && CurBlk != -1) { + return RC_EF; + } else { /*******************************************************************/ - /* Sequential reading when Placed is not true. */ + /* New block. */ /*******************************************************************/ - if (Placed) { - Tdbp->SetLine(To_Buf + CurNum * Lrecl); - Placed = false; - } else if (++CurNum < Rbuf) { - Tdbp->IncLine(Lrecl); // Used by DOSCOL functions - return RC_OK; - } else if (Rbuf < Nrec && CurBlk != -1) { + CurNum = 0; + Tdbp->SetLine(To_Buf); + + next: + if (++CurBlk >= Block) return RC_EF; - } else { - /*****************************************************************/ - /* New block. */ - /*****************************************************************/ - CurNum = 0; - Tdbp->SetLine(To_Buf); - next: - if (++CurBlk >= Block) + /*******************************************************************/ + /* 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 - /*****************************************************************/ - /* 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 + } // endif's - if (OldBlk == CurBlk) { - IsRead = true; // Was read indeed - return RC_OK; // Block is already there - } // endif OldBlk + if (OldBlk == CurBlk) { + IsRead = true; // Was read indeed + return RC_OK; // Block is already there + } // endif OldBlk - } // endif !Closing - - if (Modif) { - /*******************************************************************/ - /* The old block was modified in Update mode. */ - /* In Update mode we simply rewrite the old block on itself. */ - /*******************************************************************/ - bool moved = false; - - if (UseTemp) // Copy any intermediate lines. - if (MoveIntermediateLines(g, &moved)) - rc = RC_FX; - - if (rc == RC_OK) { - // Set file position to OldBlk position (Fpos) - if (!moved && BigSeek(g, Hfile, (BIGINT)Fpos * (BIGINT)Lrecl)) - rc = RC_FX; - else if (BigWrite(g, Tfile, To_Buf, Lrecl * Rbuf)) - rc = RC_FX; - - Spos = Fpos + Nrec; // + Rbuf ??? - } // endif rc - - if (Closing || rc != RC_OK) // Error or called from CloseDB - return rc; - - // NOTE: Next line was added to avoid a very strange fread bug. - // When the fseek is not executed (even the file has the good - // pointer position) the next read can happen anywhere in the file. - OldBlk = CurBlk; // This will force fseek to be executed - Modif = 0; - } // endif Mode + // Write modified block in mode UPDATE + if (Modif && (rc = WriteModifiedBlock(g)) != RC_OK) + return rc; Fpos = CurBlk * Nrec; @@ -1230,19 +1182,21 @@ int BGXFAM::WriteBuffer(PGLOBAL g) } else { // Mode == MODE_UPDATE // Tfile is the temporary file or the table file handle itself - if (Tfile == INVALID_HANDLE_VALUE) - { + if (Tfile == INVALID_HANDLE_VALUE) { if (UseTemp /*&& Tdbp->GetMode() == MODE_UPDATE*/) { - if ((Indxd = Tdbp->GetKindex() != NULL)) { - strcpy(g->Message, "FIX indexed udate using temp file NIY"); - return RC_FX; - } else if (OpenTempFile(g)) + if (OpenTempFile(g)) return RC_FX; } else Tfile = Hfile; - } - Modif++; // Modified line in Update mode + + } // endif Tfile + + if (Nrec > 1) + Modif++; // Modified line in blocked mode + else if (WriteModifiedBlock(g)) // Indexed update + return RC_FX; + } // endif Mode return RC_OK; @@ -1303,19 +1257,15 @@ int BGXFAM::DeleteRecords(PGLOBAL g, int irc) Spos = Tpos = Fpos; } // endif UseTemp - Indxd = Tdbp->GetKindex() != NULL; } // endif Tpos == Spos /*********************************************************************/ /* Move any intermediate lines. */ /*********************************************************************/ - if (Indxd) - // Moving will be done later, must be done in sequential order - (void)AddListValue(g, TYPE_INT, &Fpos, &To_Pos); - else if (MoveIntermediateLines(g, &moved)) + if (MoveIntermediateLines(g, &moved)) return RC_FX; - if (irc == RC_OK && !Indxd) { + if (irc == RC_OK) { if (trace) assert(Spos == Fpos); @@ -1343,9 +1293,6 @@ int BGXFAM::DeleteRecords(PGLOBAL g, int irc) return RC_FX; } else { - if (Indxd && (Abort = MakeDeletedFile(g))) - return RC_FX; - /*****************************************************************/ /* Remove extra records. */ /*****************************************************************/ @@ -1470,59 +1417,6 @@ bool BGXFAM::MoveIntermediateLines(PGLOBAL g, bool *b) } // end of MoveIntermediateLines /***********************************************************************/ -/* MakeDeletedFile. When deleting using indexing, the issue is that */ -/* record are not necessarily deleted in sequential order. Moving */ -/* intermediate lines cannot be done while deleing them because */ -/* this can cause extra wrong records to be included in the new file. */ -/* What we do here is to reorder the deleted record and make the new */ -/* deleted file from the ordered deleted records. */ -/***********************************************************************/ -bool BGXFAM::MakeDeletedFile(PGLOBAL g) - { - const char *crlf = "\n", *mode = UseTemp ? "rb" : "r+b"; - int *ix, i; - bool moved; - - /*********************************************************************/ - /* Open the temporary file, Spos is at the beginning of file. */ - /*********************************************************************/ - if (!(Posar = MakeValueArray(g, To_Pos))) { - strcpy(g->Message, "Position array is null"); - goto err; - } else if (!(ix = (int*)Posar->GetSortIndex(g))) { - strcpy(g->Message, "Error getting array sort index"); - goto err; - } // endif's - - Spos = 0; - - for (i = 0; i < Posar->GetNval(); i++) { - Fpos = Posar->GetIntValue(ix[i]); - - if (i || UseTemp) { - // Copy all not updated lines preceding this one - if (MoveIntermediateLines(g, &moved)) - goto err; - - } else - Tpos = Fpos; - - // New start position - Spos = Fpos + 1; - } // endfor i - - if (!PlugCloseFile(g, To_Fbt)) - return false; - -err: - if (trace) - htrc("%s\n", g->Message); - - PlugCloseFile(g, To_Fbt); - return true; - } // end of MakeDeletedFile - -/***********************************************************************/ /* Data Base close routine for BIGFIX access method. */ /***********************************************************************/ void BGXFAM::CloseTableFile(PGLOBAL g, bool abort) @@ -1541,7 +1435,7 @@ void BGXFAM::CloseTableFile(PGLOBAL g, bool abort) if (Modif && !Closing) { // Last updated block remains to be written Closing = true; - wrc = ReadBuffer(g); + wrc = WriteModifiedBlock(g); } // endif Modif if (UseTemp && Tfile && wrc == RC_OK) { @@ -1549,7 +1443,6 @@ void BGXFAM::CloseTableFile(PGLOBAL g, bool abort) // Copy any remaining lines bool b; - // Indxd is not implemented yet Fpos = Tdbp->Cardinality(g); Abort = MoveIntermediateLines(g, &b) != RC_OK; } // endif Abort diff --git a/storage/connect/filamfix.h b/storage/connect/filamfix.h index a29bfbbeb48..a99a36af232 100644 --- a/storage/connect/filamfix.h +++ b/storage/connect/filamfix.h @@ -34,8 +34,10 @@ class DllExport FIXFAM : public BLKFAM { virtual int MaxBlkSize(PGLOBAL g, int s) {return TXTFAM::MaxBlkSize(g, s);} virtual bool SetPos(PGLOBAL g, int recpos); + virtual int GetNextPos(void) {return Fpos + 1;} virtual bool AllocateBuffer(PGLOBAL g); virtual void ResetBuffer(PGLOBAL g); + virtual int WriteModifiedBlock(PGLOBAL g); virtual int ReadBuffer(PGLOBAL g); virtual int WriteBuffer(PGLOBAL g); virtual int DeleteRecords(PGLOBAL g, int irc); @@ -44,7 +46,7 @@ class DllExport FIXFAM : public BLKFAM { protected: virtual bool CopyHeader(PGLOBAL g) {return false;} virtual bool MoveIntermediateLines(PGLOBAL g, bool *b); - virtual bool MakeDeletedFile(PGLOBAL g); + virtual int InitDelete(PGLOBAL g, int fpos, int spos); // No additional members }; // end of class FIXFAM @@ -68,6 +70,7 @@ class BGXFAM : public FIXFAM { // Methods virtual int Cardinality(PGLOBAL g); virtual bool OpenTableFile(PGLOBAL g); + virtual int WriteModifiedBlock(PGLOBAL g); virtual int ReadBuffer(PGLOBAL g); virtual int WriteBuffer(PGLOBAL g); virtual int DeleteRecords(PGLOBAL g, int irc); @@ -77,7 +80,6 @@ class BGXFAM : public FIXFAM { protected: virtual bool OpenTempFile(PGLOBAL g); virtual bool MoveIntermediateLines(PGLOBAL g, bool *b = NULL); - virtual bool MakeDeletedFile(PGLOBAL g); int BigRead(PGLOBAL g, HANDLE h, void *inbuf, int req); bool BigWrite(PGLOBAL g, HANDLE h, void *inbuf, int req); bool BigSeek(PGLOBAL g, HANDLE h, BIGINT pos diff --git a/storage/connect/filamtxt.cpp b/storage/connect/filamtxt.cpp index 9c0cd51458d..dfd5a6638cf 100644 --- a/storage/connect/filamtxt.cpp +++ b/storage/connect/filamtxt.cpp @@ -59,7 +59,7 @@ extern int num_read, num_there, num_eq[2]; // Statistics extern "C" int trace; /***********************************************************************/ -/* Routine called externally by DOSFAM MakeUpdatedFile function. */ +/* Routine called externally by TXTFAM SortedRows functions. */ /***********************************************************************/ PARRAY MakeValueArray(PGLOBAL g, PPARM pp); @@ -102,10 +102,10 @@ TXTFAM::TXTFAM(PDOSDEF tdp) Rbuf = 0; Modif = 0; Blksize = 0; + Fpos = Spos = Tpos = 0; Padded = false; Eof = tdp->Eof; Ending = tdp->Ending; - Indxd = false; Abort = false; CrLf = (char*)(Ending == 1 ? "\n" : "\r\n"); } // end of TXTFAM standard constructor @@ -144,10 +144,12 @@ TXTFAM::TXTFAM(PTXF txfp) Rbuf = txfp->Rbuf; Modif = txfp->Modif; Blksize = txfp->Blksize; + Fpos = txfp->Fpos; + Spos = txfp->Spos; + Tpos = txfp->Tpos; Padded = txfp->Padded; Eof = txfp->Eof; Ending = txfp->Ending; - Indxd = txfp->Indxd; Abort = txfp->Abort; CrLf = txfp->CrLf; } // end of TXTFAM copy constructor @@ -280,14 +282,17 @@ bool TXTFAM::AddListValue(PGLOBAL g, int type, void *val, PPARM *top) PPARM pp = (PPARM)PlugSubAlloc(g, NULL, sizeof(PARM)); switch (type) { - case TYPE_INT: - pp->Value = PlugSubAlloc(g, NULL, sizeof(int)); - *((int*)pp->Value) = *((int*)val); - break; - case TYPE_STRING: - pp->Value = PlugSubAlloc(g, NULL, strlen((char*)val) + 1); - strcpy((char*)pp->Value, (char*)val); +// case TYPE_INT: +// pp->Value = PlugSubAlloc(g, NULL, sizeof(int)); +// *((int*)pp->Value) = *((int*)val); +// break; + case TYPE_VOID: + pp->Value = (void*)(intptr)*(int*)val; break; +// case TYPE_STRING: +// pp->Value = PlugSubAlloc(g, NULL, strlen((char*)val) + 1); +// strcpy((char*)pp->Value, (char*)val); +// break; case TYPE_PCHAR: pp->Value = val; break; @@ -302,6 +307,144 @@ bool TXTFAM::AddListValue(PGLOBAL g, int type, void *val, PPARM *top) return false; } // end of AddListValue +/***********************************************************************/ +/* Store needed values for indexed UPDATE or DELETE. */ +/***********************************************************************/ +int TXTFAM::StoreValues(PGLOBAL g, bool upd) +{ + int pos = GetPos(); + bool rc = AddListValue(g, TYPE_VOID, &pos, &To_Pos); + + if (!rc) { + pos = GetNextPos(); + rc = AddListValue(g, TYPE_VOID, &pos, &To_Sos); + } // endif rc + + if (upd && !rc) { + char *buf; + + if (Tdbp->PrepareWriting(g)) + return RC_FX; + + buf = (char*)PlugSubAlloc(g, NULL, strlen(Tdbp->GetLine()) + 1); + strcpy(buf, Tdbp->GetLine()); + rc = AddListValue(g, TYPE_PCHAR, buf, &To_Upd); + } // endif upd + + return rc ? RC_FX : RC_OK; +} // end of StoreValues + +/***********************************************************************/ +/* UpdateSortedRows. When updating using indexing, the issue is that */ +/* record are not necessarily updated in sequential order. */ +/* Moving intermediate lines cannot be done while making them because */ +/* this can cause extra wrong records to be included in the new file. */ +/* What we do here is to reorder the updated records and do all the */ +/* updates ordered by record position. */ +/***********************************************************************/ +int TXTFAM::UpdateSortedRows(PGLOBAL g) + { + int *ix, i; + + /*********************************************************************/ + /* Get the stored update values and sort them. */ + /*********************************************************************/ + if (!(Posar = MakeValueArray(g, To_Pos))) { +// strcpy(g->Message, "Position array is null"); +// return RC_INFO; + return RC_OK; // Nothing to do + } else if (!(Sosar = MakeValueArray(g, To_Sos))) { + strcpy(g->Message, "Start position array is null"); + goto err; + } else if (!(Updar = MakeValueArray(g, To_Upd))) { + strcpy(g->Message, "Updated line array is null"); + goto err; + } else if (!(ix = (int*)Posar->GetSortIndex(g))) { + strcpy(g->Message, "Error getting array sort index"); + goto err; + } // endif's + + Rewind(); + + for (i = 0; i < Posar->GetNval(); i++) { + SetPos(g, Sosar->GetIntValue(ix[i])); + Fpos = Posar->GetIntValue(ix[i]); + strcpy(Tdbp->To_Line, Updar->GetStringValue(ix[i])); + + // Now write the updated line. + if (WriteBuffer(g)) + goto err; + + } // endfor i + + return RC_OK; + +err: + if (trace) + htrc("%s\n", g->Message); + + return RC_FX; + } // end of UpdateSortedRows + +/***********************************************************************/ +/* DeleteSortedRows. When deleting using indexing, the issue is that */ +/* record are not necessarily deleted in sequential order. Moving */ +/* intermediate lines cannot be done while deleing them because */ +/* this can cause extra wrong records to be included in the new file. */ +/* What we do here is to reorder the deleted record and delete from */ +/* the file from the ordered deleted records. */ +/***********************************************************************/ +int TXTFAM::DeleteSortedRows(PGLOBAL g) + { + int *ix, i, irc; + + /*********************************************************************/ + /* Get the stored delete values and sort them. */ + /*********************************************************************/ + if (!(Posar = MakeValueArray(g, To_Pos))) { +// strcpy(g->Message, "Position array is null"); +// return RC_INFO; + return RC_OK; // Nothing to do + } else if (!(Sosar = MakeValueArray(g, To_Sos))) { + strcpy(g->Message, "Start position array is null"); + goto err; + } else if (!(ix = (int*)Posar->GetSortIndex(g))) { + strcpy(g->Message, "Error getting array sort index"); + goto err; + } // endif's + + Tpos = Spos = 0; + + for (i = 0; i < Posar->GetNval(); i++) { + if ((irc = InitDelete(g, Posar->GetIntValue(ix[i]), + Sosar->GetIntValue(ix[i])) == RC_FX)) + goto err; + + // Now delete the sorted rows + if (DeleteRecords(g, irc)) + goto err; + + } // endfor i + + return RC_OK; + +err: + if (trace) + htrc("%s\n", g->Message); + + return RC_FX; + } // end of DeleteSortedRows + +/***********************************************************************/ +/* The purpose of this function is to deal with access methods that */ +/* are not coherent regarding the use of SetPos and GetPos. */ +/***********************************************************************/ +int TXTFAM::InitDelete(PGLOBAL g, int fpos, int spos) + { + strcpy(g->Message, "InitDelete should not be used by this table type"); + return RC_FX; + } // end of InitDelete + /* --------------------------- Class DOSFAM -------------------------- */ /***********************************************************************/ @@ -312,7 +455,6 @@ DOSFAM::DOSFAM(PDOSDEF tdp) : TXTFAM(tdp) To_Fbt = NULL; Stream = NULL; T_Stream = NULL; - Fpos = Spos = Tpos = 0; UseTemp = false; Bin = false; } // end of DOSFAM standard constructor @@ -322,9 +464,6 @@ DOSFAM::DOSFAM(PDOSFAM tdfp) : TXTFAM(tdfp) To_Fbt = tdfp->To_Fbt; Stream = tdfp->Stream; T_Stream = tdfp->T_Stream; - Fpos = tdfp->Fpos; - Spos = tdfp->Spos; - Tpos = tdfp->Tpos; UseTemp = tdfp->UseTemp; Bin = tdfp->Bin; } // end of DOSFAM copy constructor @@ -399,7 +538,7 @@ bool DOSFAM::OpenTableFile(PGLOBAL g) PDBUSER dbuserp = PlgGetUser(g); // This is required when using Unix files under Windows and vice versa - Bin = (Ending != CRLF); + Bin = (Blocked || Ending != CRLF); switch (mode) { case MODE_READ: @@ -441,7 +580,7 @@ bool DOSFAM::OpenTableFile(PGLOBAL g) } // endswitch Mode // For blocked I/O or for moving lines, open the table in binary - strcat(opmode, (Blocked || Bin) ? "b" : "t"); + strcat(opmode, (Bin) ? "b" : "t"); // Now open the file stream PlugSetPath(filename, To_File, Tdbp->GetPath()); @@ -475,7 +614,7 @@ bool DOSFAM::AllocateBuffer(PGLOBAL g) MODE mode = Tdbp->Mode; // Lrecl does not include line ending - Buflen = Lrecl + Ending + ((Bin) ? 1 : 0) + 1; + Buflen = Lrecl + Ending + ((Bin) ? 1 : 0) + 1; // Sergei if (trace) htrc("SubAllocating a buffer of %d bytes\n", Buflen); @@ -552,6 +691,21 @@ bool DOSFAM::RecordPos(PGLOBAL g) } // end of RecordPos /***********************************************************************/ +/* Initialize Fpos and the current position for indexed DELETE. */ +/***********************************************************************/ +int DOSFAM::InitDelete(PGLOBAL g, int fpos, int spos) + { + Fpos = fpos; + + if (fseek(Stream, spos, SEEK_SET)) { + sprintf(g->Message, MSG(FSETPOS_ERROR), Fpos); + return RC_FX; + } // endif + + return RC_OK; + } // end of InitDelete + +/***********************************************************************/ /* Skip one record in file. */ /***********************************************************************/ int DOSFAM::SkipRecord(PGLOBAL g, bool header) @@ -713,7 +867,6 @@ int DOSFAM::WriteBuffer(PGLOBAL g) if (OpenTempFile(g)) return RC_FX; - Indxd = Tdbp->To_Kindex != NULL; } else T_Stream = Stream; @@ -735,20 +888,13 @@ int DOSFAM::WriteBuffer(PGLOBAL g) if (UseTemp) { /*****************************************************************/ /* We are using a temporary file. */ + /* Before writing the updated record, we must eventually copy */ + /* all the intermediate records that have not been updated. */ /*****************************************************************/ - if (Indxd) { - // Copying will be done later, must be done in sequential order - (void)AddListValue(g, TYPE_INT, &Fpos, &To_Pos); - (void)AddListValue(g, TYPE_INT, &curpos, &To_Sos); - } else { - // Before writing the updated record, we must eventually copy - // all the intermediate records that have not been updated. - if (MoveIntermediateLines(g, &moved)) - return RC_FX; - - Spos = curpos; // New start position - } // endif Indxd + if (MoveIntermediateLines(g, &moved)) + return RC_FX; + Spos = curpos; // New start position } else // Update is directly written back into the file, // with this (fast) method, record size cannot change. @@ -762,28 +908,24 @@ int DOSFAM::WriteBuffer(PGLOBAL g) /*********************************************************************/ /* Prepare the write the updated line. */ /*********************************************************************/ - if (!Indxd) { - strcat(strcpy(To_Buf, Tdbp->To_Line), (Bin) ? CrLf : "\n"); - - /*******************************************************************/ - /* Now start the writing process. */ - /*******************************************************************/ - if ((fputs(To_Buf, T_Stream)) == EOF) { - sprintf(g->Message, MSG(FPUTS_ERROR), strerror(errno)); - return RC_FX; - } // endif EOF + strcat(strcpy(To_Buf, Tdbp->To_Line), (Bin) ? CrLf : "\n"); - if (Tdbp->Mode == MODE_UPDATE && moved) - if (fseek(Stream, curpos, SEEK_SET)) { - sprintf(g->Message, MSG(FSEEK_ERROR), strerror(errno)); - return RC_FX; - } // endif + /*********************************************************************/ + /* Now start the writing process. */ + /*********************************************************************/ + if ((fputs(To_Buf, T_Stream)) == EOF) { + sprintf(g->Message, MSG(FPUTS_ERROR), strerror(errno)); + return RC_FX; + } // endif EOF - if (trace) - htrc("write done\n"); + if (Tdbp->Mode == MODE_UPDATE && moved) + if (fseek(Stream, curpos, SEEK_SET)) { + sprintf(g->Message, MSG(FSEEK_ERROR), strerror(errno)); + return RC_FX; + } // endif - } else // Add this updated line to the updated line list - (void)AddListValue(g, TYPE_STRING, Tdbp->To_Line, &To_Upd); + if (trace) + htrc("write done\n"); return RC_OK; } // end of WriteBuffer @@ -840,18 +982,12 @@ int DOSFAM::DeleteRecords(PGLOBAL g, int irc) Spos = Tpos = Fpos; } // endif UseTemp - Indxd = Tdbp->To_Kindex != NULL; } // endif Tpos == Spos /*********************************************************************/ /* Move any intermediate lines. */ /*********************************************************************/ - if (Indxd) { - // Moving will be done later, must be done in sequential order - (void)AddListValue(g, TYPE_INT, &Fpos, &To_Pos); - (void)AddListValue(g, TYPE_INT, &curpos, &To_Sos); - moved = false; - } else if (MoveIntermediateLines(g, &moved)) + if (MoveIntermediateLines(g, &moved)) return RC_FX; if (irc == RC_OK) { @@ -874,9 +1010,6 @@ int DOSFAM::DeleteRecords(PGLOBAL g, int irc) /* Last call after EOF has been reached. */ /* The UseTemp case is treated in CloseTableFile. */ /*******************************************************************/ - if (Indxd) - Abort = MakeDeletedFile(g); - if (!UseTemp & !Abort) { /*****************************************************************/ /* Because the chsize functionality is only accessible with a */ @@ -1001,136 +1134,6 @@ bool DOSFAM::MoveIntermediateLines(PGLOBAL g, bool *b) } // end of MoveIntermediate Lines /***********************************************************************/ -/* MakeUpdatedFile. When updating using indexing, the issue is that */ -/* record are not necessarily updated in sequential order. */ -/* Moving intermediate lines cannot be done while making them because */ -/* this can cause extra wrong records to be included in the new file. */ -/* What we do here is to reorder the updated record and make the new */ -/* updated file from the ordered updated records. */ -/***********************************************************************/ -bool DOSFAM::MakeUpdatedFile(PGLOBAL g) - { - const char *crlf = "\n", *mode = UseTemp ? "rb" : "r+b"; - int *ix, i; - bool moved, b = false; - - /*********************************************************************/ - /* Open the temporary file, Spos is at the beginning of file. */ - /*********************************************************************/ - if (!(Stream = PlugReopenFile(g, To_Fb, mode))) { - goto err; - } else if (!(Posar = MakeValueArray(g, To_Pos))) { - strcpy(g->Message, "Position array is null"); - goto err; - } else if (!(Sosar = MakeValueArray(g, To_Sos))) { - strcpy(g->Message, "Start position array is null"); - goto err; - } else if (!(Updar = MakeValueArray(g, To_Upd))) { - strcpy(g->Message, "Updated line array is null"); - goto err; - } else if (!(ix = (int*)Posar->GetSortIndex(g))) { - strcpy(g->Message, "Error getting array sort index"); - goto err; - } // endif's - - Spos = 0; - - for (i = 0; i < Posar->GetNval(); i++) { - Fpos = Posar->GetIntValue(ix[i]); - - if (i || UseTemp) { - // Copy all not updated lines preceding this one - if (MoveIntermediateLines(g, &moved)) - goto err; - - } else - Tpos = Fpos; - - // Now write the updated line. - strcat(strcpy(To_Buf, Updar->GetStringValue(ix[i])), CrLf); - - if ((fputs(To_Buf, T_Stream)) == EOF) { - sprintf(g->Message, MSG(FPUTS_ERROR), strerror(errno)); - goto err; - } // endif EOF - - // New start position - Spos = Sosar->GetIntValue(ix[i]); - } // endfor i - - // Copy eventually remaining lines - fseek(Stream, 0, SEEK_END); - Fpos = ftell(Stream); - b = MoveIntermediateLines(g, &moved) != RC_OK; - - if (!PlugCloseFile(g, To_Fbt) && !PlugCloseFile(g, To_Fb) && !b) - return false; - -err: - if (trace) - htrc("%s\n", g->Message); - - PlugCloseFile(g, To_Fbt); - return true; - } // end of MakeUpdatedFile - -/***********************************************************************/ -/* MakeDeletedFile. When deleting using indexing, the issue is that */ -/* record are not necessarily deleted in sequential order. Moving */ -/* intermediate lines cannot be done while deleing them because */ -/* this can cause extra wrong records to be included in the new file. */ -/* What we do here is to reorder the deleted record and make the new */ -/* deleted file from the ordered deleted records. */ -/***********************************************************************/ -bool DOSFAM::MakeDeletedFile(PGLOBAL g) - { - const char *crlf = "\n", *mode = UseTemp ? "rb" : "r+b"; - int *ix, i; - bool moved; - - /*********************************************************************/ - /* Open the temporary file, Spos is at the beginning of file. */ - /*********************************************************************/ - if (!(Posar = MakeValueArray(g, To_Pos))) { - strcpy(g->Message, "Position array is null"); - goto err; - } else if (!(Sosar = MakeValueArray(g, To_Sos))) { - strcpy(g->Message, "Start position array is null"); - goto err; - } else if (!(ix = (int*)Posar->GetSortIndex(g))) { - strcpy(g->Message, "Error getting array sort index"); - goto err; - } // endif's - - Spos = 0; - - for (i = 0; i < Posar->GetNval(); i++) { - Fpos = Posar->GetIntValue(ix[i]); - - if (i || UseTemp) { - // Copy all not updated lines preceding this one - if (MoveIntermediateLines(g, &moved)) - goto err; - - } else - Tpos = Fpos; - - // New start position - Spos = Sosar->GetIntValue(ix[i]); - } // endfor i - - if (!PlugCloseFile(g, To_Fbt) && !PlugCloseFile(g, To_Fb)) - return false; - -err: - if (trace) - htrc("%s\n", g->Message); - - PlugCloseFile(g, To_Fbt); - return true; - } // end of MakeDeletedFile - -/***********************************************************************/ /* Delete the old file and rename the new temp file. */ /* If aborting just delete the new temp file. */ /* If indexed, make the temp file from the arrays. */ @@ -1148,22 +1151,10 @@ int DOSFAM::RenameTempFile(PGLOBAL g) // This loop is necessary because, in case of join, // To_File can have been open several times. for (PFBLOCK fb = PlgGetUser(g)->Openlist; fb; fb = fb->Next) - if (fb == To_Fb || (fb == To_Fbt && !Indxd)) + if (fb == To_Fb || (fb == To_Fbt)) rc = PlugCloseFile(g, fb); if (!Abort) { - // If indexed the temp file must be made - if (Indxd) { - Abort = (Tdbp->Mode == MODE_UPDATE) ? MakeUpdatedFile(g) - : MakeDeletedFile(g); - - if (Abort) { - remove(tempname); - return RC_FX; - } // endif Abort - - } // endif Indxd - PlugSetPath(filename, To_File, Tdbp->GetPath()); strcat(PlugRemoveType(filetemp, filename), ".ttt"); remove(filetemp); // May still be there from previous error @@ -1199,7 +1190,7 @@ void DOSFAM::CloseTableFile(PGLOBAL g, bool abort) Abort = abort; if (UseTemp && T_Stream) { - if (Tdbp->Mode == MODE_UPDATE && !Indxd && !Abort) { + if (Tdbp->Mode == MODE_UPDATE && !Abort) { // Copy eventually remaining lines bool b; diff --git a/storage/connect/filamtxt.h b/storage/connect/filamtxt.h index 83c93ecc6f2..b89d58965f9 100644 --- a/storage/connect/filamtxt.h +++ b/storage/connect/filamtxt.h @@ -69,10 +69,13 @@ class DllExport TXTFAM : public BLOCK { virtual int DeleteRecords(PGLOBAL g, int irc) = 0; virtual void CloseTableFile(PGLOBAL g, bool abort) = 0; virtual void Rewind(void) = 0; - - protected: + virtual int InitDelete(PGLOBAL g, int fpos, int spos); bool AddListValue(PGLOBAL g, int type, void *val, PPARM *top); + int StoreValues(PGLOBAL g, bool upd); + int UpdateSortedRows(PGLOBAL g); + int DeleteSortedRows(PGLOBAL g); + protected: // Members PTDBDOS Tdbp; // To table class PSZ To_File; // Points to table file name @@ -107,9 +110,11 @@ class DllExport TXTFAM : public BLOCK { int Modif; // Number of modified lines in block int Blksize; // Size of padded blocks int Ending; // Length of line end + int Fpos; // Position of last read record + int Spos; // Start position for update/delete move + int Tpos; // Target Position for delete move bool Padded; // true if fixed size blocks are padded bool Eof; // true if an EOF (0xA) character exists - bool Indxd; // True for indexed UPDATE/DELETE bool Abort; // To abort on error char *CrLf; // End of line character(s) }; // end of class TXTFAM @@ -154,16 +159,12 @@ class DllExport DOSFAM : public TXTFAM { virtual bool OpenTempFile(PGLOBAL g); virtual bool MoveIntermediateLines(PGLOBAL g, bool *b); virtual int RenameTempFile(PGLOBAL g); - virtual bool MakeUpdatedFile(PGLOBAL g); - virtual bool MakeDeletedFile(PGLOBAL g); + virtual int InitDelete(PGLOBAL g, int fpos, int spos); // Members FILE *Stream; // Points to Dos file structure FILE *T_Stream; // Points to temporary file structure PFBLOCK To_Fbt; // Pointer to temp file block - int Fpos; // Position of last read record - int Tpos; // Target Position for delete move - int Spos; // Start position for update/delete move bool UseTemp; // True to use a temporary file in Upd/Del bool Bin; // True to force binary mode }; // end of class DOSFAM diff --git a/storage/connect/filamvct.cpp b/storage/connect/filamvct.cpp index 34f55cf831b..b93adbd13dd 100755 --- a/storage/connect/filamvct.cpp +++ b/storage/connect/filamvct.cpp @@ -93,11 +93,6 @@ typedef struct _vecheader { PVBLK AllocValBlock(PGLOBAL, void *, int, int, int, int, bool check = true, bool blank = true, bool un = false); -/***********************************************************************/ -/* Routine called externally by VCTFAM MakeUpdatedFile function. */ -/***********************************************************************/ -PARRAY MakeValueArray(PGLOBAL g, PPARM pp); - /* -------------------------- Class VCTFAM --------------------------- */ /***********************************************************************/ @@ -670,10 +665,7 @@ int VCTFAM::WriteBuffer(PGLOBAL g) // Mode Update is done in ReadDB, we just initialize it here if (!T_Stream) { if (UseTemp) { - if ((Indxd = Tdbp->GetKindex() != NULL)) { - strcpy(g->Message, "VCT indexed udate using temp file NIY"); - return RC_FX; - } else if (OpenTempFile(g)) + if (OpenTempFile(g)) return RC_FX; // Most of the time, not all table columns are updated. @@ -792,17 +784,12 @@ int VCTFAM::DeleteRecords(PGLOBAL g, int irc) Spos = Tpos = Fpos; } // endif UseTemp - Indxd = Tdbp->GetKindex() != NULL; } // endif Tpos == Spos /*********************************************************************/ /* Move any intermediate lines. */ /*********************************************************************/ - if (Indxd) { - // Moving will be done later, must be done in sequential order - (void)AddListValue(g, TYPE_INT, &Fpos, &To_Pos); - Spos = Fpos; - } else if (MoveIntermediateLines(g, &eof)) + if (MoveIntermediateLines(g, &eof)) return RC_FX; if (irc == RC_OK) { @@ -822,11 +809,6 @@ int VCTFAM::DeleteRecords(PGLOBAL g, int irc) /* Last call after EOF has been reached. */ /* Update the Block and Last values. */ /*******************************************************************/ - if (Indxd && (Abort = MakeDeletedFile(g))) - return RC_FX; - else - Indxd = false; // Not to be redone by RenameTempFile - Block = (Tpos > 0) ? (Tpos + Nrec - 1) / Nrec : 0; Last = (Tpos + Nrec - 1) % Nrec + 1; @@ -1027,63 +1009,6 @@ bool VCTFAM::MoveIntermediateLines(PGLOBAL g, bool *b) } // end of MoveIntermediateLines /***********************************************************************/ -/* MakeDeletedFile. When deleting using indexing, the issue is that */ -/* record are not necessarily deleted in sequential order. Moving */ -/* intermediate lines cannot be done while deleing them because */ -/* this can cause extra wrong records to be included in the new file. */ -/* What we do here is to reorder the deleted record and make the new */ -/* deleted file from the ordered deleted records. */ -/***********************************************************************/ -bool VCTFAM::MakeDeletedFile(PGLOBAL g) - { -//char *crlf = "\n", *mode = UseTemp ? "rb" : "r+b"; - int *ix, i, n; - bool eof = false; - - /*********************************************************************/ - /* Open the temporary file, Spos is at the beginning of file. */ - /*********************************************************************/ - if (!(Posar = MakeValueArray(g, To_Pos))) { - strcpy(g->Message, "Position array is null"); - goto err; - } else if (!(ix = (int*)Posar->GetSortIndex(g))) { - strcpy(g->Message, "Error getting array sort index"); - goto err; - } // endif's - - n = Posar->GetNval(); - Spos = 0; - - for (i = 0; i < n; i++) { - if (i == n - 1 && !MaxBlk && UseTemp) - eof = true; - - Fpos = Posar->GetIntValue(ix[i]); - - if (i || UseTemp) { - // Copy all not updated lines preceding this one - if (MoveIntermediateLines(g, &eof)) - goto err; - - } else - Tpos = Fpos; - - // New start position - Spos = Fpos + 1; - } // endfor i - - if (!PlugCloseFile(g, To_Fbt)) - return false; - -err: - if (trace) - htrc("%s\n", g->Message); - - PlugCloseFile(g, To_Fbt); - return true; - } // end of MakeDeletedFile - -/***********************************************************************/ /* Clean deleted space in a VCT or Vec table file. */ /***********************************************************************/ bool VCTFAM::CleanUnusedSpace(PGLOBAL g) @@ -1701,13 +1626,7 @@ int VCMFAM::DeleteRecords(PGLOBAL g, int irc) /* not required here, just setting of future Spos and Tpos. */ /*******************************************************************/ Tpos = Spos = Fpos; - Indxd = Tdbp->GetKindex() != NULL; - } // endif Tpos - - if (Indxd) - // Moving will be done later, must be done in sequential order - (void)AddListValue(g, TYPE_INT, &Fpos, &To_Pos); - else + } else (void)MoveIntermediateLines(g); if (irc == RC_OK) { @@ -1716,7 +1635,7 @@ int VCMFAM::DeleteRecords(PGLOBAL g, int irc) if (trace) htrc("after: Tpos=%p Spos=%p\n", Tpos, Spos); - } else if (!(Abort = (Indxd && MakeDeletedFile(g)))) { + } else { /*******************************************************************/ /* Last call after EOF has been reached. */ /*******************************************************************/ @@ -1786,8 +1705,7 @@ int VCMFAM::DeleteRecords(PGLOBAL g, int irc) // Reset Last and Block values in the catalog PlugCloseFile(g, To_Fb); // in case of Header ResetTableSize(g, Block, Last); - } else - return RC_FX; + } // endif irc return RC_OK; // All is correct } // end of DeleteRecords @@ -1842,49 +1760,6 @@ bool VCMFAM::MoveIntermediateLines(PGLOBAL g, bool *b) } // end of MoveIntermediate Lines /***********************************************************************/ -/* MakeDeletedFile. When deleting using indexing, the issue is that */ -/* record are not necessarily deleted in sequential order. Moving */ -/* intermediate lines cannot be done while deleting them. */ -/* What we do here is to reorder the deleted records and move the */ -/* intermediate files from the ordered deleted record positions. */ -/***********************************************************************/ -bool VCMFAM::MakeDeletedFile(PGLOBAL g) - { - int *ix, i; - - /*********************************************************************/ - /* Make and order the arrays from the saved values. */ - /*********************************************************************/ - if (!(Posar = MakeValueArray(g, To_Pos))) { - strcpy(g->Message, "Position array is null"); - goto err; - } else if (!(ix = (int*)Posar->GetSortIndex(g))) { - strcpy(g->Message, "Error getting array sort index"); - goto err; - } // endif's - - for (i = 0; i < Posar->GetNval(); i++) { - Fpos = Posar->GetIntValue(ix[i]); - - if (!i) { - Tpos = Fpos; - } else - (void)MoveIntermediateLines(g); - - // New start position - Spos = Fpos + 1; - } // endfor i - - return false; - -err: - if (trace) - htrc("%s\n", g->Message); - - return true; - } // end of MakeDeletedFile - -/***********************************************************************/ /* Data Base close routine for VMP access method. */ /***********************************************************************/ void VCMFAM::CloseTableFile(PGLOBAL g, bool abort) @@ -2309,10 +2184,7 @@ int VECFAM::WriteBuffer(PGLOBAL g) } else // Mode Update // Writing updates being done in ReadDB we do initialization only. if (InitUpdate) { - if ((Indxd = Tdbp->GetKindex() != NULL)) { - strcpy(g->Message, "VEC indexed udate using temp file NIY"); - return RC_FX; - } else if (OpenTempFile(g)) + if (OpenTempFile(g)) return RC_FX; InitUpdate = false; // Done @@ -2360,17 +2232,12 @@ int VECFAM::DeleteRecords(PGLOBAL g, int irc) /*****************************************************************/ Spos = Tpos = Fpos; - Indxd = Tdbp->GetKindex() != NULL; } // endif Tpos == Spos /*********************************************************************/ /* Move any intermediate lines. */ /*********************************************************************/ - if (Indxd) { - // Moving will be done later, must be done in sequential order - (void)AddListValue(g, TYPE_INT, &Fpos, &To_Pos); - Spos = Fpos; - } else if (MoveIntermediateLines(g)) + if (MoveIntermediateLines(g)) return RC_FX; if (irc == RC_OK) { @@ -2386,11 +2253,6 @@ int VECFAM::DeleteRecords(PGLOBAL g, int irc) /*******************************************************************/ /* Last call after EOF has been reached. */ /*******************************************************************/ - if (Indxd && (Abort = MakeDeletedFile(g))) - return RC_FX; -// else -// Indxd = false; // Not to be redone by RenameTempFile - if (!UseTemp) { /*****************************************************************/ /* Because the chsize functionality is only accessible with a */ @@ -2561,56 +2423,6 @@ bool VECFAM::MoveIntermediateLines(PGLOBAL g, bool *bn) } // end of MoveIntermediate Lines /***********************************************************************/ -/* MakeDeletedFile. When deleting using indexing, the issue is that */ -/* record are not necessarily deleted in sequential order. Moving */ -/* intermediate lines cannot be done while deleing them because */ -/* this can cause extra wrong records to be included in the new file. */ -/* What we do here is to reorder the deleted record and make the new */ -/* deleted file from the ordered deleted records. */ -/***********************************************************************/ -bool VECFAM::MakeDeletedFile(PGLOBAL g) - { - int *ix, i, n; - - /*********************************************************************/ - /* Open the temporary file, Spos is at the beginning of file. */ - /*********************************************************************/ - if (!(Posar = MakeValueArray(g, To_Pos))) { - strcpy(g->Message, "Position array is null"); - goto err; - } else if (!(ix = (int*)Posar->GetSortIndex(g))) { - strcpy(g->Message, "Error getting array sort index"); - goto err; - } // endif's - - n = Posar->GetNval(); - Spos = 0; - - for (i = 0; i < n; i++) { - Fpos = Posar->GetIntValue(ix[i]); - - if (i || UseTemp) { - // Copy all not updated lines preceding this one - if (MoveIntermediateLines(g)) - goto err; - - } else - Tpos = Fpos; - - // New start position - Spos = Fpos + 1; - } // endfor i - - return false; - -err: - if (trace) - htrc("%s\n", g->Message); - - return true; - } // end of MakeDeletedFile - -/***********************************************************************/ /* Delete the old files and rename the new temporary files. */ /***********************************************************************/ int VECFAM::RenameTempFile(PGLOBAL g) @@ -3109,13 +2921,7 @@ int VMPFAM::DeleteRecords(PGLOBAL g, int irc) /* not required here, just setting of future Spos and Tpos. */ /*******************************************************************/ Tpos = Fpos; // Spos is set below - Indxd = Tdbp->GetKindex() != NULL; - } // endif Tpos - - if (Indxd) - // Moving will be done later, must be done in sequential order - (void)AddListValue(g, TYPE_INT, &Fpos, &To_Pos); - else if ((n = Fpos - Spos) > 0) { + } else if ((n = Fpos - Spos) > 0) { /*******************************************************************/ /* Non consecutive line to delete. Move intermediate lines. */ /*******************************************************************/ @@ -3137,7 +2943,7 @@ int VMPFAM::DeleteRecords(PGLOBAL g, int irc) if (trace) htrc("after: Tpos=%p Spos=%p\n", Tpos, Spos); - } else if (!(Abort = (Indxd && MakeDeletedFile(g)))) { + } else { /*******************************************************************/ /* Last call after EOF has been reached. */ /* We must firstly Unmap the view and use the saved file handle */ @@ -3199,55 +3005,6 @@ int VMPFAM::DeleteRecords(PGLOBAL g, int irc) } // end of DeleteRecords /***********************************************************************/ -/* MakeDeletedFile. When deleting using indexing, the issue is that */ -/* record are not necessarily deleted in sequential order. Moving */ -/* intermediate lines cannot be done while deleting them. */ -/* What we do here is to reorder the deleted records and move the */ -/* intermediate files from the ordered deleted record positions. */ -/***********************************************************************/ -bool VMPFAM::MakeDeletedFile(PGLOBAL g) - { - int *ix, i, j, m, n; - - /*********************************************************************/ - /* Make and order the arrays from the saved values. */ - /*********************************************************************/ - if (!(Posar = MakeValueArray(g, To_Pos))) { - strcpy(g->Message, "Position array is null"); - goto err; - } else if (!(ix = (int*)Posar->GetSortIndex(g))) { - strcpy(g->Message, "Error getting array sort index"); - goto err; - } // endif's - - for (i = 0; i < Posar->GetNval(); i++) { - Fpos = Posar->GetIntValue(ix[i]); - - if (!i) { - Tpos = Fpos; - } else if ((n = Fpos - Spos) > 0) { - for (j = 0; j < Ncol; j++) { - m = Clens[j]; - memmove(Memcol[j] + Tpos * m, Memcol[j] + Spos * m, m * n); - } // endif j - - Tpos += n; - } // endif n - - // New start position - Spos = Fpos + 1; - } // endfor i - - return false; - -err: - if (trace) - htrc("%s\n", g->Message); - - return true; - } // end of MakeDeletedFile - -/***********************************************************************/ /* Data Base close routine for VMP access method. */ /***********************************************************************/ void VMPFAM::CloseTableFile(PGLOBAL g, bool abort) @@ -3969,10 +3726,7 @@ int BGVFAM::WriteBuffer(PGLOBAL g) // Mode Update is done in ReadDB, we just initialize it here if (Tfile == INVALID_HANDLE_VALUE) { if (UseTemp) { - if ((Indxd = Tdbp->GetKindex() != NULL)) { - strcpy(g->Message, "VEC indexed udate using temp file NIY"); - return RC_FX; - } else if (OpenTempFile(g)) + if (OpenTempFile(g)) return RC_FX; // Most of the time, not all table columns are updated. @@ -4099,17 +3853,12 @@ int BGVFAM::DeleteRecords(PGLOBAL g, int irc) Spos = Tpos = Fpos; } // endif UseTemp - Indxd = Tdbp->GetKindex() != NULL; } // endif Tpos == Spos /*********************************************************************/ /* Move any intermediate lines. */ /*********************************************************************/ - if (Indxd) { - // Moving will be done later, must be done in sequential order - (void)AddListValue(g, TYPE_INT, &Fpos, &To_Pos); - Spos = Fpos; - } else if (MoveIntermediateLines(g, &eof)) + if (MoveIntermediateLines(g, &eof)) return RC_FX; if (irc == RC_OK) { @@ -4125,11 +3874,6 @@ int BGVFAM::DeleteRecords(PGLOBAL g, int irc) /*******************************************************************/ /* Last call after EOF has been reached. */ /*******************************************************************/ - if (Indxd && (Abort = MakeDeletedFile(g))) - return RC_FX; - else - Indxd = false; // Not to be redone by RenameTempFile - Block = (Tpos > 0) ? (Tpos + Nrec - 1) / Nrec : 0; Last = (Tpos + Nrec - 1) % Nrec + 1; diff --git a/storage/connect/filamvct.h b/storage/connect/filamvct.h index 8acb62b14dc..be66232acfb 100644 --- a/storage/connect/filamvct.h +++ b/storage/connect/filamvct.h @@ -66,7 +66,6 @@ class DllExport VCTFAM : public FIXFAM { virtual bool MoveLines(PGLOBAL g) {return false;} virtual bool MoveIntermediateLines(PGLOBAL g, bool *b = NULL); virtual bool CleanUnusedSpace(PGLOBAL g); - virtual bool MakeDeletedFile(PGLOBAL g); virtual int GetBlockInfo(PGLOBAL g); virtual bool SetBlockInfo(PGLOBAL g); bool ResetTableSize(PGLOBAL g, int block, int last); @@ -116,7 +115,6 @@ class DllExport VCMFAM : public VCTFAM { protected: // Specific functions virtual bool MoveIntermediateLines(PGLOBAL g, bool *b = NULL); - virtual bool MakeDeletedFile(PGLOBAL g); virtual bool ReadBlock(PGLOBAL g, PVCTCOL colp); virtual bool WriteBlock(PGLOBAL g, PVCTCOL colp); @@ -162,7 +160,6 @@ class DllExport VECFAM : public VCTFAM { virtual bool MoveLines(PGLOBAL g); virtual bool MoveIntermediateLines(PGLOBAL g, bool *b = NULL); virtual int RenameTempFile(PGLOBAL g); - virtual bool MakeDeletedFile(PGLOBAL g); bool OpenColumnFile(PGLOBAL g, char *opmode, int i); // Members @@ -199,7 +196,6 @@ class DllExport VMPFAM : public VCMFAM { virtual void CloseTableFile(PGLOBAL g, bool abort); protected: - virtual bool MakeDeletedFile(PGLOBAL g); bool MapColumnFile(PGLOBAL g, MODE mode, int i); // Members diff --git a/storage/connect/ha_connect.cc b/storage/connect/ha_connect.cc index 6f9334bb604..2e1d59ff632 100644 --- a/storage/connect/ha_connect.cc +++ b/storage/connect/ha_connect.cc @@ -170,8 +170,8 @@ #define SZWMIN 4194304 // Minimum work area size 4M extern "C" { - char version[]= "Version 1.03.0002 July 17, 2014"; - char compver[]= "Version 1.03.0002 " __DATE__ " " __TIME__; + char version[]= "Version 1.03.0003 August 22, 2014"; + char compver[]= "Version 1.03.0003 " __DATE__ " " __TIME__; #if defined(WIN32) char slash= '\\'; @@ -185,11 +185,13 @@ extern "C" { int trace= 0; // The general trace value int xconv= 0; // The type conversion option int zconv= SZCONV; // The text conversion size + USETEMP Use_Temp= TMP_AUTO; // The temporary file use } // extern "C" #if defined(XMAP) bool xmap= false; #endif // XMAP + bool xinfo= false; uint worksize= SZWORK; ulong ha_connect::num= 0; @@ -200,9 +202,11 @@ static int xtrace= 0; static int conv_size= SZCONV; static uint work_size= SZWORK; static ulong type_conv= 0; +static ulong use_tempfile= 1; #if defined(XMAP) static my_bool indx_map= 0; #endif // XMAP +static my_bool exact_info= 0; /***********************************************************************/ /* Utility functions. */ @@ -224,11 +228,14 @@ static int connect_assisted_discovery(handlerton *hton, THD* thd, TABLE_SHARE *table_s, HA_CREATE_INFO *info); +/***********************************************************************/ +/* Global variables update functions. */ +/***********************************************************************/ static void update_connect_xtrace(MYSQL_THD thd, struct st_mysql_sys_var *var, void *var_ptr, const void *save) { - xtrace= *(int *)var_ptr= *(int *)save; + trace= *(int *)var_ptr= *(int *)save; } // end of update_connect_xtrace static void update_connect_zconv(MYSQL_THD thd, @@ -252,6 +259,13 @@ static void update_connect_worksize(MYSQL_THD thd, worksize= (uint)(*(ulong *)var_ptr= *(ulong *)save); } // end of update_connect_worksize +static void update_connect_usetemp(MYSQL_THD thd, + struct st_mysql_sys_var *var, + void *var_ptr, const void *save) +{ + Use_Temp= (USETEMP)(*(ulong *)var_ptr= *(ulong *)save); +} // end of update_connect_usetemp + #if defined(XMAP) static void update_connect_xmap(MYSQL_THD thd, struct st_mysql_sys_var *var, @@ -261,6 +275,13 @@ static void update_connect_xmap(MYSQL_THD thd, } // end of update_connect_xmap #endif // XMAP +static void update_connect_xinfo(MYSQL_THD thd, + struct st_mysql_sys_var *var, + void *var_ptr, const void *save) +{ + xinfo= (bool)(*(my_bool *)var_ptr= *(my_bool *)save); +} // end of update_connect_xinfo + /***********************************************************************/ /* The CONNECT handlerton object. */ /***********************************************************************/ @@ -542,6 +563,11 @@ ha_connect::ha_connect(handlerton *hton, TABLE_SHARE *table_arg) xp= (table) ? GetUser(ha_thd(), NULL) : NULL; if (xp) xp->SetHandler(this); +#if defined(WIN32) + datapath= ".\\"; +#else // !WIN32 + datapath= "./"; +#endif // !WIN32 tdbp= NULL; sdvalin= NULL; sdvalout= NULL; @@ -555,7 +581,7 @@ ha_connect::ha_connect(handlerton *hton, TABLE_SHARE *table_arg) stop= false; alter= false; mrr= false; - nox= false; + nox= true; abort= false; indexing= -1; locked= 0; @@ -1381,6 +1407,14 @@ void ha_connect::AddColName(char *cp, Field *fp) } // end of AddColName #endif // 0 +/***********************************************************************/ +/* This function sets the current database path. */ +/***********************************************************************/ +void ha_connect::SetDataPath(PGLOBAL g, const char *path) +{ + datapath= SetPath(g, path); +} // end of SetDataPath + /****************************************************************************/ /* Get the table description block of a CONNECT table. */ /****************************************************************************/ @@ -1590,7 +1624,7 @@ int ha_connect::CloseTable(PGLOBAL g) sdvalout=NULL; valid_info= false; indexing= -1; - nox= false; + nox= true; abort= false; return rc; } // end of CloseTable @@ -1697,10 +1731,10 @@ int ha_connect::MakeRecord(char *buf) // Store functions returns 1 on overflow and -1 on fatal error if (rc > 0) { - char buf[128]; + char buf[256]; THD *thd= ha_thd(); - sprintf(buf, "Out of range value %s for column '%s' at row %ld", + sprintf(buf, "Out of range value %.140s for column '%s' at row %ld", value->GetCharString(val), fp->field_name, thd->get_stmt_da()->current_row_for_warning()); @@ -2642,7 +2676,6 @@ int ha_connect::open(const char *name, int mode, uint test_if_locked) int ha_connect::optimize(THD* thd, HA_CHECK_OPT* check_opt) { int rc= 0; - bool dop= (check_opt != NULL); PGLOBAL& g= xp->g; PDBUSER dup= PlgGetUser(g); @@ -2652,9 +2685,10 @@ int ha_connect::optimize(THD* thd, HA_CHECK_OPT* check_opt) dup->Check |= CHK_OPT; if (tdbp) { - bool b= (((PTDBASE)tdbp)->GetDef()->Indexable() == 1); + bool dop= IsTypeIndexable(GetRealType(NULL)); + bool dox= (((PTDBASE)tdbp)->GetDef()->Indexable() == 1); - if ((rc= ((PTDBASE)tdbp)->ResetTableOpt(g, dop, b))) { + if ((rc= ((PTDBASE)tdbp)->ResetTableOpt(g, dop, dox))) { if (rc == RC_INFO) { push_warning(thd, Sql_condition::WARN_LEVEL_WARN, 0, g->Message); rc= 0; @@ -2739,7 +2773,8 @@ int ha_connect::write_row(uchar *buf) DBUG_RETURN(0); // Alter table on an outward partition table xmod= MODE_INSERT; - } // endif xmod + } else if (xmod == MODE_ANY) + DBUG_RETURN(0); // Probably never met // Open the table if it was not opened yet (locked) if (!IsOpened() || xmod != tdbp->GetMode()) { @@ -2751,9 +2786,6 @@ int ha_connect::write_row(uchar *buf) } // endif isopened - if (tdbp->GetMode() == MODE_ANY) - DBUG_RETURN(0); - #if 0 // AUTO_INCREMENT NIY if (table->next_number_field && buf == table->record[0]) { int error; @@ -2773,7 +2805,8 @@ int ha_connect::write_row(uchar *buf) DBUG_PRINT("write_row", ("%s", g->Message)); htrc("write_row: %s\n", g->Message); rc= HA_ERR_INTERNAL_ERROR; - } // endif RC + } else // Table is modified + nox= false; // Indexes to be remade DBUG_RETURN(rc); } // end of write_row @@ -2818,7 +2851,8 @@ int ha_connect::update_row(const uchar *old_data, uchar *new_data) DBUG_PRINT("update_row", ("%s", g->Message)); htrc("update_row CONNECT: %s\n", g->Message); rc= HA_ERR_INTERNAL_ERROR; - } // endif RC + } else + nox= false; // Table is modified DBUG_RETURN(rc); } // end of update_row @@ -2851,7 +2885,8 @@ int ha_connect::delete_row(const uchar *buf) if (CntDeleteRow(xp->g, tdbp, false)) { rc= HA_ERR_INTERNAL_ERROR; htrc("delete_row CONNECT: %s\n", xp->g->Message); - } // endif DeleteRow + } else + nox= false; // To remake indexes DBUG_RETURN(rc); } // end of delete_row @@ -2898,7 +2933,7 @@ int ha_connect::index_init(uint idx, bool sorted) DBUG_RETURN(0); } // endif locked - indexing= CntIndexInit(g, tdbp, (signed)idx); + indexing= CntIndexInit(g, tdbp, (signed)idx, sorted); if (indexing <= 0) { DBUG_PRINT("index_init", ("%s", g->Message)); @@ -2911,8 +2946,10 @@ int ha_connect::index_init(uint idx, bool sorted) ((PTDBDOX)tdbp)->GetTxfp()->ResetBuffer(g); active_index= idx; - } else // Void table - indexing= 0; +// } else { // Void table +// active_index= MAX_KEY; +// indexing= 0; + } // endif Num rc= 0; } // endif indexing @@ -3418,8 +3455,10 @@ int ha_connect::info(uint flag) } // endif xmod // This is necessary for getting file length - if (cat && table) - cat->SetDataPath(g, table->s->db.str); +// if (cat && table) +// cat->SetDataPath(g, table->s->db.str); + if (table) + SetDataPath(g, table->s->db.str); else DBUG_RETURN(HA_ERR_INTERNAL_ERROR); // Should never happen @@ -3535,7 +3574,8 @@ int ha_connect::delete_all_rows() if (CntDeleteRow(g, tdbp, true)) { htrc("%s\n", g->Message); rc= HA_ERR_INTERNAL_ERROR; - } // endif + } else + nox= false; } // endif rc @@ -4741,7 +4781,7 @@ static int connect_assisted_discovery(handlerton *hton, THD* thd, const char *fncn= "?"; const char *user, *fn, *db, *host, *pwd, *sep, *tbl, *src; const char *col, *ocl, *rnk, *pic, *fcl, *skc; - char *tab, *dsn, *shm; + char *tab, *dsn, *shm, *dpath; #if defined(WIN32) char *nsp= NULL, *cls= NULL; #endif // WIN32 @@ -4935,7 +4975,7 @@ static int connect_assisted_discovery(handlerton *hton, THD* thd, } else if (!user) user= "root"; - if (CheckSelf(g, table_s, host, db, tab, src, port)) + if (ok && CheckSelf(g, table_s, host, db, tab, src, port)) ok= false; break; @@ -4986,10 +5026,12 @@ static int connect_assisted_discovery(handlerton *hton, THD* thd, char *cnm, *rem, *dft, *xtra; int i, len, prec, dec, typ, flg; - if (cat) - cat->SetDataPath(g, table_s->db.str); - else - return HA_ERR_INTERNAL_ERROR; // Should never happen +// if (cat) +// cat->SetDataPath(g, table_s->db.str); +// else +// return HA_ERR_INTERNAL_ERROR; // Should never happen + + dpath= SetPath(g, table_s->db.str); if (src && ttp != TAB_PIVOT && ttp != TAB_ODBC) { qrp= SrcColumns(g, host, db, user, pwd, src, port); @@ -5002,7 +5044,7 @@ static int connect_assisted_discovery(handlerton *hton, THD* thd, } else switch (ttp) { case TAB_DBF: - qrp= DBFColumns(g, fn, fnc == FNC_COL); + qrp= DBFColumns(g, dpath, fn, fnc == FNC_COL); break; #if defined(ODBC_SUPPORT) case TAB_ODBC: @@ -5039,7 +5081,7 @@ static int connect_assisted_discovery(handlerton *hton, THD* thd, break; #endif // MYSQL_SUPPORT case TAB_CSV: - qrp= CSVColumns(g, fn, spc, qch, hdr, mxe, fnc == FNC_COL); + qrp= CSVColumns(g, dpath, fn, spc, qch, hdr, mxe, fnc == FNC_COL); break; #if defined(WIN32) case TAB_WMI: @@ -5705,8 +5747,10 @@ int ha_connect::create(const char *name, TABLE *table_arg, PDBUSER dup= PlgGetUser(g); PCATLG cat= (dup) ? dup->Catalog : NULL; + SetDataPath(g, table_arg->s->db.str); + if (cat) { - cat->SetDataPath(g, table_arg->s->db.str); +// cat->SetDataPath(g, table_arg->s->db.str); #if defined(WITH_PARTITION_STORAGE_ENGINE) if (part_info) @@ -6196,6 +6240,9 @@ Item *ha_connect::idx_cond_push(uint keyno_arg, Item* idx_cond_arg) struct st_mysql_storage_engine connect_storage_engine= { MYSQL_HANDLERTON_INTERFACE_VERSION }; +/***********************************************************************/ +/* CONNECT global variables definitions. */ +/***********************************************************************/ // Tracing: 0 no, 1 yes, >1 more tracing static MYSQL_SYSVAR_INT(xtrace, xtrace, PLUGIN_VAR_RQCMDARG, "Console trace value.", @@ -6233,6 +6280,35 @@ static MYSQL_SYSVAR_ENUM( 0, // def (no) &xconv_typelib); // typelib +/** + Temporary file usage: + no: Not using temporary file + auto: Using temporary file when needed + yes: Allways using temporary file + force: Force using temporary file (no MAP) + test: Reserved +*/ +const char *usetemp_names[]= +{ + "NO", "AUTO", "YES", "FORCE", "TEST", NullS +}; + +TYPELIB usetemp_typelib= +{ + array_elements(usetemp_names) - 1, "usetemp_typelib", + usetemp_names, NULL +}; + +static MYSQL_SYSVAR_ENUM( + use_tempfile, // name + use_tempfile, // varname + PLUGIN_VAR_RQCMDARG, // opt + "Temporary file use.", // comment + NULL, // check + update_connect_usetemp, // update function + 1, // def (AUTO) + &usetemp_typelib); // typelib + #if defined(XMAP) // Using file mapping for indexes if true static MYSQL_SYSVAR_BOOL(indx_map, indx_map, PLUGIN_VAR_RQCMDARG, @@ -6245,6 +6321,11 @@ static MYSQL_SYSVAR_UINT(work_size, work_size, PLUGIN_VAR_RQCMDARG, "Size of the CONNECT work area.", NULL, update_connect_worksize, SZWORK, SZWMIN, UINT_MAX, 1); +// Getting exact info values +static MYSQL_SYSVAR_BOOL(exact_info, exact_info, PLUGIN_VAR_RQCMDARG, + "Getting exact info values", + NULL, update_connect_xinfo, 0); + static struct st_mysql_sys_var* connect_system_variables[]= { MYSQL_SYSVAR(xtrace), MYSQL_SYSVAR(conv_size), @@ -6253,6 +6334,8 @@ static struct st_mysql_sys_var* connect_system_variables[]= { MYSQL_SYSVAR(indx_map), #endif // XMAP MYSQL_SYSVAR(work_size), + MYSQL_SYSVAR(use_tempfile), + MYSQL_SYSVAR(exact_info), NULL }; diff --git a/storage/connect/ha_connect.h b/storage/connect/ha_connect.h index f12582b9b19..9a73c85cdc7 100644 --- a/storage/connect/ha_connect.h +++ b/storage/connect/ha_connect.h @@ -210,7 +210,9 @@ public: bool IsSameIndex(PIXDEF xp1, PIXDEF xp2); bool IsPartitioned(void); bool IsUnique(uint n); + char *GetDataPath(void) {return (char*)datapath;} + void SetDataPath(PGLOBAL g, const char *path); PTDB GetTDB(PGLOBAL g); int OpenTable(PGLOBAL g, bool del= false); bool CheckColumnList(PGLOBAL g); @@ -521,6 +523,7 @@ protected: ulong hnum; // The number of this handler query_id_t valid_query_id; // The one when tdbp was allocated query_id_t creat_query_id; // The one when handler was allocated + char *datapath; // Is the Path of DB data directory PTDB tdbp; // To table class object PVAL sdvalin; // Used to convert date values PVAL sdvalout; // Used to convert date values diff --git a/storage/connect/maputil.cpp b/storage/connect/maputil.cpp index 7104259ebad..97c638b4254 100644 --- a/storage/connect/maputil.cpp +++ b/storage/connect/maputil.cpp @@ -154,7 +154,7 @@ HANDLE CreateFileMap(PGLOBAL g, LPCSTR fileName, } // endswitch // Try to open the addressed file. - fd= global_open(g, MSGID_NONE, fileName, openMode); + fd= global_open(g, MSGID_NONE, fileName, openMode); if (fd != INVALID_HANDLE_VALUE && mode != MODE_INSERT) { /* We must know about the size of the file. */ @@ -164,17 +164,19 @@ HANDLE CreateFileMap(PGLOBAL g, LPCSTR fileName, return INVALID_HANDLE_VALUE; } // endif fstat - filesize = st.st_size; - - // Now we are ready to load the file. If mmap() is available we try - // this first. If not available or it failed we try to load it. - mm->memory = mmap(NULL, filesize, protmode, MAP_SHARED, fd, 0); + if ((filesize = st.st_size)) + // Now we are ready to load the file. If mmap() is available we try + // this first. If not available or it failed we try to load it. + mm->memory = mmap(NULL, filesize, protmode, MAP_SHARED, fd, 0); + else + mm->memory = 0; if (mm->memory != MAP_FAILED) { mm->lenL = (mm->memory != 0) ? filesize : 0; mm->lenH = 0; } else { strcpy(g->Message, "Memory mapping failed"); + close(fd); return INVALID_HANDLE_VALUE; } // endif memory diff --git a/storage/connect/mycat.cc b/storage/connect/mycat.cc index ca09e877b1a..660e2adec2f 100644 --- a/storage/connect/mycat.cc +++ b/storage/connect/mycat.cc @@ -405,9 +405,9 @@ PQRYRES OEMColumns(PGLOBAL g, PTOS topt, char *tab, char *db, bool info) CATALOG::CATALOG(void) { #if defined(WIN32) - DataPath= ".\\"; +//DataPath= ".\\"; #else // !WIN32 - DataPath= "./"; +//DataPath= "./"; #endif // !WIN32 memset(&Ctb, 0, sizeof(CURTAB)); Cbuf= NULL; @@ -433,6 +433,7 @@ void MYCAT::Reset(void) { } // end of Reset +#if 0 /***********************************************************************/ /* This function sets the current database path. */ /***********************************************************************/ @@ -463,6 +464,7 @@ void MYCAT::SetPath(PGLOBAL g, LPCSTR *datapath, const char *path) } // endif path } // end of SetDataPath +#endif // 0 /***********************************************************************/ /* GetTableDesc: retrieve a table descriptor. */ @@ -560,7 +562,7 @@ PTDB MYCAT::GetTable(PGLOBAL g, PTABLE tablep, MODE mode, LPCSTR type) printf("tdb=%p type=%s\n", tdp, tdp->GetType()); if (tablep->GetQualifier()) - SetPath(g, &tdp->Database, tablep->GetQualifier()); + tdp->Database = SetPath(g, tablep->GetQualifier()); tdbp= tdp->GetTable(g, mode); } // endif tdp diff --git a/storage/connect/mycat.h b/storage/connect/mycat.h index b45d3a08725..1aaee4ed1e8 100644 --- a/storage/connect/mycat.h +++ b/storage/connect/mycat.h @@ -56,8 +56,8 @@ class MYCAT : public CATALOG { // Methods void Reset(void); - void SetDataPath(PGLOBAL g, const char *path) - {SetPath(g, &DataPath, path);} +//void SetDataPath(PGLOBAL g, const char *path) +// {SetPath(g, &DataPath, path);} bool StoreIndex(PGLOBAL g, PTABDEF defp) {return false;} // Temporary PRELDEF GetTableDesc(PGLOBAL g, LPCSTR name, LPCSTR type, PRELDEF *prp = NULL); @@ -67,7 +67,7 @@ class MYCAT : public CATALOG { protected: PRELDEF MakeTableDesc(PGLOBAL g, LPCSTR name, LPCSTR am); - void SetPath(PGLOBAL g, LPCSTR *datapath, const char *path); +//void SetPath(PGLOBAL g, LPCSTR *datapath, const char *path); // Members ha_connect *Hc; // The Connect handler diff --git a/storage/connect/mysql-test/connect/r/part_file.result b/storage/connect/mysql-test/connect/r/part_file.result index bd5c258a4e2..c679ed95062 100644 --- a/storage/connect/mysql-test/connect/r/part_file.result +++ b/storage/connect/mysql-test/connect/r/part_file.result @@ -1,3 +1,4 @@ +set @@global.connect_exact_info=ON; # This will be used to see what data files are created CREATE TABLE dr1 ( fname VARCHAR(256) NOT NULL FLAG=2, @@ -342,3 +343,4 @@ part2 .txt part3 .txt DROP TABLE t1; DROP TABLE dr1; +set @@global.connect_exact_info=OFF; diff --git a/storage/connect/mysql-test/connect/r/part_table.result b/storage/connect/mysql-test/connect/r/part_table.result index 09d46687f00..122c328fa59 100644 --- a/storage/connect/mysql-test/connect/r/part_table.result +++ b/storage/connect/mysql-test/connect/r/part_table.result @@ -1,3 +1,4 @@ +set @@global.connect_exact_info=ON; CREATE TABLE xt1 ( id INT KEY NOT NULL, msg VARCHAR(32)) @@ -193,3 +194,4 @@ DROP TABLE t1; DROP TABLE xt1; DROP TABLE xt2; DROP TABLE xt3; +set @@global.connect_exact_info=OFF; diff --git a/storage/connect/mysql-test/connect/r/temporary.result b/storage/connect/mysql-test/connect/r/temporary.result new file mode 100644 index 00000000000..c4e992f2a64 --- /dev/null +++ b/storage/connect/mysql-test/connect/r/temporary.result @@ -0,0 +1,6 @@ +CREATE TEMPORARY TABLE t1 (a int not null) +ENGINE=CONNECT table_type=MYSQL CONNECTION='mysql://root@127.0.0.1/test/t2'; +ERROR HY000: Table storage engine 'CONNECT' does not support the create option 'TEMPORARY' +CREATE TEMPORARY TABLE t1 +ENGINE=CONNECT table_type=MYSQL CONNECTION='mysql://root@127.0.0.1/test/t2'; +ERROR HY000: Table storage engine 'CONNECT' does not support the create option 'TEMPORARY' diff --git a/storage/connect/mysql-test/connect/r/updelx.result b/storage/connect/mysql-test/connect/r/updelx.result new file mode 100644 index 00000000000..2aed1e06928 --- /dev/null +++ b/storage/connect/mysql-test/connect/r/updelx.result @@ -0,0 +1,2570 @@ +# +# Testing indexed UPDATE and DELETE for all table types +# +# CSV table +CREATE TABLE t1 ( +id INT KEY NOT NULL, +msg VARCHAR(32)) +ENGINE=CONNECT TABLE_TYPE=CSV AVG_ROW_LENGTH=6; +Warnings: +Warning 1105 No file name. Table will use t1.csv +DELETE FROM t1; +INSERT INTO t1 VALUES(4, 'four'),(7,'seven'),(10,'ten'),(40,'forty'),(60,'sixty'),(81,'eighty one'),(72,'seventy two'),(11,'eleven'),(1,'one'),(35,'thirty five'),(8,'eight'); +SELECT * FROM t1; +id msg +4 four +7 seven +10 ten +40 forty +60 sixty +81 eighty one +72 seventy two +11 eleven +1 one +35 thirty five +8 eight +UPDATE t1 SET msg = 'bof' WHERE id = 35; +SELECT * FROM t1; +id msg +4 four +7 seven +10 ten +40 forty +60 sixty +81 eighty one +72 seventy two +11 eleven +1 one +35 bof +8 eight +UPDATE t1 SET msg = 'big' WHERE id > 50; +SELECT * FROM t1; +id msg +4 four +7 seven +10 ten +40 forty +60 big +81 big +72 big +11 eleven +1 one +35 bof +8 eight +UPDATE t1 SET msg = 'updated' WHERE id IN (8,35,60,72); +SELECT * FROM t1; +id msg +4 four +7 seven +10 ten +40 forty +60 updated +81 big +72 updated +11 eleven +1 one +35 updated +8 updated +UPDATE t1 SET msg = 'twin' WHERE id IN (81,10); +SELECT * FROM t1; +id msg +4 four +7 seven +10 twin +40 forty +60 updated +81 twin +72 updated +11 eleven +1 one +35 updated +8 updated +UPDATE t1 SET msg = 'sixty' WHERE id = 60; +SELECT * FROM t1 WHERE id = 60; +id msg +60 sixty +DELETE FROM t1 WHERE id = 4; +SELECT * FROM t1; +id msg +7 seven +10 twin +40 forty +60 sixty +81 twin +72 updated +11 eleven +1 one +35 updated +8 updated +DELETE FROM t1 WHERE id IN (40,11,35); +SELECT * FROM t1; +id msg +7 seven +10 twin +60 sixty +81 twin +72 updated +1 one +8 updated +DELETE FROM t1 WHERE id IN (4,60,1); +SELECT msg FROM t1; +msg +seven +twin +twin +updated +updated +DELETE FROM t1 WHERE id IN (81,72); +SELECT id FROM t1; +id +7 +8 +10 +DELETE FROM t1 WHERE id IN (7,10); +SELECT * FROM t1; +id msg +8 updated +DELETE FROM t1 WHERE id = 8; +SELECT * FROM t1; +id msg +ALTER TABLE t1 MAPPED=YES; +DELETE FROM t1; +INSERT INTO t1 VALUES(4, 'four'),(7,'seven'),(10,'ten'),(40,'forty'),(60,'sixty'),(81,'eighty one'),(72,'seventy two'),(11,'eleven'),(1,'one'),(35,'thirty five'),(8,'eight'); +SELECT * FROM t1; +id msg +4 four +7 seven +10 ten +40 forty +60 sixty +81 eighty one +72 seventy two +11 eleven +1 one +35 thirty five +8 eight +UPDATE t1 SET msg = 'bof' WHERE id = 35; +SELECT * FROM t1; +id msg +4 four +7 seven +10 ten +40 forty +60 sixty +81 eighty one +72 seventy two +11 eleven +1 one +35 bof +8 eight +UPDATE t1 SET msg = 'big' WHERE id > 50; +SELECT * FROM t1; +id msg +4 four +7 seven +10 ten +40 forty +60 big +81 big +72 big +11 eleven +1 one +35 bof +8 eight +UPDATE t1 SET msg = 'updated' WHERE id IN (8,35,60,72); +SELECT * FROM t1; +id msg +4 four +7 seven +10 ten +40 forty +60 updated +81 big +72 updated +11 eleven +1 one +35 updated +8 updated +UPDATE t1 SET msg = 'twin' WHERE id IN (81,10); +SELECT * FROM t1; +id msg +4 four +7 seven +10 twin +40 forty +60 updated +81 twin +72 updated +11 eleven +1 one +35 updated +8 updated +UPDATE t1 SET msg = 'sixty' WHERE id = 60; +SELECT * FROM t1 WHERE id = 60; +id msg +60 sixty +DELETE FROM t1 WHERE id = 4; +SELECT * FROM t1; +id msg +7 seven +10 twin +40 forty +60 sixty +81 twin +72 updated +11 eleven +1 one +35 updated +8 updated +DELETE FROM t1 WHERE id IN (40,11,35); +SELECT * FROM t1; +id msg +7 seven +10 twin +60 sixty +81 twin +72 updated +1 one +8 updated +DELETE FROM t1 WHERE id IN (4,60,1); +SELECT msg FROM t1; +msg +seven +twin +twin +updated +updated +DELETE FROM t1 WHERE id IN (81,72); +SELECT id FROM t1; +id +7 +8 +10 +DELETE FROM t1 WHERE id IN (7,10); +SELECT * FROM t1; +id msg +8 updated +DELETE FROM t1 WHERE id = 8; +SELECT * FROM t1; +id msg +ALTER TABLE t1 MAPPED=NO BLOCK_SIZE=6; +DELETE FROM t1; +INSERT INTO t1 VALUES(4, 'four'),(7,'seven'),(10,'ten'),(40,'forty'),(60,'sixty'),(81,'eighty one'),(72,'seventy two'),(11,'eleven'),(1,'one'),(35,'thirty five'),(8,'eight'); +SELECT * FROM t1; +id msg +4 four +7 seven +10 ten +40 forty +60 sixty +81 eighty one +72 seventy two +11 eleven +1 one +35 thirty five +8 eight +UPDATE t1 SET msg = 'bof' WHERE id = 35; +SELECT * FROM t1; +id msg +4 four +7 seven +10 ten +40 forty +60 sixty +81 eighty one +72 seventy two +11 eleven +1 one +35 bof +8 eight +UPDATE t1 SET msg = 'big' WHERE id > 50; +SELECT * FROM t1; +id msg +4 four +7 seven +10 ten +40 forty +60 big +81 big +72 big +11 eleven +1 one +35 bof +8 eight +UPDATE t1 SET msg = 'updated' WHERE id IN (8,35,60,72); +SELECT * FROM t1; +id msg +4 four +7 seven +10 ten +40 forty +60 updated +81 big +72 updated +11 eleven +1 one +35 updated +8 updated +UPDATE t1 SET msg = 'twin' WHERE id IN (81,10); +SELECT * FROM t1; +id msg +4 four +7 seven +10 twin +40 forty +60 updated +81 twin +72 updated +11 eleven +1 one +35 updated +8 updated +UPDATE t1 SET msg = 'sixty' WHERE id = 60; +SELECT * FROM t1 WHERE id = 60; +id msg +60 sixty +DELETE FROM t1 WHERE id = 4; +SELECT * FROM t1; +id msg +7 seven +10 twin +40 forty +60 sixty +81 twin +72 updated +11 eleven +1 one +35 updated +8 updated +DELETE FROM t1 WHERE id IN (40,11,35); +SELECT * FROM t1; +id msg +7 seven +10 twin +60 sixty +81 twin +72 updated +1 one +8 updated +DELETE FROM t1 WHERE id IN (4,60,1); +SELECT msg FROM t1; +msg +seven +twin +twin +updated +updated +DELETE FROM t1 WHERE id IN (81,72); +SELECT id FROM t1; +id +7 +8 +10 +DELETE FROM t1 WHERE id IN (7,10); +SELECT * FROM t1; +id msg +8 updated +DELETE FROM t1 WHERE id = 8; +SELECT * FROM t1; +id msg +ALTER TABLE t1 MAPPED=YES; +DELETE FROM t1; +INSERT INTO t1 VALUES(4, 'four'),(7,'seven'),(10,'ten'),(40,'forty'),(60,'sixty'),(81,'eighty one'),(72,'seventy two'),(11,'eleven'),(1,'one'),(35,'thirty five'),(8,'eight'); +SELECT * FROM t1; +id msg +4 four +7 seven +10 ten +40 forty +60 sixty +81 eighty one +72 seventy two +11 eleven +1 one +35 thirty five +8 eight +UPDATE t1 SET msg = 'bof' WHERE id = 35; +SELECT * FROM t1; +id msg +4 four +7 seven +10 ten +40 forty +60 sixty +81 eighty one +72 seventy two +11 eleven +1 one +35 bof +8 eight +UPDATE t1 SET msg = 'big' WHERE id > 50; +SELECT * FROM t1; +id msg +4 four +7 seven +10 ten +40 forty +60 big +81 big +72 big +11 eleven +1 one +35 bof +8 eight +UPDATE t1 SET msg = 'updated' WHERE id IN (8,35,60,72); +SELECT * FROM t1; +id msg +4 four +7 seven +10 ten +40 forty +60 updated +81 big +72 updated +11 eleven +1 one +35 updated +8 updated +UPDATE t1 SET msg = 'twin' WHERE id IN (81,10); +SELECT * FROM t1; +id msg +4 four +7 seven +10 twin +40 forty +60 updated +81 twin +72 updated +11 eleven +1 one +35 updated +8 updated +UPDATE t1 SET msg = 'sixty' WHERE id = 60; +SELECT * FROM t1 WHERE id = 60; +id msg +60 sixty +DELETE FROM t1 WHERE id = 4; +SELECT * FROM t1; +id msg +7 seven +10 twin +40 forty +60 sixty +81 twin +72 updated +11 eleven +1 one +35 updated +8 updated +DELETE FROM t1 WHERE id IN (40,11,35); +SELECT * FROM t1; +id msg +7 seven +10 twin +60 sixty +81 twin +72 updated +1 one +8 updated +DELETE FROM t1 WHERE id IN (4,60,1); +SELECT msg FROM t1; +msg +seven +twin +twin +updated +updated +DELETE FROM t1 WHERE id IN (81,72); +SELECT id FROM t1; +id +7 +8 +10 +DELETE FROM t1 WHERE id IN (7,10); +SELECT * FROM t1; +id msg +8 updated +DELETE FROM t1 WHERE id = 8; +SELECT * FROM t1; +id msg +DROP TABLE t1; +# DOS table +CREATE TABLE t1 ( +id INT(4) KEY NOT NULL, +msg VARCHAR(16)) +ENGINE=CONNECT TABLE_TYPE=DOS; +Warnings: +Warning 1105 No file name. Table will use t1.dos +DELETE FROM t1; +INSERT INTO t1 VALUES(4, 'four'),(7,'seven'),(10,'ten'),(40,'forty'),(60,'sixty'),(81,'eighty one'),(72,'seventy two'),(11,'eleven'),(1,'one'),(35,'thirty five'),(8,'eight'); +SELECT * FROM t1; +id msg +4 four +7 seven +10 ten +40 forty +60 sixty +81 eighty one +72 seventy two +11 eleven +1 one +35 thirty five +8 eight +UPDATE t1 SET msg = 'bof' WHERE id = 35; +SELECT * FROM t1; +id msg +4 four +7 seven +10 ten +40 forty +60 sixty +81 eighty one +72 seventy two +11 eleven +1 one +35 bof +8 eight +UPDATE t1 SET msg = 'big' WHERE id > 50; +SELECT * FROM t1; +id msg +4 four +7 seven +10 ten +40 forty +60 big +81 big +72 big +11 eleven +1 one +35 bof +8 eight +UPDATE t1 SET msg = 'updated' WHERE id IN (8,35,60,72); +SELECT * FROM t1; +id msg +4 four +7 seven +10 ten +40 forty +60 updated +81 big +72 updated +11 eleven +1 one +35 updated +8 updated +UPDATE t1 SET msg = 'twin' WHERE id IN (81,10); +SELECT * FROM t1; +id msg +4 four +7 seven +10 twin +40 forty +60 updated +81 twin +72 updated +11 eleven +1 one +35 updated +8 updated +UPDATE t1 SET msg = 'sixty' WHERE id = 60; +SELECT * FROM t1 WHERE id = 60; +id msg +60 sixty +DELETE FROM t1 WHERE id = 4; +SELECT * FROM t1; +id msg +7 seven +10 twin +40 forty +60 sixty +81 twin +72 updated +11 eleven +1 one +35 updated +8 updated +DELETE FROM t1 WHERE id IN (40,11,35); +SELECT * FROM t1; +id msg +7 seven +10 twin +60 sixty +81 twin +72 updated +1 one +8 updated +DELETE FROM t1 WHERE id IN (4,60,1); +SELECT msg FROM t1; +msg +seven +twin +twin +updated +updated +DELETE FROM t1 WHERE id IN (81,72); +SELECT id FROM t1; +id +7 +8 +10 +DELETE FROM t1 WHERE id IN (7,10); +SELECT * FROM t1; +id msg +8 updated +DELETE FROM t1 WHERE id = 8; +SELECT * FROM t1; +id msg +ALTER TABLE t1 MAPPED=YES; +DELETE FROM t1; +INSERT INTO t1 VALUES(4, 'four'),(7,'seven'),(10,'ten'),(40,'forty'),(60,'sixty'),(81,'eighty one'),(72,'seventy two'),(11,'eleven'),(1,'one'),(35,'thirty five'),(8,'eight'); +SELECT * FROM t1; +id msg +4 four +7 seven +10 ten +40 forty +60 sixty +81 eighty one +72 seventy two +11 eleven +1 one +35 thirty five +8 eight +UPDATE t1 SET msg = 'bof' WHERE id = 35; +SELECT * FROM t1; +id msg +4 four +7 seven +10 ten +40 forty +60 sixty +81 eighty one +72 seventy two +11 eleven +1 one +35 bof +8 eight +UPDATE t1 SET msg = 'big' WHERE id > 50; +SELECT * FROM t1; +id msg +4 four +7 seven +10 ten +40 forty +60 big +81 big +72 big +11 eleven +1 one +35 bof +8 eight +UPDATE t1 SET msg = 'updated' WHERE id IN (8,35,60,72); +SELECT * FROM t1; +id msg +4 four +7 seven +10 ten +40 forty +60 updated +81 big +72 updated +11 eleven +1 one +35 updated +8 updated +UPDATE t1 SET msg = 'twin' WHERE id IN (81,10); +SELECT * FROM t1; +id msg +4 four +7 seven +10 twin +40 forty +60 updated +81 twin +72 updated +11 eleven +1 one +35 updated +8 updated +UPDATE t1 SET msg = 'sixty' WHERE id = 60; +SELECT * FROM t1 WHERE id = 60; +id msg +60 sixty +DELETE FROM t1 WHERE id = 4; +SELECT * FROM t1; +id msg +7 seven +10 twin +40 forty +60 sixty +81 twin +72 updated +11 eleven +1 one +35 updated +8 updated +DELETE FROM t1 WHERE id IN (40,11,35); +SELECT * FROM t1; +id msg +7 seven +10 twin +60 sixty +81 twin +72 updated +1 one +8 updated +DELETE FROM t1 WHERE id IN (4,60,1); +SELECT msg FROM t1; +msg +seven +twin +twin +updated +updated +DELETE FROM t1 WHERE id IN (81,72); +SELECT id FROM t1; +id +7 +8 +10 +DELETE FROM t1 WHERE id IN (7,10); +SELECT * FROM t1; +id msg +8 updated +DELETE FROM t1 WHERE id = 8; +SELECT * FROM t1; +id msg +ALTER TABLE t1 MAPPED=NO BLOCK_SIZE=4; +DELETE FROM t1; +INSERT INTO t1 VALUES(4, 'four'),(7,'seven'),(10,'ten'),(40,'forty'),(60,'sixty'),(81,'eighty one'),(72,'seventy two'),(11,'eleven'),(1,'one'),(35,'thirty five'),(8,'eight'); +SELECT * FROM t1; +id msg +4 four +7 seven +10 ten +40 forty +60 sixty +81 eighty one +72 seventy two +11 eleven +1 one +35 thirty five +8 eight +UPDATE t1 SET msg = 'bof' WHERE id = 35; +SELECT * FROM t1; +id msg +4 four +7 seven +10 ten +40 forty +60 sixty +81 eighty one +72 seventy two +11 eleven +1 one +35 bof +8 eight +UPDATE t1 SET msg = 'big' WHERE id > 50; +SELECT * FROM t1; +id msg +4 four +7 seven +10 ten +40 forty +60 big +81 big +72 big +11 eleven +1 one +35 bof +8 eight +UPDATE t1 SET msg = 'updated' WHERE id IN (8,35,60,72); +SELECT * FROM t1; +id msg +4 four +7 seven +10 ten +40 forty +60 updated +81 big +72 updated +11 eleven +1 one +35 updated +8 updated +UPDATE t1 SET msg = 'twin' WHERE id IN (81,10); +SELECT * FROM t1; +id msg +4 four +7 seven +10 twin +40 forty +60 updated +81 twin +72 updated +11 eleven +1 one +35 updated +8 updated +UPDATE t1 SET msg = 'sixty' WHERE id = 60; +SELECT * FROM t1 WHERE id = 60; +id msg +60 sixty +DELETE FROM t1 WHERE id = 4; +SELECT * FROM t1; +id msg +7 seven +10 twin +40 forty +60 sixty +81 twin +72 updated +11 eleven +1 one +35 updated +8 updated +DELETE FROM t1 WHERE id IN (40,11,35); +SELECT * FROM t1; +id msg +7 seven +10 twin +60 sixty +81 twin +72 updated +1 one +8 updated +DELETE FROM t1 WHERE id IN (4,60,1); +SELECT msg FROM t1; +msg +seven +twin +twin +updated +updated +DELETE FROM t1 WHERE id IN (81,72); +SELECT id FROM t1; +id +7 +8 +10 +DELETE FROM t1 WHERE id IN (7,10); +SELECT * FROM t1; +id msg +8 updated +DELETE FROM t1 WHERE id = 8; +SELECT * FROM t1; +id msg +ALTER TABLE t1 MAPPED=YES; +DELETE FROM t1; +INSERT INTO t1 VALUES(4, 'four'),(7,'seven'),(10,'ten'),(40,'forty'),(60,'sixty'),(81,'eighty one'),(72,'seventy two'),(11,'eleven'),(1,'one'),(35,'thirty five'),(8,'eight'); +SELECT * FROM t1; +id msg +4 four +7 seven +10 ten +40 forty +60 sixty +81 eighty one +72 seventy two +11 eleven +1 one +35 thirty five +8 eight +UPDATE t1 SET msg = 'bof' WHERE id = 35; +SELECT * FROM t1; +id msg +4 four +7 seven +10 ten +40 forty +60 sixty +81 eighty one +72 seventy two +11 eleven +1 one +35 bof +8 eight +UPDATE t1 SET msg = 'big' WHERE id > 50; +SELECT * FROM t1; +id msg +4 four +7 seven +10 ten +40 forty +60 big +81 big +72 big +11 eleven +1 one +35 bof +8 eight +UPDATE t1 SET msg = 'updated' WHERE id IN (8,35,60,72); +SELECT * FROM t1; +id msg +4 four +7 seven +10 ten +40 forty +60 updated +81 big +72 updated +11 eleven +1 one +35 updated +8 updated +UPDATE t1 SET msg = 'twin' WHERE id IN (81,10); +SELECT * FROM t1; +id msg +4 four +7 seven +10 twin +40 forty +60 updated +81 twin +72 updated +11 eleven +1 one +35 updated +8 updated +UPDATE t1 SET msg = 'sixty' WHERE id = 60; +SELECT * FROM t1 WHERE id = 60; +id msg +60 sixty +DELETE FROM t1 WHERE id = 4; +SELECT * FROM t1; +id msg +7 seven +10 twin +40 forty +60 sixty +81 twin +72 updated +11 eleven +1 one +35 updated +8 updated +DELETE FROM t1 WHERE id IN (40,11,35); +SELECT * FROM t1; +id msg +7 seven +10 twin +60 sixty +81 twin +72 updated +1 one +8 updated +DELETE FROM t1 WHERE id IN (4,60,1); +SELECT msg FROM t1; +msg +seven +twin +twin +updated +updated +DELETE FROM t1 WHERE id IN (81,72); +SELECT id FROM t1; +id +7 +8 +10 +DELETE FROM t1 WHERE id IN (7,10); +SELECT * FROM t1; +id msg +8 updated +DELETE FROM t1 WHERE id = 8; +SELECT * FROM t1; +id msg +DROP TABLE t1; +# FIX table +CREATE TABLE t1 ( +id INT(4) KEY NOT NULL, +msg VARCHAR(16) CHARSET BINARY DISTRIB=CLUSTERED) +ENGINE=CONNECT TABLE_TYPE=FIX BLOCK_SIZE=4; +Warnings: +Warning 1105 No file name. Table will use t1.fix +DELETE FROM t1; +INSERT INTO t1 VALUES(4, 'four'),(7,'seven'),(10,'ten'),(40,'forty'),(60,'sixty'),(81,'eighty one'),(72,'seventy two'),(11,'eleven'),(1,'one'),(35,'thirty five'),(8,'eight'); +SELECT * FROM t1; +id msg +4 four +7 seven +10 ten +40 forty +60 sixty +81 eighty one +72 seventy two +11 eleven +1 one +35 thirty five +8 eight +UPDATE t1 SET msg = 'bof' WHERE id = 35; +SELECT * FROM t1; +id msg +4 four +7 seven +10 ten +40 forty +60 sixty +81 eighty one +72 seventy two +11 eleven +1 one +35 bof +8 eight +UPDATE t1 SET msg = 'big' WHERE id > 50; +SELECT * FROM t1; +id msg +4 four +7 seven +10 ten +40 forty +60 big +81 big +72 big +11 eleven +1 one +35 bof +8 eight +UPDATE t1 SET msg = 'updated' WHERE id IN (8,35,60,72); +SELECT * FROM t1; +id msg +4 four +7 seven +10 ten +40 forty +60 updated +81 big +72 updated +11 eleven +1 one +35 updated +8 updated +UPDATE t1 SET msg = 'twin' WHERE id IN (81,10); +SELECT * FROM t1; +id msg +4 four +7 seven +10 twin +40 forty +60 updated +81 twin +72 updated +11 eleven +1 one +35 updated +8 updated +UPDATE t1 SET msg = 'sixty' WHERE id = 60; +SELECT * FROM t1 WHERE id = 60; +id msg +60 sixty +DELETE FROM t1 WHERE id = 4; +SELECT * FROM t1; +id msg +7 seven +10 twin +40 forty +60 sixty +81 twin +72 updated +11 eleven +1 one +35 updated +8 updated +DELETE FROM t1 WHERE id IN (40,11,35); +SELECT * FROM t1; +id msg +7 seven +10 twin +60 sixty +81 twin +72 updated +1 one +8 updated +DELETE FROM t1 WHERE id IN (4,60,1); +SELECT msg FROM t1; +msg +seven +twin +twin +updated +updated +DELETE FROM t1 WHERE id IN (81,72); +SELECT id FROM t1; +id +7 +8 +10 +DELETE FROM t1 WHERE id IN (7,10); +SELECT * FROM t1; +id msg +8 updated +DELETE FROM t1 WHERE id = 8; +SELECT * FROM t1; +id msg +ALTER TABLE t1 MAPPED=YES; +DELETE FROM t1; +INSERT INTO t1 VALUES(4, 'four'),(7,'seven'),(10,'ten'),(40,'forty'),(60,'sixty'),(81,'eighty one'),(72,'seventy two'),(11,'eleven'),(1,'one'),(35,'thirty five'),(8,'eight'); +SELECT * FROM t1; +id msg +4 four +7 seven +10 ten +40 forty +60 sixty +81 eighty one +72 seventy two +11 eleven +1 one +35 thirty five +8 eight +UPDATE t1 SET msg = 'bof' WHERE id = 35; +SELECT * FROM t1; +id msg +4 four +7 seven +10 ten +40 forty +60 sixty +81 eighty one +72 seventy two +11 eleven +1 one +35 bof +8 eight +UPDATE t1 SET msg = 'big' WHERE id > 50; +SELECT * FROM t1; +id msg +4 four +7 seven +10 ten +40 forty +60 big +81 big +72 big +11 eleven +1 one +35 bof +8 eight +UPDATE t1 SET msg = 'updated' WHERE id IN (8,35,60,72); +SELECT * FROM t1; +id msg +4 four +7 seven +10 ten +40 forty +60 updated +81 big +72 updated +11 eleven +1 one +35 updated +8 updated +UPDATE t1 SET msg = 'twin' WHERE id IN (81,10); +SELECT * FROM t1; +id msg +4 four +7 seven +10 twin +40 forty +60 updated +81 twin +72 updated +11 eleven +1 one +35 updated +8 updated +UPDATE t1 SET msg = 'sixty' WHERE id = 60; +SELECT * FROM t1 WHERE id = 60; +id msg +60 sixty +DELETE FROM t1 WHERE id = 4; +SELECT * FROM t1; +id msg +7 seven +10 twin +40 forty +60 sixty +81 twin +72 updated +11 eleven +1 one +35 updated +8 updated +DELETE FROM t1 WHERE id IN (40,11,35); +SELECT * FROM t1; +id msg +7 seven +10 twin +60 sixty +81 twin +72 updated +1 one +8 updated +DELETE FROM t1 WHERE id IN (4,60,1); +SELECT msg FROM t1; +msg +seven +twin +twin +updated +updated +DELETE FROM t1 WHERE id IN (81,72); +SELECT id FROM t1; +id +7 +8 +10 +DELETE FROM t1 WHERE id IN (7,10); +SELECT * FROM t1; +id msg +8 updated +DELETE FROM t1 WHERE id = 8; +SELECT * FROM t1; +id msg +ALTER TABLE t1 MAPPED=NO HUGE=YES; +DELETE FROM t1; +INSERT INTO t1 VALUES(4, 'four'),(7,'seven'),(10,'ten'),(40,'forty'),(60,'sixty'),(81,'eighty one'),(72,'seventy two'),(11,'eleven'),(1,'one'),(35,'thirty five'),(8,'eight'); +SELECT * FROM t1; +id msg +4 four +7 seven +10 ten +40 forty +60 sixty +81 eighty one +72 seventy two +11 eleven +1 one +35 thirty five +8 eight +UPDATE t1 SET msg = 'bof' WHERE id = 35; +SELECT * FROM t1; +id msg +4 four +7 seven +10 ten +40 forty +60 sixty +81 eighty one +72 seventy two +11 eleven +1 one +35 bof +8 eight +UPDATE t1 SET msg = 'big' WHERE id > 50; +SELECT * FROM t1; +id msg +4 four +7 seven +10 ten +40 forty +60 big +81 big +72 big +11 eleven +1 one +35 bof +8 eight +UPDATE t1 SET msg = 'updated' WHERE id IN (8,35,60,72); +SELECT * FROM t1; +id msg +4 four +7 seven +10 ten +40 forty +60 updated +81 big +72 updated +11 eleven +1 one +35 updated +8 updated +UPDATE t1 SET msg = 'twin' WHERE id IN (81,10); +SELECT * FROM t1; +id msg +4 four +7 seven +10 twin +40 forty +60 updated +81 twin +72 updated +11 eleven +1 one +35 updated +8 updated +UPDATE t1 SET msg = 'sixty' WHERE id = 60; +SELECT * FROM t1 WHERE id = 60; +id msg +60 sixty +DELETE FROM t1 WHERE id = 4; +SELECT * FROM t1; +id msg +7 seven +10 twin +40 forty +60 sixty +81 twin +72 updated +11 eleven +1 one +35 updated +8 updated +DELETE FROM t1 WHERE id IN (40,11,35); +SELECT * FROM t1; +id msg +7 seven +10 twin +60 sixty +81 twin +72 updated +1 one +8 updated +DELETE FROM t1 WHERE id IN (4,60,1); +SELECT msg FROM t1; +msg +seven +twin +twin +updated +updated +DELETE FROM t1 WHERE id IN (81,72); +SELECT id FROM t1; +id +7 +8 +10 +DELETE FROM t1 WHERE id IN (7,10); +SELECT * FROM t1; +id msg +8 updated +DELETE FROM t1 WHERE id = 8; +SELECT * FROM t1; +id msg +DROP TABLE t1; +# BIN table +CREATE TABLE t1 ( +id INT(4) KEY NOT NULL, +msg VARCHAR(16) CHARSET BINARY DISTRIB=CLUSTERED) +ENGINE=CONNECT TABLE_TYPE=BIN BLOCK_SIZE=8; +Warnings: +Warning 1105 No file name. Table will use t1.bin +DELETE FROM t1; +INSERT INTO t1 VALUES(4, 'four'),(7,'seven'),(10,'ten'),(40,'forty'),(60,'sixty'),(81,'eighty one'),(72,'seventy two'),(11,'eleven'),(1,'one'),(35,'thirty five'),(8,'eight'); +SELECT * FROM t1; +id msg +4 four +7 seven +10 ten +40 forty +60 sixty +81 eighty one +72 seventy two +11 eleven +1 one +35 thirty five +8 eight +UPDATE t1 SET msg = 'bof' WHERE id = 35; +SELECT * FROM t1; +id msg +4 four +7 seven +10 ten +40 forty +60 sixty +81 eighty one +72 seventy two +11 eleven +1 one +35 bof +8 eight +UPDATE t1 SET msg = 'big' WHERE id > 50; +SELECT * FROM t1; +id msg +4 four +7 seven +10 ten +40 forty +60 big +81 big +72 big +11 eleven +1 one +35 bof +8 eight +UPDATE t1 SET msg = 'updated' WHERE id IN (8,35,60,72); +SELECT * FROM t1; +id msg +4 four +7 seven +10 ten +40 forty +60 updated +81 big +72 updated +11 eleven +1 one +35 updated +8 updated +UPDATE t1 SET msg = 'twin' WHERE id IN (81,10); +SELECT * FROM t1; +id msg +4 four +7 seven +10 twin +40 forty +60 updated +81 twin +72 updated +11 eleven +1 one +35 updated +8 updated +UPDATE t1 SET msg = 'sixty' WHERE id = 60; +SELECT * FROM t1 WHERE id = 60; +id msg +60 sixty +DELETE FROM t1 WHERE id = 4; +SELECT * FROM t1; +id msg +7 seven +10 twin +40 forty +60 sixty +81 twin +72 updated +11 eleven +1 one +35 updated +8 updated +DELETE FROM t1 WHERE id IN (40,11,35); +SELECT * FROM t1; +id msg +7 seven +10 twin +60 sixty +81 twin +72 updated +1 one +8 updated +DELETE FROM t1 WHERE id IN (4,60,1); +SELECT msg FROM t1; +msg +seven +twin +twin +updated +updated +DELETE FROM t1 WHERE id IN (81,72); +SELECT id FROM t1; +id +7 +8 +10 +DELETE FROM t1 WHERE id IN (7,10); +SELECT * FROM t1; +id msg +8 updated +DELETE FROM t1 WHERE id = 8; +SELECT * FROM t1; +id msg +ALTER TABLE t1 MAPPED=YES; +DELETE FROM t1; +INSERT INTO t1 VALUES(4, 'four'),(7,'seven'),(10,'ten'),(40,'forty'),(60,'sixty'),(81,'eighty one'),(72,'seventy two'),(11,'eleven'),(1,'one'),(35,'thirty five'),(8,'eight'); +SELECT * FROM t1; +id msg +4 four +7 seven +10 ten +40 forty +60 sixty +81 eighty one +72 seventy two +11 eleven +1 one +35 thirty five +8 eight +UPDATE t1 SET msg = 'bof' WHERE id = 35; +SELECT * FROM t1; +id msg +4 four +7 seven +10 ten +40 forty +60 sixty +81 eighty one +72 seventy two +11 eleven +1 one +35 bof +8 eight +UPDATE t1 SET msg = 'big' WHERE id > 50; +SELECT * FROM t1; +id msg +4 four +7 seven +10 ten +40 forty +60 big +81 big +72 big +11 eleven +1 one +35 bof +8 eight +UPDATE t1 SET msg = 'updated' WHERE id IN (8,35,60,72); +SELECT * FROM t1; +id msg +4 four +7 seven +10 ten +40 forty +60 updated +81 big +72 updated +11 eleven +1 one +35 updated +8 updated +UPDATE t1 SET msg = 'twin' WHERE id IN (81,10); +SELECT * FROM t1; +id msg +4 four +7 seven +10 twin +40 forty +60 updated +81 twin +72 updated +11 eleven +1 one +35 updated +8 updated +UPDATE t1 SET msg = 'sixty' WHERE id = 60; +SELECT * FROM t1 WHERE id = 60; +id msg +60 sixty +DELETE FROM t1 WHERE id = 4; +SELECT * FROM t1; +id msg +7 seven +10 twin +40 forty +60 sixty +81 twin +72 updated +11 eleven +1 one +35 updated +8 updated +DELETE FROM t1 WHERE id IN (40,11,35); +SELECT * FROM t1; +id msg +7 seven +10 twin +60 sixty +81 twin +72 updated +1 one +8 updated +DELETE FROM t1 WHERE id IN (4,60,1); +SELECT msg FROM t1; +msg +seven +twin +twin +updated +updated +DELETE FROM t1 WHERE id IN (81,72); +SELECT id FROM t1; +id +7 +8 +10 +DELETE FROM t1 WHERE id IN (7,10); +SELECT * FROM t1; +id msg +8 updated +DELETE FROM t1 WHERE id = 8; +SELECT * FROM t1; +id msg +ALTER TABLE t1 MAPPED=NO HUGE=YES; +DELETE FROM t1; +INSERT INTO t1 VALUES(4, 'four'),(7,'seven'),(10,'ten'),(40,'forty'),(60,'sixty'),(81,'eighty one'),(72,'seventy two'),(11,'eleven'),(1,'one'),(35,'thirty five'),(8,'eight'); +SELECT * FROM t1; +id msg +4 four +7 seven +10 ten +40 forty +60 sixty +81 eighty one +72 seventy two +11 eleven +1 one +35 thirty five +8 eight +UPDATE t1 SET msg = 'bof' WHERE id = 35; +SELECT * FROM t1; +id msg +4 four +7 seven +10 ten +40 forty +60 sixty +81 eighty one +72 seventy two +11 eleven +1 one +35 bof +8 eight +UPDATE t1 SET msg = 'big' WHERE id > 50; +SELECT * FROM t1; +id msg +4 four +7 seven +10 ten +40 forty +60 big +81 big +72 big +11 eleven +1 one +35 bof +8 eight +UPDATE t1 SET msg = 'updated' WHERE id IN (8,35,60,72); +SELECT * FROM t1; +id msg +4 four +7 seven +10 ten +40 forty +60 updated +81 big +72 updated +11 eleven +1 one +35 updated +8 updated +UPDATE t1 SET msg = 'twin' WHERE id IN (81,10); +SELECT * FROM t1; +id msg +4 four +7 seven +10 twin +40 forty +60 updated +81 twin +72 updated +11 eleven +1 one +35 updated +8 updated +UPDATE t1 SET msg = 'sixty' WHERE id = 60; +SELECT * FROM t1 WHERE id = 60; +id msg +60 sixty +DELETE FROM t1 WHERE id = 4; +SELECT * FROM t1; +id msg +7 seven +10 twin +40 forty +60 sixty +81 twin +72 updated +11 eleven +1 one +35 updated +8 updated +DELETE FROM t1 WHERE id IN (40,11,35); +SELECT * FROM t1; +id msg +7 seven +10 twin +60 sixty +81 twin +72 updated +1 one +8 updated +DELETE FROM t1 WHERE id IN (4,60,1); +SELECT msg FROM t1; +msg +seven +twin +twin +updated +updated +DELETE FROM t1 WHERE id IN (81,72); +SELECT id FROM t1; +id +7 +8 +10 +DELETE FROM t1 WHERE id IN (7,10); +SELECT * FROM t1; +id msg +8 updated +DELETE FROM t1 WHERE id = 8; +SELECT * FROM t1; +id msg +DROP TABLE t1; +# DBF table +CREATE TABLE t1 ( +id INT(4) KEY NOT NULL, +msg VARCHAR(16)) +ENGINE=CONNECT TABLE_TYPE=DBF BLOCK_SIZE=12; +Warnings: +Warning 1105 No file name. Table will use t1.dbf +DELETE FROM t1; +INSERT INTO t1 VALUES(4, 'four'),(7,'seven'),(10,'ten'),(40,'forty'),(60,'sixty'),(81,'eighty one'),(72,'seventy two'),(11,'eleven'),(1,'one'),(35,'thirty five'),(8,'eight'); +SELECT * FROM t1; +id msg +4 four +7 seven +10 ten +40 forty +60 sixty +81 eighty one +72 seventy two +11 eleven +1 one +35 thirty five +8 eight +UPDATE t1 SET msg = 'bof' WHERE id = 35; +SELECT * FROM t1; +id msg +4 four +7 seven +10 ten +40 forty +60 sixty +81 eighty one +72 seventy two +11 eleven +1 one +35 bof +8 eight +UPDATE t1 SET msg = 'big' WHERE id > 50; +SELECT * FROM t1; +id msg +4 four +7 seven +10 ten +40 forty +60 big +81 big +72 big +11 eleven +1 one +35 bof +8 eight +UPDATE t1 SET msg = 'updated' WHERE id IN (8,35,60,72); +SELECT * FROM t1; +id msg +4 four +7 seven +10 ten +40 forty +60 updated +81 big +72 updated +11 eleven +1 one +35 updated +8 updated +UPDATE t1 SET msg = 'twin' WHERE id IN (81,10); +SELECT * FROM t1; +id msg +4 four +7 seven +10 twin +40 forty +60 updated +81 twin +72 updated +11 eleven +1 one +35 updated +8 updated +UPDATE t1 SET msg = 'sixty' WHERE id = 60; +SELECT * FROM t1 WHERE id = 60; +id msg +60 sixty +DELETE FROM t1 WHERE id = 4; +SELECT * FROM t1; +id msg +7 seven +10 twin +40 forty +60 sixty +81 twin +72 updated +11 eleven +1 one +35 updated +8 updated +DELETE FROM t1 WHERE id IN (40,11,35); +SELECT * FROM t1; +id msg +7 seven +10 twin +60 sixty +81 twin +72 updated +1 one +8 updated +DELETE FROM t1 WHERE id IN (4,60,1); +SELECT msg FROM t1; +msg +seven +twin +twin +updated +updated +DELETE FROM t1 WHERE id IN (81,72); +SELECT id FROM t1; +id +7 +8 +10 +DELETE FROM t1 WHERE id IN (7,10); +SELECT * FROM t1; +id msg +8 updated +DELETE FROM t1 WHERE id = 8; +SELECT * FROM t1; +id msg +ALTER TABLE t1 MAPPED=YES; +DELETE FROM t1; +INSERT INTO t1 VALUES(4, 'four'),(7,'seven'),(10,'ten'),(40,'forty'),(60,'sixty'),(81,'eighty one'),(72,'seventy two'),(11,'eleven'),(1,'one'),(35,'thirty five'),(8,'eight'); +SELECT * FROM t1; +id msg +4 four +7 seven +10 ten +40 forty +60 sixty +81 eighty one +72 seventy two +11 eleven +1 one +35 thirty five +8 eight +UPDATE t1 SET msg = 'bof' WHERE id = 35; +SELECT * FROM t1; +id msg +4 four +7 seven +10 ten +40 forty +60 sixty +81 eighty one +72 seventy two +11 eleven +1 one +35 bof +8 eight +UPDATE t1 SET msg = 'big' WHERE id > 50; +SELECT * FROM t1; +id msg +4 four +7 seven +10 ten +40 forty +60 big +81 big +72 big +11 eleven +1 one +35 bof +8 eight +UPDATE t1 SET msg = 'updated' WHERE id IN (8,35,60,72); +SELECT * FROM t1; +id msg +4 four +7 seven +10 ten +40 forty +60 updated +81 big +72 updated +11 eleven +1 one +35 updated +8 updated +UPDATE t1 SET msg = 'twin' WHERE id IN (81,10); +SELECT * FROM t1; +id msg +4 four +7 seven +10 twin +40 forty +60 updated +81 twin +72 updated +11 eleven +1 one +35 updated +8 updated +UPDATE t1 SET msg = 'sixty' WHERE id = 60; +SELECT * FROM t1 WHERE id = 60; +id msg +60 sixty +DELETE FROM t1 WHERE id = 4; +SELECT * FROM t1; +id msg +7 seven +10 twin +40 forty +60 sixty +81 twin +72 updated +11 eleven +1 one +35 updated +8 updated +DELETE FROM t1 WHERE id IN (40,11,35); +SELECT * FROM t1; +id msg +7 seven +10 twin +60 sixty +81 twin +72 updated +1 one +8 updated +DELETE FROM t1 WHERE id IN (4,60,1); +SELECT msg FROM t1; +msg +seven +twin +twin +updated +updated +DELETE FROM t1 WHERE id IN (81,72); +SELECT id FROM t1; +id +7 +8 +10 +DELETE FROM t1 WHERE id IN (7,10); +SELECT * FROM t1; +id msg +8 updated +DELETE FROM t1 WHERE id = 8; +SELECT * FROM t1; +id msg +DROP TABLE t1; +# VEC table +CREATE TABLE t1 ( +id INT(4) KEY NOT NULL, +msg VARCHAR(16)) +ENGINE=CONNECT TABLE_TYPE=VEC BLOCK_SIZE=6 MAX_ROWS=16; +Warnings: +Warning 1105 No file name. Table will use t1.vec +DELETE FROM t1; +INSERT INTO t1 VALUES(4, 'four'),(7,'seven'),(10,'ten'),(40,'forty'),(60,'sixty'),(81,'eighty one'),(72,'seventy two'),(11,'eleven'),(1,'one'),(35,'thirty five'),(8,'eight'); +SELECT * FROM t1; +id msg +4 four +7 seven +10 ten +40 forty +60 sixty +81 eighty one +72 seventy two +11 eleven +1 one +35 thirty five +8 eight +UPDATE t1 SET msg = 'bof' WHERE id = 35; +SELECT * FROM t1; +id msg +4 four +7 seven +10 ten +40 forty +60 sixty +81 eighty one +72 seventy two +11 eleven +1 one +35 bof +8 eight +UPDATE t1 SET msg = 'big' WHERE id > 50; +SELECT * FROM t1; +id msg +4 four +7 seven +10 ten +40 forty +60 big +81 big +72 big +11 eleven +1 one +35 bof +8 eight +UPDATE t1 SET msg = 'updated' WHERE id IN (8,35,60,72); +SELECT * FROM t1; +id msg +4 four +7 seven +10 ten +40 forty +60 updated +81 big +72 updated +11 eleven +1 one +35 updated +8 updated +UPDATE t1 SET msg = 'twin' WHERE id IN (81,10); +SELECT * FROM t1; +id msg +4 four +7 seven +10 twin +40 forty +60 updated +81 twin +72 updated +11 eleven +1 one +35 updated +8 updated +UPDATE t1 SET msg = 'sixty' WHERE id = 60; +SELECT * FROM t1 WHERE id = 60; +id msg +60 sixty +DELETE FROM t1 WHERE id = 4; +SELECT * FROM t1; +id msg +7 seven +10 twin +40 forty +60 sixty +81 twin +72 updated +11 eleven +1 one +35 updated +8 updated +DELETE FROM t1 WHERE id IN (40,11,35); +SELECT * FROM t1; +id msg +7 seven +10 twin +60 sixty +81 twin +72 updated +1 one +8 updated +DELETE FROM t1 WHERE id IN (4,60,1); +SELECT msg FROM t1; +msg +seven +twin +twin +updated +updated +DELETE FROM t1 WHERE id IN (81,72); +SELECT id FROM t1; +id +7 +8 +10 +DELETE FROM t1 WHERE id IN (7,10); +SELECT * FROM t1; +id msg +8 updated +DELETE FROM t1 WHERE id = 8; +SELECT * FROM t1; +id msg +ALTER TABLE t1 MAPPED=YES; +DELETE FROM t1; +INSERT INTO t1 VALUES(4, 'four'),(7,'seven'),(10,'ten'),(40,'forty'),(60,'sixty'),(81,'eighty one'),(72,'seventy two'),(11,'eleven'),(1,'one'),(35,'thirty five'),(8,'eight'); +SELECT * FROM t1; +id msg +4 four +7 seven +10 ten +40 forty +60 sixty +81 eighty one +72 seventy two +11 eleven +1 one +35 thirty five +8 eight +UPDATE t1 SET msg = 'bof' WHERE id = 35; +SELECT * FROM t1; +id msg +4 four +7 seven +10 ten +40 forty +60 sixty +81 eighty one +72 seventy two +11 eleven +1 one +35 bof +8 eight +UPDATE t1 SET msg = 'big' WHERE id > 50; +SELECT * FROM t1; +id msg +4 four +7 seven +10 ten +40 forty +60 big +81 big +72 big +11 eleven +1 one +35 bof +8 eight +UPDATE t1 SET msg = 'updated' WHERE id IN (8,35,60,72); +SELECT * FROM t1; +id msg +4 four +7 seven +10 ten +40 forty +60 updated +81 big +72 updated +11 eleven +1 one +35 updated +8 updated +UPDATE t1 SET msg = 'twin' WHERE id IN (81,10); +SELECT * FROM t1; +id msg +4 four +7 seven +10 twin +40 forty +60 updated +81 twin +72 updated +11 eleven +1 one +35 updated +8 updated +UPDATE t1 SET msg = 'sixty' WHERE id = 60; +SELECT * FROM t1 WHERE id = 60; +id msg +60 sixty +DELETE FROM t1 WHERE id = 4; +SELECT * FROM t1; +id msg +7 seven +10 twin +40 forty +60 sixty +81 twin +72 updated +11 eleven +1 one +35 updated +8 updated +DELETE FROM t1 WHERE id IN (40,11,35); +SELECT * FROM t1; +id msg +7 seven +10 twin +60 sixty +81 twin +72 updated +1 one +8 updated +DELETE FROM t1 WHERE id IN (4,60,1); +SELECT msg FROM t1; +msg +seven +twin +twin +updated +updated +DELETE FROM t1 WHERE id IN (81,72); +SELECT id FROM t1; +id +7 +8 +10 +DELETE FROM t1 WHERE id IN (7,10); +SELECT * FROM t1; +id msg +8 updated +DELETE FROM t1 WHERE id = 8; +SELECT * FROM t1; +id msg +ALTER TABLE t1 MAPPED=NO HUGE=YES; +DELETE FROM t1; +INSERT INTO t1 VALUES(4, 'four'),(7,'seven'),(10,'ten'),(40,'forty'),(60,'sixty'),(81,'eighty one'),(72,'seventy two'),(11,'eleven'),(1,'one'),(35,'thirty five'),(8,'eight'); +SELECT * FROM t1; +id msg +4 four +7 seven +10 ten +40 forty +60 sixty +81 eighty one +72 seventy two +11 eleven +1 one +35 thirty five +8 eight +UPDATE t1 SET msg = 'bof' WHERE id = 35; +SELECT * FROM t1; +id msg +4 four +7 seven +10 ten +40 forty +60 sixty +81 eighty one +72 seventy two +11 eleven +1 one +35 bof +8 eight +UPDATE t1 SET msg = 'big' WHERE id > 50; +SELECT * FROM t1; +id msg +4 four +7 seven +10 ten +40 forty +60 big +81 big +72 big +11 eleven +1 one +35 bof +8 eight +UPDATE t1 SET msg = 'updated' WHERE id IN (8,35,60,72); +SELECT * FROM t1; +id msg +4 four +7 seven +10 ten +40 forty +60 updated +81 big +72 updated +11 eleven +1 one +35 updated +8 updated +UPDATE t1 SET msg = 'twin' WHERE id IN (81,10); +SELECT * FROM t1; +id msg +4 four +7 seven +10 twin +40 forty +60 updated +81 twin +72 updated +11 eleven +1 one +35 updated +8 updated +UPDATE t1 SET msg = 'sixty' WHERE id = 60; +SELECT * FROM t1 WHERE id = 60; +id msg +60 sixty +DELETE FROM t1 WHERE id = 4; +SELECT * FROM t1; +id msg +7 seven +10 twin +40 forty +60 sixty +81 twin +72 updated +11 eleven +1 one +35 updated +8 updated +DELETE FROM t1 WHERE id IN (40,11,35); +SELECT * FROM t1; +id msg +7 seven +10 twin +60 sixty +81 twin +72 updated +1 one +8 updated +DELETE FROM t1 WHERE id IN (4,60,1); +SELECT msg FROM t1; +msg +seven +twin +twin +updated +updated +DELETE FROM t1 WHERE id IN (81,72); +SELECT id FROM t1; +id +7 +8 +10 +DELETE FROM t1 WHERE id IN (7,10); +SELECT * FROM t1; +id msg +8 updated +DELETE FROM t1 WHERE id = 8; +SELECT * FROM t1; +id msg +DROP TABLE t1; +# Split VEC table (outward) +CREATE TABLE t1 ( +id INT(4) KEY NOT NULL, +msg VARCHAR(16)) +ENGINE=CONNECT TABLE_TYPE=VEC BLOCK_SIZE=6 FILE_NAME='tx.vec'; +DELETE FROM t1; +INSERT INTO t1 VALUES(4, 'four'),(7,'seven'),(10,'ten'),(40,'forty'),(60,'sixty'),(81,'eighty one'),(72,'seventy two'),(11,'eleven'),(1,'one'),(35,'thirty five'),(8,'eight'); +SELECT * FROM t1; +id msg +4 four +7 seven +10 ten +40 forty +60 sixty +81 eighty one +72 seventy two +11 eleven +1 one +35 thirty five +8 eight +UPDATE t1 SET msg = 'bof' WHERE id = 35; +SELECT * FROM t1; +id msg +4 four +7 seven +10 ten +40 forty +60 sixty +81 eighty one +72 seventy two +11 eleven +1 one +35 bof +8 eight +UPDATE t1 SET msg = 'big' WHERE id > 50; +SELECT * FROM t1; +id msg +4 four +7 seven +10 ten +40 forty +60 big +81 big +72 big +11 eleven +1 one +35 bof +8 eight +UPDATE t1 SET msg = 'updated' WHERE id IN (8,35,60,72); +SELECT * FROM t1; +id msg +4 four +7 seven +10 ten +40 forty +60 updated +81 big +72 updated +11 eleven +1 one +35 updated +8 updated +UPDATE t1 SET msg = 'twin' WHERE id IN (81,10); +SELECT * FROM t1; +id msg +4 four +7 seven +10 twin +40 forty +60 updated +81 twin +72 updated +11 eleven +1 one +35 updated +8 updated +UPDATE t1 SET msg = 'sixty' WHERE id = 60; +SELECT * FROM t1 WHERE id = 60; +id msg +60 sixty +DELETE FROM t1 WHERE id = 4; +SELECT * FROM t1; +id msg +7 seven +10 twin +40 forty +60 sixty +81 twin +72 updated +11 eleven +1 one +35 updated +8 updated +DELETE FROM t1 WHERE id IN (40,11,35); +SELECT * FROM t1; +id msg +7 seven +10 twin +60 sixty +81 twin +72 updated +1 one +8 updated +DELETE FROM t1 WHERE id IN (4,60,1); +SELECT msg FROM t1; +msg +seven +twin +twin +updated +updated +DELETE FROM t1 WHERE id IN (81,72); +SELECT id FROM t1; +id +7 +8 +10 +DELETE FROM t1 WHERE id IN (7,10); +SELECT * FROM t1; +id msg +8 updated +DELETE FROM t1 WHERE id = 8; +SELECT * FROM t1; +id msg +ALTER TABLE t1 MAPPED=YES; +DELETE FROM t1; +INSERT INTO t1 VALUES(4, 'four'),(7,'seven'),(10,'ten'),(40,'forty'),(60,'sixty'),(81,'eighty one'),(72,'seventy two'),(11,'eleven'),(1,'one'),(35,'thirty five'),(8,'eight'); +SELECT * FROM t1; +id msg +4 four +7 seven +10 ten +40 forty +60 sixty +81 eighty one +72 seventy two +11 eleven +1 one +35 thirty five +8 eight +UPDATE t1 SET msg = 'bof' WHERE id = 35; +SELECT * FROM t1; +id msg +4 four +7 seven +10 ten +40 forty +60 sixty +81 eighty one +72 seventy two +11 eleven +1 one +35 bof +8 eight +UPDATE t1 SET msg = 'big' WHERE id > 50; +SELECT * FROM t1; +id msg +4 four +7 seven +10 ten +40 forty +60 big +81 big +72 big +11 eleven +1 one +35 bof +8 eight +UPDATE t1 SET msg = 'updated' WHERE id IN (8,35,60,72); +SELECT * FROM t1; +id msg +4 four +7 seven +10 ten +40 forty +60 updated +81 big +72 updated +11 eleven +1 one +35 updated +8 updated +UPDATE t1 SET msg = 'twin' WHERE id IN (81,10); +SELECT * FROM t1; +id msg +4 four +7 seven +10 twin +40 forty +60 updated +81 twin +72 updated +11 eleven +1 one +35 updated +8 updated +UPDATE t1 SET msg = 'sixty' WHERE id = 60; +SELECT * FROM t1 WHERE id = 60; +id msg +60 sixty +DELETE FROM t1 WHERE id = 4; +SELECT * FROM t1; +id msg +7 seven +10 twin +40 forty +60 sixty +81 twin +72 updated +11 eleven +1 one +35 updated +8 updated +DELETE FROM t1 WHERE id IN (40,11,35); +SELECT * FROM t1; +id msg +7 seven +10 twin +60 sixty +81 twin +72 updated +1 one +8 updated +DELETE FROM t1 WHERE id IN (4,60,1); +SELECT msg FROM t1; +msg +seven +twin +twin +updated +updated +DELETE FROM t1 WHERE id IN (81,72); +SELECT id FROM t1; +id +7 +8 +10 +DELETE FROM t1 WHERE id IN (7,10); +SELECT * FROM t1; +id msg +8 updated +DELETE FROM t1 WHERE id = 8; +SELECT * FROM t1; +id msg +DROP TABLE t1; diff --git a/storage/connect/mysql-test/connect/t/part_file.test b/storage/connect/mysql-test/connect/t/part_file.test index 159908b6d9b..6efd2b9b580 100644 --- a/storage/connect/mysql-test/connect/t/part_file.test +++ b/storage/connect/mysql-test/connect/t/part_file.test @@ -1,6 +1,8 @@ --source include/have_partition.inc
let $MYSQLD_DATADIR= `select @@datadir`;
+set @@global.connect_exact_info=ON;
+
--echo # This will be used to see what data files are created
CREATE TABLE dr1 (
fname VARCHAR(256) NOT NULL FLAG=2,
@@ -153,6 +155,8 @@ DROP TABLE dr1; #
# Clean up
#
+set @@global.connect_exact_info=OFF;
+
--remove_file $MYSQLD_DATADIR/test/part1.txt
--remove_file $MYSQLD_DATADIR/test/part2.txt
--remove_file $MYSQLD_DATADIR/test/part3.txt
diff --git a/storage/connect/mysql-test/connect/t/part_table.test b/storage/connect/mysql-test/connect/t/part_table.test index 34e224efa6f..c5358d63c8e 100644 --- a/storage/connect/mysql-test/connect/t/part_table.test +++ b/storage/connect/mysql-test/connect/t/part_table.test @@ -1,6 +1,8 @@ --source include/not_embedded.inc
--source include/have_partition.inc
+set @@global.connect_exact_info=ON;
+
#
# These will be used by the t1 table partition table
#
@@ -83,3 +85,8 @@ DROP TABLE t1; DROP TABLE xt1;
DROP TABLE xt2;
DROP TABLE xt3;
+
+#
+# Clean up
+#
+set @@global.connect_exact_info=OFF;
diff --git a/storage/connect/mysql-test/connect/t/temporary.test b/storage/connect/mysql-test/connect/t/temporary.test new file mode 100644 index 00000000000..dda066c874b --- /dev/null +++ b/storage/connect/mysql-test/connect/t/temporary.test @@ -0,0 +1,13 @@ +# +# CONNECT tables cannot be TEMPORARY +# + +--error ER_ILLEGAL_HA_CREATE_OPTION +CREATE TEMPORARY TABLE t1 (a int not null) + ENGINE=CONNECT table_type=MYSQL CONNECTION='mysql://root@127.0.0.1/test/t2'; + +# also with assisted discovery +--error ER_ILLEGAL_HA_CREATE_OPTION +CREATE TEMPORARY TABLE t1 + ENGINE=CONNECT table_type=MYSQL CONNECTION='mysql://root@127.0.0.1/test/t2'; + diff --git a/storage/connect/mysql-test/connect/t/updelx.inc b/storage/connect/mysql-test/connect/t/updelx.inc new file mode 100644 index 00000000000..f38a59b9983 --- /dev/null +++ b/storage/connect/mysql-test/connect/t/updelx.inc @@ -0,0 +1,25 @@ +DELETE FROM t1; +INSERT INTO t1 VALUES(4, 'four'),(7,'seven'),(10,'ten'),(40,'forty'),(60,'sixty'),(81,'eighty one'),(72,'seventy two'),(11,'eleven'),(1,'one'),(35,'thirty five'),(8,'eight'); +SELECT * FROM t1; +UPDATE t1 SET msg = 'bof' WHERE id = 35; +SELECT * FROM t1; +UPDATE t1 SET msg = 'big' WHERE id > 50; +SELECT * FROM t1; +UPDATE t1 SET msg = 'updated' WHERE id IN (8,35,60,72); +SELECT * FROM t1; +UPDATE t1 SET msg = 'twin' WHERE id IN (81,10); +SELECT * FROM t1; +UPDATE t1 SET msg = 'sixty' WHERE id = 60; +SELECT * FROM t1 WHERE id = 60; +DELETE FROM t1 WHERE id = 4; +SELECT * FROM t1; +DELETE FROM t1 WHERE id IN (40,11,35); +SELECT * FROM t1; +DELETE FROM t1 WHERE id IN (4,60,1); +SELECT msg FROM t1; +DELETE FROM t1 WHERE id IN (81,72); +SELECT id FROM t1; +DELETE FROM t1 WHERE id IN (7,10); +SELECT * FROM t1; +DELETE FROM t1 WHERE id = 8; +SELECT * FROM t1; diff --git a/storage/connect/mysql-test/connect/t/updelx.test b/storage/connect/mysql-test/connect/t/updelx.test new file mode 100644 index 00000000000..ab336d4b168 --- /dev/null +++ b/storage/connect/mysql-test/connect/t/updelx.test @@ -0,0 +1,96 @@ +-- source include/not_embedded.inc
+let $MYSQLD_DATADIR= `select @@datadir`;
+
+--echo #
+--echo # Testing indexed UPDATE and DELETE for all table types
+--echo #
+
+--echo # CSV table
+CREATE TABLE t1 (
+id INT KEY NOT NULL,
+msg VARCHAR(32))
+ENGINE=CONNECT TABLE_TYPE=CSV AVG_ROW_LENGTH=6;
+-- source updelx.inc
+ALTER TABLE t1 MAPPED=YES;
+-- source updelx.inc
+ALTER TABLE t1 MAPPED=NO BLOCK_SIZE=6;
+-- source updelx.inc
+ALTER TABLE t1 MAPPED=YES;
+-- source updelx.inc
+DROP TABLE t1;
+
+--echo # DOS table
+CREATE TABLE t1 (
+id INT(4) KEY NOT NULL,
+msg VARCHAR(16))
+ENGINE=CONNECT TABLE_TYPE=DOS;
+-- source updelx.inc
+ALTER TABLE t1 MAPPED=YES;
+-- source updelx.inc
+ALTER TABLE t1 MAPPED=NO BLOCK_SIZE=4;
+-- source updelx.inc
+ALTER TABLE t1 MAPPED=YES;
+-- source updelx.inc
+DROP TABLE t1;
+
+--echo # FIX table
+CREATE TABLE t1 (
+id INT(4) KEY NOT NULL,
+msg VARCHAR(16) CHARSET BINARY DISTRIB=CLUSTERED)
+ENGINE=CONNECT TABLE_TYPE=FIX BLOCK_SIZE=4;
+-- source updelx.inc
+ALTER TABLE t1 MAPPED=YES;
+-- source updelx.inc
+ALTER TABLE t1 MAPPED=NO HUGE=YES;
+-- source updelx.inc
+DROP TABLE t1;
+
+--echo # BIN table
+CREATE TABLE t1 (
+id INT(4) KEY NOT NULL,
+msg VARCHAR(16) CHARSET BINARY DISTRIB=CLUSTERED)
+ENGINE=CONNECT TABLE_TYPE=BIN BLOCK_SIZE=8;
+-- source updelx.inc
+ALTER TABLE t1 MAPPED=YES;
+-- source updelx.inc
+ALTER TABLE t1 MAPPED=NO HUGE=YES;
+-- source updelx.inc
+DROP TABLE t1;
+
+--echo # DBF table
+CREATE TABLE t1 (
+id INT(4) KEY NOT NULL,
+msg VARCHAR(16))
+ENGINE=CONNECT TABLE_TYPE=DBF BLOCK_SIZE=12;
+-- source updelx.inc
+ALTER TABLE t1 MAPPED=YES;
+-- source updelx.inc
+#ALTER TABLE t1 MAPPED=NO HUGE=YES;
+#-- source updelx.inc
+DROP TABLE t1;
+
+--echo # VEC table
+CREATE TABLE t1 (
+id INT(4) KEY NOT NULL,
+msg VARCHAR(16))
+ENGINE=CONNECT TABLE_TYPE=VEC BLOCK_SIZE=6 MAX_ROWS=16;
+-- source updelx.inc
+ALTER TABLE t1 MAPPED=YES;
+-- source updelx.inc
+ALTER TABLE t1 MAPPED=NO HUGE=YES;
+-- source updelx.inc
+DROP TABLE t1;
+
+--echo # Split VEC table (outward)
+CREATE TABLE t1 (
+id INT(4) KEY NOT NULL,
+msg VARCHAR(16))
+ENGINE=CONNECT TABLE_TYPE=VEC BLOCK_SIZE=6 FILE_NAME='tx.vec';
+-- source updelx.inc
+ALTER TABLE t1 MAPPED=YES;
+-- source updelx.inc
+DROP TABLE t1;
+
+# Cleanup
+--remove_file $MYSQLD_DATADIR/test/tx1.vec
+--remove_file $MYSQLD_DATADIR/test/tx2.vec
diff --git a/storage/connect/plgdbsem.h b/storage/connect/plgdbsem.h index 1e540dfb2fe..7d5931285ce 100644 --- a/storage/connect/plgdbsem.h +++ b/storage/connect/plgdbsem.h @@ -423,7 +423,7 @@ typedef struct { /* User application block */ int Maxbmp; /* Maximum XDB2 bitmap size */ int Check; /* General level of checking */ int Numlines; /* Number of lines involved */ - USETEMP UseTemp; /* Use temporary file */ +//USETEMP UseTemp; /* Use temporary file */ int Vtdbno; /* Used for TDB number setting */ bool Remote; /* true: if remotely called */ bool Proginfo; /* true: return progress info */ @@ -549,7 +549,8 @@ typedef struct _colres { PPARM Vcolist(PGLOBAL, PTDB, PSZ, bool); void PlugPutOut(PGLOBAL, FILE *, short, void *, uint); void PlugLineDB(PGLOBAL, PSZ, short, void *, uint); -char *PlgGetDataPath(PGLOBAL g); +//ar *PlgGetDataPath(PGLOBAL g); +char *SetPath(PGLOBAL g, const char *path); char *ExtractFromPath(PGLOBAL, char *, char *, OPVAL); void AddPointer(PTABS, void *); PDTP MakeDateFormat(PGLOBAL, PSZ, bool, bool, int); diff --git a/storage/connect/plgdbutl.cpp b/storage/connect/plgdbutl.cpp index 66f7332c56a..c5b66e8f5e6 100644 --- a/storage/connect/plgdbutl.cpp +++ b/storage/connect/plgdbutl.cpp @@ -337,7 +337,7 @@ PDBUSER PlgMakeUser(PGLOBAL g) memset(dbuserp, 0, sizeof(DBUSERBLK)); dbuserp->Maxbmp = MAXBMP; - dbuserp->UseTemp = TMP_AUTO; +//dbuserp->UseTemp = TMP_AUTO; dbuserp->Check = CHK_ALL; strcpy(dbuserp->Server, "CONNECT"); return dbuserp; @@ -373,6 +373,7 @@ PCATLG PlgGetCatalog(PGLOBAL g, bool jump) return cat; } // end of PlgGetCatalog +#if 0 /***********************************************************************/ /* PlgGetDataPath: returns the default data path. */ /***********************************************************************/ @@ -382,6 +383,39 @@ char *PlgGetDataPath(PGLOBAL g) return (cat) ? cat->GetDataPath() : NULL; } // end of PlgGetDataPath +#endif // 0 + +/***********************************************************************/ +/* This function returns a database path. */ +/***********************************************************************/ +char *SetPath(PGLOBAL g, const char *path) +{ + char *buf= NULL; + + if (path) { + size_t len= strlen(path) + (*path != '.' ? 4 : 1); + + buf= (char*)PlugSubAlloc(g, NULL, len); + + if (PlugIsAbsolutePath(path)) { + strcpy(buf, path); + return buf; + } // endif path + + if (*path != '.') { +#if defined(WIN32) + char *s= "\\"; +#else // !WIN32 + char *s= "/"; +#endif // !WIN32 + strcat(strcat(strcat(strcpy(buf, "."), s), path), s); + } else + strcpy(buf, path); + + } // endif path + + return buf; +} // end of SetPath /***********************************************************************/ /* Extract from a path name the required component. */ diff --git a/storage/connect/reldef.cpp b/storage/connect/reldef.cpp index 58bcbd202f3..22076b78086 100644 --- a/storage/connect/reldef.cpp +++ b/storage/connect/reldef.cpp @@ -49,6 +49,8 @@ #include "tabmul.h" #include "ha_connect.h" +extern "C" int trace; +extern "C" USETEMP Use_Temp; /* --------------------------- Class RELDEF -------------------------- */ @@ -226,6 +228,14 @@ bool TABDEF::Define(PGLOBAL g, PCATLG cat, LPCSTR name, LPCSTR am) } // end of Define /***********************************************************************/ +/* This function returns the database data path. */ +/***********************************************************************/ +PSZ TABDEF::GetPath(void) + { + return (Database) ? (PSZ)Database : Hc->GetDataPath(); + } // end of GetPath + +/***********************************************************************/ /* This function returns column table information. */ /***********************************************************************/ int TABDEF::GetColCatInfo(PGLOBAL g) @@ -561,7 +571,7 @@ PTDB OEMDEF::GetTable(PGLOBAL g, MODE mode) PTXF txfp = NULL; PDOSDEF defp = (PDOSDEF)Pxdef; bool map = defp->Mapped && mode != MODE_INSERT && - !(PlgGetUser(g)->UseTemp == TMP_FORCE && + !(Use_Temp == TMP_FORCE && (mode == MODE_UPDATE || mode == MODE_DELETE)); int cmpr = defp->Compressed; diff --git a/storage/connect/reldef.h b/storage/connect/reldef.h index b6bd3cafc30..a1dfe87dca8 100644 --- a/storage/connect/reldef.h +++ b/storage/connect/reldef.h @@ -1,5 +1,5 @@ /*************** RelDef H Declares Source Code File (.H) ***************/ -/* Name: RELDEF.H Version 1.4 */ +/* Name: RELDEF.H Version 1.5 */ /* */ /* (C) Copyright to the author Olivier BERTRAND 2004-2014 */ /* */ @@ -79,8 +79,9 @@ class DllExport TABDEF : public RELDEF { /* Logical table descriptor */ void SetNext(PTABDEF tdfp) {Next = tdfp;} int GetMultiple(void) {return Multiple;} int GetPseudo(void) {return Pseudo;} - PSZ GetPath(void) - {return (Database) ? (PSZ)Database : Cat->GetDataPath();} + PSZ GetPath(void); +//PSZ GetPath(void) +// {return (Database) ? (PSZ)Database : Cat->GetDataPath();} bool SepIndex(void) {return GetBoolCatInfo("SepIndex", false);} bool IsReadOnly(void) {return Read_Only;} virtual AMT GetDefType(void) {return TYPE_AM_TAB;} diff --git a/storage/connect/tabdos.cpp b/storage/connect/tabdos.cpp index 4a04b0c2db4..c60c9b034f9 100644 --- a/storage/connect/tabdos.cpp +++ b/storage/connect/tabdos.cpp @@ -64,7 +64,10 @@ /* DB static variables. */ /***********************************************************************/ int num_read, num_there, num_eq[2]; // Statistics -extern "C" int trace; + +extern "C" int trace; +extern "C" USETEMP Use_Temp; +extern bool xinfo; /***********************************************************************/ /* Size of optimize file header. */ @@ -75,8 +78,8 @@ extern "C" int trace; /* 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); +PVBLK AllocValBlock(PGLOBAL, void *, int, int, int len= 0, int prec= 0, + bool check= true, bool blank= false, bool un= false); /* --------------------------- Class DOSDEF -------------------------- */ @@ -313,7 +316,7 @@ bool DOSDEF::InvalidateIndex(PGLOBAL g) PTDB DOSDEF::GetTable(PGLOBAL g, MODE mode) { // Mapping not used for insert - USETEMP tmp = PlgGetUser(g)->UseTemp; + USETEMP tmp = Use_Temp; bool map = Mapped && mode != MODE_INSERT && !(tmp != TMP_NO && Recfm == RECFM_VAR && mode == MODE_UPDATE) && @@ -432,6 +435,7 @@ TDBDOS::TDBDOS(PDOSDEF tdp, PTXF txfp) : TDBASE(tdp) //Xeval = 0; Beval = 0; Abort = false; + Indxd = false; } // end of TDBDOS standard constructor TDBDOS::TDBDOS(PGLOBAL g, PTDBDOS tdbp) : TDBASE(tdbp) @@ -446,6 +450,8 @@ TDBDOS::TDBDOS(PGLOBAL g, PTDBDOS tdbp) : TDBASE(tdbp) SavFil = tdbp->SavFil; //Xeval = tdbp->Xeval; Beval = tdbp->Beval; + Abort = tdbp->Abort; + Indxd = tdbp->Indxd; } // end of TDBDOS copy constructor // Method @@ -542,8 +548,8 @@ int TDBDOS::ResetTableOpt(PGLOBAL g, bool dop, bool dox) if (dox && (rc == RC_OK || rc == RC_INFO)) { // Remake eventual indexes - if (Mode != MODE_UPDATE) - To_SetCols = NULL; // Only used on Update +// if (Mode != MODE_UPDATE) + To_SetCols = NULL; // Positions are changed Columns = NULL; // Not used anymore Txfp->Reset(); // New start @@ -568,7 +574,8 @@ int TDBDOS::ResetTableOpt(PGLOBAL g, bool dop, bool dox) int TDBDOS::MakeBlockValues(PGLOBAL g) { int i, lg, nrec, rc, n = 0; - int curnum, curblk, block, last, savndv, savnbm; + int curnum, curblk, block, savndv, savnbm; + int last __attribute__((unused)); void *savmin, *savmax; bool blocked, xdb2 = false; //POOLHEADER save; @@ -658,6 +665,13 @@ int TDBDOS::MakeBlockValues(PGLOBAL g) cdp->SetMin(PlugSubAlloc(g, NULL, block * lg)); cdp->SetMax(PlugSubAlloc(g, NULL, block * lg)); + // Valgrind complains if there are uninitialised bytes + // after the null character ending + if (IsTypeChar(cdp->GetType())) { + memset(cdp->GetMin(), 0, block * lg); + memset(cdp->GetMax(), 0, block * lg); + } // endif Type + if (trace) htrc("min(%p) max(%p) col(%d) %s Block=%d lg=%d\n", cdp->GetMin(), cdp->GetMax(), i, cdp->GetName(), block, lg); @@ -836,6 +850,8 @@ bool TDBDOS::SaveBlockValues(PGLOBAL g) return true; } // endif opfile + memset(n, 0, sizeof(n)); // To avoid valgrind warning + if (Ftype == RECFM_VAR || defp->Compressed == 2) { /*******************************************************************/ /* Write block starting positions into the opt file. */ @@ -1336,7 +1352,8 @@ 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}; + int i, n = 0, type[2] = {0,0}; + int ctype __attribute__((unused)); bool conv = false, xdb2 = false, ok = false; PXOB *xarg2 = NULL, xp[2]; PCOL colp; @@ -1344,6 +1361,7 @@ PBF TDBDOS::CheckBlockFilari(PGLOBAL g, PXOB *arg, int op, bool *cnv) //SFROW *sfr[2]; PBF *fp = NULL, bfp = NULL; + ctype= TYPE_ERROR; for (i = 0; i < 2; i++) { switch (arg[i]->GetType()) { case TYPE_CONST: @@ -1719,7 +1737,7 @@ err: /***********************************************************************/ /* Make a dynamic index. */ /***********************************************************************/ -bool TDBDOS::InitialyzeIndex(PGLOBAL g, PIXDEF xdp) +bool TDBDOS::InitialyzeIndex(PGLOBAL g, PIXDEF xdp, bool sorted) { int k, rc; bool brc, dynamic; @@ -1808,6 +1826,12 @@ bool TDBDOS::InitialyzeIndex(PGLOBAL g, PIXDEF xdp) } // endif AmType To_Kindex= kxp; + + if (!(sorted && To_Kindex->IsSorted()) && + ((Mode == MODE_UPDATE && IsUsingTemp(g)) || + (Mode == MODE_DELETE && Txfp->GetAmType() != TYPE_AM_DBF))) + Indxd = true; + } // endif brc } else @@ -1884,7 +1908,7 @@ int TDBDOS::Cardinality(PGLOBAL g) } // endif Mode - if (Mode == MODE_ANY) { + if (Mode == MODE_ANY && xinfo) { // Using index impossible or failed, do it the hard way Mode = MODE_READ; To_Line = (char*)PlugSubAlloc(g, NULL, Lrecl + 1); @@ -1997,10 +2021,8 @@ int TDBDOS::EstimatedLength(PGLOBAL g) /***********************************************************************/ bool TDBDOS::IsUsingTemp(PGLOBAL g) { - USETEMP usetemp = PlgGetUser(g)->UseTemp; - - return (usetemp == TMP_YES || usetemp == TMP_FORCE || - (usetemp == TMP_AUTO && Mode == MODE_UPDATE)); + return (Use_Temp == TMP_YES || Use_Temp == TMP_FORCE || + (Use_Temp == TMP_AUTO && Mode == MODE_UPDATE)); } // end of IsUsingTemp /***********************************************************************/ @@ -2040,7 +2062,7 @@ bool TDBDOS::OpenDB(PGLOBAL g) Txfp = new(g) DOSFAM((PDOSDEF)To_Def); Txfp->SetTdbp(this); } else if (Txfp->Blocked && (Mode == MODE_DELETE || - (Mode == MODE_UPDATE && PlgGetUser(g)->UseTemp != TMP_NO))) { + (Mode == MODE_UPDATE && Use_Temp != TMP_NO))) { /*******************************************************************/ /* Delete is not currently handled in block mode neither Update */ /* when using a temporary file. */ @@ -2153,13 +2175,10 @@ int TDBDOS::ReadDB(PGLOBAL g) } // end of ReadDB /***********************************************************************/ -/* WriteDB: Data Base write routine for DOS access method. */ +/* PrepareWriting: Prepare the line to write. */ /***********************************************************************/ -int TDBDOS::WriteDB(PGLOBAL g) +bool TDBDOS::PrepareWriting(PGLOBAL g) { - if (trace > 1) - htrc("DOS WriteDB: R%d Mode=%d \n", Tdb_No, Mode); - if (!Ftype && (Mode == MODE_INSERT || Txfp->GetUseTemp())) { char *p; @@ -2174,6 +2193,20 @@ int TDBDOS::WriteDB(PGLOBAL g) *(++p) = '\0'; } // endif Mode + return false; + } // end of WriteDB + +/***********************************************************************/ +/* WriteDB: Data Base write routine for DOS access method. */ +/***********************************************************************/ +int TDBDOS::WriteDB(PGLOBAL g) + { + if (trace > 1) + htrc("DOS WriteDB: R%d Mode=%d \n", Tdb_No, Mode); + + // Make the line to write + (void)PrepareWriting(g); + if (trace > 1) htrc("Write: line is='%s'\n", To_Line); @@ -2201,6 +2234,7 @@ void TDBDOS::CloseDB(PGLOBAL g) } // endif Txfp->CloseTableFile(g, Abort); + RestoreNrec(); } // end of CloseDB // ------------------------ DOSCOL functions ---------------------------- @@ -2229,8 +2263,8 @@ DOSCOL::DOSCOL(PGLOBAL g, PCOLDEF cdp, PTDB tp, PCOL cp, int i, PSZ am) Deplac = cdp->GetOffset(); Long = cdp->GetLong(); To_Val = NULL; - Clustered = 0; - Sorted = 0; + Clustered = cdp->GetOpt(); + Sorted = (cdp->GetOpt() == 2) ? 1 : 0; Ndv = 0; // Currently used only for XDB2 Nbm = 0; // Currently used only for XDB2 Min = NULL; diff --git a/storage/connect/tabdos.h b/storage/connect/tabdos.h index 7f2c4f5e7ee..1c772e8bf23 100644 --- a/storage/connect/tabdos.h +++ b/storage/connect/tabdos.h @@ -136,6 +136,7 @@ class DllExport TDBDOS : public TDBASE { virtual PTDB CopyOne(PTABS t); virtual void ResetDB(void) {Txfp->Reset();} virtual bool IsUsingTemp(PGLOBAL g); + virtual bool IsIndexed(void) {return Indxd;} virtual void ResetSize(void) {MaxSize = Cardinal = -1;} virtual int ResetTableOpt(PGLOBAL g, bool dop, bool dox); virtual int MakeBlockValues(PGLOBAL g); @@ -171,11 +172,12 @@ class DllExport TDBDOS : public TDBASE { // Optimization routines virtual int MakeIndex(PGLOBAL g, PIXDEF pxdf, bool add); - bool InitialyzeIndex(PGLOBAL g, PIXDEF xdp); + bool InitialyzeIndex(PGLOBAL g, PIXDEF xdp, bool sorted); void ResetBlockFilter(PGLOBAL g); bool GetDistinctColumnValues(PGLOBAL g, int nrec); protected: + virtual bool PrepareWriting(PGLOBAL g); PBF CheckBlockFilari(PGLOBAL g, PXOB *arg, int op, bool *cnv); // Members @@ -185,6 +187,7 @@ class DllExport TDBDOS : public TDBASE { PFIL SavFil; // Saved hidden filter char *To_Line; // Points to current processed line bool Abort; // TRUE when aborting UPDATE/DELETE + bool Indxd; // TRUE for indexed UPDATE/DELETE int Lrecl; // Logical Record Length int AvgLen; // Logical Record Average Length //int Xeval; // BlockTest return value diff --git a/storage/connect/tabfix.cpp b/storage/connect/tabfix.cpp index fe04fe52627..91f06536272 100644 --- a/storage/connect/tabfix.cpp +++ b/storage/connect/tabfix.cpp @@ -51,7 +51,9 @@ /***********************************************************************/ /* DB static variables. */ /***********************************************************************/ -extern "C" int trace; +extern "C" int trace; +extern "C" USETEMP Use_Temp; + extern int num_read, num_there, num_eq[2]; // Statistics static const longlong M2G = 0x80000000; static const longlong M4G = (longlong)2 * M2G; @@ -135,6 +137,10 @@ int TDBFIX::ResetTableOpt(PGLOBAL g, bool dop, bool dox) MaxSize = -1; // Size must be recalculated Cardinal = -1; // as well as Cardinality + // After the table was modified the indexes + // are invalid and we should mark them as such... + rc = ((PDOSDEF)To_Def)->InvalidateIndex(g); + if (dop) { Columns = NULL; // Not used anymore Txfp->Reset(); @@ -153,12 +159,8 @@ int TDBFIX::ResetTableOpt(PGLOBAL g, bool dop, bool dox) 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. + if (PlgGetUser(g)->Check & CHK_OPT) + // We must remake indexes. rc = MakeIndex(g, NULL, FALSE); rc = (rc == RC_INFO) ? prc : rc; @@ -269,9 +271,11 @@ int TDBFIX::RowNumber(PGLOBAL g, bool b) /***********************************************************************/ bool TDBFIX::IsUsingTemp(PGLOBAL g) { - USETEMP usetemp = PlgGetUser(g)->UseTemp; - - return (usetemp == TMP_YES || usetemp == TMP_FORCE); + // Not ready yet to handle using a temporary file with mapping + // or while deleting from DBF files. + return ((Use_Temp == TMP_YES && Txfp->GetAmType() != TYPE_AM_MAP && + !(Mode == MODE_DELETE && Txfp->GetAmType() == TYPE_AM_DBF)) || + Use_Temp == TMP_FORCE || Use_Temp == TMP_TEST); } // end of IsUsingTemp /***********************************************************************/ @@ -302,8 +306,9 @@ bool TDBFIX::OpenDB(PGLOBAL g) return false; } // endif use - if (Mode == MODE_DELETE && !Next && Txfp->GetAmType() == TYPE_AM_MAP) { - // Delete all lines. Not handled in MAP mode + if (Mode == MODE_DELETE && Txfp->GetAmType() == TYPE_AM_MAP && + (!Next || Use_Temp == TMP_FORCE)) { + // Delete all lines or using temp. Not handled in MAP mode Txfp = new(g) FIXFAM((PDOSDEF)To_Def); Txfp->SetTdbp(this); } // endif Mode diff --git a/storage/connect/tabfix.h b/storage/connect/tabfix.h index 5feb3589928..7d5b964da2a 100644 --- a/storage/connect/tabfix.h +++ b/storage/connect/tabfix.h @@ -51,6 +51,8 @@ class DllExport TDBFIX : public TDBDOS { virtual int WriteDB(PGLOBAL g); protected: + virtual bool PrepareWriting(PGLOBAL g) {return false;} + // Members are inherited from TDBDOS }; // end of class TDBFIX @@ -89,7 +91,8 @@ class TDBDCL : public TDBCAT { protected: // Specific routines - virtual PQRYRES GetResult(PGLOBAL g) {return DBFColumns(g, Fn, false);} + virtual PQRYRES GetResult(PGLOBAL g) + {return DBFColumns(g, ((PTABDEF)To_Def)->GetPath(), Fn, false);} // Members char *Fn; // The DBF file (path) name diff --git a/storage/connect/tabfmt.cpp b/storage/connect/tabfmt.cpp index c015b6adad3..c1119c57065 100644 --- a/storage/connect/tabfmt.cpp +++ b/storage/connect/tabfmt.cpp @@ -66,7 +66,8 @@ #define MAXCOL 200 /* Default max column nb in result */ #define TYPE_UNKNOWN 10 /* Must be greater than other types */ -extern "C" int trace; +extern "C" int trace; +extern "C" USETEMP Use_Temp; /***********************************************************************/ /* CSVColumns: constructs the result blocks containing the description */ @@ -75,8 +76,8 @@ extern "C" int trace; /* of types (TYPE_STRING < TYPE_DOUBLE < TYPE_INT) (1 < 2 < 7). */ /* If these values are changed, this will have to be revisited. */ /***********************************************************************/ -PQRYRES CSVColumns(PGLOBAL g, const char *fn, char sep, char q, - int hdr, int mxr, bool info) +PQRYRES CSVColumns(PGLOBAL g, char *dp, const char *fn, char sep, + char q, int hdr, int mxr, bool info) { static int buftyp[] = {TYPE_STRING, TYPE_SHORT, TYPE_STRING, TYPE_INT, TYPE_INT, TYPE_SHORT}; @@ -130,7 +131,7 @@ PQRYRES CSVColumns(PGLOBAL g, const char *fn, char sep, char q, /*********************************************************************/ /* Open the input file. */ /*********************************************************************/ - PlugSetPath(filename, fn, PlgGetDataPath(g)); + PlugSetPath(filename, fn, dp); if (!(infile= global_fopen(g, MSGID_CANNOT_OPEN, filename, "r"))) return NULL; @@ -441,7 +442,7 @@ PTDB CSVDEF::GetTable(PGLOBAL g, MODE mode) PTDBASE tdbp; if (Catfunc != FNC_COL) { - USETEMP tmp = PlgGetUser(g)->UseTemp; + USETEMP tmp = Use_Temp; bool map = Mapped && mode != MODE_INSERT && !(tmp != TMP_NO && mode == MODE_UPDATE) && !(tmp == TMP_FORCE && @@ -479,6 +480,36 @@ PTDB CSVDEF::GetTable(PGLOBAL g, MODE mode) if (Multiple) tdbp = new(g) TDBMUL(tdbp); + 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 (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 + + } // endelse } else tdbp = new(g)TDBCCL(this); @@ -605,14 +636,12 @@ int TDBCSV::EstimatedLength(PGLOBAL g) #if 0 /***********************************************************************/ -/* CSV tables favor the use temporary files for Update. */ +/* CSV tables needs the use temporary files for Update. */ /***********************************************************************/ bool TDBCSV::IsUsingTemp(PGLOBAL g) { - USETEMP usetemp = PlgGetUser(g)->UseTemp; - - return (usetemp == TMP_YES || usetemp == TMP_FORCE || - (usetemp == TMP_AUTO && Mode == MODE_UPDATE)); + return (Use_Temp == TMP_YES || Use_Temp == TMP_FORCE || + (Use_Temp == TMP_AUTO && Mode == MODE_UPDATE)); } // end of IsUsingTemp #endif // 0 (Same as TDBDOS one) @@ -899,9 +928,9 @@ int TDBCSV::ReadBuffer(PGLOBAL g) } // end of ReadBuffer /***********************************************************************/ -/* Data Base write routine CSV file access method. */ +/* Prepare the line to write. */ /***********************************************************************/ -int TDBCSV::WriteDB(PGLOBAL g) +bool TDBCSV::PrepareWriting(PGLOBAL g) { char sep[2], qot[2]; int i, nlen, oldlen = strlen(To_Line); @@ -912,7 +941,7 @@ int TDBCSV::WriteDB(PGLOBAL g) // Before writing the line we must check its length if ((nlen = CheckWrite(g)) < 0) - return RC_FX; + return true; // Before writing the line we must make it sep[0] = Sep; @@ -975,6 +1004,18 @@ int TDBCSV::WriteDB(PGLOBAL g) if (trace > 1) htrc("Write: line is=%s", To_Line); + return false; + } // end of PrepareWriting + +/***********************************************************************/ +/* Data Base write routine CSV file access method. */ +/***********************************************************************/ +int TDBCSV::WriteDB(PGLOBAL g) + { + // Before writing the line we must check and prepare it + if (PrepareWriting(g)) + return RC_FX; + /*********************************************************************/ /* Now start the writing process. */ /*********************************************************************/ @@ -1430,7 +1471,8 @@ TDBCCL::TDBCCL(PCSVDEF tdp) : TDBCAT(tdp) /***********************************************************************/ PQRYRES TDBCCL::GetResult(PGLOBAL g) { - return CSVColumns(g, Fn, Sep, Qtd, Hdr, Mxr, false); + return CSVColumns(g, ((PTABDEF)To_Def)->GetPath(), + Fn, Sep, Qtd, Hdr, Mxr, false); } // end of GetResult /* ------------------------ End of TabFmt ---------------------------- */ diff --git a/storage/connect/tabfmt.h b/storage/connect/tabfmt.h index aa14b4481f0..1b39a47e7d9 100644 --- a/storage/connect/tabfmt.h +++ b/storage/connect/tabfmt.h @@ -1,188 +1,193 @@ -/*************** TabFmt H Declares Source Code File (.H) ***************/
-/* Name: TABFMT.H Version 2.4 */
-/* */
-/* (C) Copyright to the author Olivier BERTRAND 2001-2014 */
-/* */
-/* This file contains the CSV and FMT classes declares. */
-/***********************************************************************/
-#include "xtable.h" // Base class declares
-#include "tabdos.h"
-
-typedef class TDBFMT *PTDBFMT;
-
-/***********************************************************************/
-/* Functions used externally. */
-/***********************************************************************/
-PQRYRES CSVColumns(PGLOBAL g, const char *fn, char sep, char q,
- int hdr, int mxr, bool info);
-
-/***********************************************************************/
-/* CSV table. */
-/***********************************************************************/
-class DllExport CSVDEF : public DOSDEF { /* Logical table description */
- friend class TDBCSV;
- friend class TDBCCL;
- public:
- // Constructor
- CSVDEF(void);
-
- // Implementation
- virtual const char *GetType(void) {return "CSV";}
- char GetSep(void) {return Sep;}
- char GetQot(void) {return Qot;}
-
- // Methods
- virtual bool DefineAM(PGLOBAL g, LPCSTR am, int poff);
- virtual PTDB GetTable(PGLOBAL g, MODE mode);
-
- protected:
- // Members
- bool Fmtd; /* true for formatted files */
-//bool Accept; /* true if wrong lines are accepted */
- bool Header; /* true if first line contains headers */
-//int Maxerr; /* Maximum number of bad records */
- int Quoted; /* Quoting level for quoted fields */
- char Sep; /* Separator for standard CSV files */
- char Qot; /* Character for quoted strings */
- }; // end of CSVDEF
-
-/***********************************************************************/
-/* This is the DOS/UNIX Access Method class declaration for files */
-/* that are CSV files with columns separated by the Sep character. */
-/***********************************************************************/
-class TDBCSV : public TDBDOS {
- friend class CSVCOL;
- public:
- // Constructor
- TDBCSV(PCSVDEF tdp, PTXF txfp);
- TDBCSV(PGLOBAL g, PTDBCSV tdbp);
-
- // Implementation
- virtual AMT GetAmType(void) {return TYPE_AM_CSV;}
- virtual PTDB Duplicate(PGLOBAL g)
- {return (PTDB)new(g) TDBCSV(g, this);}
-
- // Methods
- virtual PTDB CopyOne(PTABS t);
-//virtual bool IsUsingTemp(PGLOBAL g);
- virtual int GetBadLines(void) {return (int)Nerr;}
-
- // Database routines
- virtual PCOL MakeCol(PGLOBAL g, PCOLDEF cdp, PCOL cprec, int n);
- virtual bool OpenDB(PGLOBAL g);
- virtual int WriteDB(PGLOBAL g);
- virtual int CheckWrite(PGLOBAL g);
- virtual int ReadBuffer(PGLOBAL g); // Physical file read
-
- // Specific routines
- virtual int EstimatedLength(PGLOBAL g);
- virtual bool SkipHeader(PGLOBAL g);
- virtual bool CheckErr(void);
-
- protected:
- // Members
- PSZ *Field; // Field to write to current line
- int *Offset; // Column offsets for current record
- int *Fldlen; // Column field length for current record
- bool *Fldtyp; // true for numeric fields
- int Fields; // Number of fields to handle
- int Nerr; // Number of bad records
- int Maxerr; // Maximum number of bad records
- int Quoted; // Quoting level for quoted fields
- bool Accept; // true if bad lines are accepted
- bool Header; // true if first line contains column headers
- char Sep; // Separator
- char Qot; // Quoting character
- }; // end of class TDBCSV
-
-/***********************************************************************/
-/* Class CSVCOL: CSV access method column descriptor. */
-/* This A.M. is used for Comma Separated V(?) files. */
-/***********************************************************************/
-class CSVCOL : public DOSCOL {
- friend class TDBCSV;
- friend class TDBFMT;
- public:
- // Constructors
- CSVCOL(PGLOBAL g, PCOLDEF cdp, PTDB tdbp, PCOL cprec, int i);
- CSVCOL(CSVCOL *colp, PTDB tdbp); // Constructor used in copy process
-
- // Implementation
- virtual int GetAmType() {return TYPE_AM_CSV;}
-
- // Methods
- virtual bool VarSize(void);
- virtual void ReadColumn(PGLOBAL g);
- virtual void WriteColumn(PGLOBAL g);
-
- protected:
- // Default constructor not to be used
- CSVCOL(void) {}
-
- // Members
- int Fldnum; // Field ordinal number (0 based)
- }; // end of class CSVCOL
-
-/***********************************************************************/
-/* This is the DOS/UNIX Access Method class declaration for files */
-/* whose record format is described by a Format keyword. */
-/***********************************************************************/
-class TDBFMT : public TDBCSV {
- friend class CSVCOL;
-//friend class FMTCOL;
- public:
- // Standard constructor
- TDBFMT(PCSVDEF tdp, PTXF txfp) : TDBCSV(tdp, txfp)
- {FldFormat = NULL; To_Fld = NULL; FmtTest = NULL; Linenum = 0;}
-
- // Copy constructor
- TDBFMT(PGLOBAL g, PTDBFMT tdbp);
-
- // Implementation
- virtual AMT GetAmType(void) {return TYPE_AM_FMT;}
- virtual PTDB Duplicate(PGLOBAL g)
- {return (PTDB)new(g) TDBFMT(g, this);}
-
- // Methods
- virtual PTDB CopyOne(PTABS t);
-
- // Database routines
- virtual PCOL MakeCol(PGLOBAL g, PCOLDEF cdp, PCOL cprec, int n);
-//virtual int GetMaxSize(PGLOBAL g);
- virtual bool OpenDB(PGLOBAL g);
- virtual int WriteDB(PGLOBAL g);
-//virtual int CheckWrite(PGLOBAL g);
- virtual int ReadBuffer(PGLOBAL g); // Physical file read
-
- // Specific routines
- virtual int EstimatedLength(PGLOBAL g);
-
- protected:
- // Members
- PSZ *FldFormat; // Field read format
- void *To_Fld; // To field test buffer
- int *FmtTest; // Test on ending by %n or %m
- int Linenum; // Last read line
- }; // end of class TDBFMT
-
-/***********************************************************************/
-/* This is the class declaration for the CSV catalog table. */
-/***********************************************************************/
-class TDBCCL : public TDBCAT {
- public:
- // Constructor
- TDBCCL(PCSVDEF tdp);
-
- protected:
- // Specific routines
- virtual PQRYRES GetResult(PGLOBAL g);
-
- // Members
- char *Fn; // The CSV file (path) name
- bool Hdr; // true if first line contains headers
- int Mxr; // Maximum number of bad records
- int Qtd; // Quoting level for quoted fields
- char Sep; // Separator for standard CSV files
- }; // end of class TDBCCL
-
-/* ------------------------- End of TabFmt.H ------------------------- */
+/*************** TabFmt H Declares Source Code File (.H) ***************/ +/* Name: TABFMT.H Version 2.4 */ +/* */ +/* (C) Copyright to the author Olivier BERTRAND 2001-2014 */ +/* */ +/* This file contains the CSV and FMT classes declares. */ +/***********************************************************************/ +#include "xtable.h" // Base class declares +#include "tabdos.h" + +typedef class TDBFMT *PTDBFMT; + +/***********************************************************************/ +/* Functions used externally. */ +/***********************************************************************/ +PQRYRES CSVColumns(PGLOBAL g, char *dp, const char *fn, char sep, + char q, int hdr, int mxr, bool info); + +/***********************************************************************/ +/* CSV table. */ +/***********************************************************************/ +class DllExport CSVDEF : public DOSDEF { /* Logical table description */ + friend class TDBCSV; + friend class TDBCCL; + public: + // Constructor + CSVDEF(void); + + // Implementation + virtual const char *GetType(void) {return "CSV";} + char GetSep(void) {return Sep;} + char GetQot(void) {return Qot;} + + // Methods + virtual bool DefineAM(PGLOBAL g, LPCSTR am, int poff); + virtual PTDB GetTable(PGLOBAL g, MODE mode); + + protected: + // Members + bool Fmtd; /* true for formatted files */ +//bool Accept; /* true if wrong lines are accepted */ + bool Header; /* true if first line contains headers */ +//int Maxerr; /* Maximum number of bad records */ + int Quoted; /* Quoting level for quoted fields */ + char Sep; /* Separator for standard CSV files */ + char Qot; /* Character for quoted strings */ + }; // end of CSVDEF + +/***********************************************************************/ +/* This is the DOS/UNIX Access Method class declaration for files */ +/* that are CSV files with columns separated by the Sep character. */ +/***********************************************************************/ +class TDBCSV : public TDBDOS { + friend class CSVCOL; + public: + // Constructor + TDBCSV(PCSVDEF tdp, PTXF txfp); + TDBCSV(PGLOBAL g, PTDBCSV tdbp); + + // Implementation + virtual AMT GetAmType(void) {return TYPE_AM_CSV;} + virtual PTDB Duplicate(PGLOBAL g) + {return (PTDB)new(g) TDBCSV(g, this);} + + // Methods + virtual PTDB CopyOne(PTABS t); +//virtual bool IsUsingTemp(PGLOBAL g); + virtual int GetBadLines(void) {return (int)Nerr;} + + // Database routines + virtual PCOL MakeCol(PGLOBAL g, PCOLDEF cdp, PCOL cprec, int n); + virtual bool OpenDB(PGLOBAL g); + virtual int WriteDB(PGLOBAL g); + virtual int CheckWrite(PGLOBAL g); + virtual int ReadBuffer(PGLOBAL g); // Physical file read + + // Specific routines + virtual int EstimatedLength(PGLOBAL g); + virtual bool SkipHeader(PGLOBAL g); + virtual bool CheckErr(void); + + protected: + virtual bool PrepareWriting(PGLOBAL g); + + // Members + PSZ *Field; // Field to write to current line + int *Offset; // Column offsets for current record + int *Fldlen; // Column field length for current record + bool *Fldtyp; // true for numeric fields + int Fields; // Number of fields to handle + int Nerr; // Number of bad records + int Maxerr; // Maximum number of bad records + int Quoted; // Quoting level for quoted fields + bool Accept; // true if bad lines are accepted + bool Header; // true if first line contains column headers + char Sep; // Separator + char Qot; // Quoting character + }; // end of class TDBCSV + +/***********************************************************************/ +/* Class CSVCOL: CSV access method column descriptor. */ +/* This A.M. is used for Comma Separated V(?) files. */ +/***********************************************************************/ +class CSVCOL : public DOSCOL { + friend class TDBCSV; + friend class TDBFMT; + public: + // Constructors + CSVCOL(PGLOBAL g, PCOLDEF cdp, PTDB tdbp, PCOL cprec, int i); + CSVCOL(CSVCOL *colp, PTDB tdbp); // Constructor used in copy process + + // Implementation + virtual int GetAmType() {return TYPE_AM_CSV;} + + // Methods + virtual bool VarSize(void); + virtual void ReadColumn(PGLOBAL g); + virtual void WriteColumn(PGLOBAL g); + + protected: + // Default constructor not to be used + CSVCOL(void) {} + + // Members + int Fldnum; // Field ordinal number (0 based) + }; // end of class CSVCOL + +/***********************************************************************/ +/* This is the DOS/UNIX Access Method class declaration for files */ +/* whose record format is described by a Format keyword. */ +/***********************************************************************/ +class TDBFMT : public TDBCSV { + friend class CSVCOL; +//friend class FMTCOL; + public: + // Standard constructor + TDBFMT(PCSVDEF tdp, PTXF txfp) : TDBCSV(tdp, txfp) + {FldFormat = NULL; To_Fld = NULL; FmtTest = NULL; Linenum = 0;} + + // Copy constructor + TDBFMT(PGLOBAL g, PTDBFMT tdbp); + + // Implementation + virtual AMT GetAmType(void) {return TYPE_AM_FMT;} + virtual PTDB Duplicate(PGLOBAL g) + {return (PTDB)new(g) TDBFMT(g, this);} + + // Methods + virtual PTDB CopyOne(PTABS t); + + // Database routines + virtual PCOL MakeCol(PGLOBAL g, PCOLDEF cdp, PCOL cprec, int n); +//virtual int GetMaxSize(PGLOBAL g); + virtual bool OpenDB(PGLOBAL g); + virtual int WriteDB(PGLOBAL g); +//virtual int CheckWrite(PGLOBAL g); + virtual int ReadBuffer(PGLOBAL g); // Physical file read + + // Specific routines + virtual int EstimatedLength(PGLOBAL g); + + protected: + virtual bool PrepareWriting(PGLOBAL g) + {strcpy(g->Message, "FMT is read only"); return true;} + + // Members + PSZ *FldFormat; // Field read format + void *To_Fld; // To field test buffer + int *FmtTest; // Test on ending by %n or %m + int Linenum; // Last read line + }; // end of class TDBFMT + +/***********************************************************************/ +/* This is the class declaration for the CSV catalog table. */ +/***********************************************************************/ +class TDBCCL : public TDBCAT { + public: + // Constructor + TDBCCL(PCSVDEF tdp); + + protected: + // Specific routines + virtual PQRYRES GetResult(PGLOBAL g); + + // Members + char *Fn; // The CSV file (path) name + bool Hdr; // true if first line contains headers + int Mxr; // Maximum number of bad records + int Qtd; // Quoting level for quoted fields + char Sep; // Separator for standard CSV files + }; // end of class TDBCCL + +/* ------------------------- End of TabFmt.H ------------------------- */ diff --git a/storage/connect/table.cpp b/storage/connect/table.cpp index 94c00ebb061..5db50d44787 100644 --- a/storage/connect/table.cpp +++ b/storage/connect/table.cpp @@ -216,10 +216,11 @@ PCOL TDBASE::ColDB(PGLOBAL g, PSZ name, int num) /* Also find where to insert the new block. */ /*****************************************************************/ for (cp = Columns; cp; cp = cp->GetNext()) - if (cp->GetIndex() < i) + if ((num && cp->GetIndex() == i) || + (name && !stricmp(cp->GetName(), name))) + break; // Found + else if (cp->GetIndex() < i) cprec = cp; - else if (cp->GetIndex() == i) - break; if (trace) htrc("cdp(%d).Name=%s cp=%p\n", i, cdp->GetName(), cp); diff --git a/storage/connect/tabmul.cpp b/storage/connect/tabmul.cpp index 6e4a63d0f6d..4b40e6c5509 100755 --- a/storage/connect/tabmul.cpp +++ b/storage/connect/tabmul.cpp @@ -680,7 +680,7 @@ char* TDBDIR::Path(PGLOBAL g) #if defined(WIN32) if (!*Drive) { - PlugSetPath(Fpath, To_File, cat->GetDataPath()); + PlugSetPath(Fpath, To_File, ((PTABDEF)To_Def)->GetPath()); _splitpath(Fpath, Drive, Direc, Fname, Ftype); } else _makepath(Fpath, Drive, Direc, Fname, Ftype); // Usefull ??? @@ -688,7 +688,7 @@ char* TDBDIR::Path(PGLOBAL g) return Fpath; #else // !WIN32 if (!Done) { - PlugSetPath(Fpath, To_File, cat->GetDataPath()); + PlugSetPath(Fpath, To_File, ((PTABDEF)To_Def)->GetPath()); _splitpath(Fpath, NULL, Direc, Fname, Ftype); strcat(strcpy(Pattern, Fname), Ftype); Done = true; diff --git a/storage/connect/tabmysql.cpp b/storage/connect/tabmysql.cpp index d84f6c9aab4..6acdcbb3a8e 100644 --- a/storage/connect/tabmysql.cpp +++ b/storage/connect/tabmysql.cpp @@ -68,6 +68,7 @@ void PrintResult(PGLOBAL, PSEM, PQRYRES); #endif // _CONSOLE extern "C" int trace; +extern bool xinfo; // Used to check whether a MYSQL table is created on itself bool CheckSelf(PGLOBAL g, TABLE_SHARE *s, const char *host, @@ -754,7 +755,7 @@ int TDBMYSQL::Cardinality(PGLOBAL g) if (!g) return (Mode == MODE_ANY && !Srcdef) ? 1 : 0; - if (Cardinal < 0 && Mode == MODE_ANY && !Srcdef) { + if (Cardinal < 0 && Mode == MODE_ANY && !Srcdef && xinfo) { // Info command, we must return the exact table row number char query[96]; MYSQLC myc; @@ -905,7 +906,7 @@ bool TDBMYSQL::OpenDB(PGLOBAL g) } // endif MakeInsert if (m_Rc != RC_FX) { - int rc; + int rc __attribute__((unused)); char cmd[64]; int w; diff --git a/storage/connect/tabodbc.cpp b/storage/connect/tabodbc.cpp index 5542e832a54..023d7efa708 100644 --- a/storage/connect/tabodbc.cpp +++ b/storage/connect/tabodbc.cpp @@ -1,11 +1,11 @@ /************* Tabodbc C++ Program Source Code File (.CPP) *************/ /* PROGRAM NAME: TABODBC */ /* ------------- */ -/* Version 2.7 */ +/* Version 2.8 */ /* */ /* COPYRIGHT: */ /* ---------- */ -/* (C) Copyright to the author Olivier BERTRAND 2000-2013 */ +/* (C) Copyright to the author Olivier BERTRAND 2000-2014 */ /* */ /* WHAT THIS PROGRAM DOES: */ /* ----------------------- */ @@ -76,6 +76,7 @@ #include "sql_string.h" extern "C" int trace; +extern bool xinfo; /***********************************************************************/ /* DB static variables. */ @@ -671,7 +672,7 @@ int TDBODBC::Cardinality(PGLOBAL g) if (!g) return (Mode == MODE_ANY && !Srcdef) ? 1 : 0; - if (Cardinal < 0 && Mode == MODE_ANY && !Srcdef) { + if (Cardinal < 0 && Mode == MODE_ANY && !Srcdef && xinfo) { // Info command, we must return the exact table row number char qry[96], tbn[64]; ODBConn *ocp = new(g) ODBConn(g, this); diff --git a/storage/connect/tabvct.cpp b/storage/connect/tabvct.cpp index 043d3c2c496..6d7059e2306 100644 --- a/storage/connect/tabvct.cpp +++ b/storage/connect/tabvct.cpp @@ -76,7 +76,8 @@ char *strerror(int num); #endif // UNIX -extern "C" int trace; +extern "C" int trace; +extern "C" USETEMP Use_Temp; /***********************************************************************/ /* Char VCT column blocks are right filled with blanks (blank = true) */ @@ -208,7 +209,7 @@ PTDB VCTDEF::GetTable(PGLOBAL g, MODE mode) // Mapping not used for insert (except for true VEC not split tables) // or when UseTemp is forced bool map = Mapped && (Estimate || mode != MODE_INSERT) && - !(PlgGetUser(g)->UseTemp == TMP_FORCE && + !(Use_Temp == TMP_FORCE && (mode == MODE_UPDATE || mode == MODE_DELETE)); PTXF txfp; PTDB tdbp; @@ -285,6 +286,15 @@ PCOL TDBVCT::MakeCol(PGLOBAL g, PCOLDEF cdp, PCOL cprec, int n) } // end of MakeCol /***********************************************************************/ +/* VEC tables are not ready yet to use temporary files. */ +/***********************************************************************/ +bool TDBVCT::IsUsingTemp(PGLOBAL g) + { + // For developpers + return (Use_Temp == TMP_TEST); + } // end of IsUsingTemp + +/***********************************************************************/ /* VCT Access Method opening routine. */ /* New method now that this routine is called recursively (last table */ /* first in reverse order): index blocks are immediately linked to */ diff --git a/storage/connect/tabvct.h b/storage/connect/tabvct.h index 0a67a5e03b2..8ad3c8e21be 100644 --- a/storage/connect/tabvct.h +++ b/storage/connect/tabvct.h @@ -1,123 +1,124 @@ -/*************** TabVct H Declares Source Code File (.H) ***************/
-/* Name: TABVCT.H Version 3.4 */
-/* */
-/* (C) Copyright to the author Olivier BERTRAND 1999-2011 */
-/* */
-/* This file contains the TDBVCT class declares. */
-/***********************************************************************/
-#ifndef __TABVCT__
-#define __TABVCT__
-
-#include "tabfix.h"
-#if defined(UNIX)
-//#include <string.h.SUNWCCh>
-#endif
-
-typedef class TDBVCT *PTDBVCT;
-typedef class VCTCOL *PVCTCOL;
-
-/***********************************************************************/
-/* VCT table. */
-/***********************************************************************/
-class DllExport VCTDEF : public DOSDEF { /* Logical table description */
- friend class TDBVCT;
- friend class VCTFAM;
- friend class VECFAM;
- friend class VMPFAM;
- public:
- // Constructor
- VCTDEF(void) {Split = false; Estimate = Header = 0;}
-
- // Implementation
- virtual const char *GetType(void) {return "VCT";}
- int GetEstimate(void) {return Estimate;}
-
- // Methods
- virtual bool DefineAM(PGLOBAL g, LPCSTR am, int poff);
- virtual PTDB GetTable(PGLOBAL g, MODE mode);
-
- protected:
- int MakeFnPattern(char *fpat);
-
- // Members
- bool Split; /* Columns in separate files */
- int Estimate; /* Estimated maximum size of table */
- int Header; /* 0: no, 1: separate, 2: in data file */
- }; // end of VCTDEF
-
-/***********************************************************************/
-/* This is the DOS/UNIX Access Method class declaration for files */
-/* in blocked vector format. In each block containing "Elements" */
-/* records, values of each columns are consecutively stored (vector). */
-/***********************************************************************/
-class DllExport TDBVCT : public TDBFIX {
- friend class VCTCOL;
- friend class VCTFAM;
- friend class VCMFAM;
- friend class VECFAM;
- friend class VMPFAM;
- public:
- // Constructors
- TDBVCT(PVCTDEF tdp, PTXF txfp);
- TDBVCT(PGLOBAL g, PTDBVCT tdbp);
-
- // Implementation
- virtual AMT GetAmType(void) {return TYPE_AM_VCT;}
- virtual PTDB Duplicate(PGLOBAL g)
- {return (PTDB)new(g) TDBVCT(g, this);}
- bool IsSplit(void) {return ((VCTDEF*)To_Def)->Split;}
-
- // Methods
- virtual PTDB CopyOne(PTABS t);
-
- // Database routines
- virtual PCOL MakeCol(PGLOBAL g, PCOLDEF cdp, PCOL cprec, int n);
- virtual bool OpenDB(PGLOBAL g);
- virtual int ReadDB(PGLOBAL g);
- virtual void CloseDB(PGLOBAL g);
-
- protected:
- // Members
- }; // end of class TDBVCT
-
-/***********************************************************************/
-/* Class VCTCOL: VCT access method column descriptor. */
-/* This A.M. is used for file having column wise organization. */
-/***********************************************************************/
-class DllExport VCTCOL : public DOSCOL {
- friend class TDBVCT;
- friend class VCTFAM;
- friend class VCMFAM;
- friend class VECFAM;
- friend class VMPFAM;
- friend class BGVFAM;
- public:
- // Constructors
- VCTCOL(PGLOBAL g, PCOLDEF cdp, PTDB tdbp, PCOL cprec, int i);
- VCTCOL(VCTCOL *colp, PTDB tdbp); // Constructor used in copy process
-
- // Implementation
- virtual int GetAmType(void) {return TYPE_AM_VCT;}
-
- // Methods
- virtual void ReadColumn(PGLOBAL g);
- virtual void WriteColumn(PGLOBAL g);
- virtual bool SetBuffer(PGLOBAL g, PVAL value, bool ok, bool check);
- virtual void SetOk(void);
-
- protected:
- virtual void ReadBlock(PGLOBAL g);
- virtual void WriteBlock(PGLOBAL g);
-
- VCTCOL(void) {} // Default constructor not to be used
-
- // Members
- PVBLK Blk; // Block buffer
- int Clen; // Internal length in table
- int ColBlk; // Block pointed by column
- int ColPos; // Last position read
- int Modif; // Number of modified lines in block
- }; // end of class VCTCOL
-
-#endif // __TABVCT__
-
+/*************** TabVct H Declares Source Code File (.H) ***************/ +/* Name: TABVCT.H Version 3.4 */ +/* */ +/* (C) Copyright to the author Olivier BERTRAND 1999-2011 */ +/* */ +/* This file contains the TDBVCT class declares. */ +/***********************************************************************/ +#ifndef __TABVCT__ +#define __TABVCT__ + +#include "tabfix.h" +#if defined(UNIX) +//#include <string.h.SUNWCCh> +#endif + +typedef class TDBVCT *PTDBVCT; +typedef class VCTCOL *PVCTCOL; + +/***********************************************************************/ +/* VCT table. */ +/***********************************************************************/ +class DllExport VCTDEF : public DOSDEF { /* Logical table description */ + friend class TDBVCT; + friend class VCTFAM; + friend class VECFAM; + friend class VMPFAM; + public: + // Constructor + VCTDEF(void) {Split = false; Estimate = Header = 0;} + + // Implementation + virtual const char *GetType(void) {return "VCT";} + int GetEstimate(void) {return Estimate;} + + // Methods + virtual bool DefineAM(PGLOBAL g, LPCSTR am, int poff); + virtual PTDB GetTable(PGLOBAL g, MODE mode); + + protected: + int MakeFnPattern(char *fpat); + + // Members + bool Split; /* Columns in separate files */ + int Estimate; /* Estimated maximum size of table */ + int Header; /* 0: no, 1: separate, 2: in data file */ + }; // end of VCTDEF + +/***********************************************************************/ +/* This is the DOS/UNIX Access Method class declaration for files */ +/* in blocked vector format. In each block containing "Elements" */ +/* records, values of each columns are consecutively stored (vector). */ +/***********************************************************************/ +class DllExport TDBVCT : public TDBFIX { + friend class VCTCOL; + friend class VCTFAM; + friend class VCMFAM; + friend class VECFAM; + friend class VMPFAM; + public: + // Constructors + TDBVCT(PVCTDEF tdp, PTXF txfp); + TDBVCT(PGLOBAL g, PTDBVCT tdbp); + + // Implementation + virtual AMT GetAmType(void) {return TYPE_AM_VCT;} + virtual PTDB Duplicate(PGLOBAL g) + {return (PTDB)new(g) TDBVCT(g, this);} + bool IsSplit(void) {return ((VCTDEF*)To_Def)->Split;} + + // Methods + virtual PTDB CopyOne(PTABS t); + virtual bool IsUsingTemp(PGLOBAL g); + + // Database routines + virtual PCOL MakeCol(PGLOBAL g, PCOLDEF cdp, PCOL cprec, int n); + virtual bool OpenDB(PGLOBAL g); + virtual int ReadDB(PGLOBAL g); + virtual void CloseDB(PGLOBAL g); + + protected: + // Members + }; // end of class TDBVCT + +/***********************************************************************/ +/* Class VCTCOL: VCT access method column descriptor. */ +/* This A.M. is used for file having column wise organization. */ +/***********************************************************************/ +class DllExport VCTCOL : public DOSCOL { + friend class TDBVCT; + friend class VCTFAM; + friend class VCMFAM; + friend class VECFAM; + friend class VMPFAM; + friend class BGVFAM; + public: + // Constructors + VCTCOL(PGLOBAL g, PCOLDEF cdp, PTDB tdbp, PCOL cprec, int i); + VCTCOL(VCTCOL *colp, PTDB tdbp); // Constructor used in copy process + + // Implementation + virtual int GetAmType(void) {return TYPE_AM_VCT;} + + // Methods + virtual void ReadColumn(PGLOBAL g); + virtual void WriteColumn(PGLOBAL g); + virtual bool SetBuffer(PGLOBAL g, PVAL value, bool ok, bool check); + virtual void SetOk(void); + + protected: + virtual void ReadBlock(PGLOBAL g); + virtual void WriteBlock(PGLOBAL g); + + VCTCOL(void) {} // Default constructor not to be used + + // Members + PVBLK Blk; // Block buffer + int Clen; // Internal length in table + int ColBlk; // Block pointed by column + int ColPos; // Last position read + int Modif; // Number of modified lines in block + }; // end of class VCTCOL + +#endif // __TABVCT__ + diff --git a/storage/connect/valblk.cpp b/storage/connect/valblk.cpp index e435a49cbd2..3827deec43d 100644 --- a/storage/connect/valblk.cpp +++ b/storage/connect/valblk.cpp @@ -827,12 +827,12 @@ void CHRBLK::SetValue(PVBLK pv, int n1, int n2) longjmp(g->jumper[g->jump_level], Type); } // endif Type - if (!(b = pv->IsNull(n2) && Nullable)) + if (!(b = pv->IsNull(n2))) memcpy(Chrp + n1 * Long, ((CHRBLK*)pv)->Chrp + n2 * Long, Long); else Reset(n1); - SetNull(n1, b); + SetNull(n1, b && Nullable); } // end of SetValue /***********************************************************************/ diff --git a/storage/connect/value.h b/storage/connect/value.h index 3dc7940b964..151ddacf509 100644 --- a/storage/connect/value.h +++ b/storage/connect/value.h @@ -52,6 +52,7 @@ DllExport PVAL AllocateValue(PGLOBAL, int, int len = 0, int prec = 0, bool uns = false, PSZ fmt = NULL); DllExport ulonglong CharToNumber(char *, int, ulonglong, bool, bool *minus = NULL, bool *rc = NULL); +DllExport BYTE OpBmp(PGLOBAL g, OPVAL opc); /***********************************************************************/ /* Class VALUE represents a constant or variable of any valid type. */ diff --git a/storage/connect/xindex.cpp b/storage/connect/xindex.cpp index 12781b2ac05..7cc52580760 100755 --- a/storage/connect/xindex.cpp +++ b/storage/connect/xindex.cpp @@ -50,7 +50,7 @@ /***********************************************************************/ /* Macro or external routine definition */ /***********************************************************************/ -#define NZ 7 +#define NZ 8 #define NW 5 #define MAX_INDX 10 #ifndef INVALID_SET_FILE_POINTER @@ -264,9 +264,6 @@ void XINDEX::Close(void) kcp->FreeData(); } // endfor kcp - if (Tdbp) - Tdbp->RestoreNrec(); - } // end of Close /***********************************************************************/ @@ -411,7 +408,7 @@ bool XINDEX::Make(PGLOBAL g, PIXDEF sxp) kcp = new(g) KXYCOL(this); - if (kcp->Init(g, colp, n, true, NULL)) + if (kcp->Init(g, colp, n, true, 0)) return true; if (trace) @@ -547,7 +544,7 @@ bool XINDEX::Make(PGLOBAL g, PIXDEF sxp) if ((Ndif = Qsort(g, Num_K)) < 0) goto err; // Error during sort -// if (trace) + 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); @@ -820,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; @@ -869,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 (trace) { htrc("Saving index %s\n", Xdp->GetName()); - htrc("ID=%d Nk=%d nof=%d Num_K=%d Incr=%d Nblk=%d Sblk=%d\n", - ID, Nk, nof, Num_K, Incr, Nblk, Sblk); + 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 @@ -903,20 +901,20 @@ 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 (trace) @@ -1019,12 +1017,22 @@ 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 (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\n", - nv[0], nv[1], nv[2], nv[3], nv[4], nv[5], nv[6]); + 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 @@ -1271,11 +1279,20 @@ bool XINDEX::MapInit(PGLOBAL g) // Now start the mapping process. nv = (int*)mbase; - mbase += NZ * sizeof(int); + + 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\n", - nv[0], nv[1], nv[2], nv[3], nv[4], nv[5], nv[6]); + 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 @@ -2453,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); @@ -2461,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; @@ -2553,7 +2570,7 @@ bool XHUGE::Open(PGLOBAL g, char *filename, int id, MODE 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 */ @@ -2564,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); @@ -2597,6 +2614,9 @@ bool XHUGE::Open(PGLOBAL g, char *filename, int id, MODE mode) 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. @@ -2604,18 +2624,26 @@ 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 @@ -2749,6 +2777,9 @@ 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); @@ -2766,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 @@ -2795,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 diff --git a/storage/connect/xindex.h b/storage/connect/xindex.h index 4988a12326a..c702baeec83 100644 --- a/storage/connect/xindex.h +++ b/storage/connect/xindex.h @@ -192,6 +192,7 @@ class DllExport XXBASE : public CSORT, public BLOCK { void SetNth(int n) {Nth = n;} int *GetPof(void) {return Pof;} int *GetPex(void) {return Pex;} + bool IsSorted(void) {return Srtd;} void FreeIndex(void) {PlgDBfree(Index);} // Methods diff --git a/storage/connect/xtable.h b/storage/connect/xtable.h index 2d95acdb6d4..628ab96135d 100644 --- a/storage/connect/xtable.h +++ b/storage/connect/xtable.h @@ -147,6 +147,7 @@ class DllExport TDBASE : public TDB { inline PKXBASE GetKindex(void) {return To_Kindex;} inline PCOL GetSetCols(void) {return To_SetCols;} inline void SetSetCols(PCOL colp) {To_SetCols = colp;} + inline void SetKey_Col(PCOL *cpp) {To_Key_Col = cpp;} inline void SetXdp(PIXDEF xdp) {To_Xdp = xdp;} inline void SetKindex(PKXBASE kxp) {To_Kindex = kxp;} @@ -156,6 +157,7 @@ class DllExport TDBASE : public TDB { // Methods virtual bool IsUsingTemp(PGLOBAL g) {return false;} + virtual bool IsIndexed(void) {return false;} virtual PCATLG GetCat(void); virtual PSZ GetPath(void); virtual void PrintAM(FILE *f, char *m); @@ -190,6 +192,9 @@ class DllExport TDBASE : public TDB { {assert(false); return true;} protected: + virtual bool PrepareWriting(PGLOBAL g) {strcpy(g->Message, + "This function should not be called for this table"); return true;} + // Members PTABDEF To_Def; // Points to catalog description block PXOB *To_Link; // Points to column of previous relations |