summaryrefslogtreecommitdiff
path: root/storage/connect
diff options
context:
space:
mode:
Diffstat (limited to 'storage/connect')
-rw-r--r--storage/connect/array.cpp16
-rw-r--r--storage/connect/catalog.h10
-rw-r--r--storage/connect/checklvl.h7
-rw-r--r--storage/connect/connect.cc78
-rw-r--r--storage/connect/connect.h8
-rw-r--r--storage/connect/filamap.cpp100
-rw-r--r--storage/connect/filamap.h5
-rw-r--r--storage/connect/filamdbf.cpp44
-rw-r--r--storage/connect/filamdbf.h11
-rw-r--r--storage/connect/filamfix.cpp471
-rw-r--r--storage/connect/filamfix.h6
-rw-r--r--storage/connect/filamtxt.cpp397
-rw-r--r--storage/connect/filamtxt.h17
-rwxr-xr-xstorage/connect/filamvct.cpp278
-rw-r--r--storage/connect/filamvct.h4
-rw-r--r--storage/connect/ha_connect.cc147
-rw-r--r--storage/connect/ha_connect.h3
-rw-r--r--storage/connect/maputil.cpp14
-rw-r--r--storage/connect/mycat.cc8
-rw-r--r--storage/connect/mycat.h6
-rw-r--r--storage/connect/mysql-test/connect/r/part_file.result2
-rw-r--r--storage/connect/mysql-test/connect/r/part_table.result2
-rw-r--r--storage/connect/mysql-test/connect/r/temporary.result6
-rw-r--r--storage/connect/mysql-test/connect/r/updelx.result2570
-rw-r--r--storage/connect/mysql-test/connect/t/part_file.test4
-rw-r--r--storage/connect/mysql-test/connect/t/part_table.test7
-rw-r--r--storage/connect/mysql-test/connect/t/temporary.test13
-rw-r--r--storage/connect/mysql-test/connect/t/updelx.inc25
-rw-r--r--storage/connect/mysql-test/connect/t/updelx.test96
-rw-r--r--storage/connect/plgdbsem.h5
-rw-r--r--storage/connect/plgdbutl.cpp36
-rw-r--r--storage/connect/reldef.cpp12
-rw-r--r--storage/connect/reldef.h7
-rw-r--r--storage/connect/tabdos.cpp78
-rw-r--r--storage/connect/tabdos.h5
-rw-r--r--storage/connect/tabfix.cpp29
-rw-r--r--storage/connect/tabfix.h5
-rw-r--r--storage/connect/tabfmt.cpp70
-rw-r--r--storage/connect/tabfmt.h381
-rw-r--r--storage/connect/table.cpp7
-rwxr-xr-xstorage/connect/tabmul.cpp4
-rw-r--r--storage/connect/tabmysql.cpp5
-rw-r--r--storage/connect/tabodbc.cpp7
-rw-r--r--storage/connect/tabvct.cpp14
-rw-r--r--storage/connect/tabvct.h247
-rw-r--r--storage/connect/valblk.cpp4
-rw-r--r--storage/connect/value.h1
-rwxr-xr-xstorage/connect/xindex.cpp116
-rw-r--r--storage/connect/xindex.h1
-rw-r--r--storage/connect/xtable.h5
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