summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--sql/sql_partition.cc15
-rw-r--r--storage/connect/CMakeLists.txt26
-rw-r--r--storage/connect/colblk.cpp43
-rw-r--r--storage/connect/colblk.h32
-rw-r--r--storage/connect/connect.cc35
-rw-r--r--storage/connect/connect.h4
-rw-r--r--storage/connect/filamap.cpp2
-rw-r--r--storage/connect/filamap.h4
-rw-r--r--storage/connect/filamdbf.cpp22
-rw-r--r--storage/connect/filamdbf.h2
-rw-r--r--storage/connect/filamfix.cpp59
-rw-r--r--storage/connect/filamfix.h4
-rw-r--r--storage/connect/filamtxt.cpp80
-rw-r--r--storage/connect/filamtxt.h8
-rwxr-xr-xstorage/connect/filamvct.cpp113
-rw-r--r--storage/connect/filamvct.h31
-rw-r--r--storage/connect/filamzip.cpp10
-rw-r--r--storage/connect/filamzip.h6
-rw-r--r--storage/connect/ha_connect.cc329
-rw-r--r--storage/connect/ha_connect.h8
-rw-r--r--storage/connect/mycat.cc1
-rw-r--r--storage/connect/myconn.cpp37
-rw-r--r--storage/connect/myconn.h1
-rw-r--r--storage/connect/mysql-test/connect/r/part_file.result355
-rw-r--r--storage/connect/mysql-test/connect/r/part_table.result180
-rw-r--r--storage/connect/mysql-test/connect/t/part_file.test159
-rw-r--r--storage/connect/mysql-test/connect/t/part_table.test85
-rw-r--r--storage/connect/plgdbsem.h2
-rw-r--r--storage/connect/plgdbutl.cpp25
-rw-r--r--storage/connect/reldef.cpp11
-rw-r--r--storage/connect/reldef.h1
-rw-r--r--storage/connect/tabcol.h2
-rw-r--r--storage/connect/tabdos.cpp67
-rw-r--r--storage/connect/tabdos.h3
-rw-r--r--storage/connect/tabfix.cpp2
-rw-r--r--storage/connect/tabfmt.cpp7
-rw-r--r--storage/connect/table.cpp30
-rw-r--r--storage/connect/tabmysql.cpp81
-rw-r--r--storage/connect/tabmysql.h3
-rw-r--r--storage/connect/tabodbc.cpp88
-rw-r--r--storage/connect/tabodbc.h3
-rw-r--r--storage/connect/tabsys.cpp61
-rw-r--r--storage/connect/tabsys.h11
-rw-r--r--storage/connect/tabtbl.cpp4
-rw-r--r--storage/connect/tabutil.cpp29
-rw-r--r--storage/connect/tabvct.cpp2
-rw-r--r--storage/connect/tabxml.cpp2
-rwxr-xr-xstorage/connect/xindex.cpp22
-rw-r--r--storage/connect/xindex.h2
-rw-r--r--storage/connect/xtable.h2
50 files changed, 1703 insertions, 408 deletions
diff --git a/sql/sql_partition.cc b/sql/sql_partition.cc
index 1ce952b9030..95cd66c84d7 100644
--- a/sql/sql_partition.cc
+++ b/sql/sql_partition.cc
@@ -3195,13 +3195,26 @@ uint32 get_partition_id_cols_list_for_endpoint(partition_info *part_info,
(list_index - 1)*num_columns,
nparts, left_endpoint,
include_endpoint)));
-
+#if 0
if (!left_endpoint)
{
/* Set the end after this list tuple if not already after the last. */
if (list_index < part_info->num_parts)
list_index++;
}
+#else
+ if (!left_endpoint && list_index < part_info->num_list_values)
+ {
+ /*
+ Set the end after this list tuple if it is not already after the last
+ and it matches.
+ */
+ int cmp = cmp_rec_and_tuple_prune(list_col_array + list_index*num_columns,
+ nparts, left_endpoint, include_endpoint);
+ if (cmp >= 0)
+ list_index++;
+ }
+#endif
DBUG_RETURN(list_index);
}
diff --git a/storage/connect/CMakeLists.txt b/storage/connect/CMakeLists.txt
index f8db000a486..40d38fdc3b5 100644
--- a/storage/connect/CMakeLists.txt
+++ b/storage/connect/CMakeLists.txt
@@ -19,20 +19,20 @@ SET(CONNECT_PLUGIN_DYNAMIC "connect")
SET(CONNECT_SOURCES
ha_connect.cc connect.cc user_connect.cc mycat.cc
fmdlex.c osutil.c plugutil.c rcmsg.c rcmsg.h
-csort.cpp maputil.cpp plgdbutl.cpp
-colblk.cpp reldef.cpp tabcol.cpp table.cpp
-filamap.cpp filamdbf.cpp filamfix.cpp filamtxt.cpp filamvct.cpp
-tabdos.cpp tabfix.cpp tabfmt.cpp tabmul.cpp tabsys.cpp tabvct.cpp
+array.cpp blkfil.cpp colblk.cpp csort.cpp
+filamap.cpp filamdbf.cpp filamfix.cpp filamtxt.cpp filamvct.cpp filamzip.cpp
+filter.cpp maputil.cpp myutil.cpp plgdbutl.cpp reldef.cpp tabcol.cpp
+tabdos.cpp tabfix.cpp tabfmt.cpp table.cpp tabmul.cpp taboccur.cpp
+tabpivot.cpp tabsys.cpp tabtbl.cpp tabutil.cpp tabvct.cpp tabxcl.cpp
valblk.cpp value.cpp xindex.cpp xobject.cpp
-filamzip.cpp tabtbl.cpp myutil.cpp
-tabutil.cpp tabxcl.cpp taboccur.cpp tabpivot.cpp
-block.h catalog.h checklvl.h colblk.h connect.h csort.h engmsg.h
-filamap.h filamdbf.h filamfix.h filamtxt.h filamvct.h filamzip.h
-global.h ha_connect.h inihandl.h maputil.h msgid.h mycat.h myutil.h os.h
-osutil.h plgcnx.h plgdbsem.h preparse.h reldef.h resource.h tabcol.h
-tabdos.h tabfix.h tabfmt.h tabmul.h tabsys.h tabtbl.h tabvct.h
-user_connect.h valblk.h value.h xindex.h xobject.h xtable.h
-tabutil.h tabxcl.h taboccur.h tabpivot.h)
+
+array.h blkfil.h block.h catalog.h checklvl.h colblk.h connect.h csort.h
+engmsg.h filamap.h filamdbf.h filamfix.h filamtxt.h filamvct.h filamzip.h
+filter.h global.h ha_connect.h inihandl.h maputil.h msgid.h mycat.h myutil.h
+os.h osutil.h plgcnx.h plgdbsem.h preparse.h reldef.h resource.h tabcol.h
+tabdos.h tabfix.h tabfmt.h tabmul.h taboccur.h tabpivot.h tabsys.h
+tabtbl.h tabutil.h tabvct.h tabxcl.h user_connect.h valblk.h value.h
+xindex.h xobject.h xtable.h)
#
# Definitions that are shared for all OSes
diff --git a/storage/connect/colblk.cpp b/storage/connect/colblk.cpp
index a3fb5587ba9..81ab1ad7245 100644
--- a/storage/connect/colblk.cpp
+++ b/storage/connect/colblk.cpp
@@ -292,7 +292,7 @@ void RIDBLK::ReadColumn(PGLOBAL g)
/***********************************************************************/
/* FIDBLK constructor for the FILEID special column. */
/***********************************************************************/
-FIDBLK::FIDBLK(PCOLUMN cp) : SPCBLK(cp)
+FIDBLK::FIDBLK(PCOLUMN cp, OPVAL op) : SPCBLK(cp), Op(op)
{
//Is_Key = 2; for when the MUL table indexed reading will be implemented.
Precision = Long = _MAX_PATH;
@@ -319,7 +319,14 @@ void FIDBLK::ReadColumn(PGLOBAL g)
Fn = ((PTDBASE)To_Tdb)->GetFile(g);
PlugSetPath(filename, Fn, ((PTDBASE)To_Tdb)->GetPath());
- Value->SetValue_psz(filename);
+
+ if (Op != OP_XX) {
+ char buff[_MAX_PATH];
+
+ Value->SetValue_psz(ExtractFromPath(g, buff, filename, Op));
+ } else
+ Value->SetValue_psz(filename);
+
} // endif Fn
} // end of ReadColumn
@@ -352,6 +359,38 @@ void TIDBLK::ReadColumn(PGLOBAL g)
} // end of ReadColumn
/***********************************************************************/
+/* PRTBLK constructor for the PARTID special column. */
+/***********************************************************************/
+PRTBLK::PRTBLK(PCOLUMN cp) : SPCBLK(cp)
+ {
+//Is_Key = 2; for when the MUL table indexed reading will be implemented.
+ Precision = Long = 64;
+ Buf_Type = TYPE_STRING;
+ *Format.Type = 'C';
+ Format.Length = Long;
+ Format.Prec = 1; // Case insensitive
+ Constant = true; // TODO: check whether this is true indeed
+ Pname = NULL;
+ } // end of PRTBLK constructor
+
+/***********************************************************************/
+/* ReadColumn: what this routine does is to return the partition ID. */
+/***********************************************************************/
+void PRTBLK::ReadColumn(PGLOBAL g)
+ {
+ if (Pname == NULL) {
+ char *p;
+ PTDBASE tdbp = (PTDBASE)To_Tdb;
+
+ Pname = tdbp->GetDef()->GetStringCatInfo(g, "partname", "?");
+
+ p = strrchr(Pname, '#');
+ Value->SetValue_psz((p) ? p + 1 : Pname);
+ } // endif Pname
+
+ } // end of ReadColumn
+
+/***********************************************************************/
/* SIDBLK constructor for the SERVID special column. */
/***********************************************************************/
SIDBLK::SIDBLK(PCOLUMN cp) : SPCBLK(cp)
diff --git a/storage/connect/colblk.h b/storage/connect/colblk.h
index d004b96b5b3..5e8dc77ff69 100644
--- a/storage/connect/colblk.h
+++ b/storage/connect/colblk.h
@@ -107,7 +107,7 @@ class DllExport SPCBLK : public COLBLK {
// Implementation
virtual int GetAmType(void) = 0;
- virtual bool GetRnm(void) {return false;}
+ virtual bool GetRnm(void) {return false;}
// Methods
virtual bool IsSpecial(void) {return true;}
@@ -129,7 +129,7 @@ class DllExport RIDBLK : public SPCBLK {
// Implementation
virtual int GetAmType(void) {return TYPE_AM_ROWID;}
- virtual bool GetRnm(void) {return Rnm;}
+ virtual bool GetRnm(void) {return Rnm;}
// Methods
virtual void ReadColumn(PGLOBAL g);
@@ -144,7 +144,7 @@ class DllExport RIDBLK : public SPCBLK {
class DllExport FIDBLK : public SPCBLK {
public:
// Constructor
- FIDBLK(PCOLUMN cp);
+ FIDBLK(PCOLUMN cp, OPVAL op);
// Implementation
virtual int GetAmType(void) {return TYPE_AM_FILID;}
@@ -154,7 +154,8 @@ class DllExport FIDBLK : public SPCBLK {
virtual void ReadColumn(PGLOBAL g);
protected:
- PSZ Fn; // The current To_File of the table
+ PSZ Fn; // The current To_File of the table
+ OPVAL Op; // The file part operator
}; // end of class FIDBLK
/***********************************************************************/
@@ -181,6 +182,29 @@ class DllExport TIDBLK : public SPCBLK {
}; // end of class TIDBLK
/***********************************************************************/
+/* Class PRTBLK: PARTID special column descriptor. */
+/***********************************************************************/
+class DllExport PRTBLK : public SPCBLK {
+ public:
+ // Constructor
+ PRTBLK(PCOLUMN cp);
+
+ // Implementation
+ virtual int GetAmType(void) {return TYPE_AM_PRTID;}
+
+ // Methods
+ virtual void Reset(void) {} // This is a pseudo constant column
+ virtual void ReadColumn(PGLOBAL g);
+
+ protected:
+ // Default constructor not to be used
+ PRTBLK(void) {}
+
+ // Members
+ PSZ Pname; // The current partition name
+ }; // end of class PRTBLK
+
+/***********************************************************************/
/* Class SIDBLK: SERVID special column descriptor. */
/***********************************************************************/
class DllExport SIDBLK : public SPCBLK {
diff --git a/storage/connect/connect.cc b/storage/connect/connect.cc
index 70f05b242d5..e782fbbfff3 100644
--- a/storage/connect/connect.cc
+++ b/storage/connect/connect.cc
@@ -142,7 +142,7 @@ bool CntCheckDB(PGLOBAL g, PHC handler, const char *pathname)
return true;
((MYCAT *)dbuserp->Catalog)->SetDataPath(g, pathname);
- dbuserp->UseTemp= TMP_YES; // Must use temporary file
+ dbuserp->UseTemp= TMP_AUTO;
/*********************************************************************/
/* All is correct. */
@@ -167,7 +167,12 @@ bool CntInfo(PGLOBAL g, PTDB tp, PXF info)
if (tdbp) {
b= tdbp->GetFtype() != RECFM_NAF;
info->data_file_length= (b) ? (ulonglong)tdbp->GetFileLength(g) : 0;
- info->records= (unsigned)tdbp->GetMaxSize(g);
+
+ if (!b || info->data_file_length)
+ info->records= (unsigned)tdbp->GetMaxSize(g);
+ else
+ info->records= 0;
+
// info->mean_rec_length= tdbp->GetLrecl();
info->mean_rec_length= 0;
info->data_file_name= (b) ? tdbp->GetFile(g) : NULL;
@@ -343,12 +348,12 @@ bool CntOpenTable(PGLOBAL g, PTDB tdbp, MODE mode, char *c1, char *c2,
//tdbp->SetMode(mode);
- if (del && ((PTDBASE)tdbp)->GetFtype() != RECFM_NAF) {
+ if (del/* && ((PTDBASE)tdbp)->GetFtype() != RECFM_NAF*/) {
// To avoid erasing the table when doing a partial delete
// make a fake Next
- PDOSDEF ddp= new(g) DOSDEF;
- PTDB tp= new(g) TDBDOS(ddp, NULL);
- tdbp->SetNext(tp);
+// PDOSDEF ddp= new(g) DOSDEF;
+// PTDB tp= new(g) TDBDOS(ddp, NULL);
+ tdbp->SetNext((PTDB)1);
dup->Check &= ~CHK_DELETE;
} // endif del
@@ -544,16 +549,23 @@ RCODE CntDeleteRow(PGLOBAL g, PTDB tdbp, bool all)
/***********************************************************************/
/* CLOSETAB: Close a table. */
/***********************************************************************/
-int CntCloseTable(PGLOBAL g, PTDB tdbp)
+int CntCloseTable(PGLOBAL g, PTDB tdbp, bool nox, bool abort)
{
int rc= RC_OK;
TDBDOX *tbxp= NULL;
- if (!tdbp || tdbp->GetUse() != USE_OPEN)
+ if (!tdbp)
return rc; // Nothing to do
+ else if (tdbp->GetUse() != USE_OPEN) {
+ if (tdbp->GetAmType() == TYPE_AM_XML)
+ tdbp->CloseDB(g); // Opened by GetMaxSize
+
+ return rc;
+ } // endif !USE_OPEN
if (trace)
- printf("CntCloseTable: tdbp=%p mode=%d\n", tdbp, tdbp->GetMode());
+ 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
@@ -572,8 +584,9 @@ int CntCloseTable(PGLOBAL g, PTDB tdbp)
// This will close the table file(s) and also finalize write
// operations such as Insert, Update, or Delete.
+ tdbp->SetAbort(abort);
tdbp->CloseDB(g);
-
+ tdbp->SetAbort(false);
g->jump_level--;
if (trace > 1)
@@ -582,7 +595,7 @@ int CntCloseTable(PGLOBAL g, PTDB tdbp)
//if (!((PTDBDOX)tdbp)->GetModified())
// return 0;
- if (tdbp->GetMode() == MODE_READ || tdbp->GetMode() == MODE_ANY)
+ if (nox || tdbp->GetMode() == MODE_READ || tdbp->GetMode() == MODE_ANY)
return 0;
if (trace > 1)
diff --git a/storage/connect/connect.h b/storage/connect/connect.h
index 380da7c29b9..145991a3b74 100644
--- a/storage/connect/connect.h
+++ b/storage/connect/connect.h
@@ -33,7 +33,7 @@ bool CntCheckDB(PGLOBAL g, PHC handler, const char *pathname);
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);
+int CntCloseTable(PGLOBAL g, PTDB tdbp, bool nox, bool abort);
int CntIndexInit(PGLOBAL g, PTDB tdbp, int id);
RCODE CntReadNext(PGLOBAL g, PTDB tdbp);
RCODE CntIndexRead(PGLOBAL g, PTDB, OPVAL op, const void *k, int n, bool mrr);
@@ -58,7 +58,7 @@ class DOXDEF: public DOSDEF {
/***********************************************************************/
class TDBDOX: public TDBDOS {
friend int MakeIndex(PGLOBAL, PTDB, PIXDEF);
- friend int CntCloseTable(PGLOBAL, PTDB);
+ friend int CntCloseTable(PGLOBAL, PTDB, bool, bool);
friend int CntIndexInit(PGLOBAL, PTDB, int);
friend RCODE CntIndexRead(PGLOBAL, PTDB, OPVAL, const void*, int, bool);
friend RCODE CntDeleteRow(PGLOBAL, PTDB, bool);
diff --git a/storage/connect/filamap.cpp b/storage/connect/filamap.cpp
index 87cb2e83cfa..1e7a9ba0d12 100644
--- a/storage/connect/filamap.cpp
+++ b/storage/connect/filamap.cpp
@@ -476,7 +476,7 @@ int MAPFAM::DeleteRecords(PGLOBAL g, int irc)
/***********************************************************************/
/* Table file close routine for MAP access method. */
/***********************************************************************/
-void MAPFAM::CloseTableFile(PGLOBAL g)
+void MAPFAM::CloseTableFile(PGLOBAL g, bool abort)
{
PlugCloseFile(g, To_Fb);
To_Fb = NULL; // To get correct file size in Cardinality
diff --git a/storage/connect/filamap.h b/storage/connect/filamap.h
index adee5816e12..ccdbf6cb8bd 100644
--- a/storage/connect/filamap.h
+++ b/storage/connect/filamap.h
@@ -42,8 +42,8 @@ class DllExport MAPFAM : public TXTFAM {
virtual bool DeferReading(void) {return false;}
virtual int ReadBuffer(PGLOBAL g);
virtual int WriteBuffer(PGLOBAL g);
- virtual int DeleteRecords(PGLOBAL g, int irc);
- virtual void CloseTableFile(PGLOBAL g);
+ virtual int DeleteRecords(PGLOBAL g, int irc);
+ virtual void CloseTableFile(PGLOBAL g, bool abort);
virtual void Rewind(void);
protected:
diff --git a/storage/connect/filamdbf.cpp b/storage/connect/filamdbf.cpp
index 7ca98eeff55..e840800a117 100644
--- a/storage/connect/filamdbf.cpp
+++ b/storage/connect/filamdbf.cpp
@@ -791,7 +791,7 @@ void DBFFAM::Rewind(void)
/***********************************************************************/
/* Table file close routine for DBF access method. */
/***********************************************************************/
-void DBFFAM::CloseTableFile(PGLOBAL g)
+void DBFFAM::CloseTableFile(PGLOBAL g, bool abort)
{
int rc = RC_OK, wrc = RC_OK;
MODE mode = Tdbp->GetMode();
@@ -810,17 +810,17 @@ void DBFFAM::CloseTableFile(PGLOBAL g)
} // endif Modif
if (UseTemp && T_Stream && wrc == RC_OK) {
- // Copy any remaining lines
- bool b;
-
- Fpos = Tdbp->Cardinality(g);
-
- if ((rc = MoveIntermediateLines(g, &b)) == RC_OK) {
- // Delete the old file and rename the new temp file.
- RenameTempFile(g);
- goto fin;
- } // endif rc
+ if (!abort) {
+ // Copy any remaining lines
+ bool b;
+
+ Fpos = Tdbp->Cardinality(g);
+ abort = MoveIntermediateLines(g, &b) != RC_OK;
+ } // endif abort
+ // Delete the old file and rename the new temp file.
+ RenameTempFile(g, abort);
+ goto fin;
} // endif UseTemp
} // endif's mode
diff --git a/storage/connect/filamdbf.h b/storage/connect/filamdbf.h
index b85b9fc47fe..0345c0338e8 100644
--- a/storage/connect/filamdbf.h
+++ b/storage/connect/filamdbf.h
@@ -67,7 +67,7 @@ class DllExport DBFFAM : public FIXFAM, public DBFBASE {
virtual void ResetBuffer(PGLOBAL g);
virtual int ReadBuffer(PGLOBAL g);
virtual int DeleteRecords(PGLOBAL g, int irc);
- virtual void CloseTableFile(PGLOBAL g);
+ virtual void CloseTableFile(PGLOBAL g, bool abort);
virtual void Rewind(void);
protected:
diff --git a/storage/connect/filamfix.cpp b/storage/connect/filamfix.cpp
index df76ca82b18..e37dff3b90e 100644
--- a/storage/connect/filamfix.cpp
+++ b/storage/connect/filamfix.cpp
@@ -315,8 +315,7 @@ int FIXFAM::WriteBuffer(PGLOBAL g)
} else { // Mode == MODE_UPDATE
// T_Stream is the temporary stream or the table file stream itself
- if (!T_Stream)
- {
+ if (!T_Stream) {
if (UseTemp /*&& Tdbp->GetMode() == MODE_UPDATE*/) {
if (OpenTempFile(g))
return RC_FX;
@@ -326,7 +325,9 @@ int FIXFAM::WriteBuffer(PGLOBAL g)
} else
T_Stream = Stream;
- }
+
+ } // endif T_Stream
+
Modif++; // Modified line in Update mode
} // endif Mode
@@ -420,7 +421,7 @@ int FIXFAM::DeleteRecords(PGLOBAL g, int irc)
/*****************************************************************/
/* Ok, now delete old file and rename new temp file. */
/*****************************************************************/
- if (RenameTempFile(g))
+ if (RenameTempFile(g, false))
return RC_FX;
} else {
@@ -527,7 +528,7 @@ bool FIXFAM::MoveIntermediateLines(PGLOBAL g, bool *b)
/***********************************************************************/
/* Table file close routine for FIX access method. */
/***********************************************************************/
-void FIXFAM::CloseTableFile(PGLOBAL g)
+void FIXFAM::CloseTableFile(PGLOBAL g, bool abort)
{
int rc = RC_OK, wrc = RC_OK;
MODE mode = Tdbp->GetMode();
@@ -546,17 +547,17 @@ void FIXFAM::CloseTableFile(PGLOBAL g)
} // endif Modif
if (UseTemp && T_Stream && wrc == RC_OK) {
- // Copy any remaining lines
- bool b;
-
- Fpos = Tdbp->Cardinality(g);
-
- if ((rc = MoveIntermediateLines(g, &b)) == RC_OK) {
- // Delete the old file and rename the new temp file.
- RenameTempFile(g);
- goto fin;
- } // endif rc
-
+ if (!abort) {
+ // Copy any remaining lines
+ bool b;
+
+ Fpos = Tdbp->Cardinality(g);
+ abort = MoveIntermediateLines(g, &b) != RC_OK;
+ } // endif // abort
+
+ // Delete the old file and rename the new temp file.
+ RenameTempFile(g, abort);
+ goto fin;
} // endif UseTemp
} // endif's mode
@@ -1245,7 +1246,7 @@ int BGXFAM::DeleteRecords(PGLOBAL g, int irc)
/*****************************************************************/
/* Ok, now delete old file and rename new temp file. */
/*****************************************************************/
- if (RenameTempFile(g))
+ if (RenameTempFile(g, false))
return RC_FX;
} else {
@@ -1375,7 +1376,7 @@ bool BGXFAM::MoveIntermediateLines(PGLOBAL g, bool *b)
/***********************************************************************/
/* Data Base close routine for BIGFIX access method. */
/***********************************************************************/
-void BGXFAM::CloseTableFile(PGLOBAL g)
+void BGXFAM::CloseTableFile(PGLOBAL g, bool abort)
{
int rc = RC_OK, wrc = RC_OK;
MODE mode = Tdbp->GetMode();
@@ -1393,17 +1394,17 @@ void BGXFAM::CloseTableFile(PGLOBAL g)
} // endif Modif
if (UseTemp && Tfile && wrc == RC_OK) {
- // Copy any remaining lines
- bool b;
-
- Fpos = Tdbp->Cardinality(g);
-
- if ((rc = MoveIntermediateLines(g, &b)) == RC_OK) {
- // Delete the old file and rename the new temp file.
- RenameTempFile(g);
- goto fin;
- } // endif rc
-
+ if (!abort) {
+ // Copy any remaining lines
+ bool b;
+
+ Fpos = Tdbp->Cardinality(g);
+ abort = MoveIntermediateLines(g, &b) != RC_OK;
+ } // endif abort
+
+ // Delete the old file and rename the new temp file.
+ RenameTempFile(g, abort);
+ goto fin;
} // endif UseTemp
} // endif's mode
diff --git a/storage/connect/filamfix.h b/storage/connect/filamfix.h
index 80523fa05e8..22f84552320 100644
--- a/storage/connect/filamfix.h
+++ b/storage/connect/filamfix.h
@@ -38,7 +38,7 @@ class DllExport FIXFAM : public BLKFAM {
virtual int ReadBuffer(PGLOBAL g);
virtual int WriteBuffer(PGLOBAL g);
virtual int DeleteRecords(PGLOBAL g, int irc);
- virtual void CloseTableFile(PGLOBAL g);
+ virtual void CloseTableFile(PGLOBAL g, bool abort);
protected:
virtual bool CopyHeader(PGLOBAL g) {return false;}
@@ -69,7 +69,7 @@ class BGXFAM : public FIXFAM {
virtual int ReadBuffer(PGLOBAL g);
virtual int WriteBuffer(PGLOBAL g);
virtual int DeleteRecords(PGLOBAL g, int irc);
- virtual void CloseTableFile(PGLOBAL g);
+ virtual void CloseTableFile(PGLOBAL g, bool abort);
virtual void Rewind(void);
protected:
diff --git a/storage/connect/filamtxt.cpp b/storage/connect/filamtxt.cpp
index 60a9f944415..0812fa935fb 100644
--- a/storage/connect/filamtxt.cpp
+++ b/storage/connect/filamtxt.cpp
@@ -552,7 +552,7 @@ int DOSFAM::ReadBuffer(PGLOBAL g)
CurBlk = (int)Rows++;
- if (trace > 1)
+ if (trace > 1)
htrc("ReadBuffer: CurBlk=%d\n", CurBlk);
/********************************************************************/
@@ -922,13 +922,16 @@ bool DOSFAM::MoveIntermediateLines(PGLOBAL g, bool *b)
/***********************************************************************/
/* Delete the old file and rename the new temp file. */
+/* If aborting just delete the new temp file. */
/***********************************************************************/
-int DOSFAM::RenameTempFile(PGLOBAL g)
+int DOSFAM::RenameTempFile(PGLOBAL g, bool abort)
{
char *tempname, filetemp[_MAX_PATH], filename[_MAX_PATH];
- int rc;
+ int rc = RC_OK;
- if (!To_Fbt)
+ if (To_Fbt)
+ tempname = (char*)To_Fbt->Fname;
+ else
return RC_INFO; // Nothing to do ???
// This loop is necessary because, in case of join,
@@ -937,26 +940,28 @@ int DOSFAM::RenameTempFile(PGLOBAL g)
if (fb == To_Fb || fb == To_Fbt)
rc = PlugCloseFile(g, fb);
- tempname = (char*)To_Fbt->Fname;
- PlugSetPath(filename, To_File, Tdbp->GetPath());
- strcat(PlugRemoveType(filetemp, filename), ".ttt");
- remove(filetemp); // May still be there from previous error
+ if (!abort) {
+ PlugSetPath(filename, To_File, Tdbp->GetPath());
+ strcat(PlugRemoveType(filetemp, filename), ".ttt");
+ remove(filetemp); // May still be there from previous error
+
+ if (rename(filename, filetemp)) { // Save file for security
+ sprintf(g->Message, MSG(RENAME_ERROR),
+ filename, filetemp, strerror(errno));
+ rc = RC_FX;
+ } else if (rename(tempname, filename)) {
+ sprintf(g->Message, MSG(RENAME_ERROR),
+ tempname, filename, strerror(errno));
+ rc = rename(filetemp, filename); // Restore saved file
+ rc = RC_FX;
+ } else if (remove(filetemp)) {
+ sprintf(g->Message, MSG(REMOVE_ERROR),
+ filetemp, strerror(errno));
+ rc = RC_INFO; // Acceptable
+ } // endif's
- if (rename(filename, filetemp)) { // Save file for security
- sprintf(g->Message, MSG(RENAME_ERROR),
- filename, filetemp, strerror(errno));
- rc = RC_FX;
- } else if (rename(tempname, filename)) {
- sprintf(g->Message, MSG(RENAME_ERROR),
- tempname, filename, strerror(errno));
- rc = rename(filetemp, filename); // Restore saved file
- rc = RC_FX;
- } else if (remove(filetemp)) {
- sprintf(g->Message, MSG(REMOVE_ERROR),
- filetemp, strerror(errno));
- rc = RC_INFO; // Acceptable
} else
- rc = RC_OK;
+ remove(tempname);
return rc;
} // end of RenameTempFile
@@ -964,22 +969,22 @@ int DOSFAM::RenameTempFile(PGLOBAL g)
/***********************************************************************/
/* Table file close routine for DOS access method. */
/***********************************************************************/
-void DOSFAM::CloseTableFile(PGLOBAL g)
+void DOSFAM::CloseTableFile(PGLOBAL g, bool abort)
{
int rc;
if (UseTemp && T_Stream) {
- if (Tdbp->Mode == MODE_UPDATE) {
+ if (Tdbp->Mode == MODE_UPDATE && !abort) {
// Copy eventually remaining lines
bool b;
fseek(Stream, 0, SEEK_END);
Fpos = ftell(Stream);
- rc = MoveIntermediateLines(g, &b);
- } // endif Mode
+ abort = MoveIntermediateLines(g, &b) != RC_OK;
+ } // endif abort
// Delete the old file and rename the new temp file.
- RenameTempFile(g); // Also close all files
+ RenameTempFile(g, abort); // Also close all files
} else {
rc = PlugCloseFile(g, To_Fb);
@@ -1045,9 +1050,7 @@ void BLKFAM::Reset(void)
/***********************************************************************/
int BLKFAM::Cardinality(PGLOBAL g)
{
- // Should not be called in this version
- return (g) ? -1 : 0;
-//return (g) ? (int)((Block - 1) * Nrec + Last) : 1;
+ return (g) ? (int)((Block - 1) * Nrec + Last) : 1;
} // end of Cardinality
/***********************************************************************/
@@ -1382,27 +1385,22 @@ int BLKFAM::WriteBuffer(PGLOBAL g)
/***********************************************************************/
/* Table file close routine for DOS access method. */
/***********************************************************************/
-void BLKFAM::CloseTableFile(PGLOBAL g)
+void BLKFAM::CloseTableFile(PGLOBAL g, bool abort)
{
int rc, wrc = RC_OK;
if (UseTemp && T_Stream) {
- if (Tdbp->GetMode() == MODE_UPDATE) {
+ if (Tdbp->GetMode() == MODE_UPDATE && !abort) {
// Copy eventually remaining lines
bool b;
fseek(Stream, 0, SEEK_END);
Fpos = ftell(Stream);
- rc = MoveIntermediateLines(g, &b);
- } else
- rc = RC_OK;
-
- if (rc == RC_OK)
- // Delete the old file and rename the new temp file.
- rc = RenameTempFile(g); // Also close all files
- else
- rc = PlugCloseFile(g, To_Fb);
+ abort = MoveIntermediateLines(g, &b) != RC_OK;
+ } // endif abort
+ // Delete the old file and rename the new temp file.
+ rc = RenameTempFile(g, abort); // Also close all files
} else {
// Closing is True if last Write was in error
if (Tdbp->GetMode() == MODE_INSERT && CurNum && !Closing) {
diff --git a/storage/connect/filamtxt.h b/storage/connect/filamtxt.h
index 94d518044cc..abe8f2f2324 100644
--- a/storage/connect/filamtxt.h
+++ b/storage/connect/filamtxt.h
@@ -66,7 +66,7 @@ class DllExport TXTFAM : public BLOCK {
virtual int ReadBuffer(PGLOBAL g) = 0;
virtual int WriteBuffer(PGLOBAL g) = 0;
virtual int DeleteRecords(PGLOBAL g, int irc) = 0;
- virtual void CloseTableFile(PGLOBAL g) = 0;
+ virtual void CloseTableFile(PGLOBAL g, bool abort) = 0;
virtual void Rewind(void) = 0;
protected:
@@ -135,13 +135,13 @@ class DllExport DOSFAM : public TXTFAM {
virtual int ReadBuffer(PGLOBAL g);
virtual int WriteBuffer(PGLOBAL g);
virtual int DeleteRecords(PGLOBAL g, int irc);
- virtual void CloseTableFile(PGLOBAL g);
+ virtual void CloseTableFile(PGLOBAL g, bool abort);
virtual void Rewind(void);
protected:
virtual bool OpenTempFile(PGLOBAL g);
virtual bool MoveIntermediateLines(PGLOBAL g, bool *b);
- virtual int RenameTempFile(PGLOBAL g);
+ virtual int RenameTempFile(PGLOBAL g, bool abort);
// Members
FILE *Stream; // Points to Dos file structure
@@ -182,7 +182,7 @@ class DllExport BLKFAM : public DOSFAM {
virtual int SkipRecord(PGLOBAL g, bool header);
virtual int ReadBuffer(PGLOBAL g);
virtual int WriteBuffer(PGLOBAL g);
- virtual void CloseTableFile(PGLOBAL g);
+ virtual void CloseTableFile(PGLOBAL g, bool abort);
virtual void Rewind(void);
protected:
diff --git a/storage/connect/filamvct.cpp b/storage/connect/filamvct.cpp
index b07ae8a2213..076222e9e7f 100755
--- a/storage/connect/filamvct.cpp
+++ b/storage/connect/filamvct.cpp
@@ -137,6 +137,39 @@ VCTFAM::VCTFAM(PVCTFAM txfp) : FIXFAM(txfp)
} // end of VCTFAM copy constructor
/***********************************************************************/
+/* VCT GetFileLength: returns file size in number of bytes. */
+/* This function is here to be accessible by VECFAM and VMPFAM. */
+/***********************************************************************/
+int VCTFAM::GetFileLength(PGLOBAL g)
+ {
+ if (Split) {
+ // Get the total file length
+ char filename[_MAX_PATH];
+ char *savfile = To_File;
+ int i, len = 0;
+
+ // Initialize the array of file structures
+ if (!Colfn) {
+ // Prepare the column file name pattern and set Ncol
+ Colfn = (char*)PlugSubAlloc(g, NULL, _MAX_PATH);
+ Ncol = ((PVCTDEF)Tdbp->GetDef())->MakeFnPattern(Colfn);
+ } // endif Colfn
+
+ To_File = filename;
+
+ for (i = 0; i < Ncol; i++) {
+ sprintf(filename, Colfn, i+1);
+ len += TXTFAM::GetFileLength(g);
+ } // endfor i
+
+ To_File = savfile;
+ return len;
+ } else
+ return TXTFAM::GetFileLength(g);
+
+ } // end of GetFileLength
+
+/***********************************************************************/
/* Reset read/write position values. */
/***********************************************************************/
void VCTFAM::Reset(void)
@@ -295,7 +328,7 @@ int VCTFAM::Cardinality(PGLOBAL g)
clen = cdp->GetClen();
sprintf(filename, Colfn, 1);
To_File = filename;
- len = GetFileLength(g);
+ len = TXTFAM::GetFileLength(g);
To_File = savfn;
if (len >= 0) {
@@ -1042,7 +1075,7 @@ bool VCTFAM::CleanUnusedSpace(PGLOBAL g)
/***********************************************************************/
/* Data Base close routine for VCT access method. */
/***********************************************************************/
-void VCTFAM::CloseTableFile(PGLOBAL g)
+void VCTFAM::CloseTableFile(PGLOBAL g, bool abort)
{
int rc = 0, wrc = RC_OK;
MODE mode = Tdbp->GetMode();
@@ -1078,7 +1111,7 @@ void VCTFAM::CloseTableFile(PGLOBAL g)
colp->WriteBlock(g);
if (UseTemp && T_Stream) {
- rc = RenameTempFile(g);
+ rc = RenameTempFile(g, abort);
if (Header) {
// Header must be set because it was not set in temp file
@@ -1092,7 +1125,7 @@ void VCTFAM::CloseTableFile(PGLOBAL g)
if (MaxBlk)
rc = CleanUnusedSpace(g);
- if ((rc = RenameTempFile(g)) != RC_FX) {
+ if ((rc = RenameTempFile(g, abort)) != RC_FX) {
Stream = T_Stream = NULL; // For SetBlockInfo
rc = ResetTableSize(g, Block, Last);
} // endif rc
@@ -1715,7 +1748,7 @@ int VCMFAM::DeleteRecords(PGLOBAL g, int irc)
/***********************************************************************/
/* Data Base close routine for VMP access method. */
/***********************************************************************/
-void VCMFAM::CloseTableFile(PGLOBAL g)
+void VCMFAM::CloseTableFile(PGLOBAL g, bool abort)
{
int wrc = RC_OK;
MODE mode = Tdbp->GetMode();
@@ -2252,7 +2285,7 @@ int VECFAM::DeleteRecords(PGLOBAL g, int irc)
} else // UseTemp
// Ok, now delete old files and rename new temp files
- if (RenameTempFile(g) == RC_FX)
+ if (RenameTempFile(g, false) == RC_FX)
return RC_FX;
// Reset these values for TDBVCT::MakeBlockValues
@@ -2382,7 +2415,7 @@ bool VECFAM::MoveIntermediateLines(PGLOBAL g, bool *bn)
/***********************************************************************/
/* Delete the old files and rename the new temporary files. */
/***********************************************************************/
-int VECFAM::RenameTempFile(PGLOBAL g)
+int VECFAM::RenameTempFile(PGLOBAL g, bool abort)
{
char *tempname, filetemp[_MAX_PATH], filename[_MAX_PATH];
int rc = RC_OK;
@@ -2398,25 +2431,30 @@ int VECFAM::RenameTempFile(PGLOBAL g)
continue;
tempname = (char*)T_Fbs[i]->Fname;
- sprintf(filename, Colfn, i+1);
- PlugSetPath(filename, filename, Tdbp->GetPath());
- strcat(PlugRemoveType(filetemp, filename), ".ttt");
- remove(filetemp); // May still be there from previous error
-
- if (rename(filename, filetemp)) { // Save file for security
- sprintf(g->Message, MSG(RENAME_ERROR),
- filename, filetemp, strerror(errno));
- rc = RC_FX;
- } else if (rename(tempname, filename)) {
- sprintf(g->Message, MSG(RENAME_ERROR),
- tempname, filename, strerror(errno));
- rc = rename(filetemp, filename); // Restore saved file
- rc = RC_FX;
- } else if (remove(filetemp)) {
- sprintf(g->Message, MSG(REMOVE_ERROR),
- filetemp, strerror(errno));
- rc = RC_INFO; // Acceptable
- } // endif's
+
+ if (!abort) {
+ sprintf(filename, Colfn, i+1);
+ PlugSetPath(filename, filename, Tdbp->GetPath());
+ strcat(PlugRemoveType(filetemp, filename), ".ttt");
+ remove(filetemp); // May still be there from previous error
+
+ if (rename(filename, filetemp)) { // Save file for security
+ sprintf(g->Message, MSG(RENAME_ERROR),
+ filename, filetemp, strerror(errno));
+ rc = RC_FX;
+ } else if (rename(tempname, filename)) {
+ sprintf(g->Message, MSG(RENAME_ERROR),
+ tempname, filename, strerror(errno));
+ rc = rename(filetemp, filename); // Restore saved file
+ rc = RC_FX;
+ } else if (remove(filetemp)) {
+ sprintf(g->Message, MSG(REMOVE_ERROR),
+ filetemp, strerror(errno));
+ rc = RC_INFO; // Acceptable
+ } // endif's
+
+ } else
+ remove(tempname);
} // endfor i
@@ -2426,7 +2464,7 @@ int VECFAM::RenameTempFile(PGLOBAL g)
/***********************************************************************/
/* Data Base close routine for VEC access method. */
/***********************************************************************/
-void VECFAM::CloseTableFile(PGLOBAL g)
+void VECFAM::CloseTableFile(PGLOBAL g, bool abort)
{
int rc = 0, wrc = RC_OK;
MODE mode = Tdbp->GetMode();
@@ -2453,10 +2491,10 @@ void VECFAM::CloseTableFile(PGLOBAL g)
longjmp(g->jumper[g->jump_level], 44);
} else if (mode == MODE_UPDATE) {
- if (UseTemp && !InitUpdate) {
+ if (UseTemp && !InitUpdate && !abort) {
// Write any intermediate lines to temp file
Fpos = OldBlk * Nrec;
- wrc = MoveIntermediateLines(g);
+ abort = MoveIntermediateLines(g) != RC_OK;
// Spos = Fpos + Nrec;
} // endif UseTemp
@@ -2466,20 +2504,17 @@ void VECFAM::CloseTableFile(PGLOBAL g)
colp; colp = (PVCTCOL)colp->Next)
colp->WriteBlock(g);
- if (wrc == RC_OK && UseTemp && !InitUpdate) {
+ if (wrc == RC_OK && UseTemp && !InitUpdate && !abort) {
// Write any intermediate lines to temp file
Fpos = (Block - 1) * Nrec + Last;
- wrc = MoveIntermediateLines(g);
+ abort = MoveIntermediateLines(g) != RC_OK;
} // endif UseTemp
} // endif's mode
if (UseTemp && !InitUpdate) {
// If they are errors, leave files unchanged
- if (wrc == RC_OK)
- rc = RenameTempFile(g);
- else
- longjmp(g->jumper[g->jump_level], 44);
+ rc = RenameTempFile(g, abort);
} else if (Streams)
for (int i = 0; i < Ncol; i++)
@@ -2950,7 +2985,7 @@ int VMPFAM::DeleteRecords(PGLOBAL g, int irc)
/***********************************************************************/
/* Data Base close routine for VMP access method. */
/***********************************************************************/
-void VMPFAM::CloseTableFile(PGLOBAL g)
+void VMPFAM::CloseTableFile(PGLOBAL g, bool abort)
{
if (Tdbp->GetMode() == MODE_DELETE) {
// Set Block and Nrec values for TDBVCT::MakeBlockValues
@@ -4072,7 +4107,7 @@ bool BGVFAM::CleanUnusedSpace(PGLOBAL g)
/***********************************************************************/
/* Data Base close routine for huge VEC access method. */
/***********************************************************************/
-void BGVFAM::CloseTableFile(PGLOBAL g)
+void BGVFAM::CloseTableFile(PGLOBAL g, bool abort)
{
int rc = 0, wrc = RC_OK;
MODE mode = Tdbp->GetMode();
@@ -4108,7 +4143,7 @@ void BGVFAM::CloseTableFile(PGLOBAL g)
colp->WriteBlock(g);
if (UseTemp && Tfile) {
- rc = RenameTempFile(g);
+ rc = RenameTempFile(g, abort);
Hfile = Tfile = INVALID_HANDLE_VALUE;
if (Header)
@@ -4121,7 +4156,7 @@ void BGVFAM::CloseTableFile(PGLOBAL g)
if (MaxBlk)
rc = CleanUnusedSpace(g);
- if ((rc = RenameTempFile(g)) != RC_FX) {
+ if ((rc = RenameTempFile(g, abort)) != RC_FX) {
Hfile = Tfile = INVALID_HANDLE_VALUE; // For SetBlockInfo
rc = ResetTableSize(g, Block, Last);
} // endif rc
diff --git a/storage/connect/filamvct.h b/storage/connect/filamvct.h
index f528f00372b..2e599ccc749 100644
--- a/storage/connect/filamvct.h
+++ b/storage/connect/filamvct.h
@@ -37,6 +37,7 @@ class DllExport VCTFAM : public FIXFAM {
virtual AMT GetAmType(void) {return TYPE_AM_VCT;}
virtual PTXF Duplicate(PGLOBAL g)
{return (PTXF)new(g) VCTFAM(this);}
+ virtual int GetFileLength(PGLOBAL g);
// Methods
virtual void Reset(void);
@@ -51,8 +52,8 @@ class DllExport VCTFAM : public FIXFAM {
virtual bool OpenTableFile(PGLOBAL g);
virtual int ReadBuffer(PGLOBAL g);
virtual int WriteBuffer(PGLOBAL g);
- virtual int DeleteRecords(PGLOBAL g, int irc);
- virtual void CloseTableFile(PGLOBAL g);
+ virtual int DeleteRecords(PGLOBAL g, int irc);
+ virtual void CloseTableFile(PGLOBAL g, bool abort);
virtual void Rewind(void);
// Specific functions
@@ -60,19 +61,19 @@ class DllExport VCTFAM : public FIXFAM {
virtual bool WriteBlock(PGLOBAL g, PVCTCOL colp);
protected:
- virtual bool MakeEmptyFile(PGLOBAL g, char *fn);
+ virtual bool MakeEmptyFile(PGLOBAL g, char *fn);
virtual bool OpenTempFile(PGLOBAL g);
virtual bool MoveLines(PGLOBAL g) {return false;}
virtual bool MoveIntermediateLines(PGLOBAL g, bool *b = NULL);
virtual bool CleanUnusedSpace(PGLOBAL g);
- virtual int GetBlockInfo(PGLOBAL g);
- virtual bool SetBlockInfo(PGLOBAL g);
+ virtual int GetBlockInfo(PGLOBAL g);
+ virtual bool SetBlockInfo(PGLOBAL g);
bool ResetTableSize(PGLOBAL g, int block, int last);
// Members
char *NewBlock; // To block written on Insert
- char *Colfn; // Pattern for column file names (VER)
- char *Tempat; // Pattern for temp file names (VER)
+ char *Colfn; // Pattern for column file names (VEC)
+ char *Tempat; // Pattern for temp file names (VEC)
int *Clens; // Pointer to col size array
int *Deplac; // Pointer to col start position array
bool *Isnum; // Pointer to buffer type isnum result
@@ -108,8 +109,8 @@ class DllExport VCMFAM : public VCTFAM {
// Database routines
virtual bool OpenTableFile(PGLOBAL g);
virtual int WriteBuffer(PGLOBAL g);
- virtual int DeleteRecords(PGLOBAL g, int irc);
- virtual void CloseTableFile(PGLOBAL g);
+ virtual int DeleteRecords(PGLOBAL g, int irc);
+ virtual void CloseTableFile(PGLOBAL g, bool abort);
// Specific functions
virtual bool ReadBlock(PGLOBAL g, PVCTCOL colp);
@@ -145,18 +146,18 @@ class DllExport VECFAM : public VCTFAM {
// Database routines
virtual bool OpenTableFile(PGLOBAL g);
virtual int WriteBuffer(PGLOBAL g);
- virtual int DeleteRecords(PGLOBAL g, int irc);
- virtual void CloseTableFile(PGLOBAL g);
+ virtual int DeleteRecords(PGLOBAL g, int irc);
+ virtual void CloseTableFile(PGLOBAL g, bool abort);
// Specific functions
virtual bool ReadBlock(PGLOBAL g, PVCTCOL colp);
virtual bool WriteBlock(PGLOBAL g, PVCTCOL colp);
protected:
- virtual bool OpenTempFile(PGLOBAL g);
+ virtual bool OpenTempFile(PGLOBAL g);
virtual bool MoveLines(PGLOBAL g);
virtual bool MoveIntermediateLines(PGLOBAL g, bool *b = NULL);
- virtual int RenameTempFile(PGLOBAL g);
+ virtual int RenameTempFile(PGLOBAL g, bool abort);
bool OpenColumnFile(PGLOBAL g, char *opmode, int i);
// Members
@@ -190,7 +191,7 @@ class DllExport VMPFAM : public VCMFAM {
// Database routines
virtual bool OpenTableFile(PGLOBAL g);
virtual int DeleteRecords(PGLOBAL g, int irc);
- virtual void CloseTableFile(PGLOBAL g);
+ virtual void CloseTableFile(PGLOBAL g, bool abort);
protected:
bool MapColumnFile(PGLOBAL g, MODE mode, int i);
@@ -221,7 +222,7 @@ class BGVFAM : public VCTFAM {
virtual bool OpenTableFile(PGLOBAL g);
virtual int WriteBuffer(PGLOBAL g);
virtual int DeleteRecords(PGLOBAL g, int irc);
- virtual void CloseTableFile(PGLOBAL g);
+ virtual void CloseTableFile(PGLOBAL g, bool abort);
virtual void Rewind(void);
// Specific functions
diff --git a/storage/connect/filamzip.cpp b/storage/connect/filamzip.cpp
index 22ddffe26a1..8e4bce2bf3e 100644
--- a/storage/connect/filamzip.cpp
+++ b/storage/connect/filamzip.cpp
@@ -386,7 +386,7 @@ int ZIPFAM::DeleteRecords(PGLOBAL g, int irc)
/***********************************************************************/
/* Data Base close routine for DOS access method. */
/***********************************************************************/
-void ZIPFAM::CloseTableFile(PGLOBAL g)
+void ZIPFAM::CloseTableFile(PGLOBAL g, bool abort)
{
int rc = gzclose(Zfile);
@@ -456,9 +456,7 @@ int ZBKFAM::MaxBlkSize(PGLOBAL g, int s)
/***********************************************************************/
int ZBKFAM::Cardinality(PGLOBAL g)
{
- // Should not be called in this version
- return (g) ? -1 : 0;
-//return (g) ? (int)((Block - 1) * Nrec + Last) : 1;
+ return (g) ? (int)((Block - 1) * Nrec + Last) : 1;
} // end of Cardinality
/***********************************************************************/
@@ -671,7 +669,7 @@ int ZBKFAM::DeleteRecords(PGLOBAL g, int irc)
/***********************************************************************/
/* Data Base close routine for ZBK access method. */
/***********************************************************************/
-void ZBKFAM::CloseTableFile(PGLOBAL g)
+void ZBKFAM::CloseTableFile(PGLOBAL g, bool abort)
{
int rc = RC_OK;
@@ -1328,7 +1326,7 @@ bool ZLBFAM::WriteCompressedBuffer(PGLOBAL g)
/***********************************************************************/
/* Table file close routine for DOS access method. */
/***********************************************************************/
-void ZLBFAM::CloseTableFile(PGLOBAL g)
+void ZLBFAM::CloseTableFile(PGLOBAL g, bool abort)
{
int rc = RC_OK;
diff --git a/storage/connect/filamzip.h b/storage/connect/filamzip.h
index 8111bc1ad97..d0b03f8cd9a 100644
--- a/storage/connect/filamzip.h
+++ b/storage/connect/filamzip.h
@@ -48,7 +48,7 @@ class DllExport ZIPFAM : public TXTFAM {
virtual int ReadBuffer(PGLOBAL g);
virtual int WriteBuffer(PGLOBAL g);
virtual int DeleteRecords(PGLOBAL g, int irc);
- virtual void CloseTableFile(PGLOBAL g);
+ virtual void CloseTableFile(PGLOBAL g, bool abort);
virtual void Rewind(void);
protected:
@@ -86,7 +86,7 @@ class DllExport ZBKFAM : public ZIPFAM {
virtual int ReadBuffer(PGLOBAL g);
virtual int WriteBuffer(PGLOBAL g);
virtual int DeleteRecords(PGLOBAL g, int irc);
- virtual void CloseTableFile(PGLOBAL g);
+ virtual void CloseTableFile(PGLOBAL g, bool abort);
virtual void Rewind(void);
protected:
@@ -152,7 +152,7 @@ class DllExport ZLBFAM : public BLKFAM {
virtual bool AllocateBuffer(PGLOBAL g);
virtual int ReadBuffer(PGLOBAL g);
virtual int WriteBuffer(PGLOBAL g);
- virtual void CloseTableFile(PGLOBAL g);
+ virtual void CloseTableFile(PGLOBAL g, bool abort);
virtual void Rewind(void);
protected:
diff --git a/storage/connect/ha_connect.cc b/storage/connect/ha_connect.cc
index e7aeddf38fb..f0261dda7ff 100644
--- a/storage/connect/ha_connect.cc
+++ b/storage/connect/ha_connect.cc
@@ -108,7 +108,6 @@
#define MYSQL_SERVER 1
#define DONT_DEFINE_VOID
-//#include "sql_partition.h"
#include "sql_class.h"
#include "create_options.h"
#include "mysql_com.h"
@@ -316,11 +315,12 @@ ha_create_table_option connect_field_option_list[]=
{
HA_FOPTION_NUMBER("FLAG", offset, (ulonglong) -1, 0, INT_MAX32, 1),
HA_FOPTION_NUMBER("MAX_DIST", freq, 0, 0, INT_MAX32, 1), // BLK_INDX
- HA_FOPTION_NUMBER("DISTRIB", opt, 0, 0, 2, 1), // used for BLK_INDX
+//HA_FOPTION_NUMBER("DISTRIB", opt, 0, 0, 2, 1), // used for BLK_INDX
HA_FOPTION_NUMBER("FIELD_LENGTH", fldlen, 0, 0, INT_MAX32, 1),
HA_FOPTION_STRING("DATE_FORMAT", dateformat),
HA_FOPTION_STRING("FIELD_FORMAT", fieldformat),
HA_FOPTION_STRING("SPECIAL", special),
+ HA_FOPTION_ENUM("DISTRIB", opt, "scattered,clustered,sorted", 0),
HA_FOPTION_END
};
@@ -332,7 +332,6 @@ ha_create_table_option connect_field_option_list[]=
*/
ha_create_table_option connect_index_option_list[]=
{
- HA_IOPTION_BOOL("DYNAMIC", dynamic, 0),
HA_IOPTION_BOOL("DYNAM", dynamic, 0),
HA_IOPTION_BOOL("MAPPED", mapped, 0),
HA_IOPTION_END
@@ -553,8 +552,12 @@ ha_connect::ha_connect(handlerton *hton, TABLE_SHARE *table_arg)
stop= false;
alter= false;
mrr= false;
+ nox= false;
+ abort= false;
indexing= -1;
+ only= -1;
locked= 0;
+ part_id= NULL;
data_file_name= NULL;
index_file_name= NULL;
enable_activate_all_index= 0;
@@ -819,7 +822,17 @@ char *ha_connect::GetStringOption(char *opname, char *sdef)
char *opval= NULL;
PTOS options= GetTableOptionStruct();
- if (!options)
+ if (!stricmp(opname, "Connect")) {
+ LEX_STRING cnc= (tshp) ? tshp->connect_string : table->s->connect_string;
+
+ if (cnc.length)
+ opval= cnc.str;
+
+ } else if (!stricmp(opname, "Query_String"))
+ opval= thd_query_string(table->in_use)->str;
+ else if (!stricmp(opname, "Partname"))
+ opval= partname;
+ else if (!options)
;
else if (!stricmp(opname, "Type"))
opval= (char*)options->type;
@@ -836,8 +849,6 @@ char *ha_connect::GetStringOption(char *opname, char *sdef)
opval= (char*)options->dbname;
else if (!stricmp(opname, "Separator"))
opval= (char*)options->separator;
- else if (!stricmp(opname, "Connect"))
- opval= (tshp) ? tshp->connect_string.str : table->s->connect_string.str;
else if (!stricmp(opname, "Qchar"))
opval= (char*)options->qchar;
else if (!stricmp(opname, "Module"))
@@ -852,8 +863,6 @@ char *ha_connect::GetStringOption(char *opname, char *sdef)
opval= (char*)options->colist;
else if (!stricmp(opname, "Data_charset"))
opval= (char*)options->data_charset;
- else if (!stricmp(opname, "Query_String"))
- opval= thd_query_string(table->in_use)->str;
if (!opval && options && options->oplist)
opval= GetListOption(xp->g, opname, options->oplist);
@@ -1199,6 +1208,17 @@ bool ha_connect::GetIndexOption(KEY *kp, char *opname)
/****************************************************************************/
/* Returns the index description structure used to make the index. */
/****************************************************************************/
+bool ha_connect::IsUnique(uint n)
+{
+ TABLE_SHARE *s= (table) ? table->s : NULL;
+ KEY kp= s->key_info[n];
+
+ return (kp.flags & 1) != 0;
+} // end of IsUnique
+
+/****************************************************************************/
+/* Returns the index description structure used to make the index. */
+/****************************************************************************/
PIXDEF ha_connect::GetIndexInfo(TABLE_SHARE *s)
{
char *name, *pn;
@@ -1280,6 +1300,7 @@ bool ha_connect::IsPartitioned(void)
return true;
else
return false;
+
} // end of IsPartitioned
const char *ha_connect::GetDBName(const char* name)
@@ -1365,7 +1386,7 @@ PTDB ha_connect::GetTDB(PGLOBAL g)
tp->SetMode(xmod);
} else if ((tp= CntGetTDB(g, table_name, xmod, this))) {
valid_query_id= xp->last_query_id;
- tp->SetMode(xmod);
+// tp->SetMode(xmod);
} else
htrc("GetTDB: %s\n", g->Message);
@@ -1444,6 +1465,17 @@ int ha_connect::OpenTable(PGLOBAL g, bool del)
for (field= table->field; fp= *field; field++)
if (bitmap_is_set(ump, fp->field_index)) {
strcpy(p, (char*)fp->field_name);
+
+ if (part_id && bitmap_is_set(part_id, fp->field_index)) {
+ // Trying to update a column used for partitioning
+ // This cannot be currently done because it may require
+ // a row to be moved in another partition.
+ sprintf(g->Message,
+ "Cannot update column %s because it is used for partitioning",
+ p);
+ return HA_ERR_INTERNAL_ERROR;
+ } // endif part_id
+
p+= (strlen(p) + 1);
} // endif used field
@@ -1476,6 +1508,50 @@ int ha_connect::OpenTable(PGLOBAL g, bool del)
/****************************************************************************/
+/* CheckColumnList: check that all bitmap columns do exist. */
+/****************************************************************************/
+bool ha_connect::CheckColumnList(PGLOBAL g)
+{
+ // Check the list of used fields (columns)
+ int rc;
+ bool brc= false;
+ PCOL colp;
+ Field* *field;
+ Field* fp;
+ MY_BITMAP *map= table->read_set;
+
+ // Save stack and allocation environment and prepare error return
+ if (g->jump_level == MAX_JUMP) {
+ strcpy(g->Message, MSG(TOO_MANY_JUMPS));
+ return true;
+ } // endif jump_level
+
+ if ((rc= setjmp(g->jumper[++g->jump_level])) == 0) {
+ for (field= table->field; fp= *field; field++)
+ if (bitmap_is_set(map, fp->field_index)) {
+ if (!(colp= tdbp->ColDB(g, (PSZ)fp->field_name, 0))) {
+ sprintf(g->Message, "Column %s not found in %s",
+ fp->field_name, tdbp->GetName());
+ brc= true;
+ goto fin;
+ } // endif colp
+
+ if ((brc= colp->InitValue(g)))
+ goto fin;
+
+ colp->AddColUse(U_P); // For PLG tables
+ } // endif
+
+ } else
+ brc= true;
+
+ fin:
+ g->jump_level--;
+ return brc;
+} // end of CheckColumnList
+
+
+/****************************************************************************/
/* IsOpened: returns true if the table is already opened. */
/****************************************************************************/
bool ha_connect::IsOpened(void)
@@ -1490,12 +1566,15 @@ bool ha_connect::IsOpened(void)
/****************************************************************************/
int ha_connect::CloseTable(PGLOBAL g)
{
- int rc= CntCloseTable(g, tdbp);
+ int rc= CntCloseTable(g, tdbp, nox, abort);
tdbp= NULL;
sdvalin=NULL;
sdvalout=NULL;
valid_info= false;
indexing= -1;
+ nox= false;
+ abort= false;
+ only= -1;
return rc;
} // end of CloseTable
@@ -1623,6 +1702,11 @@ int ha_connect::MakeRecord(char *buf)
} // endfor field
+ // This is sometimes required for partition tables because the buf
+ // can be different from the table->record[0] buffer
+ if (buf != (char*)table->record[0])
+ memcpy(buf, table->record[0], table->s->stored_rec_length);
+
// This is copied from ha_tina and is necessary to avoid asserts
dbug_tmp_restore_column_map(table->write_set, org_bitmap);
DBUG_RETURN(rc);
@@ -1773,7 +1857,11 @@ bool ha_connect::MakeKeyWhere(PGLOBAL g, char *qry, OPVAL op, char *q,
KEY_PART_INFO *kpart;
if (active_index == MAX_KEY)
- return 0;
+ return false;
+ else if (!key) {
+ strcpy(g->Message, "MakeKeyWhere: No key");
+ return true;
+ } // endif key
strcat(qry, " WHERE (");
kfp= &table->key_info[active_index];
@@ -2448,6 +2536,21 @@ bool ha_connect::get_error_message(int error, String* buf)
DBUG_RETURN(false);
} // end of get_error_message
+/**
+ Convert a filename partition name to system
+*/
+static char *decode(PGLOBAL g, const char *pn)
+ {
+ char *buf= (char*)PlugSubAlloc(g, NULL, strlen(pn) + 1);
+ uint dummy_errors;
+ uint32 len= copy_and_convert(buf, strlen(pn) + 1,
+ system_charset_info,
+ pn, strlen(pn),
+ &my_charset_filename,
+ &dummy_errors);
+ buf[len]= '\0';
+ return buf;
+ } // end of decode
/**
@brief
@@ -2499,11 +2602,14 @@ int ha_connect::open(const char *name, int mode, uint test_if_locked)
#if defined(WITH_PARTITION_STORAGE_ENGINE)
if (table->part_info) {
- if (GetStringOption("Filename") || GetStringOption("Tabname"))
- strcpy(partname, strrchr(name, '#') + 1);
- else // Inward table
+ if (GetStringOption("Filename") || GetStringOption("Tabname")
+ || GetStringOption("Connect")) {
+ strcpy(partname, decode(g, strrchr(name, '#') + 1));
+// strcpy(partname, table->part_info->curr_part_elem->partition_name);
+ part_id= &table->part_info->full_part_field_set;
+ } else // Inward table
strcpy(partname, strrchr(name, slash) + 1);
-
+ part_id= &table->part_info->full_part_field_set; // Temporary
} // endif part_info
#endif // WITH_PARTITION_STORAGE_ENGINE
} else
@@ -2610,8 +2716,13 @@ int ha_connect::write_row(uchar *buf)
DBUG_ENTER("ha_connect::write_row");
// This is not tested yet
- if (xmod == MODE_ALTER)
+ if (xmod == MODE_ALTER) {
+ if (IsPartitioned() && GetStringOption("Filename", NULL))
+ // Why does this happen now that check_if_supported_inplace_alter is called?
+ DBUG_RETURN(0); // Alter table on an outward partition table
+
xmod= MODE_INSERT;
+ } // endif xmod
// Open the table if it was not opened yet (locked)
if (!IsOpened() || xmod != tdbp->GetMode()) {
@@ -2684,7 +2795,7 @@ int ha_connect::update_row(const uchar *old_data, uchar *new_data)
// Check values for possible change in indexed column
if ((rc= CheckRecord(g, old_data, new_data)))
- return rc;
+ DBUG_RETURN(rc);
if (CntUpdateRow(g, tdbp)) {
DBUG_PRINT("update_row", ("%s", g->Message));
@@ -2742,12 +2853,19 @@ int ha_connect::index_init(uint idx, bool sorted)
htrc("index_init: this=%p idx=%u sorted=%d\n", this, idx, sorted);
if (GetIndexType(GetRealType()) == 2) {
- // This is a remote index
- xmod= MODE_READX;
+ if (xmod == MODE_READ)
+ // This is a remote index
+ xmod= MODE_READX;
if (!(rc= rnd_init(0))) {
- active_index= idx;
- indexing= 2; // TO DO: mul?
+ if (xmod == MODE_READX) {
+ active_index= idx;
+ indexing= IsUnique(idx) ? 1 : 2;
+ } else {
+ active_index= MAX_KEY;
+ indexing= 0;
+ } // endif xmod
+
} //endif rc
DBUG_RETURN(rc);
@@ -2756,11 +2874,17 @@ int ha_connect::index_init(uint idx, bool sorted)
if ((rc= rnd_init(0)))
DBUG_RETURN(rc);
- if (locked == 2) {
+ if ((xmod == MODE_UPDATE && ((TDBASE*)tdbp)->IsUsingTemp(g)) ||
+ xmod == MODE_DELETE || locked == 2) {
// Indexes are not updated in lock write mode
- active_index= MAX_KEY;
- indexing= 0;
- DBUG_RETURN(0);
+ // and cannot be used for DELETE or UPDATE using temp file.
+ if (locked == 2 || xmod == MODE_DELETE || !IsUnique(idx)) {
+ active_index= MAX_KEY;
+ indexing= 0;
+ DBUG_RETURN(0);
+ } else
+ only= 1; // Indexing acceptable for only one value
+
} // endif locked
indexing= CntIndexInit(g, tdbp, (signed)idx);
@@ -2874,10 +2998,16 @@ int ha_connect::index_read(uchar * buf, const uchar * key, uint key_len,
if (xtrace > 1)
htrc("%p index_read: op=%d\n", this, op);
- if (indexing > 0)
+ if ((indexing > 0 && (only < 0 || (only == 1 && op == OP_EQ)))
+ || GetIndexType(GetRealType()) == 2) {
rc= ReadIndexed(buf, op, key, key_len);
- else
- rc= HA_ERR_INTERNAL_ERROR;
+ only= (only == 1) ? 0 : -1;
+ } else {
+ nox= true; // To block making indexes
+ abort= true; // Don't rename temp file
+ strcpy(xp->g->Message, "Cannot use indexing for this command");
+ rc= HA_ERR_INTERNAL_ERROR; // HA_ERR_KEY_NOT_FOUND ?
+ } // endelse
DBUG_RETURN(rc);
} // end of index_read
@@ -3032,6 +3162,10 @@ int ha_connect::rnd_init(bool scan)
// Do not close the table if it was opened yet (locked?)
if (IsOpened()) {
+ if (IsPartitioned() && xmod != MODE_INSERT)
+ if (CheckColumnList(g)) // map can have been changed
+ DBUG_RETURN(HA_ERR_INTERNAL_ERROR);
+
if (tdbp->OpenDB(g)) // Rewind table
DBUG_RETURN(HA_ERR_INTERNAL_ERROR);
else
@@ -3260,27 +3394,30 @@ int ha_connect::info(uint flag)
if (xtrace)
htrc("%p In info: flag=%u valid_info=%d\n", this, flag, valid_info);
- if (!valid_info) {
- // tdbp must be available to get updated info
- if (xp->CheckQuery(valid_query_id) || !tdbp) {
- PDBUSER dup= PlgGetUser(g);
- PCATLG cat= (dup) ? dup->Catalog : NULL;
-
- if (xmod == MODE_ANY || xmod == MODE_ALTER) {
- // Pure info, not a query
- pure= true;
- xp->CheckCleanup();
- } // endif xmod
-
- // This is necessary for getting file length
- if (cat && table)
- cat->SetDataPath(g, table->s->db.str);
- else
- DBUG_RETURN(HA_ERR_INTERNAL_ERROR); // Should never happen
+ // tdbp must be available to get updated info
+ if (xp->CheckQuery(valid_query_id) || !tdbp) {
+ PDBUSER dup= PlgGetUser(g);
+ PCATLG cat= (dup) ? dup->Catalog : NULL;
- tdbp= GetTDB(g);
- } // endif tdbp
+ if (xmod == MODE_ANY || xmod == MODE_ALTER) {
+ // Pure info, not a query
+ pure= true;
+ xp->CheckCleanup();
+ } // endif xmod
+ // This is necessary for getting file length
+ if (cat && table)
+ cat->SetDataPath(g, table->s->db.str);
+ else
+ DBUG_RETURN(HA_ERR_INTERNAL_ERROR); // Should never happen
+
+ if (!(tdbp= GetTDB(g)))
+ DBUG_RETURN(HA_ERR_INTERNAL_ERROR); // Should never happen
+
+ valid_info = false;
+ } // endif tdbp
+
+ if (!valid_info) {
valid_info= CntInfo(g, tdbp, &xinfo);
if (((signed)xinfo.records) < 0)
@@ -3532,11 +3669,6 @@ MODE ha_connect::CheckMode(PGLOBAL g, THD *thd,
case SQLCOM_RENAME_TABLE:
newmode= MODE_ANY;
break;
- case SQLCOM_DROP_INDEX:
- case SQLCOM_CREATE_INDEX:
- newmode= MODE_ANY;
-// stop= true;
- break;
case SQLCOM_CREATE_VIEW:
case SQLCOM_DROP_VIEW:
newmode= MODE_ANY;
@@ -3544,6 +3676,13 @@ MODE ha_connect::CheckMode(PGLOBAL g, THD *thd,
case SQLCOM_ALTER_TABLE:
newmode= MODE_ALTER;
break;
+ case SQLCOM_DROP_INDEX:
+ case SQLCOM_CREATE_INDEX:
+// if (!IsPartitioned()) {
+ newmode= MODE_ANY;
+ break;
+// } // endif partitioned
+
default:
htrc("Unsupported sql_command=%d\n", thd_sql_command(thd));
strcpy(g->Message, "CONNECT Unsupported command");
@@ -3573,10 +3712,6 @@ MODE ha_connect::CheckMode(PGLOBAL g, THD *thd,
case SQLCOM_LOCK_TABLES:
locked= 1;
break;
- case SQLCOM_DROP_INDEX:
- case SQLCOM_CREATE_INDEX:
- *chk= true;
-// stop= true;
case SQLCOM_DROP_TABLE:
case SQLCOM_RENAME_TABLE:
newmode= MODE_ANY;
@@ -3589,6 +3724,14 @@ MODE ha_connect::CheckMode(PGLOBAL g, THD *thd,
*chk= true;
newmode= MODE_ALTER;
break;
+ case SQLCOM_DROP_INDEX:
+ case SQLCOM_CREATE_INDEX:
+// if (!IsPartitioned()) {
+ *chk= true;
+ newmode= MODE_ANY;
+ break;
+// } // endif partitioned
+
default:
htrc("Unsupported sql_command=%d\n", thd_sql_command(thd));
strcpy(g->Message, "CONNECT Unsupported command");
@@ -3809,6 +3952,7 @@ int ha_connect::external_lock(THD *thd, int lock_type)
} // endif Close
locked= 0;
+ xmod= MODE_ANY; // For info commands
DBUG_RETURN(rc);
} // endif MODE_ANY
@@ -4128,7 +4272,7 @@ ha_rows ha_connect::records_in_range(uint inx, key_range *min_key,
if (xtrace)
htrc("records_in_range: inx=%d indexing=%d\n", inx, indexing);
- if (indexing > 0) {
+ if (indexing > 0 && only < 0) {
int nval;
uint len[2];
const uchar *key[2];
@@ -4149,10 +4293,11 @@ ha_rows ha_connect::records_in_range(uint inx, key_range *min_key,
else
rows= (ha_rows)nval;
- } else if (indexing < 0)
- rows= HA_POS_ERROR;
- else
+ } else if (indexing == 0) {
rows= 100000000; // Don't use missing index
+ only= -1;
+ } else
+ rows= HA_POS_ERROR;
DBUG_RETURN(rows);
} // end of records_in_range
@@ -4160,7 +4305,7 @@ ha_rows ha_connect::records_in_range(uint inx, key_range *min_key,
/**
Convert an ISO-8859-1 column name to UTF-8
*/
-static char *encode(PGLOBAL g, char *cnm)
+static char *encode(PGLOBAL g, const char *cnm)
{
char *buf= (char*)PlugSubAlloc(g, NULL, strlen(cnm) * 3);
uint dummy_errors;
@@ -4171,7 +4316,7 @@ static char *encode(PGLOBAL g, char *cnm)
&dummy_errors);
buf[len]= '\0';
return buf;
- } // end of Encode
+ } // end of encode
/**
Store field definition for create.
@@ -4547,7 +4692,7 @@ static void add_option(THD* thd, HA_CREATE_INFO *create_info,
} // end of add_option
// Used to check whether a MYSQL table is created on itself
-static bool CheckSelf(PGLOBAL g, TABLE_SHARE *s, const char *host,
+bool CheckSelf(PGLOBAL g, TABLE_SHARE *s, const char *host,
const char *db, char *tab, const char *src, int port)
{
if (src)
@@ -5129,7 +5274,7 @@ int ha_connect::create(const char *name, TABLE *table_arg,
HA_CREATE_INFO *create_info)
{
int rc= RC_OK;
- bool dbf;
+ bool dbf, inward;
Field* *field;
Field *fp;
TABTYPE type;
@@ -5144,7 +5289,6 @@ int ha_connect::create(const char *name, TABLE *table_arg,
DBUG_ENTER("ha_connect::create");
int sqlcom= thd_sql_command(table_arg->in_use);
PTOS options= GetTableOptionStruct(table_arg->s);
- bool inward= !options->filename;
table= table_arg; // Used by called functions
@@ -5175,6 +5319,8 @@ int ha_connect::create(const char *name, TABLE *table_arg,
if (check_privileges(thd, options, GetDBfromName(name)))
DBUG_RETURN(HA_ERR_INTERNAL_ERROR);
+ inward= IsFileType(type) && !options->filename;
+
if (options->data_charset) {
const CHARSET_INFO *data_charset;
@@ -5226,6 +5372,9 @@ int ha_connect::create(const char *name, TABLE *table_arg,
} // endif tabname
case TAB_MYSQL:
+#if defined(WITH_PARTITION_STORAGE_ENGINE)
+ if (!part_info)
+#endif // WITH_PARTITION_STORAGE_ENGINE
{const char *src= options->srcdef;
char *host, *db, *tab= (char*)options->tabname;
int port;
@@ -5419,8 +5568,7 @@ int ha_connect::create(const char *name, TABLE *table_arg,
} // endfor field
- if ((sqlcom == SQLCOM_CREATE_TABLE || *GetTableName() == '#')
- && IsFileType(type) && inward) {
+ if ((sqlcom == SQLCOM_CREATE_TABLE || *GetTableName() == '#') && inward) {
// The file name is not specified, create a default file in
// the database directory named table_name.table_type.
// (temporarily not done for XML because a void file causes
@@ -5504,19 +5652,32 @@ int ha_connect::create(const char *name, TABLE *table_arg,
// We should be in CREATE TABLE, ALTER_TABLE or CREATE INDEX
if (!(sqlcom == SQLCOM_CREATE_TABLE || sqlcom == SQLCOM_ALTER_TABLE ||
- (sqlcom == SQLCOM_CREATE_INDEX && part_info) ||
- (sqlcom == SQLCOM_DROP_INDEX && part_info)))
+ sqlcom == SQLCOM_CREATE_INDEX || sqlcom == SQLCOM_DROP_INDEX))
+// (sqlcom == SQLCOM_CREATE_INDEX && part_info) ||
+// (sqlcom == SQLCOM_DROP_INDEX && part_info)))
push_warning(thd, Sql_condition::WARN_LEVEL_WARN, 0,
"Unexpected command in create, please contact CONNECT team");
- if (sqlcom == SQLCOM_ALTER_TABLE && g->Alchecked == 0 &&
+#if defined(WITH_PARTITION_STORAGE_ENGINE)
+ if (part_info && !inward)
+ strcpy(partname, decode(g, strrchr(name, '#') + 1));
+// strcpy(partname, part_info->curr_part_elem->partition_name);
+#endif // WITH_PARTITION_STORAGE_ENGINE
+
+ if (g->Alchecked == 0 &&
(!IsFileType(type) || FileExists(options->filename))) {
- // This is an ALTER to CONNECT from another engine.
- // It cannot be accepted because the table data would be lost
- // except when the target file does not exist.
- strcpy(g->Message, "Operation denied. Table data would be lost.");
- my_message(ER_UNKNOWN_ERROR, g->Message, MYF(0));
- DBUG_RETURN(HA_ERR_INTERNAL_ERROR);
+ if (part_info) {
+ sprintf(g->Message, "Data repartition in %s is unchecked", partname);
+ push_warning(thd, Sql_condition::WARN_LEVEL_WARN, 0, g->Message);
+ } else if (sqlcom == SQLCOM_ALTER_TABLE) {
+ // This is an ALTER to CONNECT from another engine.
+ // It cannot be accepted because the table data would be modified
+ // except when the target file does not exist.
+ strcpy(g->Message, "Operation denied. Table data would be modified.");
+ my_message(ER_UNKNOWN_ERROR, g->Message, MYF(0));
+ DBUG_RETURN(HA_ERR_INTERNAL_ERROR);
+ } // endif part_info
+
} // endif outward
// Get the index definitions
@@ -5581,7 +5742,8 @@ bool ha_connect::FileExists(const char *fn)
return false;
if (table) {
- char *s, filename[_MAX_PATH], path[128];
+ char *s, tfn[_MAX_PATH], filename[_MAX_PATH], path[128];
+ bool b= false;
int n;
struct stat info;
@@ -5594,9 +5756,18 @@ bool ha_connect::FileExists(const char *fn)
#else // !WIN32
s= "/";
#endif // !WIN32
+ if (IsPartitioned()) {
+ sprintf(tfn, fn, GetPartName());
+
+ // This is to avoid an initialization error raised by the
+ // test on check_table_flags made in ha_partition::open
+ // that can fail if some partition files are empty.
+ b= true;
+ } else
+ strcpy(tfn, fn);
strcat(strcat(strcat(strcpy(path, "."), s), table->s->db.str), s);
- PlugSetPath(filename, fn, path);
+ PlugSetPath(filename, tfn, path);
n= stat(filename, &info);
if (n < 0) {
@@ -5610,7 +5781,7 @@ bool ha_connect::FileExists(const char *fn)
return false;
} else
- return (info.st_size) ? true : false;
+ return (info.st_size || b) ? true : false;
} // endif table
diff --git a/storage/connect/ha_connect.h b/storage/connect/ha_connect.h
index 33e52165289..e5b58a7a6b8 100644
--- a/storage/connect/ha_connect.h
+++ b/storage/connect/ha_connect.h
@@ -124,8 +124,8 @@ struct ha_field_option_struct
{
ulonglong offset;
ulonglong freq;
- ulonglong opt;
ulonglong fldlen;
+ uint opt;
const char *dateformat;
const char *fieldformat;
char *special;
@@ -208,9 +208,11 @@ public:
TABLE *GetTable(void) {return table;}
bool IsSameIndex(PIXDEF xp1, PIXDEF xp2);
bool IsPartitioned(void);
+ bool IsUnique(uint n);
PTDB GetTDB(PGLOBAL g);
int OpenTable(PGLOBAL g, bool del= false);
+ bool CheckColumnList(PGLOBAL g);
bool IsOpened(void);
int CloseTable(PGLOBAL g);
int MakeRecord(char *buf);
@@ -529,8 +531,12 @@ protected:
bool stop; // Used when creating index
bool alter; // True when converting to other engine
bool mrr; // True when getting index positions
+ bool nox; // True when index should not be made
+ bool abort; // True after error in UPDATE/DELETE
int indexing; // Type of indexing for CONNECT
+ int only; // If only one action is accepted
int locked; // Table lock
+ MY_BITMAP *part_id; // Columns used for partition func
THR_LOCK_DATA lock_data;
public:
diff --git a/storage/connect/mycat.cc b/storage/connect/mycat.cc
index 10b12c0809b..ca09e877b1a 100644
--- a/storage/connect/mycat.cc
+++ b/storage/connect/mycat.cc
@@ -571,6 +571,7 @@ PTDB MYCAT::GetTable(PGLOBAL g, PTABLE tablep, MODE mode, LPCSTR type)
tdbp->GetAmType());
tablep->SetTo_Tdb(tdbp);
tdbp->SetTable(tablep);
+ tdbp->SetMode(mode);
} // endif tdbp
return (tdbp);
diff --git a/storage/connect/myconn.cpp b/storage/connect/myconn.cpp
index 0964e0c0bbb..0c4b50f1d0b 100644
--- a/storage/connect/myconn.cpp
+++ b/storage/connect/myconn.cpp
@@ -686,19 +686,48 @@ int MYSQLC::ExecSQL(PGLOBAL g, const char *query, int *w)
rc = RC_NF;
} // endif field count
-if (w)
-//*w = mysql_warning_count(m_DB);
- *w = m_DB->warning_count;
+ if (w)
+// *w = mysql_warning_count(m_DB);
+ *w = m_DB->warning_count;
return rc;
} // end of ExecSQL
/***********************************************************************/
+/* Get table size by executing "select count(*) from table_name". */
+/***********************************************************************/
+int MYSQLC::GetTableSize(PGLOBAL g, PSZ query)
+ {
+ if (mysql_real_query(m_DB, query, strlen(query))) {
+#if defined(_DEBUG)
+ char *msg = (char*)PlugSubAlloc(g, NULL, 512 + strlen(query));
+
+ sprintf(msg, "(%d) %s [%s]", mysql_errno(m_DB),
+ mysql_error(m_DB), query);
+ strncpy(g->Message, msg, sizeof(g->Message) - 1);
+ g->Message[sizeof(g->Message) - 1] = 0;
+#endif // _DEBUG
+ return -2;
+ } // endif mysql_real_query
+
+ if (!(m_Res = mysql_store_result(m_DB)))
+ return -3;
+
+ // Get the resulting count value
+ m_Rows = (int)mysql_num_rows(m_Res); // Should be 1
+
+ if (m_Rows && (m_Row = mysql_fetch_row(m_Res)))
+ return atoi(*m_Row);
+
+ return -4;
+ } // end of GetTableSize
+
+/***********************************************************************/
/* Move to a specific row and column */
/***********************************************************************/
void MYSQLC::DataSeek(my_ulonglong row)
{
- MYSQL_ROWS *tmp=0;
+ MYSQL_ROWS *tmp = 0;
//DBUG_PRINT("info",("mysql_data_seek(%ld)",(long) row));
if (m_Res->data)
diff --git a/storage/connect/myconn.h b/storage/connect/myconn.h
index 7e892eece34..65e6531aee4 100644
--- a/storage/connect/myconn.h
+++ b/storage/connect/myconn.h
@@ -64,6 +64,7 @@ class DllItem MYSQLC {
// Methods
int GetResultSize(PGLOBAL g, PSZ sql);
+ int GetTableSize(PGLOBAL g, PSZ query);
int Open(PGLOBAL g, const char *host, const char *db,
const char *user= "root", const char *pwd= "*",
int pt= 0);
diff --git a/storage/connect/mysql-test/connect/r/part_file.result b/storage/connect/mysql-test/connect/r/part_file.result
new file mode 100644
index 00000000000..b342059bff0
--- /dev/null
+++ b/storage/connect/mysql-test/connect/r/part_file.result
@@ -0,0 +1,355 @@
+# This will be used to see what data files are created
+CREATE TABLE dr1 (
+FNAME VARCHAR(256) NOT NULL FLAG=2,
+FTYPE CHAR(8) NOT NULL FLAG=3
+# ,FSIZE INT(6) NOT NULL FLAG=5 removed because Unix size != Windows size
+) engine=CONNECT table_type=DIR file_name='t1#P#*.*';
+#
+# Testing partitioning on inward table
+#
+CREATE TABLE t1 (
+id INT NOT NULL,
+msg VARCHAR(32)
+) ENGINE=CONNECT TABLE_TYPE=CSV
+PARTITION BY RANGE(id) (
+PARTITION first VALUES LESS THAN(10),
+PARTITION middle VALUES LESS THAN(50),
+PARTITION last VALUES LESS THAN(MAXVALUE));
+INSERT INTO t1 VALUES(4, 'four'),(24, 'twenty four');
+INSERT INTO t1 VALUES(7,'seven'),(10,'ten'),(40,'forty'),(60,'sixty'),(81,'eighty one');
+SELECT partition_name, table_rows FROM information_schema.partitions WHERE table_name = 't1';
+partition_name table_rows
+first 2
+middle 3
+last 2
+SELECT * FROM t1;
+id msg
+4 four
+7 seven
+24 twenty four
+10 ten
+40 forty
+60 sixty
+81 eighty one
+EXPLAIN PARTITIONS SELECT * FROM t1 WHERE id > 50;
+id select_type table partitions type possible_keys key key_len ref rows Extra
+1 SIMPLE t1 last ALL NULL NULL NULL NULL 13 Using where
+SELECT * FROM t1 WHERE id > 50;
+id msg
+60 sixty
+81 eighty one
+SHOW TABLE STATUS LIKE 't1';
+Name Engine Version Row_format Rows Avg_row_length Data_length Max_data_length Index_length Data_free Auto_increment Create_time Update_time Check_time Collation Checksum Create_options Comment
+t1 CONNECT 10 Dynamic 7 10 76 0 0 0 NULL NULL NULL NULL latin1_swedish_ci NULL partitioned `TABLE_TYPE`=CSV
+UPDATE t1 set id = 41 WHERE msg = 'four';
+ERROR HY000: Got error 174 'Cannot update column id because it is used for partitioning' from CONNECT
+UPDATE t1 set msg = 'quatre' WHERE id = 4;
+SELECT * FROM dr1;
+FNAME FTYPE
+t1#P#first .csv
+t1#P#last .csv
+t1#P#middle .csv
+#
+# Altering partitioning on inward table
+#
+ALTER TABLE t1
+PARTITION by range(id) (
+PARTITION first VALUES LESS THAN(11),
+PARTITION middle VALUES LESS THAN(50),
+PARTITION last VALUES LESS THAN(MAXVALUE));
+SELECT partition_name, table_rows FROM information_schema.partitions WHERE table_name = 't1';
+partition_name table_rows
+first 3
+middle 2
+last 2
+SELECT * FROM dr1;
+FNAME FTYPE
+t1#P#first .csv
+t1#P#last .csv
+t1#P#middle .csv
+EXPLAIN PARTITIONS SELECT * FROM t1 WHERE id=10;
+id select_type table partitions type possible_keys key key_len ref rows Extra
+1 SIMPLE t1 first ALL NULL NULL NULL NULL 14 Using where
+SELECT * FROM t1 WHERE id=10;
+id msg
+10 ten
+DELETE FROM t1 WHERE id in (4,60);
+SELECT * FROM t1;
+id msg
+7 seven
+10 ten
+24 twenty four
+40 forty
+81 eighty one
+DROP TABLE t1;
+SELECT * FROM dr1;
+FNAME FTYPE
+#
+# Testing partitioning on a void outward table
+#
+ALTER TABLE dr1 file_name='part*.*';
+Warnings:
+Warning 1105 This is an outward table, table data were not modified.
+CREATE TABLE t1 (
+rwid INT(6) DEFAULT 0 SPECIAL=ROWID,
+rnum INT(6) DEFAULT 0 SPECIAL=ROWNUM,
+prtn VARCHAR(64) DEFAULT '' SPECIAL=PARTID,
+tbn VARCHAR(64) DEFAULT '' SPECIAL=TABID,
+fid VARCHAR(256) DEFAULT '' SPECIAL=FNAME,
+id INT KEY NOT NULL,
+msg VARCHAR(32)
+) ENGINE=CONNECT TABLE_TYPE=FIX FILE_NAME='part%s.txt';
+ALTER TABLE t1
+PARTITION by range columns(id) (
+PARTITION `1` VALUES LESS THAN(10),
+PARTITION `2` VALUES LESS THAN(50),
+PARTITION `3` VALUES LESS THAN(MAXVALUE));
+Warnings:
+Warning 1105 Open(rb) error 2 on DATADIR/test/part%s.txt: No such file or directory
+SHOW INDEX FROM t1;
+Table Non_unique Key_name Seq_in_index Column_name Collation Cardinality Sub_part Packed Null Index_type Comment Index_comment
+t1 0 PRIMARY 1 id A NULL NULL NULL XINDEX
+SELECT * FROM dr1;
+FNAME FTYPE
+INSERT INTO t1(id,msg) VALUES(4, 'four');
+SELECT * FROM dr1;
+FNAME FTYPE
+part1 .fnx
+part1 .txt
+INSERT INTO t1(id,msg) VALUES(7,'seven'),(10,'ten'),(40,'forty'),(60,'sixty'),(81,'eighty one');
+INSERT INTO t1(id,msg) VALUES(72,'seventy two'),(20,'twenty'),(1,'one'),(35,'thirty five'),(8,'eight');
+SELECT partition_name, table_rows FROM information_schema.partitions WHERE table_name = 't1';
+partition_name table_rows
+1 4
+2 4
+3 3
+SELECT * FROM t1;
+rwid rnum prtn tbn fid id msg
+1 1 1 t1 part1 4 four
+2 2 1 t1 part1 7 seven
+3 3 1 t1 part1 1 one
+4 4 1 t1 part1 8 eight
+1 1 2 t1 part2 10 ten
+2 2 2 t1 part2 40 forty
+3 3 2 t1 part2 20 twenty
+4 4 2 t1 part2 35 thirty five
+1 1 3 t1 part3 60 sixty
+2 2 3 t1 part3 81 eighty one
+3 3 3 t1 part3 72 seventy two
+SELECT * FROM t1 order by id;
+rwid rnum prtn tbn fid id msg
+3 3 1 t1 part1 1 one
+1 1 1 t1 part1 4 four
+2 2 1 t1 part1 7 seven
+4 4 1 t1 part1 8 eight
+1 1 2 t1 part2 10 ten
+3 3 2 t1 part2 20 twenty
+4 4 2 t1 part2 35 thirty five
+2 2 2 t1 part2 40 forty
+1 1 3 t1 part3 60 sixty
+3 3 3 t1 part3 72 seventy two
+2 2 3 t1 part3 81 eighty one
+EXPLAIN PARTITIONS SELECT * FROM t1 WHERE id = 10;
+id select_type table partitions type possible_keys key key_len ref rows Extra
+1 SIMPLE t1 2 const PRIMARY PRIMARY 4 const 1
+SELECT * FROM t1 WHERE id = 10;
+rwid rnum prtn tbn fid id msg
+1 1 2 t1 part2 10 ten
+EXPLAIN PARTITIONS SELECT * FROM t1 WHERE id >= 10;
+id select_type table partitions type possible_keys key key_len ref rows Extra
+1 SIMPLE t1 2,3 range PRIMARY PRIMARY 4 NULL 7 Using where
+SELECT * FROM t1 WHERE id >= 10;
+rwid rnum prtn tbn fid id msg
+1 1 2 t1 part2 10 ten
+3 3 2 t1 part2 20 twenty
+4 4 2 t1 part2 35 thirty five
+2 2 2 t1 part2 40 forty
+1 1 3 t1 part3 60 sixty
+3 3 3 t1 part3 72 seventy two
+2 2 3 t1 part3 81 eighty one
+SELECT count(*) FROM t1 WHERE id < 10;
+count(*)
+4
+SELECT case when id < 10 then 1 when id < 50 then 2 else 3 end as pn, count(*) FROM t1 group by pn;
+pn count(*)
+1 4
+2 4
+3 3
+SELECT prtn, count(*) FROM t1 group by prtn;
+prtn count(*)
+1 4
+2 4
+3 3
+EXPLAIN PARTITIONS SELECT * FROM t1 WHERE id > 50;
+id select_type table partitions type possible_keys key key_len ref rows Extra
+1 SIMPLE t1 3 range PRIMARY PRIMARY 4 NULL 3 Using where
+SELECT * FROM t1 WHERE id = 35;
+rwid rnum prtn tbn fid id msg
+4 4 2 t1 part2 35 thirty five
+SELECT * FROM dr1;
+FNAME FTYPE
+part1 .fnx
+part1 .txt
+part2 .fnx
+part2 .txt
+part3 .fnx
+part3 .txt
+# This does not change the partition file data and is WRONG
+ALTER TABLE t1
+PARTITION by range columns(id) (
+PARTITION `1` VALUES LESS THAN(11),
+PARTITION `2` VALUES LESS THAN(70),
+PARTITION `3` VALUES LESS THAN(MAXVALUE));
+Warnings:
+Warning 1105 Data repartition in 1 is unchecked
+Warning 1105 Data repartition in 2 is unchecked
+Warning 1105 Data repartition in 3 is unchecked
+SELECT CASE WHEN id < 11 THEN 1 WHEN id < 70 THEN 2 ELSE 3 END AS pn, COUNT(*) FROM t1 GROUP BY pn;
+pn COUNT(*)
+1 5
+2 4
+3 2
+SELECT partition_name, table_rows FROM information_schema.partitions WHERE table_name = 't1';
+partition_name table_rows
+1 4
+2 4
+3 3
+SELECT * FROM dr1;
+FNAME FTYPE
+part1 .fnx
+part1 .txt
+part2 .fnx
+part2 .txt
+part3 .fnx
+part3 .txt
+#
+# This is the correct way to change partitioning:
+# Save table values, erase the table, then re-insert saved values in modified table
+#
+CREATE TABLE t2 (
+id INT NOT NULL,
+msg VARCHAR(32)
+) ENGINE=CONNECT TABLE_TYPE=FIX;
+Warnings:
+Warning 1105 No file name. Table will use t2.fix
+INSERT INTO t2 SELECT id, msg FROM t1;
+DELETE FROM t1;
+INSERT INTO t1(id,msg) SELECT * FROM t2;
+SELECT partition_name, table_rows FROM information_schema.partitions WHERE table_name = 't1';
+partition_name table_rows
+1 5
+2 4
+3 2
+SELECT * FROM t1;
+rwid rnum prtn tbn fid id msg
+1 1 1 t1 part1 4 four
+2 2 1 t1 part1 7 seven
+3 3 1 t1 part1 1 one
+4 4 1 t1 part1 8 eight
+5 5 1 t1 part1 10 ten
+1 1 2 t1 part2 40 forty
+2 2 2 t1 part2 20 twenty
+3 3 2 t1 part2 35 thirty five
+4 4 2 t1 part2 60 sixty
+1 1 3 t1 part3 81 eighty one
+2 2 3 t1 part3 72 seventy two
+SELECT * FROM dr1;
+FNAME FTYPE
+part1 .fnx
+part1 .txt
+part2 .fnx
+part2 .txt
+part3 .fnx
+part3 .txt
+DROP TABLE t2;
+DROP TABLE t1;
+#
+# Testing partitioning on a populated outward table
+#
+CREATE TABLE t1 (
+id INT NOT NULL,
+msg VARCHAR(32)
+) ENGINE=CONNECT TABLE_TYPE=FIX FILE_NAME='part%s.txt'
+PARTITION by range columns(id) (
+PARTITION `1` VALUES LESS THAN(11),
+PARTITION `2` VALUES LESS THAN(70),
+PARTITION `3` VALUES LESS THAN(MAXVALUE));
+Warnings:
+Warning 1105 Data repartition in 1 is unchecked
+Warning 1105 Data repartition in 2 is unchecked
+Warning 1105 Data repartition in 3 is unchecked
+SELECT partition_name, table_rows FROM information_schema.partitions WHERE table_name = 't1';
+partition_name table_rows
+1 5
+2 4
+3 2
+SELECT * FROM t1 WHERE id < 11;
+id msg
+4 four
+7 seven
+1 one
+8 eight
+10 ten
+SELECT * FROM t1 WHERE id >= 70;
+id msg
+81 eighty one
+72 seventy two
+SELECT * FROM dr1;
+FNAME FTYPE
+part1 .fnx
+part1 .txt
+part2 .fnx
+part2 .txt
+part3 .fnx
+part3 .txt
+#
+# Testing indexing on a partitioned table
+#
+CREATE INDEX XID ON t1(id);
+SHOW INDEX FROM t1;
+Table Non_unique Key_name Seq_in_index Column_name Collation Cardinality Sub_part Packed Null Index_type Comment Index_comment
+t1 1 XID 1 id A NULL NULL NULL XINDEX
+SELECT * FROM dr1;
+FNAME FTYPE
+part1 .fnx
+part1 .txt
+part2 .fnx
+part2 .txt
+part3 .fnx
+part3 .txt
+EXPLAIN PARTITIONS SELECT * FROM t1 WHERE id = 10;
+id select_type table partitions type possible_keys key key_len ref rows Extra
+1 SIMPLE t1 1 ref XID XID 4 const 1
+DROP INDEX XID ON t1;
+SHOW INDEX FROM t1;
+Table Non_unique Key_name Seq_in_index Column_name Collation Cardinality Sub_part Packed Null Index_type Comment Index_comment
+SELECT * FROM dr1;
+FNAME FTYPE
+part1 .txt
+part2 .txt
+part3 .txt
+ALTER TABLE t1 ADD PRIMARY KEY (id);
+SHOW INDEX FROM t1;
+Table Non_unique Key_name Seq_in_index Column_name Collation Cardinality Sub_part Packed Null Index_type Comment Index_comment
+t1 0 PRIMARY 1 id A NULL NULL NULL XINDEX
+SELECT * FROM dr1;
+FNAME FTYPE
+part1 .fnx
+part1 .txt
+part2 .fnx
+part2 .txt
+part3 .fnx
+part3 .txt
+EXPLAIN PARTITIONS SELECT * FROM t1 WHERE id = 10;
+id select_type table partitions type possible_keys key key_len ref rows Extra
+1 SIMPLE t1 1 const PRIMARY PRIMARY 4 const 1
+ALTER TABLE t1 DROP PRIMARY KEY;
+SHOW INDEX FROM t1;
+Table Non_unique Key_name Seq_in_index Column_name Collation Cardinality Sub_part Packed Null Index_type Comment Index_comment
+SELECT * FROM dr1;
+FNAME FTYPE
+part1 .txt
+part2 .txt
+part3 .txt
+DROP TABLE t1;
+DROP TABLE dr1;
diff --git a/storage/connect/mysql-test/connect/r/part_table.result b/storage/connect/mysql-test/connect/r/part_table.result
new file mode 100644
index 00000000000..03c130548fa
--- /dev/null
+++ b/storage/connect/mysql-test/connect/r/part_table.result
@@ -0,0 +1,180 @@
+CREATE TABLE xt1 (
+id INT KEY NOT NULL,
+msg VARCHAR(32))
+ENGINE=MyISAM;
+INSERT INTO xt1 VALUES(4, 'four'),(7,'seven'),(1,'one'),(8,'eight');
+SELECT * FROM xt1;
+id msg
+4 four
+7 seven
+1 one
+8 eight
+CREATE TABLE xt2 (
+id INT KEY NOT NULL,
+msg VARCHAR(32));
+INSERT INTO xt2 VALUES(10,'ten'),(40,'forty'),(11,'eleven'),(35,'thirty five');
+SELECT * FROM xt2;
+id msg
+10 ten
+40 forty
+11 eleven
+35 thirty five
+CREATE TABLE xt3 (
+id INT KEY NOT NULL,
+msg VARCHAR(32))
+ENGINE=CONNECT TABLE_TYPE=CSV;
+Warnings:
+Warning 1105 No file name. Table will use xt3.csv
+INSERT INTO xt3 VALUES(60,'sixty'),(81,'eighty one'),(72,'seventy two');
+SELECT * FROM xt3;
+id msg
+60 sixty
+81 eighty one
+72 seventy two
+CREATE TABLE t1 (
+id INT NOT NULL,
+msg VARCHAR(32))
+ENGINE=CONNECT TABLE_TYPE=PROXY TABNAME='xt%s'
+PARTITION BY RANGE COLUMNS(id) (
+PARTITION `1` VALUES LESS THAN(10),
+PARTITION `2` VALUES LESS THAN(50),
+PARTITION `3` VALUES LESS THAN(MAXVALUE));
+Warnings:
+Warning 1105 Data repartition in 1 is unchecked
+Warning 1105 Data repartition in 2 is unchecked
+Warning 1105 Data repartition in 3 is unchecked
+SELECT partition_name, table_rows FROM information_schema.partitions WHERE table_name = 't1';
+partition_name table_rows
+1 4
+2 4
+3 3
+SELECT * FROM t1;
+id msg
+4 four
+7 seven
+1 one
+8 eight
+10 ten
+40 forty
+11 eleven
+35 thirty five
+60 sixty
+81 eighty one
+72 seventy two
+DELETE FROM t1;
+Warnings:
+Note 1105 xt1: 4 affected rows
+Note 1105 xt2: 4 affected rows
+ALTER TABLE t1 ADD INDEX XID(id);
+ERROR HY000: Table type PROXY is not indexable
+INSERT INTO t1 VALUES(4, 'four');
+INSERT INTO t1 VALUES(7,'seven'),(10,'ten'),(40,'forty'),(60,'sixty'),(81,'eighty one');
+INSERT INTO t1 VALUES(72,'seventy two'),(11,'eleven'),(1,'one'),(35,'thirty five'),(8,'eight');
+SELECT partition_name, table_rows FROM information_schema.partitions WHERE table_name = 't1';
+partition_name table_rows
+1 4
+2 4
+3 3
+SELECT * FROM t1;
+id msg
+4 four
+7 seven
+1 one
+8 eight
+10 ten
+40 forty
+11 eleven
+35 thirty five
+60 sixty
+81 eighty one
+72 seventy two
+EXPLAIN PARTITIONS
+SELECT * FROM t1 WHERE id = 81;
+id select_type table partitions type possible_keys key key_len ref rows Extra
+1 SIMPLE t1 3 ALL NULL NULL NULL NULL 21 Using where
+DELETE FROM t1;
+Warnings:
+Note 1105 xt1: 4 affected rows
+Note 1105 xt2: 4 affected rows
+DROP TABLE t1;
+CREATE TABLE t1 (
+id INT KEY NOT NULL,
+msg VARCHAR(32))
+ENGINE=CONNECT TABLE_TYPE=MYSQL TABNAME='xt%s'
+PARTITION BY RANGE COLUMNS(id) (
+PARTITION `1` VALUES LESS THAN(10),
+PARTITION `2` VALUES LESS THAN(50),
+PARTITION `3` VALUES LESS THAN(MAXVALUE));
+Warnings:
+Warning 1105 Data repartition in 1 is unchecked
+Warning 1105 Data repartition in 2 is unchecked
+Warning 1105 Data repartition in 3 is unchecked
+SHOW INDEX FROM t1;
+Table Non_unique Key_name Seq_in_index Column_name Collation Cardinality Sub_part Packed Null Index_type Comment Index_comment
+t1 0 PRIMARY 1 id NULL NULL NULL NULL REMOTE
+INSERT INTO t1 VALUES(4, 'four');
+INSERT INTO t1 VALUES(40, 'forty');
+INSERT INTO t1 VALUES(72,'seventy two');
+INSERT INTO t1 VALUES(7,'seven'),(10,'ten'),(60,'sixty'),(81,'eighty one'),(11,'eleven'),(1,'one'),(35,'thirty five'),(8,'eight');
+SELECT partition_name, table_rows FROM information_schema.partitions WHERE table_name = 't1';
+partition_name table_rows
+1 4
+2 4
+3 3
+SELECT * FROM t1;
+id msg
+4 four
+7 seven
+1 one
+8 eight
+40 forty
+10 ten
+11 eleven
+35 thirty five
+72 seventy two
+60 sixty
+81 eighty one
+EXPLAIN PARTITIONS SELECT * FROM t1 WHERE id = 81;
+id select_type table partitions type possible_keys key key_len ref rows Extra
+1 SIMPLE t1 3 const PRIMARY PRIMARY 4 const 1
+SELECT * FROM t1 WHERE id = 7;
+id msg
+7 seven
+SELECT * FROM t1 WHERE id = 35;
+id msg
+35 thirty five
+UPDATE t1 SET msg = 'number' WHERE id in (60,72);
+ERROR HY000: Got error 122 'Remote: Got error 122 'Cannot use indexing for this command' from CONNECT' from CONNECT
+UPDATE t1 SET msg = 'soixante' WHERE id = 60;
+Warnings:
+Note 1105 xt3: 1 affected rows
+SELECT * FROM t1 WHERE id > 50;
+id msg
+60 soixante
+72 seventy two
+81 eighty one
+UPDATE t1 SET msg = 'big' WHERE id > 50;
+Warnings:
+Note 1105 xt3: 3 affected rows
+UPDATE t1 SET msg = 'sept' WHERE id = 7;
+Warnings:
+Note 1105 xt1: 1 affected rows
+SELECT * FROM t1;
+id msg
+4 four
+7 sept
+1 one
+8 eight
+40 forty
+10 ten
+11 eleven
+35 thirty five
+72 big
+60 big
+81 big
+DELETE FROM t1 WHERE id in (60,72);
+ERROR HY000: Got error 122 'Remote: Got error 122 'Cannot use indexing for this command' from CONNECT' from CONNECT
+DROP TABLE t1;
+DROP TABLE xt1;
+DROP TABLE xt2;
+DROP TABLE xt3;
diff --git a/storage/connect/mysql-test/connect/t/part_file.test b/storage/connect/mysql-test/connect/t/part_file.test
new file mode 100644
index 00000000000..52225a3cead
--- /dev/null
+++ b/storage/connect/mysql-test/connect/t/part_file.test
@@ -0,0 +1,159 @@
+--source include/have_partition.inc
+let $MYSQLD_DATADIR= `select @@datadir`;
+
+--echo # This will be used to see what data files are created
+CREATE TABLE dr1 (
+ FNAME VARCHAR(256) NOT NULL FLAG=2,
+ FTYPE CHAR(8) NOT NULL FLAG=3
+# ,FSIZE INT(6) NOT NULL FLAG=5 removed because Unix size != Windows size
+) engine=CONNECT table_type=DIR file_name='t1#P#*.*';
+
+--echo #
+--echo # Testing partitioning on inward table
+--echo #
+CREATE TABLE t1 (
+ id INT NOT NULL,
+ msg VARCHAR(32)
+) ENGINE=CONNECT TABLE_TYPE=CSV
+PARTITION BY RANGE(id) (
+PARTITION first VALUES LESS THAN(10),
+PARTITION middle VALUES LESS THAN(50),
+PARTITION last VALUES LESS THAN(MAXVALUE));
+INSERT INTO t1 VALUES(4, 'four'),(24, 'twenty four');
+INSERT INTO t1 VALUES(7,'seven'),(10,'ten'),(40,'forty'),(60,'sixty'),(81,'eighty one');
+SELECT partition_name, table_rows FROM information_schema.partitions WHERE table_name = 't1';
+SELECT * FROM t1;
+EXPLAIN PARTITIONS SELECT * FROM t1 WHERE id > 50;
+SELECT * FROM t1 WHERE id > 50;
+SHOW TABLE STATUS LIKE 't1';
+--error ER_GET_ERRMSG
+UPDATE t1 set id = 41 WHERE msg = 'four';
+UPDATE t1 set msg = 'quatre' WHERE id = 4;
+SELECT * FROM dr1;
+--echo #
+--echo # Altering partitioning on inward table
+--echo #
+ALTER TABLE t1
+PARTITION by range(id) (
+PARTITION first VALUES LESS THAN(11),
+PARTITION middle VALUES LESS THAN(50),
+PARTITION last VALUES LESS THAN(MAXVALUE));
+SELECT partition_name, table_rows FROM information_schema.partitions WHERE table_name = 't1';
+SELECT * FROM dr1;
+EXPLAIN PARTITIONS SELECT * FROM t1 WHERE id=10;
+SELECT * FROM t1 WHERE id=10;
+DELETE FROM t1 WHERE id in (4,60);
+SELECT * FROM t1;
+DROP TABLE t1;
+SELECT * FROM dr1;
+
+--echo #
+--echo # Testing partitioning on a void outward table
+--echo #
+ALTER TABLE dr1 file_name='part*.*';
+CREATE TABLE t1 (
+ rwid INT(6) DEFAULT 0 SPECIAL=ROWID,
+ rnum INT(6) DEFAULT 0 SPECIAL=ROWNUM,
+ prtn VARCHAR(64) DEFAULT '' SPECIAL=PARTID,
+ tbn VARCHAR(64) DEFAULT '' SPECIAL=TABID,
+ fid VARCHAR(256) DEFAULT '' SPECIAL=FNAME,
+ id INT KEY NOT NULL,
+ msg VARCHAR(32)
+) ENGINE=CONNECT TABLE_TYPE=FIX FILE_NAME='part%s.txt';
+--replace_result $MYSQLD_DATADIR "DATADIR/"
+ALTER TABLE t1
+PARTITION by range columns(id) (
+PARTITION `1` VALUES LESS THAN(10),
+PARTITION `2` VALUES LESS THAN(50),
+PARTITION `3` VALUES LESS THAN(MAXVALUE));
+SHOW INDEX FROM t1;
+SELECT * FROM dr1;
+INSERT INTO t1(id,msg) VALUES(4, 'four');
+SELECT * FROM dr1;
+INSERT INTO t1(id,msg) VALUES(7,'seven'),(10,'ten'),(40,'forty'),(60,'sixty'),(81,'eighty one');
+INSERT INTO t1(id,msg) VALUES(72,'seventy two'),(20,'twenty'),(1,'one'),(35,'thirty five'),(8,'eight');
+SELECT partition_name, table_rows FROM information_schema.partitions WHERE table_name = 't1';
+SELECT * FROM t1;
+SELECT * FROM t1 order by id;
+EXPLAIN PARTITIONS SELECT * FROM t1 WHERE id = 10;
+SELECT * FROM t1 WHERE id = 10;
+EXPLAIN PARTITIONS SELECT * FROM t1 WHERE id >= 10;
+SELECT * FROM t1 WHERE id >= 10;
+SELECT count(*) FROM t1 WHERE id < 10;
+SELECT case when id < 10 then 1 when id < 50 then 2 else 3 end as pn, count(*) FROM t1 group by pn;
+SELECT prtn, count(*) FROM t1 group by prtn;
+EXPLAIN PARTITIONS SELECT * FROM t1 WHERE id > 50;
+SELECT * FROM t1 WHERE id = 35;
+SELECT * FROM dr1;
+--echo # This does not change the partition file data and is WRONG
+ALTER TABLE t1
+PARTITION by range columns(id) (
+PARTITION `1` VALUES LESS THAN(11),
+PARTITION `2` VALUES LESS THAN(70),
+PARTITION `3` VALUES LESS THAN(MAXVALUE));
+SELECT CASE WHEN id < 11 THEN 1 WHEN id < 70 THEN 2 ELSE 3 END AS pn, COUNT(*) FROM t1 GROUP BY pn;
+SELECT partition_name, table_rows FROM information_schema.partitions WHERE table_name = 't1';
+SELECT * FROM dr1;
+--echo #
+--echo # This is the correct way to change partitioning:
+--echo # Save table values, erase the table, then re-insert saved values in modified table
+--echo #
+CREATE TABLE t2 (
+ id INT NOT NULL,
+ msg VARCHAR(32)
+) ENGINE=CONNECT TABLE_TYPE=FIX;
+INSERT INTO t2 SELECT id, msg FROM t1;
+DELETE FROM t1;
+INSERT INTO t1(id,msg) SELECT * FROM t2;
+SELECT partition_name, table_rows FROM information_schema.partitions WHERE table_name = 't1';
+SELECT * FROM t1;
+SELECT * FROM dr1;
+DROP TABLE t2;
+DROP TABLE t1;
+
+--echo #
+--echo # Testing partitioning on a populated outward table
+--echo #
+CREATE TABLE t1 (
+ id INT NOT NULL,
+ msg VARCHAR(32)
+) ENGINE=CONNECT TABLE_TYPE=FIX FILE_NAME='part%s.txt'
+PARTITION by range columns(id) (
+PARTITION `1` VALUES LESS THAN(11),
+PARTITION `2` VALUES LESS THAN(70),
+PARTITION `3` VALUES LESS THAN(MAXVALUE));
+SELECT partition_name, table_rows FROM information_schema.partitions WHERE table_name = 't1';
+SELECT * FROM t1 WHERE id < 11;
+SELECT * FROM t1 WHERE id >= 70;
+SELECT * FROM dr1;
+
+--echo #
+--echo # Testing indexing on a partitioned table
+--echo #
+CREATE INDEX XID ON t1(id);
+SHOW INDEX FROM t1;
+SELECT * FROM dr1;
+EXPLAIN PARTITIONS SELECT * FROM t1 WHERE id = 10;
+DROP INDEX XID ON t1;
+SHOW INDEX FROM t1;
+SELECT * FROM dr1;
+ALTER TABLE t1 ADD PRIMARY KEY (id);
+SHOW INDEX FROM t1;
+SELECT * FROM dr1;
+EXPLAIN PARTITIONS SELECT * FROM t1 WHERE id = 10;
+ALTER TABLE t1 DROP PRIMARY KEY;
+SHOW INDEX FROM t1;
+SELECT * FROM dr1;
+DROP TABLE t1;
+DROP TABLE dr1;
+
+#
+# Clean up
+#
+--remove_file $MYSQLD_DATADIR/test/part1.txt
+--remove_file $MYSQLD_DATADIR/test/part2.txt
+--remove_file $MYSQLD_DATADIR/test/part3.txt
+#--remove_file $MYSQLD_DATADIR/test/part%s.fnx
+#--remove_file $MYSQLD_DATADIR/test/part1.fnx
+#--remove_file $MYSQLD_DATADIR/test/part2.fnx
+#--remove_file $MYSQLD_DATADIR/test/part3.fnx
diff --git a/storage/connect/mysql-test/connect/t/part_table.test b/storage/connect/mysql-test/connect/t/part_table.test
new file mode 100644
index 00000000000..d6cb1e80fce
--- /dev/null
+++ b/storage/connect/mysql-test/connect/t/part_table.test
@@ -0,0 +1,85 @@
+--source include/have_partition.inc
+
+#
+# These will be used by the t1 table partition table
+#
+CREATE TABLE xt1 (
+id INT KEY NOT NULL,
+msg VARCHAR(32))
+ENGINE=MyISAM;
+INSERT INTO xt1 VALUES(4, 'four'),(7,'seven'),(1,'one'),(8,'eight');
+SELECT * FROM xt1;
+
+CREATE TABLE xt2 (
+id INT KEY NOT NULL,
+msg VARCHAR(32));
+INSERT INTO xt2 VALUES(10,'ten'),(40,'forty'),(11,'eleven'),(35,'thirty five');
+SELECT * FROM xt2;
+
+CREATE TABLE xt3 (
+id INT KEY NOT NULL,
+msg VARCHAR(32))
+ENGINE=CONNECT TABLE_TYPE=CSV;
+INSERT INTO xt3 VALUES(60,'sixty'),(81,'eighty one'),(72,'seventy two');
+SELECT * FROM xt3;
+
+#
+# Based on PROXY the table is not indexable
+#
+CREATE TABLE t1 (
+id INT NOT NULL,
+msg VARCHAR(32))
+ENGINE=CONNECT TABLE_TYPE=PROXY TABNAME='xt%s'
+PARTITION BY RANGE COLUMNS(id) (
+PARTITION `1` VALUES LESS THAN(10),
+PARTITION `2` VALUES LESS THAN(50),
+PARTITION `3` VALUES LESS THAN(MAXVALUE));
+SELECT partition_name, table_rows FROM information_schema.partitions WHERE table_name = 't1';
+SELECT * FROM t1;
+DELETE FROM t1;
+--error ER_UNKNOWN_ERROR
+ALTER TABLE t1 ADD INDEX XID(id);
+INSERT INTO t1 VALUES(4, 'four');
+INSERT INTO t1 VALUES(7,'seven'),(10,'ten'),(40,'forty'),(60,'sixty'),(81,'eighty one');
+INSERT INTO t1 VALUES(72,'seventy two'),(11,'eleven'),(1,'one'),(35,'thirty five'),(8,'eight');
+SELECT partition_name, table_rows FROM information_schema.partitions WHERE table_name = 't1';
+SELECT * FROM t1;
+EXPLAIN PARTITIONS
+SELECT * FROM t1 WHERE id = 81;
+DELETE FROM t1;
+DROP TABLE t1;
+
+#
+# Based on MYSQL the table is indexable
+#
+CREATE TABLE t1 (
+id INT KEY NOT NULL,
+msg VARCHAR(32))
+ENGINE=CONNECT TABLE_TYPE=MYSQL TABNAME='xt%s'
+PARTITION BY RANGE COLUMNS(id) (
+PARTITION `1` VALUES LESS THAN(10),
+PARTITION `2` VALUES LESS THAN(50),
+PARTITION `3` VALUES LESS THAN(MAXVALUE));
+SHOW INDEX FROM t1;
+INSERT INTO t1 VALUES(4, 'four');
+INSERT INTO t1 VALUES(40, 'forty');
+INSERT INTO t1 VALUES(72,'seventy two');
+INSERT INTO t1 VALUES(7,'seven'),(10,'ten'),(60,'sixty'),(81,'eighty one'),(11,'eleven'),(1,'one'),(35,'thirty five'),(8,'eight');
+SELECT partition_name, table_rows FROM information_schema.partitions WHERE table_name = 't1';
+SELECT * FROM t1;
+EXPLAIN PARTITIONS SELECT * FROM t1 WHERE id = 81;
+SELECT * FROM t1 WHERE id = 7;
+SELECT * FROM t1 WHERE id = 35;
+--error ER_GET_ERRMSG
+UPDATE t1 SET msg = 'number' WHERE id in (60,72);
+UPDATE t1 SET msg = 'soixante' WHERE id = 60;
+SELECT * FROM t1 WHERE id > 50;
+UPDATE t1 SET msg = 'big' WHERE id > 50;
+UPDATE t1 SET msg = 'sept' WHERE id = 7;
+SELECT * FROM t1;
+--error ER_GET_ERRMSG
+DELETE FROM t1 WHERE id in (60,72);
+DROP TABLE t1;
+DROP TABLE xt1;
+DROP TABLE xt2;
+DROP TABLE xt3;
diff --git a/storage/connect/plgdbsem.h b/storage/connect/plgdbsem.h
index d37b275ebed..e0022baed93 100644
--- a/storage/connect/plgdbsem.h
+++ b/storage/connect/plgdbsem.h
@@ -85,6 +85,7 @@ enum AMT {TYPE_AM_ERROR = 0, /* Type not defined */
TYPE_AM_SRVID = 5, /* SERVID type (special column) */
TYPE_AM_TABID = 6, /* TABID type (special column) */
TYPE_AM_CNSID = 7, /* CONSTID type (special column) */
+ TYPE_AM_PRTID = 8, /* PARTID type (special column) */
TYPE_AM_COUNT = 10, /* CPT AM type no (count table) */
TYPE_AM_DCD = 20, /* Decode access method type no */
TYPE_AM_CMS = 30, /* CMS access method type no */
@@ -549,6 +550,7 @@ PPARM Vcolist(PGLOBAL, PTDB, PSZ, bool);
void PlugPutOut(PGLOBAL, FILE *, short, void *, uint);
void PlugLineDB(PGLOBAL, PSZ, short, void *, uint);
char *PlgGetDataPath(PGLOBAL g);
+char *ExtractFromPath(PGLOBAL, char *, char *, OPVAL);
void AddPointer(PTABS, void *);
PDTP MakeDateFormat(PGLOBAL, PSZ, bool, bool, int);
int ExtractDate(char *, PDTP, int, int val[6]);
diff --git a/storage/connect/plgdbutl.cpp b/storage/connect/plgdbutl.cpp
index 70fdd6c0bb5..329b78c0a1a 100644
--- a/storage/connect/plgdbutl.cpp
+++ b/storage/connect/plgdbutl.cpp
@@ -384,6 +384,31 @@ char *PlgGetDataPath(PGLOBAL g)
} // end of PlgGetDataPath
/***********************************************************************/
+/* Extract from a path name the required component. */
+/* This function assumes there is enough space in the buffer. */
+/***********************************************************************/
+char *ExtractFromPath(PGLOBAL g, char *pBuff, char *FileName, OPVAL op)
+ {
+ char *drive = NULL, *direc = NULL, *fname = NULL, *ftype = NULL;
+
+ switch (op) { // Determine which part to extract
+#if !defined(UNIX)
+ case OP_FDISK: drive = pBuff; break;
+#endif // !UNIX
+ case OP_FPATH: direc = pBuff; break;
+ case OP_FNAME: fname = pBuff; break;
+ case OP_FTYPE: ftype = pBuff; break;
+ default:
+ sprintf(g->Message, MSG(INVALID_OPER), op, "ExtractFromPath");
+ return NULL;
+ } // endswitch op
+
+ // Now do the extraction
+ _splitpath(FileName, drive, direc, fname, ftype);
+ return pBuff;
+ } // end of PlgExtractFromPath
+
+/***********************************************************************/
/* Check the occurence and matching of a pattern against a string. */
/* Because this function is only used for catalog name checking, */
/* it must be case insensitive. */
diff --git a/storage/connect/reldef.cpp b/storage/connect/reldef.cpp
index 7b3818cc98b..f483171ea7a 100644
--- a/storage/connect/reldef.cpp
+++ b/storage/connect/reldef.cpp
@@ -127,6 +127,14 @@ int RELDEF::GetCharCatInfo(PSZ what, PSZ sdef, char *buf, int size)
} // end of GetCharCatInfo
/***********************************************************************/
+/* To be used by any TDB's. */
+/***********************************************************************/
+bool RELDEF::Partitioned(void)
+ {
+ return Hc->IsPartitioned();
+ } // end of Partitioned
+
+/***********************************************************************/
/* This function returns string table information. */
/* Default parameter is "*" to get the handler default. */
/***********************************************************************/
@@ -136,7 +144,8 @@ char *RELDEF::GetStringCatInfo(PGLOBAL g, PSZ what, PSZ sdef)
if (s) {
if (Hc->IsPartitioned() &&
- (!stricmp(what, "filename") || !stricmp(what, "tabname"))) {
+ (!stricmp(what, "filename") || !stricmp(what, "tabname")
+ || !stricmp(what, "connect"))) {
name= Hc->GetPartName();
sval= (char*)PlugSubAlloc(g, NULL, strlen(s) + strlen(name));
sprintf(sval, s, name);
diff --git a/storage/connect/reldef.h b/storage/connect/reldef.h
index fbf66de373c..b6bd3cafc30 100644
--- a/storage/connect/reldef.h
+++ b/storage/connect/reldef.h
@@ -42,6 +42,7 @@ class DllExport RELDEF : public BLOCK { // Relation definition block
// Methods
bool GetBoolCatInfo(PSZ what, bool bdef);
bool SetIntCatInfo(PSZ what, int ival);
+ bool Partitioned(void);
int GetIntCatInfo(PSZ what, int idef);
int GetSizeCatInfo(PSZ what, PSZ sdef);
int GetCharCatInfo(PSZ what, PSZ sdef, char *buf, int size);
diff --git a/storage/connect/tabcol.h b/storage/connect/tabcol.h
index fdee653207e..3bfc37e69c1 100644
--- a/storage/connect/tabcol.h
+++ b/storage/connect/tabcol.h
@@ -97,7 +97,7 @@ class DllExport COLUMN: public XOBJECT { // Column Name/Qualifier block.
/***********************************************************************/
/* Definition of class SPCCOL with all its method functions. */
/* Note: Currently the special columns are ROWID, ROWNUM, FILEID, */
-/* SERVID, TABID, and CONID. */
+/* SERVID, TABID, PARTID, and CONID. */
/***********************************************************************/
class SPCCOL: public COLUMN { // Special Column Name/Qualifier block.
public:
diff --git a/storage/connect/tabdos.cpp b/storage/connect/tabdos.cpp
index 81e7772e062..7dbe8c71aa6 100644
--- a/storage/connect/tabdos.cpp
+++ b/storage/connect/tabdos.cpp
@@ -414,12 +414,12 @@ TDBDOS::TDBDOS(PDOSDEF tdp, PTXF txfp) : TDBASE(tdp)
AvgLen = tdp->AvgLen;
Ftype = tdp->Recfm;
To_Line = NULL;
- Cardinal = -1;
//To_BlkIdx = NULL;
To_BlkFil = NULL;
SavFil = NULL;
//Xeval = 0;
Beval = 0;
+ Abort = false;
} // end of TDBDOS standard constructor
TDBDOS::TDBDOS(PGLOBAL g, PTDBDOS tdbp) : TDBASE(tdbp)
@@ -429,7 +429,6 @@ TDBDOS::TDBDOS(PGLOBAL g, PTDBDOS tdbp) : TDBASE(tdbp)
AvgLen = tdbp->AvgLen;
Ftype = tdbp->Ftype;
To_Line = tdbp->To_Line;
- Cardinal = tdbp->Cardinal;
//To_BlkIdx = tdbp->To_BlkIdx;
To_BlkFil = tdbp->To_BlkFil;
SavFil = tdbp->SavFil;
@@ -561,8 +560,13 @@ int TDBDOS::MakeBlockValues(PGLOBAL g)
//void *memp = cat->GetDescp();
if ((nrec = defp->GetElemt()) < 2) {
- strcpy(g->Message, MSG(TABLE_NOT_OPT));
- return RC_INFO; // Not to be optimized
+ if (!To_Def->Partitioned()) {
+ // This may be wrong to do in some cases
+ strcpy(g->Message, MSG(TABLE_NOT_OPT));
+ return RC_INFO; // Not to be optimized
+ } else
+ return RC_OK;
+
} else if (GetMaxSize(g) == 0 || !(dup->Check & CHK_OPT)) {
// Suppress the opt file firstly if the table is void,
// secondly when it was modified with OPTIMIZATION unchecked
@@ -1565,7 +1569,13 @@ int TDBDOS::MakeIndex(PGLOBAL g, PIXDEF pxdf, bool add)
Mode = MODE_READ;
Use = USE_READY;
dfp = (PDOSDEF)To_Def;
- fixed = Cardinality(g) >= 0;
+
+ if (!Cardinality(g)) {
+ // Void table erase eventual index file(s)
+ (void)dfp->DeleteIndexFile(g, NULL);
+ return RC_OK;
+ } else
+ fixed = Cardinality(g) >= 0;
// Are we are called from CreateTable or CreateIndex?
if (pxdf) {
@@ -1823,11 +1833,50 @@ int TDBDOS::RowNumber(PGLOBAL g, bool b)
/***********************************************************************/
int TDBDOS::Cardinality(PGLOBAL g)
{
+ int n = Txfp->Cardinality(NULL);
+
if (!g)
- return Txfp->Cardinality(g);
+ return (Mode == MODE_ANY) ? 1 : n;
+
+ if (Cardinal < 0) {
+ if (Mode == MODE_ANY && n == 0) {
+ // Info command, we must return exact row number
+ PDOSDEF dfp = (PDOSDEF)To_Def;
+ PIXDEF xdp = dfp->To_Indx;
+
+ if (xdp) {
+ // Cardinality can be retreived from one index
+ PXLOAD pxp;
+
+ if (dfp->Huge)
+ pxp = new(g) XHUGE;
+ else
+ pxp = new(g) XFILE;
+
+ PXINDEX kxp = new(g) XINDEX(this, xdp, pxp, NULL, NULL);
+
+ if (!(kxp->GetAllSizes(g, Cardinal)))
+ return Cardinal;
+
+ } // endif Mode
+
+ // Using index impossible or failed, do it the hard way
+ Mode = MODE_READ;
+ To_Line = (char*)PlugSubAlloc(g, NULL, Lrecl + 1);
+
+ if (Txfp->OpenTableFile(g))
+ return (Cardinal = Txfp->Cardinality(g));
+
+ for (Cardinal = 0; n != RC_EF;)
+ if (!(n = Txfp->ReadBuffer(g)))
+ Cardinal++;
+
+ Txfp->CloseTableFile(g, false);
+ Mode = MODE_ANY;
+ } else
+ Cardinal = Txfp->Cardinality(g);
- if (Cardinal < 0)
- Cardinal = Txfp->Cardinality(g);
+ } // endif Cardinal
return Cardinal;
} // end of Cardinality
@@ -2104,7 +2153,7 @@ void TDBDOS::CloseDB(PGLOBAL g)
To_Kindex = NULL;
} // endif
- Txfp->CloseTableFile(g);
+ Txfp->CloseTableFile(g, Abort);
} // end of CloseDB
// ------------------------ DOSCOL functions ----------------------------
diff --git a/storage/connect/tabdos.h b/storage/connect/tabdos.h
index 62639787325..3f1fff0c72b 100644
--- a/storage/connect/tabdos.h
+++ b/storage/connect/tabdos.h
@@ -125,6 +125,7 @@ class DllExport TDBDOS : public TDBASE {
virtual AMT GetAmType(void) {return Txfp->GetAmType();}
virtual PSZ GetFile(PGLOBAL g) {return Txfp->To_File;}
virtual void SetFile(PGLOBAL g, PSZ fn) {Txfp->To_File = fn;}
+ virtual void SetAbort(bool b) {Abort = b;}
virtual RECFM GetFtype(void) {return Ftype;}
virtual bool SkipHeader(PGLOBAL g) {return false;}
virtual void RestoreNrec(void) {Txfp->SetNrec(1);}
@@ -183,8 +184,8 @@ class DllExport TDBDOS : public TDBASE {
PBF To_BlkFil; // To evaluation block filter
PFIL SavFil; // Saved hidden filter
char *To_Line; // Points to current processed line
- int Cardinal; // Table Cardinality
RECFM Ftype; // File type: 0-var 1-fixed 2-binary (VCT)
+ bool Abort; // TRUE when aborting 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 c376f76d377..f4bdb3011e3 100644
--- a/storage/connect/tabfix.cpp
+++ b/storage/connect/tabfix.cpp
@@ -63,12 +63,10 @@ static const longlong M4G = (longlong)2 * M2G;
/***********************************************************************/
TDBFIX::TDBFIX(PDOSDEF tdp, PTXF txfp) : TDBDOS(tdp, txfp)
{
-//Cardinal = -1;
} // end of TDBFIX standard constructor
TDBFIX::TDBFIX(PGLOBAL g, PTDBFIX tdbp) : TDBDOS(g, tdbp)
{
-//Cardinal = tdbp->Cardinal;
} // end of TDBFIX copy constructor
// Method
diff --git a/storage/connect/tabfmt.cpp b/storage/connect/tabfmt.cpp
index e4a280fefd2..5a944db1948 100644
--- a/storage/connect/tabfmt.cpp
+++ b/storage/connect/tabfmt.cpp
@@ -648,7 +648,7 @@ bool TDBCSV::OpenDB(PGLOBAL g)
} else
for (cdp = tdp->GetCols(); cdp; cdp = cdp->GetNext())
- if (!cdp->IsVirtual())
+ if (!cdp->IsSpecial() && !cdp->IsVirtual())
Fields++;
Offset = (int*)PlugSubAlloc(g, NULL, sizeof(int) * Fields);
@@ -685,7 +685,7 @@ bool TDBCSV::OpenDB(PGLOBAL g)
} else // MODE_UPDATE
for (cdp = tdp->GetCols(); cdp; cdp = cdp->GetNext())
- if (!cdp->IsVirtual()) {
+ if (!cdp->IsSpecial() && !cdp->IsVirtual()) {
i = cdp->GetOffset() - 1;
len = cdp->GetLength();
Field[i] = (PSZ)PlugSubAlloc(g, NULL, len + 1);
@@ -1117,7 +1117,8 @@ bool TDBFMT::OpenDB(PGLOBAL g)
// Get the column formats
for (cdp = tdp->GetCols(); cdp; cdp = cdp->GetNext())
- if (!cdp->IsVirtual() && (i = cdp->GetOffset() - 1) < Fields) {
+ if (!cdp->IsSpecial() && !cdp->IsVirtual()
+ && (i = cdp->GetOffset() - 1) < Fields) {
if (!(pfm = cdp->GetFmt())) {
sprintf(g->Message, MSG(NO_FLD_FORMAT), i + 1, Name);
return true;
diff --git a/storage/connect/table.cpp b/storage/connect/table.cpp
index 42cca1d2691..4683cabcb41 100644
--- a/storage/connect/table.cpp
+++ b/storage/connect/table.cpp
@@ -52,7 +52,8 @@ TDB::TDB(PTABDEF tdp) : Tdb_No(++Tnum)
To_Table = NULL;
Columns = NULL;
Degree = (tdp) ? tdp->GetDegree() : 0;
- Mode = MODE_READ;
+ Mode = MODE_ANY;
+ Cardinal = -1;
} // end of TDB standard constructor
TDB::TDB(PTDB tdbp) : Tdb_No(++Tnum)
@@ -67,6 +68,7 @@ TDB::TDB(PTDB tdbp) : Tdb_No(++Tnum)
Columns = NULL;
Degree = tdbp->Degree;
Mode = tdbp->Mode;
+ Cardinal = tdbp->Cardinal;
} // end of TDB copy constructor
// Methods
@@ -227,7 +229,7 @@ PCOL TDBASE::ColDB(PGLOBAL g, PSZ name, int num)
colp = cp;
else if (!(cdp->Flags & U_SPECIAL))
colp = MakeCol(g, cdp, cprec, i);
- else if (Mode == MODE_READ)
+ else if (Mode != MODE_INSERT)
colp = InsertSpcBlk(g, cdp);
if (trace)
@@ -267,22 +269,38 @@ PCOL TDBASE::InsertSpcBlk(PGLOBAL g, PCOLDEF cdp)
PCOL colp;
cp= new(g) COLUMN(cdp->GetName());
- cp->SetTo_Table(To_Table);
- if (!stricmp(name, "FILEID") ||
- !stricmp(name, "SERVID")) {
+ if (! To_Table) {
+ strcpy(g->Message, "Cannot make special column: To_Table is NULL");
+ return NULL;
+ } else
+ cp->SetTo_Table(To_Table);
+
+ if (!stricmp(name, "FILEID") || !stricmp(name, "FDISK") ||
+ !stricmp(name, "FPATH") || !stricmp(name, "FNAME") ||
+ !stricmp(name, "FTYPE") || !stricmp(name, "SERVID")) {
if (!To_Def || !(To_Def->GetPseudo() & 2)) {
sprintf(g->Message, MSG(BAD_SPEC_COLUMN));
return NULL;
} // endif Pseudo
if (!stricmp(name, "FILEID"))
- colp = new(g) FIDBLK(cp);
+ colp = new(g) FIDBLK(cp, OP_XX);
+ else if (!stricmp(name, "FDISK"))
+ colp = new(g) FIDBLK(cp, OP_FDISK);
+ else if (!stricmp(name, "FPATH"))
+ colp = new(g) FIDBLK(cp, OP_FPATH);
+ else if (!stricmp(name, "FNAME"))
+ colp = new(g) FIDBLK(cp, OP_FNAME);
+ else if (!stricmp(name, "FTYPE"))
+ colp = new(g) FIDBLK(cp, OP_FTYPE);
else
colp = new(g) SIDBLK(cp);
} else if (!stricmp(name, "TABID")) {
colp = new(g) TIDBLK(cp);
+ } else if (!stricmp(name, "PARTID")) {
+ colp = new(g) PRTBLK(cp);
//} else if (!stricmp(name, "CONID")) {
// colp = new(g) CIDBLK(cp);
} else if (!stricmp(name, "ROWID")) {
diff --git a/storage/connect/tabmysql.cpp b/storage/connect/tabmysql.cpp
index 931e78f598e..0d0b17c3dcc 100644
--- a/storage/connect/tabmysql.cpp
+++ b/storage/connect/tabmysql.cpp
@@ -1,7 +1,7 @@
/************* TabMySQL C++ Program Source Code File (.CPP) *************/
/* PROGRAM NAME: TABMYSQL */
/* ------------- */
-/* Version 1.8 */
+/* Version 1.9 */
/* */
/* AUTHOR: */
/* ------- */
@@ -69,6 +69,10 @@ void PrintResult(PGLOBAL, PSEM, PQRYRES);
extern "C" int trace;
+// Used to check whether a MYSQL table is created on itself
+bool CheckSelf(PGLOBAL g, TABLE_SHARE *s, const char *host,
+ const char *db, char *tab, const char *src, int port);
+
/* -------------- Implementation of the MYSQLDEF class --------------- */
/***********************************************************************/
@@ -353,8 +357,12 @@ bool MYSQLDEF::DefineAM(PGLOBAL g, LPCSTR am, int poff)
Tabname = Name;
} // endif am
- if ((Srcdef = GetStringCatInfo(g, "Srcdef", NULL)))
+ if ((Srcdef = GetStringCatInfo(g, "Srcdef", NULL))) {
+ Read_Only = true;
Isview = true;
+ } else if (CheckSelf(g, Hc->GetTable()->s, Hostname, Database,
+ Tabname, Srcdef, Portnumber))
+ return true;
// Used for Update and Delete
Qrystr = GetStringCatInfo(g, "Query_String", "?");
@@ -603,9 +611,7 @@ bool TDBMYSQL::MakeInsert(PGLOBAL g)
else
qlen += colp->GetLength();
- } // endif Prep
-
- if (Prep)
+ } else // Prep
strcat(valist, "?");
} // endfor colp
@@ -740,33 +746,49 @@ int TDBMYSQL::MakeDelete(PGLOBAL g)
#endif // 0
/***********************************************************************/
-/* XCV GetMaxSize: returns the maximum number of rows in the table. */
+/* MYSQL Cardinality: returns the number of rows in the table. */
/***********************************************************************/
-int TDBMYSQL::GetMaxSize(PGLOBAL g)
- {
- if (MaxSize < 0) {
-#if 0
- if (MakeSelect(g))
- return -2;
+int TDBMYSQL::Cardinality(PGLOBAL g)
+{
+ if (!g)
+ return (Mode == MODE_ANY && !Srcdef) ? 1 : 0;
- if (!Myc.Connected()) {
- if (Myc.Open(g, Host, Database, User, Pwd, Port))
- return -1;
+ if (Cardinal < 0 && Mode == MODE_ANY && !Srcdef) {
+ // Info command, we must return the exact table row number
+ char query[96];
+ MYSQLC myc;
- } // endif connected
+ if (myc.Open(g, Host, Database, User, Pwd, Port))
+ return -1;
- if ((MaxSize = Myc.GetResultSize(g, Query)) < 0) {
- Myc.Close();
- return -3;
- } // endif MaxSize
+ strcpy(query, "SELECT COUNT(*) FROM ");
- // FIXME: Columns should be known when Info calls GetMaxSize
- if (!Columns)
- Query = NULL; // Must be remade when columns are known
-#endif // 0
+ if (Quoted > 0)
+ strcat(strcat(strcat(query, "`"), Tabname), "`");
+ else
+ strcat(query, Tabname);
+
+ Cardinal = myc.GetTableSize(g, query);
+ myc.Close();
+ } // endif Cardinal
+
+ return Cardinal;
+} // end of Cardinality
+
+/***********************************************************************/
+/* MYSQL GetMaxSize: returns the maximum number of rows in the table. */
+/***********************************************************************/
+int TDBMYSQL::GetMaxSize(PGLOBAL g)
+ {
+ if (MaxSize < 0) {
+ if (Mode == MODE_DELETE)
+ // Return 0 in mode DELETE in case of delete all.
+ MaxSize = 0;
+ else if (!Cardinality(NULL))
+ MaxSize = 10; // To make MySQL happy
+ else if ((MaxSize = Cardinality(g)) < 0)
+ MaxSize = 12; // So we can see an error occured
- // Return 0 in mode DELETE in case of delete all.
- MaxSize = (Mode == MODE_DELETE) ? 0 : 10; // To make MySQL happy
} // endif MaxSize
return MaxSize;
@@ -881,11 +903,12 @@ bool TDBMYSQL::OpenDB(PGLOBAL g)
} // endif MakeInsert
if (m_Rc != RC_FX) {
+ int rc;
char cmd[64];
int w;
sprintf(cmd, "ALTER TABLE `%s` DISABLE KEYS", Tabname);
- m_Rc = Myc.ExecSQL(g, cmd, &w);
+ rc = Myc.ExecSQL(g, cmd, &w); // may fail for some engines
} // endif m_Rc
} else
@@ -1012,7 +1035,7 @@ bool TDBMYSQL::ReadKey(PGLOBAL g, OPVAL op, const void *key, int len)
{
int oldlen = strlen(Query);
- if (op == OP_NEXT)
+ if (!key || op == OP_NEXT)
return false;
else if (op == OP_FIRST) {
if (To_CondFil)
@@ -1129,7 +1152,7 @@ void TDBMYSQL::CloseDB(PGLOBAL g)
dup->Step = "Enabling indexes";
sprintf(cmd, "ALTER TABLE `%s` ENABLE KEYS", Tabname);
Myc.m_Rows = -1; // To execute the query
- m_Rc = Myc.ExecSQL(g, cmd, &w);
+ m_Rc = Myc.ExecSQL(g, cmd, &w); // May fail for some engines
} // endif m_Rc
Myc.Close();
diff --git a/storage/connect/tabmysql.h b/storage/connect/tabmysql.h
index 96991fb14c1..5400ab1985a 100644
--- a/storage/connect/tabmysql.h
+++ b/storage/connect/tabmysql.h
@@ -1,4 +1,4 @@
-// TDBMYSQL.H Olivier Bertrand 2007-2013
+// TDBMYSQL.H Olivier Bertrand 2007-2014
#include "myconn.h" // MySQL connection declares
typedef class MYSQLDEF *PMYDEF;
@@ -92,6 +92,7 @@ class TDBMYSQL : public TDBASE {
// Database routines
virtual PCOL MakeCol(PGLOBAL g, PCOLDEF cdp, PCOL cprec, int n);
+ virtual int Cardinality(PGLOBAL g);
virtual int GetMaxSize(PGLOBAL g);
virtual bool OpenDB(PGLOBAL g);
virtual int ReadDB(PGLOBAL g);
diff --git a/storage/connect/tabodbc.cpp b/storage/connect/tabodbc.cpp
index 65226c9e36f..0b05fc68299 100644
--- a/storage/connect/tabodbc.cpp
+++ b/storage/connect/tabodbc.cpp
@@ -100,7 +100,13 @@ ODBCDEF::ODBCDEF(void)
/***********************************************************************/
bool ODBCDEF::DefineAM(PGLOBAL g, LPCSTR am, int poff)
{
- Desc = Connect = GetStringCatInfo(g, "Connect", "");
+ Desc = Connect = GetStringCatInfo(g, "Connect", NULL);
+
+ if (!Connect && !Catfunc) {
+ sprintf(g->Message, "Missing connection for ODBC table %s", Name);
+ return true;
+ } // endif Connect
+
Tabname = GetStringCatInfo(g, "Name",
(Catfunc & (FNC_TABLE | FNC_COL)) ? NULL : Name);
Tabname = GetStringCatInfo(g, "Tabname", Tabname);
@@ -108,7 +114,10 @@ bool ODBCDEF::DefineAM(PGLOBAL g, LPCSTR am, int poff)
Tabschema = GetStringCatInfo(g, "Schema", Tabschema);
Tabcat = GetStringCatInfo(g, "Qualifier", NULL);
Tabcat = GetStringCatInfo(g, "Catalog", Tabcat);
- Srcdef = GetStringCatInfo(g, "Srcdef", NULL);
+
+ if ((Srcdef = GetStringCatInfo(g, "Srcdef", NULL)))
+ Read_Only = true;
+
Qrystr = GetStringCatInfo(g, "Query_String", "?");
Sep = GetStringCatInfo(g, "Separator", NULL);
Catver = GetIntCatInfo("Catver", 2);
@@ -655,40 +664,57 @@ void TDBODBC::ResetSize(void)
} // end of ResetSize
/***********************************************************************/
+/* ODBC Cardinality: returns table size in number of rows. */
+/***********************************************************************/
+int TDBODBC::Cardinality(PGLOBAL g)
+ {
+ if (!g)
+ return (Mode == MODE_ANY && !Srcdef) ? 1 : 0;
+
+ if (Cardinal < 0 && Mode == MODE_ANY && !Srcdef) {
+ // Info command, we must return the exact table row number
+ char qry[96], tbn[64];
+ ODBConn *ocp = new(g) ODBConn(g, this);
+
+ if (ocp->Open(Connect, Options) < 1)
+ return -1;
+
+ // Table name can be encoded in UTF-8
+ Decode(TableName, tbn, sizeof(tbn));
+ strcpy(qry, "SELECT COUNT(*) FROM ");
+
+ if (Quote)
+ strcat(strcat(strcat(qry, Quote), tbn), Quote);
+ else
+ strcat(qry, tbn);
+
+ // Allocate a Count(*) column (must not use the default constructor)
+ Cnp = new(g) ODBCCOL;
+ Cnp->InitValue(g);
+
+ if ((Cardinal = ocp->GetResultSize(qry, Cnp)) < 0)
+ return -3;
+
+ ocp->Close();
+ } // endif Cardinal
+
+ return Cardinal;
+ } // end of Cardinality
+
+/***********************************************************************/
/* ODBC GetMaxSize: returns table size estimate in number of lines. */
/***********************************************************************/
int TDBODBC::GetMaxSize(PGLOBAL g)
{
if (MaxSize < 0) {
- // Make MariaDB happy
- MaxSize = (Mode == MODE_DELETE) ? 0 : 10;
-#if 0
- // This is unuseful and takes time
- if (Srcdef) {
- // Return a reasonable guess
- MaxSize = 100;
- return MaxSize;
- } // endif Srcdef
-
- if (!Ocp)
- Ocp = new(g) ODBConn(g, this);
-
- if (!Ocp->IsOpen())
- if (Ocp->Open(Connect, Options) < 1)
- return -1;
-
- if (!Count && !(Count = MakeSQL(g, true)))
- return -2;
-
- if (!Cnp) {
- // Allocate a Count(*) column (must not use the default constructor)
- Cnp = new(g) ODBCCOL;
- Cnp->InitValue(g);
- } // endif Cnp
-
- if ((MaxSize = Ocp->GetResultSize(Count, Cnp)) < 0)
- return -3;
-#endif // 0
+ if (Mode == MODE_DELETE)
+ // Return 0 in mode DELETE in case of delete all.
+ MaxSize = 0;
+ else if (!Cardinality(NULL))
+ MaxSize = 10; // To make MySQL happy
+ else if ((MaxSize = Cardinality(g)) < 0)
+ MaxSize = 12; // So we can see an error occured
+
} // endif MaxSize
return MaxSize;
diff --git a/storage/connect/tabodbc.h b/storage/connect/tabodbc.h
index 5db8cbb8cff..e1594b3b44e 100644
--- a/storage/connect/tabodbc.h
+++ b/storage/connect/tabodbc.h
@@ -94,8 +94,9 @@ class TDBODBC : public TDBASE {
// Database routines
virtual PCOL MakeCol(PGLOBAL g, PCOLDEF cdp, PCOL cprec, int n);
- virtual int GetProgMax(PGLOBAL g);
+ virtual int Cardinality(PGLOBAL g);
virtual int GetMaxSize(PGLOBAL g);
+ virtual int GetProgMax(PGLOBAL g);
virtual bool OpenDB(PGLOBAL g);
virtual int ReadDB(PGLOBAL g);
virtual int WriteDB(PGLOBAL g);
diff --git a/storage/connect/tabsys.cpp b/storage/connect/tabsys.cpp
index e8ea7f4e43a..c7b0baddadc 100644
--- a/storage/connect/tabsys.cpp
+++ b/storage/connect/tabsys.cpp
@@ -1,9 +1,9 @@
/************* TabSys C++ Program Source Code File (.CPP) **************/
/* PROGRAM NAME: TABSYS */
/* ------------- */
-/* Version 2.2 */
+/* Version 2.3 */
/* */
-/* Author Olivier BERTRAND 2004-2013 */
+/* Author Olivier BERTRAND 2004-2014 */
/* */
/* This program are the INI/CFG tables classes. */
/***********************************************************************/
@@ -203,18 +203,35 @@ PCOL TDBINI::MakeCol(PGLOBAL g, PCOLDEF cdp, PCOL cprec, int n)
} // end of MakeCol
/***********************************************************************/
-/* INI GetMaxSize: returns the number of sections in the INI file. */
+/* INI Cardinality: returns the number of sections in the INI file. */
/***********************************************************************/
-int TDBINI::GetMaxSize(PGLOBAL g)
+int TDBINI::Cardinality(PGLOBAL g)
{
- if (MaxSize < 0 && GetSeclist(g)) {
+ if (!g)
+ return 1;
+
+ if (Cardinal < 0) {
// Count the number of sections from the section list
- char *p;
+ char *p = GetSeclist(g);
+
+ Cardinal = 0;
+
+ if (p)
+ for (; *p; p += (strlen(p) + 1))
+ Cardinal++;
- for (MaxSize = 0, p = Seclist; *p; p += (strlen(p) + 1))
- MaxSize++;
+ } // endif Cardinal
- } // endif MaxSize
+ return Cardinal;
+ } // end of Cardinality
+
+/***********************************************************************/
+/* INI GetMaxSize: returns the table cardinality. */
+/***********************************************************************/
+int TDBINI::GetMaxSize(PGLOBAL g)
+ {
+ if (MaxSize < 0)
+ MaxSize = Cardinality(g);
return MaxSize;
} // end of GetMaxSize
@@ -609,22 +626,28 @@ PCOL TDBXIN::MakeCol(PGLOBAL g, PCOLDEF cdp, PCOL cprec, int n)
} // end of MakeCol
/***********************************************************************/
-/* XIN GetMaxSize: returns the number of sections in the XIN file. */
+/* XIN Cardinality: returns the number of keys in the XIN file. */
/***********************************************************************/
-int TDBXIN::GetMaxSize(PGLOBAL g)
+int TDBXIN::Cardinality(PGLOBAL g)
{
- if (MaxSize < 0 && GetSeclist(g)) {
+ if (!g)
+ return 1;
+
+ if (Cardinal < 0) {
// Count the number of keys from the section list
- char *p, *k;
+ char *k, *p = GetSeclist(g);
- for (MaxSize = 0, p = Seclist; *p; p += (strlen(p) + 1))
- for (k = GetKeylist(g, p); *k; k += (strlen(k) + 1))
- MaxSize++;
+ Cardinal = 0;
- } // endif MaxSize
+ if (p)
+ for (; *p; p += (strlen(p) + 1))
+ for (k = GetKeylist(g, p); *k; k += (strlen(k) + 1))
+ Cardinal++;
- return MaxSize;
- } // end of GetMaxSize
+ } // endif Cardinal
+
+ return Cardinal;
+ } // end of Cardinality
/***********************************************************************/
/* Record position is Section+Key. */
diff --git a/storage/connect/tabsys.h b/storage/connect/tabsys.h
index b508aa5fe96..9741a43434c 100644
--- a/storage/connect/tabsys.h
+++ b/storage/connect/tabsys.h
@@ -1,7 +1,7 @@
/*************** TabSys H Declares Source Code File (.H) ***************/
-/* Name: TABSYS.H Version 2.2 */
+/* Name: TABSYS.H Version 2.3 */
/* */
-/* (C) Copyright to the author Olivier BERTRAND 2004-2013 */
+/* (C) Copyright to the author Olivier BERTRAND 2004-2014 */
/* */
/* This file contains the XDB system tables classes declares. */
/***********************************************************************/
@@ -37,7 +37,7 @@ class DllExport INIDEF : public TABDEF { /* INI table description */
// Members
char *Fn; /* Path/Name of corresponding file */
char *Xname; /* The eventual table name */
- char Layout; /* R: Row, C: Column */
+ char Layout; /* R: Row, C: Column */
int Ln; /* Length of section list buffer */
}; // end of INIDEF
@@ -61,7 +61,7 @@ class TDBINI : public TDBASE {
virtual int GetRecpos(void) {return N;}
virtual int GetProgCur(void) {return N;}
virtual int GetAffectedRows(void) {return 0;}
- virtual PSZ GetFile(PGLOBAL g) {return Ifile;}
+ virtual PSZ GetFile(PGLOBAL g) {return Ifile;}
virtual void SetFile(PGLOBAL g, PSZ fn) {Ifile = fn;}
virtual void ResetDB(void) {Seclist = Section = NULL; N = 0;}
virtual void ResetSize(void) {MaxSize = -1; Seclist = NULL;}
@@ -70,6 +70,7 @@ class TDBINI : public TDBASE {
// Database routines
virtual PCOL MakeCol(PGLOBAL g, PCOLDEF cdp, PCOL cprec, int n);
+ virtual int Cardinality(PGLOBAL g);
virtual int GetMaxSize(PGLOBAL g);
virtual bool OpenDB(PGLOBAL g);
virtual int ReadDB(PGLOBAL g);
@@ -144,7 +145,7 @@ class TDBXIN : public TDBINI {
// Database routines
virtual PCOL MakeCol(PGLOBAL g, PCOLDEF cdp, PCOL cprec, int n);
- virtual int GetMaxSize(PGLOBAL g);
+ virtual int Cardinality(PGLOBAL g);
virtual bool OpenDB(PGLOBAL g);
virtual int ReadDB(PGLOBAL g);
virtual int WriteDB(PGLOBAL g);
diff --git a/storage/connect/tabtbl.cpp b/storage/connect/tabtbl.cpp
index 0aeeb0b9d8d..4f2cf3038b9 100644
--- a/storage/connect/tabtbl.cpp
+++ b/storage/connect/tabtbl.cpp
@@ -435,7 +435,7 @@ bool TDBTBL::OpenDB(PGLOBAL g)
if ((CurTable = Tablist)) {
Tdbp = (PTDBASE)CurTable->GetTo_Tdb();
- Tdbp->SetMode(Mode);
+// Tdbp->SetMode(Mode);
// Tdbp->ResetDB();
// Tdbp->ResetSize();
@@ -685,7 +685,7 @@ bool TDBTBM::OpenDB(PGLOBAL g)
/*********************************************************************/
if ((CurTable = Tablist)) {
Tdbp = (PTDBASE)CurTable->GetTo_Tdb();
- Tdbp->SetMode(Mode);
+// Tdbp->SetMode(Mode);
// Check and initialize the subtable columns
for (PCOL cp = Columns; cp; cp = cp->GetNext())
diff --git a/storage/connect/tabutil.cpp b/storage/connect/tabutil.cpp
index e1dc58ce404..bc048f1bdfe 100644
--- a/storage/connect/tabutil.cpp
+++ b/storage/connect/tabutil.cpp
@@ -425,7 +425,7 @@ PTDBASE TDBPRX::GetSubTable(PGLOBAL g, PTABLE tabp, bool b)
if (mysql) {
#if defined(MYSQL_SUPPORT)
// Access sub-table via MySQL API
- if (!(tdbp= cat->GetTable(g, tabp, MODE_READ, "MYPRX"))) {
+ if (!(tdbp= cat->GetTable(g, tabp, Mode, "MYPRX"))) {
char buf[MAX_STR];
strcpy(buf, g->Message);
@@ -437,6 +437,9 @@ PTDBASE TDBPRX::GetSubTable(PGLOBAL g, PTABLE tabp, bool b)
if (db)
((PTDBMY)tdbp)->SetDatabase(tabp->GetQualifier());
+ if (Mode == MODE_UPDATE || Mode == MODE_DELETE)
+ tdbp->SetName(Name); // For Make_Command
+
#else // !MYSQL_SUPPORT
sprintf(g->Message, "%s.%s is not a CONNECT table",
db, tblp->Name);
@@ -480,7 +483,7 @@ bool TDBPRX::InitTable(PGLOBAL g)
if (!(Tdbp = GetSubTable(g, ((PPRXDEF)To_Def)->Tablep)))
return true;
- Tdbp->SetMode(Mode);
+// Tdbp->SetMode(Mode);
} // endif Tdbp
return false;
@@ -530,16 +533,12 @@ bool TDBPRX::OpenDB(PGLOBAL g)
return Tdbp->OpenDB(g);
} // endif use
- if (Mode == MODE_DELETE) {
- /*******************************************************************/
- /* Currently XCOL tables cannot be modified. */
- /*******************************************************************/
- strcpy(g->Message, "No DELETE for PROXY tables");
- return true;
- } // endif Mode
-
if (InitTable(g))
return true;
+ else if (Mode != MODE_READ && (Read_Only || Tdbp->IsReadOnly())) {
+ strcpy(g->Message, "Cannot modify a read only table");
+ return true;
+ } // endif tp
/*********************************************************************/
/* Check and initialize the subtable columns. */
@@ -565,7 +564,8 @@ bool TDBPRX::OpenDB(PGLOBAL g)
if (((PPRXCOL)cp)->Init(g, utp))
return true;
- } // endif MODE_UPDATE
+ } else if (Mode == MODE_DELETE)
+ Tdbp->SetNext(Next);
/*********************************************************************/
/* Physically open the object table. */
@@ -573,6 +573,7 @@ bool TDBPRX::OpenDB(PGLOBAL g)
if (Tdbp->OpenDB(g))
return true;
+ Tdbp->SetNext(NULL);
Use = USE_OPEN;
return false;
} // end of OpenDB
@@ -593,8 +594,6 @@ int TDBPRX::ReadDB(PGLOBAL g)
/***********************************************************************/
int TDBPRX::WriteDB(PGLOBAL g)
{
-//sprintf(g->Message, "%s tables are read only", To_Def->GetType());
-//return RC_FX;
return Tdbp->WriteDB(g);
} // end of WriteDB
@@ -603,9 +602,7 @@ int TDBPRX::WriteDB(PGLOBAL g)
/***********************************************************************/
int TDBPRX::DeleteDB(PGLOBAL g, int irc)
{
- sprintf(g->Message, "Delete not enabled for %s tables",
- To_Def->GetType());
- return RC_FX;
+ return Tdbp->DeleteDB(g, irc);
} // end of DeleteDB
/***********************************************************************/
diff --git a/storage/connect/tabvct.cpp b/storage/connect/tabvct.cpp
index ba5cf36a640..d90ec66c982 100644
--- a/storage/connect/tabvct.cpp
+++ b/storage/connect/tabvct.cpp
@@ -388,7 +388,7 @@ void TDBVCT::CloseDB(PGLOBAL g)
To_Kindex = NULL;
} // endif
- Txfp->CloseTableFile(g);
+ Txfp->CloseTableFile(g, false);
} // end of CloseDB
// ------------------------ VCTCOL functions ----------------------------
diff --git a/storage/connect/tabxml.cpp b/storage/connect/tabxml.cpp
index ee5749d8ab7..88c029aefd2 100644
--- a/storage/connect/tabxml.cpp
+++ b/storage/connect/tabxml.cpp
@@ -366,7 +366,7 @@ int TDBXML::LoadTableFile(PGLOBAL g, char *filename)
/*********************************************************************/
/* Firstly we check whether this file have been already loaded. */
/*********************************************************************/
- if (Mode == MODE_READ)
+ if (Mode == MODE_READ || Mode == MODE_ANY)
for (fp = dup->Openlist; fp; fp = fp->Next)
if (fp->Type == type && fp->Length && fp->Count)
if (!stricmp(fp->Fname, filename))
diff --git a/storage/connect/xindex.cpp b/storage/connect/xindex.cpp
index ff682517251..4f8cab213fe 100755
--- a/storage/connect/xindex.cpp
+++ b/storage/connect/xindex.cpp
@@ -1380,16 +1380,19 @@ err:
/***********************************************************************/
/* Get Ndif and Num_K from the index file. */
/***********************************************************************/
-bool XINDEX::GetAllSizes(PGLOBAL g, int &ndif, int &numk)
+bool XINDEX::GetAllSizes(PGLOBAL g,/* int &ndif,*/ int &numk)
{
char *ftype;
char fn[_MAX_PATH];
- int n, nv[NZ], id = -1;
- bool estim = false;
+ int nv[NZ], id = -1; // n
+//bool estim = false;
+ bool rc = true;
PDOSDEF defp = (PDOSDEF)Tdbp->To_Def;
- ndif = numk = 0;
+// ndif = numk = 0;
+ numk = 0;
+#if 0
/*********************************************************************/
/* Get the estimated table size. */
/* Note: for fixed tables we must use cardinality to avoid the call */
@@ -1417,6 +1420,7 @@ bool XINDEX::GetAllSizes(PGLOBAL g, int &ndif, int &numk)
strcpy(g->Message, MSG(NO_KEY_COL));
return true; // Error
} // endif Nk
+#endif // 0
switch (Tdbp->Ftype) {
case RECFM_VAR: ftype = ".dnx"; break;
@@ -1480,6 +1484,7 @@ bool XINDEX::GetAllSizes(PGLOBAL g, int &ndif, int &numk)
goto err;
} // endif
+#if 0
if (nv[2]) {
Mul = true;
Ndif = nv[2] - 1; // nv[2] is offset size, equal to Ndif + 1
@@ -1495,9 +1500,11 @@ bool XINDEX::GetAllSizes(PGLOBAL g, int &ndif, int &numk)
sprintf(g->Message, MSG(OPT_NOT_MATCH), fn);
goto err;
} // endif
+#endif // 0
Num_K = nv[3];
+#if 0
if (Nk > 1) {
if (nv[2] && X->Seek(g, nv[2] * sizeof(int), 0, SEEK_CUR))
goto err;
@@ -1518,17 +1525,18 @@ bool XINDEX::GetAllSizes(PGLOBAL g, int &ndif, int &numk)
Ndif = nv[0];
} // endif Nk
+#endif // 0
/*********************************************************************/
/* Set size values. */
/*********************************************************************/
- ndif = Ndif;
+//ndif = Ndif;
numk = Num_K;
- return false;
+ rc = false;
err:
X->Close();
- return true;
+ return rc;
} // end of GetAllSizes
/***********************************************************************/
diff --git a/storage/connect/xindex.h b/storage/connect/xindex.h
index 6800c18944d..c5ab829b33f 100644
--- a/storage/connect/xindex.h
+++ b/storage/connect/xindex.h
@@ -275,7 +275,7 @@ class DllExport XINDEX : public XXBASE {
virtual bool Make(PGLOBAL g, PIXDEF sxp);
virtual bool SaveIndex(PGLOBAL g, PIXDEF sxp);
virtual bool Reorder(PGLOBAL g);
- bool GetAllSizes(PGLOBAL g, int &ndif, int &numk);
+ bool GetAllSizes(PGLOBAL g,/* int &ndif,*/ int &numk);
protected:
bool AddColumns(PIXDEF xdp);
diff --git a/storage/connect/xtable.h b/storage/connect/xtable.h
index c4537ac0417..ff1f0bce899 100644
--- a/storage/connect/xtable.h
+++ b/storage/connect/xtable.h
@@ -79,6 +79,7 @@ class DllExport TDB: public BLOCK { // Table Descriptor Block.
virtual int GetTdb_No(void) {return Tdb_No;}
virtual PTDB GetNext(void) {return Next;}
virtual PCATLG GetCat(void) {return NULL;}
+ virtual void SetAbort(bool b) {;}
// Methods
virtual bool IsSame(PTDB tp) {return tp == this;}
@@ -125,6 +126,7 @@ class DllExport TDB: public BLOCK { // Table Descriptor Block.
PCOL Columns; // Points to the first column of the table
MODE Mode; // 10 Read, 30 Update, 40 Insert, 50 Delete
int Degree; // Number of columns
+ int Cardinal; // Table number of rows
}; // end of class TDB
/***********************************************************************/