mirror of
https://github.com/MariaDB/server.git
synced 2025-08-08 11:22:35 +03:00
This commit brings many changes, in particular two important ones:
1) Support of partitioning by connect. A table can be partitioned by files, this is an enhanced MULTIPLE table. It can be also partitioned by sub-tables like TBL and this enables table sharding. 2) Handling a CONNECT bug that causes in some cases extraneous rows to remain in the table after an UPDATE or DELETE when the command uses indexing (for not fixed file tables). Until a real fix is done, CONNECT tries to ignore indexing and if it cannot do it abort the command with an error message. - Add tests on partitioning added: storage/connect/mysql-test/connect/r/part_file.result storage/connect/mysql-test/connect/r/part_table.result storage/connect/mysql-test/connect/t/part_file.test storage/connect/mysql-test/connect/t/part_table.test - Temporary fix modified: sql/sql_partition.cc - Add partition support modified: storage/connect/ha_connect.cc storage/connect/ha_connect.h storage/connect/reldef.cpp storage/connect/reldef.h storage/connect/tabdos.cpp - Add functions ha_connect::IsUnique and ha_connect::CheckColumnList modified: storage/connect/ha_connect.cc storage/connect/ha_connect.h - Prevent updating a partition table column that is part of the partition function (outward tables only) modified: storage/connect/ha_connect.cc - Support INSERT/UPDATE/DELETE for PROXY tables modified: storage/connect/tabutil.cpp - Handle the bug on updating rows via indexing. Waiting for a real fix, Don't use indexing when possible else raise an error and abort. modified: storage/connect/ha_connect.cc - dbuserp->UseTemp set to TMP_AUTO modified: storage/connect/connect.cc - Add members nox, abort and only modified: storage/connect/ha_connect.cc storage/connect/ha_connect.h - Add arguments nox and abort to CntCloseTable modified: storage/connect/connect.cc storage/connect/connect.h storage/connect/filamap.cpp storage/connect/filamap.h storage/connect/filamdbf.cpp storage/connect/filamdbf.h storage/connect/filamfix.cpp storage/connect/filamfix.h storage/connect/filamtxt.cpp storage/connect/filamtxt.h storage/connect/filamvct.cpp storage/connect/filamvct.h storage/connect/filamzip.cpp storage/connect/filamzip.h storage/connect/ha_connect.cc - Add arguments abort to CloseTableFile and RenameTempFile modified: storage/connect/filamap.cpp storage/connect/filamap.h storage/connect/filamdbf.cpp storage/connect/filamdbf.h storage/connect/filamfix.cpp storage/connect/filamfix.h storage/connect/filamtxt.cpp storage/connect/filamtxt.h storage/connect/filamvct.cpp storage/connect/filamvct.h storage/connect/filamzip.cpp storage/connect/filamzip.h storage/connect/tabdos.cpp storage/connect/tabdos.h storage/connect/tabvct.cpp storage/connect/xtable.h - Fix info->records when file does not exists modified: storage/connect/connect.cc - Close XML table when opened for info modified: storage/connect/connect.cc - Add function VCTFAM::GetFileLength modified: storage/connect/filamvct.cpp storage/connect/filamvct.h - Column option DISTRIB -> ENUM modified: storage/connect/ha_connect.cc - Options connect, query_string and partname allways available modified: storage/connect/ha_connect.cc - Add function MYSQLC::GetTableSize modified: storage/connect/myconn.cpp storage/connect/myconn.h - Add new special columns (PARTNAME, FNAME, FPATH, FTYPE and FDISK) modified: storage/connect/colblk.cpp storage/connect/colblk.h storage/connect/plgdbsem.h storage/connect/table.cpp - Add function ExtractFromPath modified: storage/connect/colblk.cpp storage/connect/plgdbsem.h storage/connect/plgdbutl.cpp - Enhance Cardinality for some table types modified: storage/connect/tabdos.cpp storage/connect/tabmysql.cpp storage/connect/tabmysql.h storage/connect/tabodbc.cpp storage/connect/tabodbc.h storage/connect/tabsys.cpp storage/connect/tabsys.h storage/connect/xindex.cpp storage/connect/xindex.h storage/connect/xtable.h - Add test on special column modified: storage/connect/tabfmt.cpp - Add new files (added for block indexing) modified: storage/connect/CMakeLists.txt
This commit is contained in:
@@ -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);
|
||||
}
|
||||
|
@@ -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
|
||||
|
@@ -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
|
||||
@@ -351,6 +358,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. */
|
||||
/***********************************************************************/
|
||||
|
@@ -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
|
||||
|
||||
/***********************************************************************/
|
||||
@@ -180,6 +181,29 @@ class DllExport TIDBLK : public SPCBLK {
|
||||
PSZ Tname; // The current table name
|
||||
}; // 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. */
|
||||
/***********************************************************************/
|
||||
|
@@ -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)
|
||||
|
@@ -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);
|
||||
|
@@ -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
|
||||
|
@@ -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:
|
||||
|
@@ -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
|
||||
|
@@ -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:
|
||||
|
@@ -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
|
||||
|
@@ -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:
|
||||
|
@@ -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) {
|
||||
|
@@ -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:
|
||||
|
@@ -136,6 +136,39 @@ VCTFAM::VCTFAM(PVCTFAM txfp) : FIXFAM(txfp)
|
||||
Ncol = txfp->Ncol;
|
||||
} // 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. */
|
||||
/***********************************************************************/
|
||||
@@ -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
|
||||
|
@@ -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
|
||||
|
@@ -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;
|
||||
|
||||
|
@@ -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:
|
||||
|
@@ -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);
|
||||
@@ -1196,6 +1205,17 @@ bool ha_connect::GetIndexOption(KEY *kp, char *opname)
|
||||
return opval;
|
||||
} // end of GetIndexOption
|
||||
|
||||
/****************************************************************************/
|
||||
/* 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. */
|
||||
/****************************************************************************/
|
||||
@@ -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
|
||||
|
||||
@@ -1475,6 +1507,50 @@ int ha_connect::OpenTable(PGLOBAL g, bool del)
|
||||
} // end of OpenTable
|
||||
|
||||
|
||||
/****************************************************************************/
|
||||
/* 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. */
|
||||
/****************************************************************************/
|
||||
@@ -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);
|
||||
|
||||
// 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
|
||||
|
||||
if (!(tdbp= GetTDB(g)))
|
||||
DBUG_RETURN(HA_ERR_INTERNAL_ERROR); // Should never happen
|
||||
|
||||
valid_info = false;
|
||||
} // endif tdbp
|
||||
|
||||
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= GetTDB(g);
|
||||
} // endif tdbp
|
||||
|
||||
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
|
||||
|
||||
|
@@ -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:
|
||||
|
@@ -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);
|
||||
|
@@ -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)
|
||||
|
@@ -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);
|
||||
|
355
storage/connect/mysql-test/connect/r/part_file.result
Normal file
355
storage/connect/mysql-test/connect/r/part_file.result
Normal file
@@ -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;
|
180
storage/connect/mysql-test/connect/r/part_table.result
Normal file
180
storage/connect/mysql-test/connect/r/part_table.result
Normal file
@@ -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;
|
159
storage/connect/mysql-test/connect/t/part_file.test
Normal file
159
storage/connect/mysql-test/connect/t/part_file.test
Normal file
@@ -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
|
85
storage/connect/mysql-test/connect/t/part_table.test
Normal file
85
storage/connect/mysql-test/connect/t/part_table.test
Normal file
@@ -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;
|
@@ -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]);
|
||||
|
@@ -383,6 +383,31 @@ char *PlgGetDataPath(PGLOBAL g)
|
||||
return (cat) ? cat->GetDataPath() : NULL;
|
||||
} // 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, */
|
||||
|
@@ -126,6 +126,14 @@ int RELDEF::GetCharCatInfo(PSZ what, PSZ sdef, char *buf, int size)
|
||||
return 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);
|
||||
|
@@ -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);
|
||||
|
@@ -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:
|
||||
|
@@ -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)
|
||||
{
|
||||
if (!g)
|
||||
return Txfp->Cardinality(g);
|
||||
int n = Txfp->Cardinality(NULL);
|
||||
|
||||
if (Cardinal < 0)
|
||||
Cardinal = Txfp->Cardinality(g);
|
||||
if (!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);
|
||||
|
||||
} // 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 ----------------------------
|
||||
|
@@ -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
|
||||
|
@@ -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
|
||||
|
@@ -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;
|
||||
|
@@ -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")) {
|
||||
|
@@ -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::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 query[96];
|
||||
MYSQLC myc;
|
||||
|
||||
if (myc.Open(g, Host, Database, User, Pwd, Port))
|
||||
return -1;
|
||||
|
||||
strcpy(query, "SELECT COUNT(*) FROM ");
|
||||
|
||||
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 0
|
||||
if (MakeSelect(g))
|
||||
return -2;
|
||||
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
|
||||
|
||||
if (!Myc.Connected()) {
|
||||
if (Myc.Open(g, Host, Database, User, Pwd, Port))
|
||||
return -1;
|
||||
|
||||
} // endif connected
|
||||
|
||||
if ((MaxSize = Myc.GetResultSize(g, Query)) < 0) {
|
||||
Myc.Close();
|
||||
return -3;
|
||||
} // endif MaxSize
|
||||
|
||||
// FIXME: Columns should be known when Info calls GetMaxSize
|
||||
if (!Columns)
|
||||
Query = NULL; // Must be remade when columns are known
|
||||
#endif // 0
|
||||
|
||||
// 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();
|
||||
|
@@ -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);
|
||||
|
@@ -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);
|
||||
@@ -654,41 +663,58 @@ 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 (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
|
||||
|
||||
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
|
||||
} // endif MaxSize
|
||||
|
||||
return MaxSize;
|
||||
|
@@ -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);
|
||||
|
@@ -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::Cardinality(PGLOBAL g)
|
||||
{
|
||||
if (!g)
|
||||
return 1;
|
||||
|
||||
if (Cardinal < 0) {
|
||||
// Count the number of sections from the section list
|
||||
char *p = GetSeclist(g);
|
||||
|
||||
Cardinal = 0;
|
||||
|
||||
if (p)
|
||||
for (; *p; p += (strlen(p) + 1))
|
||||
Cardinal++;
|
||||
|
||||
} // endif Cardinal
|
||||
|
||||
return Cardinal;
|
||||
} // end of Cardinality
|
||||
|
||||
/***********************************************************************/
|
||||
/* INI GetMaxSize: returns the table cardinality. */
|
||||
/***********************************************************************/
|
||||
int TDBINI::GetMaxSize(PGLOBAL g)
|
||||
{
|
||||
if (MaxSize < 0 && GetSeclist(g)) {
|
||||
// Count the number of sections from the section list
|
||||
char *p;
|
||||
|
||||
for (MaxSize = 0, p = Seclist; *p; p += (strlen(p) + 1))
|
||||
MaxSize++;
|
||||
|
||||
} // endif MaxSize
|
||||
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. */
|
||||
|
@@ -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);
|
||||
|
@@ -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())
|
||||
|
@@ -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
|
||||
|
||||
/***********************************************************************/
|
||||
|
@@ -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 ----------------------------
|
||||
|
@@ -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))
|
||||
|
@@ -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
|
||||
|
||||
/***********************************************************************/
|
||||
|
@@ -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);
|
||||
|
@@ -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
|
||||
|
||||
/***********************************************************************/
|
||||
|
Reference in New Issue
Block a user