10.0-connect merge

This commit is contained in:
Sergei Golubchik 2014-09-12 16:44:27 +02:00
commit 86957d414f
48 changed files with 4002 additions and 1361 deletions

View File

@ -127,6 +127,10 @@ PARRAY MakeValueArray(PGLOBAL g, PPARM pp)
case TYPE_PCHAR:
par->AddValue(g, parmp->Value);
break;
case TYPE_VOID:
// Integer stored inside pp->Value
par->AddValue(g, (int)parmp->Value);
break;
} // endswitch valtyp
/*********************************************************************/
@ -152,14 +156,17 @@ ARRAY::ARRAY(PGLOBAL g, int type, int size, int length, int prec)
Xsize = -1;
Len = 1;
switch ((Type = type)) {
switch (type) {
case TYPE_STRING:
Len = length;
break;
case TYPE_SHORT:
case TYPE_INT:
case TYPE_DOUBLE:
case TYPE_PCHAR:
Type = type;
break;
case TYPE_VOID:
Type = TYPE_INT;
break;
#if 0
case TYPE_TOKEN:
@ -973,7 +980,7 @@ PSZ ARRAY::MakeArrayList(PGLOBAL g)
size_t z, len = 2;
if (Type == TYPE_LIST)
return "(???)"; // To be implemented
return "(?" "?" "?)"; // To be implemented
z = MY_MAX(24, GetTypeSize(Type, Len) + 4);
tp = (char*)PlugSubAlloc(g, NULL, z);

View File

@ -1,7 +1,7 @@
/*************** Catalog H Declares Source Code File (.H) **************/
/* Name: CATALOG.H Version 3.2 */
/* Name: CATALOG.H Version 3.3 */
/* */
/* (C) Copyright to the author Olivier BERTRAND 2000-2012 */
/* (C) Copyright to the author Olivier BERTRAND 2000-2014 */
/* */
/* This file contains the CATALOG PlugDB classes definitions. */
/***********************************************************************/
@ -68,11 +68,11 @@ class DllExport CATALOG {
bool GetDefHuge(void) {return DefHuge;}
void SetDefHuge(bool b) {DefHuge = b;}
char *GetCbuf(void) {return Cbuf;}
char *GetDataPath(void) {return (char*)DataPath;}
//char *GetDataPath(void) {return (char*)DataPath;}
// Methods
virtual void Reset(void) {}
virtual void SetDataPath(PGLOBAL g, const char *path) {}
//virtual void SetDataPath(PGLOBAL g, const char *path) {}
virtual bool CheckName(PGLOBAL g, char *name) {return true;}
virtual bool ClearName(PGLOBAL g, PSZ name) {return true;}
virtual PRELDEF MakeOneTableDesc(PGLOBAL g, LPCSTR name, LPCSTR am) {return NULL;}
@ -106,7 +106,7 @@ class DllExport CATALOG {
int Cblen; /* Length of suballoc. buffer */
CURTAB Ctb; /* Used to enumerate tables */
bool DefHuge; /* true: tables default to huge */
LPCSTR DataPath; /* Is the Path of DB data dir */
//LPCSTR DataPath; /* Is the Path of DB data dir */
}; // end of class CATALOG
#endif // __CATALOG__H

View File

@ -34,9 +34,10 @@ enum XMOD {XMOD_EXECUTE = 0, /* DOS execution mode */
/***********************************************************************/
/* Following definitions indicate the use of a temporay file. */
/***********************************************************************/
enum USETEMP {TMP_AUTO = 0, /* Best choice */
TMP_NO = 1, /* Never */
enum USETEMP {TMP_NO = 0, /* Never */
TMP_AUTO = 1, /* Best choice */
TMP_YES = 2, /* Always */
TMP_FORCE = 3}; /* Forced for MAP tables */
TMP_FORCE = 3, /* Forced for MAP tables */
TMP_TEST = 4}; /* Testing value */
#endif // _CHKLVL_DEFINED_

View File

@ -122,9 +122,12 @@ bool CntCheckDB(PGLOBAL g, PHC handler, const char *pathname)
(dbuserp->Catalog) ? ((MYCAT*)dbuserp->Catalog)->GetHandler() : NULL,
handler);
// Set the database path for this table
handler->SetDataPath(g, pathname);
if (dbuserp->Catalog) {
// ((MYCAT *)dbuserp->Catalog)->SetHandler(handler); done later
((MYCAT *)dbuserp->Catalog)->SetDataPath(g, pathname);
// ((MYCAT *)dbuserp->Catalog)->SetDataPath(g, pathname);
return false; // Nothing else to do
} // endif Catalog
@ -141,8 +144,8 @@ bool CntCheckDB(PGLOBAL g, PHC handler, const char *pathname)
if (!(dbuserp->Catalog= new MYCAT(handler)))
return true;
((MYCAT *)dbuserp->Catalog)->SetDataPath(g, pathname);
dbuserp->UseTemp= TMP_AUTO;
//((MYCAT *)dbuserp->Catalog)->SetDataPath(g, pathname);
//dbuserp->UseTemp= TMP_AUTO;
/*********************************************************************/
/* All is correct. */
@ -479,7 +482,7 @@ RCODE CntReadNext(PGLOBAL g, PTDB tdbp)
/***********************************************************************/
RCODE CntWriteRow(PGLOBAL g, PTDB tdbp)
{
RCODE rc;
RCODE rc;
PCOL colp;
PTDBASE tp= (PTDBASE)tdbp;
@ -503,11 +506,12 @@ RCODE CntWriteRow(PGLOBAL g, PTDB tdbp)
if (!colp->GetColUse(U_VIRTUAL))
colp->WriteColumn(g);
// if (tdbp->GetMode() == MODE_INSERT)
// tbxp->SetModified(true);
// Return result code from write operation
rc= (RCODE)tdbp->WriteDB(g);
if (tp->IsIndexed())
// Index values must be sorted before updating
rc= (RCODE)((PTDBDOS)tp)->GetTxfp()->StoreValues(g, true);
else
// Return result code from write operation
rc= (RCODE)tdbp->WriteDB(g);
err:
g->jump_level--;
@ -517,7 +521,7 @@ RCODE CntWriteRow(PGLOBAL g, PTDB tdbp)
/***********************************************************************/
/* UpdateRow: Update a row into a table. */
/***********************************************************************/
RCODE CntUpdateRow(PGLOBAL g, PTDB tdbp)
RCODE CntUpdateRow(PGLOBAL g, PTDB tdbp)
{
if (!tdbp || tdbp->GetMode() != MODE_UPDATE)
return RC_FX;
@ -531,19 +535,28 @@ RCODE CntUpdateRow(PGLOBAL g, PTDB tdbp)
/***********************************************************************/
RCODE CntDeleteRow(PGLOBAL g, PTDB tdbp, bool all)
{
RCODE rc;
RCODE rc;
PTDBASE tp= (PTDBASE)tdbp;
if (!tdbp || tdbp->GetMode() != MODE_DELETE)
return RC_FX;
else if (tdbp->IsReadOnly())
return RC_NF;
if (((PTDBASE)tdbp)->GetDef()->Indexable() && all)
((PTDBDOS)tdbp)->Cardinal= 0;
if (all) {
if (((PTDBASE)tdbp)->GetDef()->Indexable())
((PTDBDOS)tdbp)->Cardinal= 0;
// Note: if all, this call will be done when closing the table
rc= (RCODE)tdbp->DeleteDB(g, RC_FX);
//} else if (tp->GetKindex() && !tp->GetKindex()->IsSorted() &&
// tp->Txfp->GetAmType() != TYPE_AM_DBF) {
} else if(tp->IsIndexed()) {
// Index values must be sorted before updating
rc= (RCODE)((PTDBDOS)tp)->GetTxfp()->StoreValues(g, false);
} else // Return result code from delete operation
rc= (RCODE)tdbp->DeleteDB(g, RC_OK);
// Return result code from delete operation
// Note: if all, this call will be done when closing the table
rc= (RCODE)tdbp->DeleteDB(g, (all) ? RC_FX : RC_OK);
return rc;
} // end of CntDeleteRow
@ -553,7 +566,7 @@ RCODE CntDeleteRow(PGLOBAL g, PTDB tdbp, bool all)
int CntCloseTable(PGLOBAL g, PTDB tdbp, bool nox, bool abort)
{
int rc= RC_OK;
TDBDOX *tbxp= NULL;
TDBASE *tbxp= (PTDBASE)tdbp;
if (!tdbp)
return rc; // Nothing to do
@ -568,8 +581,24 @@ int CntCloseTable(PGLOBAL g, PTDB tdbp, bool nox, bool abort)
printf("CntCloseTable: tdbp=%p mode=%d nox=%d abort=%d\n",
tdbp, tdbp->GetMode(), nox, abort);
if (tdbp->GetMode() == MODE_DELETE && tdbp->GetUse() == USE_OPEN)
rc= tdbp->DeleteDB(g, RC_EF); // Specific A.M. delete routine
if (tdbp->GetMode() == MODE_DELETE && tdbp->GetUse() == USE_OPEN) {
if (tbxp->IsIndexed())
rc= ((PTDBDOS)tdbp)->GetTxfp()->DeleteSortedRows(g);
if (!rc)
rc= tdbp->DeleteDB(g, RC_EF); // Specific A.M. delete routine
} else if (tbxp->GetMode() == MODE_UPDATE && tbxp->IsIndexed())
rc= ((PTDBDOX)tdbp)->Txfp->UpdateSortedRows(g);
switch(rc) {
case RC_FX:
abort= true;
break;
case RC_INFO:
PushWarning(g, tbxp);
break;
} // endswitch rc
// Prepare error return
if (g->jump_level == MAX_JUMP) {
@ -606,9 +635,8 @@ int CntCloseTable(PGLOBAL g, PTDB tdbp, bool nox, bool abort)
// Make all the eventual indexes
tbxp= (TDBDOX*)tdbp;
tbxp->ResetKindex(g, NULL);
tbxp->To_Key_Col= NULL;
rc= tbxp->ResetTableOpt(g, true,
((PTDBASE)tdbp)->GetDef()->Indexable() == 1);
tbxp->SetKey_Col(NULL);
rc= tbxp->ResetTableOpt(g, true, tbxp->GetDef()->Indexable() == 1);
err:
if (trace > 1)
@ -622,7 +650,7 @@ int CntCloseTable(PGLOBAL g, PTDB tdbp, bool nox, bool abort)
/* This is the condition(s) for doing indexing. */
/* Note: FIX table are not reset here to Nrec= 1. */
/***********************************************************************/
int CntIndexInit(PGLOBAL g, PTDB ptdb, int id)
int CntIndexInit(PGLOBAL g, PTDB ptdb, int id, bool sorted)
{
PIXDEF xdp;
PTDBDOX tdbp;
@ -674,7 +702,7 @@ int CntIndexInit(PGLOBAL g, PTDB ptdb, int id)
#endif // 0
// Static indexes must be initialized now for records_in_range
if (tdbp->InitialyzeIndex(g, xdp))
if (tdbp->InitialyzeIndex(g, xdp, sorted))
return 0;
return (tdbp->To_Kindex->IsMul()) ? 2 : 1;
@ -721,7 +749,7 @@ RCODE CntIndexRead(PGLOBAL g, PTDB ptdb, OPVAL op,
#if 0
} // endif !To_Xdp
// Now it's time to make the dynamic index
if (tdbp->InitialyzeIndex(g, NULL)) {
if (tdbp->InitialyzeIndex(g, NULL, false)) {
sprintf(g->Message, "Fail to make dynamic index %s",
tdbp->To_Xdp->GetName());
return RC_FX;

View File

@ -34,7 +34,7 @@ PTDB CntGetTDB(PGLOBAL g, const char *name, MODE xmod, PHC);
bool CntOpenTable(PGLOBAL g, PTDB tdbp, MODE, char *, char *, bool, PHC);
bool CntRewindTable(PGLOBAL g, PTDB tdbp);
int CntCloseTable(PGLOBAL g, PTDB tdbp, bool nox, bool abort);
int CntIndexInit(PGLOBAL g, PTDB tdbp, int id);
int CntIndexInit(PGLOBAL g, PTDB tdbp, int id, bool sorted);
RCODE CntReadNext(PGLOBAL g, PTDB tdbp);
RCODE CntIndexRead(PGLOBAL g, PTDB, OPVAL op, const void *k, int n, bool mrr);
RCODE CntWriteRow(PGLOBAL g, PTDB tdbp);
@ -50,7 +50,7 @@ PGLOBAL CntExit(PGLOBAL g);
/* These classes purpose is chiefly to access protected items! */
/***********************************************************************/
class DOXDEF: public DOSDEF {
friend int CntIndexInit(PGLOBAL, PTDB, int);
friend int CntIndexInit(PGLOBAL, PTDB, int, bool);
}; // end of class DOXDEF
/***********************************************************************/
@ -59,7 +59,7 @@ class DOXDEF: public DOSDEF {
class TDBDOX: public TDBDOS {
friend int MakeIndex(PGLOBAL, PTDB, PIXDEF);
friend int CntCloseTable(PGLOBAL, PTDB, bool, bool);
friend int CntIndexInit(PGLOBAL, PTDB, int);
friend int CntIndexInit(PGLOBAL, PTDB, int, bool);
friend RCODE CntIndexRead(PGLOBAL, PTDB, OPVAL, const void*, int, bool);
friend RCODE CntDeleteRow(PGLOBAL, PTDB, bool);
friend int CntIndexRange(PGLOBAL, PTDB, const uchar**, uint*,
@ -70,7 +70,7 @@ class TDBDOX: public TDBDOS {
class XKPDEF: public KPARTDEF {
friend class TDBDOX;
friend class ha_connect;
friend int CntIndexInit(PGLOBAL, PTDB, int);
friend int CntIndexInit(PGLOBAL, PTDB, int, bool);
public:
XKPDEF(const char *name, int n) : KPARTDEF((PSZ)name, n) {}
}; // end of class XKPDEF

View File

@ -48,11 +48,6 @@
extern "C" int trace;
/***********************************************************************/
/* Routine called externally by MAPFAM MakeDeletedFile function. */
/***********************************************************************/
PARRAY MakeValueArray(PGLOBAL g, PPARM pp);
/* --------------------------- Class MAPFAM -------------------------- */
/***********************************************************************/
@ -134,9 +129,9 @@ bool MAPFAM::OpenTableFile(PGLOBAL g)
&& fp->Count && fp->Mode == mode)
break;
#ifdef DEBTRACE
htrc("Mapping file, fp=%p\n", fp);
#endif
if (trace)
htrc("Mapping file, fp=%p\n", fp);
} else
fp = NULL;
@ -290,6 +285,16 @@ bool MAPFAM::RecordPos(PGLOBAL g)
return false;
} // end of RecordPos
/***********************************************************************/
/* Initialize Fpos and Mempos for indexed DELETE. */
/***********************************************************************/
int MAPFAM::InitDelete(PGLOBAL g, int fpos, int spos)
{
Fpos = Memory + fpos;
Mempos = Memory + spos;
return RC_OK;
} // end of InitDelete
/***********************************************************************/
/* Skip one record in file. */
/***********************************************************************/
@ -342,11 +347,12 @@ int MAPFAM::ReadBuffer(PGLOBAL g)
return RC_EF;
case RC_NF:
// Skip this record
if ((rc = SkipRecord(g, FALSE)) != RC_OK)
if ((rc = SkipRecord(g, false)) != RC_OK)
return rc;
goto next;
} // endswitch rc
} else
Placed = false;
@ -409,17 +415,10 @@ int MAPFAM::DeleteRecords(PGLOBAL g, int irc)
/* not required here, just setting of future Spos and Tpos. */
/*******************************************************************/
Tpos = Spos = Fpos;
Indxd = Tdbp->GetKindex() != NULL;
} // endif Tpos
if (Indxd) {
// Moving will be done later, must be done in sequential order
(void)AddListValue(g, TYPE_PCHAR, Fpos, &To_Pos);
(void)AddListValue(g, TYPE_PCHAR, Mempos, &To_Sos);
} else if ((n = Fpos - Spos) > 0) {
/*****************************************************************/
/* Non consecutive line to delete. Move intermediate lines. */
/*****************************************************************/
/*******************************************************************/
/* Non consecutive line to delete. Move intermediate lines. */
/*******************************************************************/
memmove(Tpos, Spos, n);
Tpos += n;
@ -437,10 +436,6 @@ int MAPFAM::DeleteRecords(PGLOBAL g, int irc)
} else if (To_Fb) { // Can be NULL for deleted files
/*******************************************************************/
/* Last call after EOF has been reached. */
/*******************************************************************/
Abort = (Indxd && MakeDeletedFile(g));
/*******************************************************************/
/* We must firstly Unmap the view and use the saved file handle */
/* to put an EOF at the end of the copied part of the file. */
/*******************************************************************/
@ -495,55 +490,6 @@ int MAPFAM::DeleteRecords(PGLOBAL g, int irc)
return RC_OK; // All is correct
} // end of DeleteRecords
/***********************************************************************/
/* MakeDeletedFile. When deleting using indexing, the issue is that */
/* record are not necessarily deleted in sequential order. Moving */
/* intermediate lines cannot be done while deleting them. */
/* What we do here is to reorder the deleted records and move the */
/* intermediate files from the ordered deleted record positions. */
/***********************************************************************/
bool MAPFAM::MakeDeletedFile(PGLOBAL g)
{
int *ix, i, n;
/*********************************************************************/
/* Make and order the arrays from the saved values. */
/*********************************************************************/
if (!(Posar = MakeValueArray(g, To_Pos))) {
strcpy(g->Message, "Position array is null");
goto err;
} else if (!(Sosar = MakeValueArray(g, To_Sos))) {
strcpy(g->Message, "Start position array is null");
goto err;
} else if (!(ix = (int*)Posar->GetSortIndex(g))) {
strcpy(g->Message, "Error getting array sort index");
goto err;
} // endif's
for (i = 0; i < Posar->GetNval(); i++) {
Fpos = Posar->GetStringValue(ix[i]);
if (!i) {
Tpos = Fpos;
} else if ((n = Fpos - Spos) >= 0) {
// Move all not deleted lines preceding this one
memmove(Tpos, Spos, n);
Tpos += n;
} // endif n
// New start position
Spos = Sosar->GetStringValue(ix[i]);
} // endfor i
return false;
err:
if (trace)
htrc("%s\n", g->Message);
return true;
} // end of MakeDeletedFile
/***********************************************************************/
/* Table file close routine for MAP access method. */
/***********************************************************************/
@ -734,6 +680,16 @@ bool MPXFAM::SetPos(PGLOBAL g, int pos)
return false;
} // end of SetPos
/***********************************************************************/
/* Initialize CurBlk, CurNum, Mempos and Fpos for indexed DELETE. */
/***********************************************************************/
int MPXFAM::InitDelete(PGLOBAL g, int fpos, int spos)
{
Fpos = Memory + Headlen + fpos * Lrecl;
Mempos = Fpos + Lrecl;
return RC_OK;
} // end of InitDelete
/***********************************************************************/
/* ReadBuffer: Read one line for a mapped Fix file. */
/***********************************************************************/

View File

@ -47,7 +47,7 @@ class DllExport MAPFAM : public TXTFAM {
virtual void Rewind(void);
protected:
bool MakeDeletedFile(PGLOBAL g);
virtual int InitDelete(PGLOBAL g, int fpos, int spos);
// Members
char *Memory; // Pointer on file mapping view.
@ -104,11 +104,14 @@ class DllExport MPXFAM : public MBKFAM {
virtual int MaxBlkSize(PGLOBAL g, int s)
{return TXTFAM::MaxBlkSize(g, s);}
virtual bool SetPos(PGLOBAL g, int recpos);
virtual int GetNextPos(void) {return (int)Fpos + Nrec;}
virtual bool DeferReading(void) {return false;}
virtual int ReadBuffer(PGLOBAL g);
virtual int WriteBuffer(PGLOBAL g);
protected:
virtual int InitDelete(PGLOBAL g, int fpos, int spos);
// No additional members
}; // end of class MPXFAM

View File

@ -176,7 +176,7 @@ static int dbfhead(PGLOBAL g, FILE *file, PSZ fn, DBFHEADER *buf)
/* DBFColumns: constructs the result blocks containing the description */
/* of all the columns of a DBF file that will be retrieved by #GetData. */
/****************************************************************************/
PQRYRES DBFColumns(PGLOBAL g, const char *fn, BOOL info)
PQRYRES DBFColumns(PGLOBAL g, char *dp, const char *fn, bool info)
{
int buftyp[] = {TYPE_STRING, TYPE_SHORT, TYPE_STRING,
TYPE_INT, TYPE_INT, TYPE_SHORT};
@ -186,7 +186,7 @@ PQRYRES DBFColumns(PGLOBAL g, const char *fn, BOOL info)
char buf[2], filename[_MAX_PATH];
int ncol = sizeof(buftyp) / sizeof(int);
int rc, type, len, field, fields;
BOOL bad;
bool bad;
DBFHEADER mainhead;
DESCRIPTOR thisfield;
FILE *infile = NULL;
@ -205,7 +205,7 @@ PQRYRES DBFColumns(PGLOBAL g, const char *fn, BOOL info)
/************************************************************************/
/* Open the input file. */
/************************************************************************/
PlugSetPath(filename, fn, PlgGetDataPath(g));
PlugSetPath(filename, fn, dp);
if (!(infile= global_fopen(g, MSGID_CANNOT_OPEN, filename, "rb")))
return NULL;
@ -750,6 +750,36 @@ bool DBFFAM::CopyHeader(PGLOBAL g)
return rc;
} // end of CopyHeader
#if 0 // Not useful when UseTemp is false.
/***********************************************************************/
/* Mark the line to delete with '*' (soft delete). */
/* NOTE: this is not ready for UseTemp. */
/***********************************************************************/
int DBFFAM::InitDelete(PGLOBAL g, int fpos, int spos)
{
int rc = RC_FX;
size_t lrecl = (size_t)Lrecl;
if (Nrec != 1)
strcpy(g->Message, "Cannot delete in block mode");
else if (fseek(Stream, Headlen + fpos * Lrecl, SEEK_SET))
sprintf(g->Message, MSG(FSETPOS_ERROR), 0);
else if (fread(To_Buf, 1, lrecl, Stream) != lrecl)
sprintf(g->Message, MSG(READ_ERROR), To_File, strerror(errno));
else
*To_Buf = '*';
if (fseek(Stream, Headlen + fpos * Lrecl, SEEK_SET))
sprintf(g->Message, MSG(FSETPOS_ERROR), 0);
else if (fwrite(To_Buf, 1, lrecl, Stream) != lrecl)
sprintf(g->Message, MSG(FWRITE_ERROR), strerror(errno));
else
rc = RC_NF; // Ok, Nothing else to do
return rc;
} // end of InitDelete
#endif // 0
/***********************************************************************/
/* Data Base delete line routine for DBF access methods. */
/* Deleted lines are just flagged in the first buffer character. */
@ -760,16 +790,12 @@ int DBFFAM::DeleteRecords(PGLOBAL g, int irc)
// T_Stream is the temporary stream or the table file stream itself
if (!T_Stream)
if (UseTemp) {
if ((Indxd = Tdbp->GetKindex() != NULL)) {
strcpy(g->Message, "DBF indexed udate using temp file NIY");
return RC_FX;
} else if (OpenTempFile(g))
if (OpenTempFile(g))
return RC_FX;
if (CopyHeader(g)) // For DBF tables
return RC_FX;
// Indxd = Tdbp->GetKindex() != NULL;
} else
T_Stream = Stream;
@ -809,7 +835,7 @@ void DBFFAM::CloseTableFile(PGLOBAL g, bool abort)
if (Modif && !Closing) {
// Last updated block remains to be written
Closing = true;
wrc = ReadBuffer(g);
wrc = WriteModifiedBlock(g);
} // endif Modif
if (UseTemp && T_Stream && wrc == RC_OK) {

View File

@ -1,7 +1,7 @@
/***************** FilAmDbf H Declares Source Code File (.H) ****************/
/* Name: filamdbf.h Version 1.3 */
/* Name: filamdbf.h Version 1.4 */
/* */
/* (C) Copyright to the author Olivier BERTRAND 2005-2012 */
/* (C) Copyright to the author Olivier BERTRAND 2005-2014 */
/* */
/* This file contains the DBF file access method classes declares. */
/****************************************************************************/
@ -19,7 +19,7 @@ typedef class DBMFAM *PDBMFAM;
/****************************************************************************/
/* Functions used externally. */
/****************************************************************************/
PQRYRES DBFColumns(PGLOBAL g, const char *fn, BOOL info);
PQRYRES DBFColumns(PGLOBAL g, char *dp, const char *fn, bool info);
/****************************************************************************/
/* This is the base class for dBASE file access methods. */
@ -40,8 +40,8 @@ class DllExport DBFBASE {
// Members
int Records; /* records in the file */
bool Accept; /* true if bad lines are accepted */
int Nerr; /* Number of bad records */
int Maxerr; /* Maximum number of bad records */
int Nerr; /* Number of bad records */
int Maxerr; /* Maximum number of bad records */
int ReadMode; /* 1: ALL 2: DEL 0: NOT DEL */
}; // end of class DBFBASE
@ -72,6 +72,7 @@ class DllExport DBFFAM : public FIXFAM, public DBFBASE {
protected:
virtual bool CopyHeader(PGLOBAL g);
//virtual int InitDelete(PGLOBAL g, int fpos, int spos);
// Members
}; // end of class DBFFAM

View File

@ -55,11 +55,6 @@
extern "C" int trace;
extern int num_read, num_there, num_eq[2]; // Statistics
/***********************************************************************/
/* Routine called externally by BGXFAM MakeDeletedFile function. */
/***********************************************************************/
PARRAY MakeValueArray(PGLOBAL g, PPARM pp);
/* --------------------------- Class FIXFAM -------------------------- */
/***********************************************************************/
@ -105,6 +100,16 @@ bool FIXFAM::SetPos(PGLOBAL g, int pos)
return false;
} // end of SetPos
/***********************************************************************/
/* Initialize CurBlk and CurNum for indexed DELETE. */
/***********************************************************************/
int FIXFAM::InitDelete(PGLOBAL g, int fpos, int spos)
{
CurBlk = fpos / Nrec;
CurNum = fpos % Nrec;
return RC_OK;
} // end of InitDelete
/***********************************************************************/
/* Allocate the block buffer for the table. */
/***********************************************************************/
@ -166,6 +171,45 @@ void FIXFAM::ResetBuffer(PGLOBAL g)
} // end of ResetBuffer
/***********************************************************************/
/* WriteModifiedBlock: Used when updating. */
/***********************************************************************/
int FIXFAM::WriteModifiedBlock(PGLOBAL g)
{
/*********************************************************************/
/* The old block was modified in Update mode. */
/* In Update mode we simply rewrite the old block on itself. */
/*********************************************************************/
int rc = RC_OK;
bool moved = false;
// Using temp copy any intermediate lines.
if (UseTemp && MoveIntermediateLines(g, &moved))
rc = RC_FX;
// Fpos is last position, Headlen is DBF file header length
else if (!moved && fseek(Stream, Headlen + Fpos * Lrecl, SEEK_SET)) {
sprintf(g->Message, MSG(FSETPOS_ERROR), 0);
rc = RC_FX;
} else if (fwrite(To_Buf, Lrecl, Rbuf, T_Stream) != (size_t)Rbuf) {
sprintf(g->Message, MSG(FWRITE_ERROR), strerror(errno));
rc = RC_FX;
} else
Spos = Fpos + Nrec; // + Rbuf ???
if (Closing || rc != RC_OK) { // Error or called from CloseDB
Closing = true; // To tell CloseDB about error
return rc;
} // endif Closing
// NOTE: Next line was added to avoid a very strange fread bug.
// When the fseek is not executed (even the file has the good
// pointer position) the next read can happen anywhere in the file.
OldBlk = CurBlk; // This will force fseek to be executed
Modif = 0;
return rc;
} // end of WriteModifiedBlock
/***********************************************************************/
/* ReadBuffer: Read one line for a FIX file. */
/***********************************************************************/
@ -173,84 +217,48 @@ int FIXFAM::ReadBuffer(PGLOBAL g)
{
int n, rc = RC_OK;
if (!Closing) {
/*********************************************************************/
/* Sequential reading when Placed is not true. */
/*********************************************************************/
if (Placed) {
Tdbp->SetLine(To_Buf + CurNum * Lrecl);
Placed = false;
} else if (++CurNum < Rbuf) {
Tdbp->IncLine(Lrecl); // Used by DOSCOL functions
return RC_OK;
} else if (Rbuf < Nrec && CurBlk != -1) {
return RC_EF;
} else {
/*******************************************************************/
/* Sequential reading when Placed is not true. */
/* New block. */
/*******************************************************************/
if (Placed) {
Tdbp->SetLine(To_Buf + CurNum * Lrecl);
Placed = false;
} else if (++CurNum < Rbuf) {
Tdbp->IncLine(Lrecl); // Used by DOSCOL functions
return RC_OK;
} else if (Rbuf < Nrec && CurBlk != -1) {
CurNum = 0;
Tdbp->SetLine(To_Buf);
next:
if (++CurBlk >= Block)
return RC_EF;
} else {
/*****************************************************************/
/* New block. */
/*****************************************************************/
CurNum = 0;
Tdbp->SetLine(To_Buf);
next:
if (++CurBlk >= Block)
/*******************************************************************/
/* Before reading a new block, check whether block indexing */
/* can be done, as well as for join as for local filtering. */
/*******************************************************************/
switch (Tdbp->TestBlock(g)) {
case RC_EF:
return RC_EF;
case RC_NF:
goto next;
} // endswitch rc
} // endif's
/*****************************************************************/
/* Before reading a new block, check whether block indexing */
/* can be done, as well as for join as for local filtering. */
/*****************************************************************/
switch (Tdbp->TestBlock(g)) {
case RC_EF:
return RC_EF;
case RC_NF:
goto next;
} // endswitch rc
} // endif's
if (OldBlk == CurBlk) {
IsRead = true; // Was read indeed
return RC_OK; // Block is already there
} // endif OldBlk
if (OldBlk == CurBlk) {
IsRead = true; // Was read indeed
return RC_OK; // Block is already there
} // endif OldBlk
} // endif !Closing
if (Modif) {
/*******************************************************************/
/* The old block was modified in Update mode. */
/* In Update mode we simply rewrite the old block on itself. */
/*******************************************************************/
bool moved = false;
if (UseTemp) // Copy any intermediate lines.
if (MoveIntermediateLines(g, &moved))
rc = RC_FX;
if (rc == RC_OK) {
// Fpos is last position, Headlen is DBF file header length
if (!moved && fseek(Stream, Headlen + Fpos * Lrecl, SEEK_SET)) {
sprintf(g->Message, MSG(FSETPOS_ERROR), 0);
rc = RC_FX;
} else if (fwrite(To_Buf, Lrecl, Rbuf, T_Stream) != (size_t)Rbuf) {
sprintf(g->Message, MSG(FWRITE_ERROR), strerror(errno));
rc = RC_FX;
} // endif fwrite
Spos = Fpos + Nrec; // + Rbuf ???
} // endif rc
if (Closing || rc != RC_OK) { // Error or called from CloseDB
Closing = true; // To tell CloseDB about error
return rc;
} // endif Closing
// NOTE: Next line was added to avoid a very strange fread bug.
// When the fseek is not executed (even the file has the good
// pointer position) the next read can happen anywhere in the file.
OldBlk = CurBlk; // This will force fseek to be executed
Modif = 0;
// Spos = Fpos + Nrec; done above
} // endif Mode
// Write modified block in mode UPDATE
if (Modif && (rc = WriteModifiedBlock(g)) != RC_OK)
return rc;
// This could be done only for new block. However note that FPOS
// is used as block position when updating and as line position
@ -268,8 +276,6 @@ int FIXFAM::ReadBuffer(PGLOBAL g)
if (trace > 1)
htrc("File position is now %d\n", ftell(Stream));
//long tell = ftell(Stream); not used
if (Padded)
n = fread(To_Buf, (size_t)Blksize, 1, Stream);
else
@ -340,21 +346,21 @@ int FIXFAM::WriteBuffer(PGLOBAL g)
// T_Stream is the temporary stream or the table file stream itself
if (!T_Stream) {
if (UseTemp) {
if ((Indxd = Tdbp->GetKindex() != NULL)) {
strcpy(g->Message, "FIX indexed udate using temp file NIY");
return RC_FX;
} else if (OpenTempFile(g))
if (OpenTempFile(g))
return RC_FX;
else if (CopyHeader(g)) // For DBF tables
return RC_FX;
// Indxd = Tdbp->GetKindex() != NULL;
} else
T_Stream = Stream;
} // endif T_Stream
Modif++; // Modified line in Update mode
if (Nrec > 1)
Modif++; // Modified line in blocked mode
else if (WriteModifiedBlock(g)) // Indexed update
return RC_FX;
} // endif Mode
return RC_OK;
@ -413,17 +419,12 @@ int FIXFAM::DeleteRecords(PGLOBAL g, int irc)
Spos = Tpos = Fpos;
} // endif UseTemp
Indxd = Tdbp->GetKindex() != NULL;
} // endif Tpos == Spos
/*********************************************************************/
/* Move any intermediate lines. */
/*********************************************************************/
if (Indxd) {
// Moving will be done later, must be done in sequential order
(void)AddListValue(g, TYPE_INT, &Fpos, &To_Pos);
moved = false;
} else if (MoveIntermediateLines(g, &moved))
if (MoveIntermediateLines(g, &moved))
return RC_FX;
if (irc == RC_OK) {
@ -456,9 +457,6 @@ int FIXFAM::DeleteRecords(PGLOBAL g, int irc)
return RC_FX;
} else {
if (Indxd && (Abort = MakeDeletedFile(g)))
return RC_FX;
/*****************************************************************/
/* Because the chsize functionality is only accessible with a */
/* system call we must close the file and reopen it with the */
@ -559,59 +557,6 @@ bool FIXFAM::MoveIntermediateLines(PGLOBAL g, bool *b)
return false;
} // end of MoveIntermediate Lines
/***********************************************************************/
/* MakeDeletedFile. When deleting using indexing, the issue is that */
/* record are not necessarily deleted in sequential order. Moving */
/* intermediate lines cannot be done while deleing them because */
/* this can cause extra wrong records to be included in the new file. */
/* What we do here is to reorder the deleted record and make the new */
/* deleted file from the ordered deleted records. */
/***********************************************************************/
bool FIXFAM::MakeDeletedFile(PGLOBAL g)
{
const char *crlf = "\n", *mode = UseTemp ? "rb" : "r+b";
int *ix, i;
bool moved;
/*********************************************************************/
/* Open the temporary file, Spos is at the beginning of file. */
/*********************************************************************/
if (!(Posar = MakeValueArray(g, To_Pos))) {
strcpy(g->Message, "Position array is null");
goto err;
} else if (!(ix = (int*)Posar->GetSortIndex(g))) {
strcpy(g->Message, "Error getting array sort index");
goto err;
} // endif's
Spos = 0;
for (i = 0; i < Posar->GetNval(); i++) {
Fpos = Posar->GetIntValue(ix[i]);
if (i || UseTemp) {
// Copy all not updated lines preceding this one
if (MoveIntermediateLines(g, &moved))
goto err;
} else
Tpos = Fpos;
// New start position
Spos = Fpos + 1;
} // endfor i
if (!PlugCloseFile(g, To_Fbt) && !PlugCloseFile(g, To_Fb))
return false;
err:
if (trace)
htrc("%s\n", g->Message);
PlugCloseFile(g, To_Fbt);
return true;
} // end of MakeDeletedFile
/***********************************************************************/
/* Table file close routine for FIX access method. */
/***********************************************************************/
@ -626,13 +571,12 @@ void FIXFAM::CloseTableFile(PGLOBAL g, bool abort)
if (mode == MODE_INSERT && CurNum && !Closing) {
// Some more inserted lines remain to be written
Rbuf = CurNum--;
// Closing = true;
wrc = WriteBuffer(g);
} else if (mode == MODE_UPDATE) {
if (Modif && !Closing) {
// Last updated block remains to be written
Closing = true;
wrc = ReadBuffer(g);
Closing = true; // ???
wrc = WriteModifiedBlock(g);
} // endif Modif
if (UseTemp && T_Stream && wrc == RC_OK) {
@ -640,7 +584,6 @@ void FIXFAM::CloseTableFile(PGLOBAL g, bool abort)
// Copy any remaining lines
bool b;
// Note: Indxd is not implemented yet
Fpos = Tdbp->Cardinality(g);
Abort = MoveIntermediateLines(g, &b) != RC_OK;
} // endif Abort
@ -704,7 +647,9 @@ bool BGXFAM::BigSeek(PGLOBAL g, HANDLE h, BIGINT pos, int org)
} // endif
#else // !WIN32
if (lseek64(h, pos, org) < 0) {
sprintf(g->Message, MSG(ERROR_IN_LSK), errno);
// sprintf(g->Message, MSG(ERROR_IN_LSK), errno);
sprintf(g->Message, "lseek64: %s", strerror(errno));
printf("%s\n", g->Message);
return true;
} // endif
#endif // !WIN32
@ -906,7 +851,7 @@ bool BGXFAM::OpenTableFile(PGLOBAL g)
#else // UNIX
int rc = 0;
int oflag = O_LARGEFILE; // Enable file size > 2G
mode_t tmode = 0;
mode_t tmode = S_IRUSR | S_IWUSR | S_IRGRP | S_IWGRP | S_IROTH | S_IWOTH;
/*********************************************************************/
/* Create the file object according to access mode */
@ -931,7 +876,7 @@ bool BGXFAM::OpenTableFile(PGLOBAL g)
break;
case MODE_INSERT:
oflag |= (O_WRONLY | O_CREAT | O_APPEND);
tmode = S_IREAD | S_IWRITE;
// tmode = S_IREAD | S_IWRITE;
break;
default:
sprintf(g->Message, MSG(BAD_OPEN_MODE), mode);
@ -1089,6 +1034,43 @@ int BGXFAM::Cardinality(PGLOBAL g)
} // end of Cardinality
/***********************************************************************/
/* WriteModifiedBlock: Used when updating. */
/***********************************************************************/
int BGXFAM::WriteModifiedBlock(PGLOBAL g)
{
/*********************************************************************/
/* The old block was modified in Update mode. */
/* In Update mode we simply rewrite the old block on itself. */
/*********************************************************************/
int rc = RC_OK;
bool moved = false;
if (UseTemp) // Copy any intermediate lines.
if (MoveIntermediateLines(g, &moved))
rc = RC_FX;
if (rc == RC_OK) {
// Set file position to OldBlk position (Fpos)
if (!moved && BigSeek(g, Hfile, (BIGINT)Fpos * (BIGINT)Lrecl))
rc = RC_FX;
else if (BigWrite(g, Tfile, To_Buf, Lrecl * Rbuf))
rc = RC_FX;
Spos = Fpos + Nrec; // + Rbuf ???
} // endif rc
if (Closing || rc != RC_OK) // Error or called from CloseDB
return rc;
// NOTE: Next line was added to avoid a very strange fread bug.
// When the fseek is not executed (even the file has the good
// pointer position) the next read can happen anywhere in the file.
OldBlk = CurBlk; // This will force fseek to be executed
Modif = 0;
return rc;
} // end of WriteModifiedBlock
/***********************************************************************/
/* ReadBuffer: Read Nrec lines for a big fixed/binary file. */
/***********************************************************************/
@ -1096,79 +1078,49 @@ int BGXFAM::ReadBuffer(PGLOBAL g)
{
int nbr, rc = RC_OK;
if (!Closing) {
/*********************************************************************/
/* Sequential reading when Placed is not true. */
/*********************************************************************/
if (Placed) {
Tdbp->SetLine(To_Buf + CurNum * Lrecl);
Placed = false;
} else if (++CurNum < Rbuf) {
Tdbp->IncLine(Lrecl); // Used by DOSCOL functions
return RC_OK;
} else if (Rbuf < Nrec && CurBlk != -1) {
return RC_EF;
} else {
/*******************************************************************/
/* Sequential reading when Placed is not true. */
/* New block. */
/*******************************************************************/
if (Placed) {
Tdbp->SetLine(To_Buf + CurNum * Lrecl);
Placed = false;
} else if (++CurNum < Rbuf) {
Tdbp->IncLine(Lrecl); // Used by DOSCOL functions
return RC_OK;
} else if (Rbuf < Nrec && CurBlk != -1) {
CurNum = 0;
Tdbp->SetLine(To_Buf);
next:
if (++CurBlk >= Block)
return RC_EF;
} else {
/*****************************************************************/
/* New block. */
/*****************************************************************/
CurNum = 0;
Tdbp->SetLine(To_Buf);
next:
if (++CurBlk >= Block)
/*******************************************************************/
/* Before reading a new block, check whether block optimization */
/* can be done, as well as for join as for local filtering. */
/*******************************************************************/
switch (Tdbp->TestBlock(g)) {
case RC_EF:
return RC_EF;
case RC_NF:
goto next;
} // endswitch rc
/*****************************************************************/
/* Before reading a new block, check whether block optimization */
/* can be done, as well as for join as for local filtering. */
/*****************************************************************/
switch (Tdbp->TestBlock(g)) {
case RC_EF:
return RC_EF;
case RC_NF:
goto next;
} // endswitch rc
} // endif's
} // endif's
if (OldBlk == CurBlk) {
IsRead = true; // Was read indeed
return RC_OK; // Block is already there
} // endif OldBlk
if (OldBlk == CurBlk) {
IsRead = true; // Was read indeed
return RC_OK; // Block is already there
} // endif OldBlk
} // endif !Closing
if (Modif) {
/*******************************************************************/
/* The old block was modified in Update mode. */
/* In Update mode we simply rewrite the old block on itself. */
/*******************************************************************/
bool moved = false;
if (UseTemp) // Copy any intermediate lines.
if (MoveIntermediateLines(g, &moved))
rc = RC_FX;
if (rc == RC_OK) {
// Set file position to OldBlk position (Fpos)
if (!moved && BigSeek(g, Hfile, (BIGINT)Fpos * (BIGINT)Lrecl))
rc = RC_FX;
else if (BigWrite(g, Tfile, To_Buf, Lrecl * Rbuf))
rc = RC_FX;
Spos = Fpos + Nrec; // + Rbuf ???
} // endif rc
if (Closing || rc != RC_OK) // Error or called from CloseDB
return rc;
// NOTE: Next line was added to avoid a very strange fread bug.
// When the fseek is not executed (even the file has the good
// pointer position) the next read can happen anywhere in the file.
OldBlk = CurBlk; // This will force fseek to be executed
Modif = 0;
} // endif Mode
// Write modified block in mode UPDATE
if (Modif && (rc = WriteModifiedBlock(g)) != RC_OK)
return rc;
Fpos = CurBlk * Nrec;
@ -1230,19 +1182,21 @@ int BGXFAM::WriteBuffer(PGLOBAL g)
} else { // Mode == MODE_UPDATE
// Tfile is the temporary file or the table file handle itself
if (Tfile == INVALID_HANDLE_VALUE)
{
if (Tfile == INVALID_HANDLE_VALUE) {
if (UseTemp /*&& Tdbp->GetMode() == MODE_UPDATE*/) {
if ((Indxd = Tdbp->GetKindex() != NULL)) {
strcpy(g->Message, "FIX indexed udate using temp file NIY");
return RC_FX;
} else if (OpenTempFile(g))
if (OpenTempFile(g))
return RC_FX;
} else
Tfile = Hfile;
}
Modif++; // Modified line in Update mode
} // endif Tfile
if (Nrec > 1)
Modif++; // Modified line in blocked mode
else if (WriteModifiedBlock(g)) // Indexed update
return RC_FX;
} // endif Mode
return RC_OK;
@ -1303,19 +1257,15 @@ int BGXFAM::DeleteRecords(PGLOBAL g, int irc)
Spos = Tpos = Fpos;
} // endif UseTemp
Indxd = Tdbp->GetKindex() != NULL;
} // endif Tpos == Spos
/*********************************************************************/
/* Move any intermediate lines. */
/*********************************************************************/
if (Indxd)
// Moving will be done later, must be done in sequential order
(void)AddListValue(g, TYPE_INT, &Fpos, &To_Pos);
else if (MoveIntermediateLines(g, &moved))
if (MoveIntermediateLines(g, &moved))
return RC_FX;
if (irc == RC_OK && !Indxd) {
if (irc == RC_OK) {
if (trace)
assert(Spos == Fpos);
@ -1343,9 +1293,6 @@ int BGXFAM::DeleteRecords(PGLOBAL g, int irc)
return RC_FX;
} else {
if (Indxd && (Abort = MakeDeletedFile(g)))
return RC_FX;
/*****************************************************************/
/* Remove extra records. */
/*****************************************************************/
@ -1469,59 +1416,6 @@ bool BGXFAM::MoveIntermediateLines(PGLOBAL g, bool *b)
return false;
} // end of MoveIntermediateLines
/***********************************************************************/
/* MakeDeletedFile. When deleting using indexing, the issue is that */
/* record are not necessarily deleted in sequential order. Moving */
/* intermediate lines cannot be done while deleing them because */
/* this can cause extra wrong records to be included in the new file. */
/* What we do here is to reorder the deleted record and make the new */
/* deleted file from the ordered deleted records. */
/***********************************************************************/
bool BGXFAM::MakeDeletedFile(PGLOBAL g)
{
const char *crlf = "\n", *mode = UseTemp ? "rb" : "r+b";
int *ix, i;
bool moved;
/*********************************************************************/
/* Open the temporary file, Spos is at the beginning of file. */
/*********************************************************************/
if (!(Posar = MakeValueArray(g, To_Pos))) {
strcpy(g->Message, "Position array is null");
goto err;
} else if (!(ix = (int*)Posar->GetSortIndex(g))) {
strcpy(g->Message, "Error getting array sort index");
goto err;
} // endif's
Spos = 0;
for (i = 0; i < Posar->GetNval(); i++) {
Fpos = Posar->GetIntValue(ix[i]);
if (i || UseTemp) {
// Copy all not updated lines preceding this one
if (MoveIntermediateLines(g, &moved))
goto err;
} else
Tpos = Fpos;
// New start position
Spos = Fpos + 1;
} // endfor i
if (!PlugCloseFile(g, To_Fbt))
return false;
err:
if (trace)
htrc("%s\n", g->Message);
PlugCloseFile(g, To_Fbt);
return true;
} // end of MakeDeletedFile
/***********************************************************************/
/* Data Base close routine for BIGFIX access method. */
/***********************************************************************/
@ -1541,7 +1435,7 @@ void BGXFAM::CloseTableFile(PGLOBAL g, bool abort)
if (Modif && !Closing) {
// Last updated block remains to be written
Closing = true;
wrc = ReadBuffer(g);
wrc = WriteModifiedBlock(g);
} // endif Modif
if (UseTemp && Tfile && wrc == RC_OK) {
@ -1549,7 +1443,6 @@ void BGXFAM::CloseTableFile(PGLOBAL g, bool abort)
// Copy any remaining lines
bool b;
// Indxd is not implemented yet
Fpos = Tdbp->Cardinality(g);
Abort = MoveIntermediateLines(g, &b) != RC_OK;
} // endif Abort

View File

@ -34,8 +34,10 @@ class DllExport FIXFAM : public BLKFAM {
virtual int MaxBlkSize(PGLOBAL g, int s)
{return TXTFAM::MaxBlkSize(g, s);}
virtual bool SetPos(PGLOBAL g, int recpos);
virtual int GetNextPos(void) {return Fpos + 1;}
virtual bool AllocateBuffer(PGLOBAL g);
virtual void ResetBuffer(PGLOBAL g);
virtual int WriteModifiedBlock(PGLOBAL g);
virtual int ReadBuffer(PGLOBAL g);
virtual int WriteBuffer(PGLOBAL g);
virtual int DeleteRecords(PGLOBAL g, int irc);
@ -44,7 +46,7 @@ class DllExport FIXFAM : public BLKFAM {
protected:
virtual bool CopyHeader(PGLOBAL g) {return false;}
virtual bool MoveIntermediateLines(PGLOBAL g, bool *b);
virtual bool MakeDeletedFile(PGLOBAL g);
virtual int InitDelete(PGLOBAL g, int fpos, int spos);
// No additional members
}; // end of class FIXFAM
@ -68,6 +70,7 @@ class BGXFAM : public FIXFAM {
// Methods
virtual int Cardinality(PGLOBAL g);
virtual bool OpenTableFile(PGLOBAL g);
virtual int WriteModifiedBlock(PGLOBAL g);
virtual int ReadBuffer(PGLOBAL g);
virtual int WriteBuffer(PGLOBAL g);
virtual int DeleteRecords(PGLOBAL g, int irc);
@ -77,7 +80,6 @@ class BGXFAM : public FIXFAM {
protected:
virtual bool OpenTempFile(PGLOBAL g);
virtual bool MoveIntermediateLines(PGLOBAL g, bool *b = NULL);
virtual bool MakeDeletedFile(PGLOBAL g);
int BigRead(PGLOBAL g, HANDLE h, void *inbuf, int req);
bool BigWrite(PGLOBAL g, HANDLE h, void *inbuf, int req);
bool BigSeek(PGLOBAL g, HANDLE h, BIGINT pos

View File

@ -59,7 +59,7 @@ extern int num_read, num_there, num_eq[2]; // Statistics
extern "C" int trace;
/***********************************************************************/
/* Routine called externally by DOSFAM MakeUpdatedFile function. */
/* Routine called externally by TXTFAM SortedRows functions. */
/***********************************************************************/
PARRAY MakeValueArray(PGLOBAL g, PPARM pp);
@ -102,10 +102,10 @@ TXTFAM::TXTFAM(PDOSDEF tdp)
Rbuf = 0;
Modif = 0;
Blksize = 0;
Fpos = Spos = Tpos = 0;
Padded = false;
Eof = tdp->Eof;
Ending = tdp->Ending;
Indxd = false;
Abort = false;
CrLf = (char*)(Ending == 1 ? "\n" : "\r\n");
} // end of TXTFAM standard constructor
@ -144,10 +144,12 @@ TXTFAM::TXTFAM(PTXF txfp)
Rbuf = txfp->Rbuf;
Modif = txfp->Modif;
Blksize = txfp->Blksize;
Fpos = txfp->Fpos;
Spos = txfp->Spos;
Tpos = txfp->Tpos;
Padded = txfp->Padded;
Eof = txfp->Eof;
Ending = txfp->Ending;
Indxd = txfp->Indxd;
Abort = txfp->Abort;
CrLf = txfp->CrLf;
} // end of TXTFAM copy constructor
@ -280,14 +282,17 @@ bool TXTFAM::AddListValue(PGLOBAL g, int type, void *val, PPARM *top)
PPARM pp = (PPARM)PlugSubAlloc(g, NULL, sizeof(PARM));
switch (type) {
case TYPE_INT:
pp->Value = PlugSubAlloc(g, NULL, sizeof(int));
*((int*)pp->Value) = *((int*)val);
break;
case TYPE_STRING:
pp->Value = PlugSubAlloc(g, NULL, strlen((char*)val) + 1);
strcpy((char*)pp->Value, (char*)val);
// case TYPE_INT:
// pp->Value = PlugSubAlloc(g, NULL, sizeof(int));
// *((int*)pp->Value) = *((int*)val);
// break;
case TYPE_VOID:
pp->Value = (void*)(intptr)*(int*)val;
break;
// case TYPE_STRING:
// pp->Value = PlugSubAlloc(g, NULL, strlen((char*)val) + 1);
// strcpy((char*)pp->Value, (char*)val);
// break;
case TYPE_PCHAR:
pp->Value = val;
break;
@ -302,6 +307,144 @@ bool TXTFAM::AddListValue(PGLOBAL g, int type, void *val, PPARM *top)
return false;
} // end of AddListValue
/***********************************************************************/
/* Store needed values for indexed UPDATE or DELETE. */
/***********************************************************************/
int TXTFAM::StoreValues(PGLOBAL g, bool upd)
{
int pos = GetPos();
bool rc = AddListValue(g, TYPE_VOID, &pos, &To_Pos);
if (!rc) {
pos = GetNextPos();
rc = AddListValue(g, TYPE_VOID, &pos, &To_Sos);
} // endif rc
if (upd && !rc) {
char *buf;
if (Tdbp->PrepareWriting(g))
return RC_FX;
buf = (char*)PlugSubAlloc(g, NULL, strlen(Tdbp->GetLine()) + 1);
strcpy(buf, Tdbp->GetLine());
rc = AddListValue(g, TYPE_PCHAR, buf, &To_Upd);
} // endif upd
return rc ? RC_FX : RC_OK;
} // end of StoreValues
/***********************************************************************/
/* UpdateSortedRows. When updating using indexing, the issue is that */
/* record are not necessarily updated in sequential order. */
/* Moving intermediate lines cannot be done while making them because */
/* this can cause extra wrong records to be included in the new file. */
/* What we do here is to reorder the updated records and do all the */
/* updates ordered by record position. */
/***********************************************************************/
int TXTFAM::UpdateSortedRows(PGLOBAL g)
{
int *ix, i;
/*********************************************************************/
/* Get the stored update values and sort them. */
/*********************************************************************/
if (!(Posar = MakeValueArray(g, To_Pos))) {
// strcpy(g->Message, "Position array is null");
// return RC_INFO;
return RC_OK; // Nothing to do
} else if (!(Sosar = MakeValueArray(g, To_Sos))) {
strcpy(g->Message, "Start position array is null");
goto err;
} else if (!(Updar = MakeValueArray(g, To_Upd))) {
strcpy(g->Message, "Updated line array is null");
goto err;
} else if (!(ix = (int*)Posar->GetSortIndex(g))) {
strcpy(g->Message, "Error getting array sort index");
goto err;
} // endif's
Rewind();
for (i = 0; i < Posar->GetNval(); i++) {
SetPos(g, Sosar->GetIntValue(ix[i]));
Fpos = Posar->GetIntValue(ix[i]);
strcpy(Tdbp->To_Line, Updar->GetStringValue(ix[i]));
// Now write the updated line.
if (WriteBuffer(g))
goto err;
} // endfor i
return RC_OK;
err:
if (trace)
htrc("%s\n", g->Message);
return RC_FX;
} // end of UpdateSortedRows
/***********************************************************************/
/* DeleteSortedRows. When deleting using indexing, the issue is that */
/* record are not necessarily deleted in sequential order. Moving */
/* intermediate lines cannot be done while deleing them because */
/* this can cause extra wrong records to be included in the new file. */
/* What we do here is to reorder the deleted record and delete from */
/* the file from the ordered deleted records. */
/***********************************************************************/
int TXTFAM::DeleteSortedRows(PGLOBAL g)
{
int *ix, i, irc;
/*********************************************************************/
/* Get the stored delete values and sort them. */
/*********************************************************************/
if (!(Posar = MakeValueArray(g, To_Pos))) {
// strcpy(g->Message, "Position array is null");
// return RC_INFO;
return RC_OK; // Nothing to do
} else if (!(Sosar = MakeValueArray(g, To_Sos))) {
strcpy(g->Message, "Start position array is null");
goto err;
} else if (!(ix = (int*)Posar->GetSortIndex(g))) {
strcpy(g->Message, "Error getting array sort index");
goto err;
} // endif's
Tpos = Spos = 0;
for (i = 0; i < Posar->GetNval(); i++) {
if ((irc = InitDelete(g, Posar->GetIntValue(ix[i]),
Sosar->GetIntValue(ix[i])) == RC_FX))
goto err;
// Now delete the sorted rows
if (DeleteRecords(g, irc))
goto err;
} // endfor i
return RC_OK;
err:
if (trace)
htrc("%s\n", g->Message);
return RC_FX;
} // end of DeleteSortedRows
/***********************************************************************/
/* The purpose of this function is to deal with access methods that */
/* are not coherent regarding the use of SetPos and GetPos. */
/***********************************************************************/
int TXTFAM::InitDelete(PGLOBAL g, int fpos, int spos)
{
strcpy(g->Message, "InitDelete should not be used by this table type");
return RC_FX;
} // end of InitDelete
/* --------------------------- Class DOSFAM -------------------------- */
/***********************************************************************/
@ -312,7 +455,6 @@ DOSFAM::DOSFAM(PDOSDEF tdp) : TXTFAM(tdp)
To_Fbt = NULL;
Stream = NULL;
T_Stream = NULL;
Fpos = Spos = Tpos = 0;
UseTemp = false;
Bin = false;
} // end of DOSFAM standard constructor
@ -322,9 +464,6 @@ DOSFAM::DOSFAM(PDOSFAM tdfp) : TXTFAM(tdfp)
To_Fbt = tdfp->To_Fbt;
Stream = tdfp->Stream;
T_Stream = tdfp->T_Stream;
Fpos = tdfp->Fpos;
Spos = tdfp->Spos;
Tpos = tdfp->Tpos;
UseTemp = tdfp->UseTemp;
Bin = tdfp->Bin;
} // end of DOSFAM copy constructor
@ -399,7 +538,7 @@ bool DOSFAM::OpenTableFile(PGLOBAL g)
PDBUSER dbuserp = PlgGetUser(g);
// This is required when using Unix files under Windows and vice versa
Bin = (Ending != CRLF);
Bin = (Blocked || Ending != CRLF);
switch (mode) {
case MODE_READ:
@ -441,7 +580,7 @@ bool DOSFAM::OpenTableFile(PGLOBAL g)
} // endswitch Mode
// For blocked I/O or for moving lines, open the table in binary
strcat(opmode, (Blocked || Bin) ? "b" : "t");
strcat(opmode, (Bin) ? "b" : "t");
// Now open the file stream
PlugSetPath(filename, To_File, Tdbp->GetPath());
@ -475,7 +614,7 @@ bool DOSFAM::AllocateBuffer(PGLOBAL g)
MODE mode = Tdbp->Mode;
// Lrecl does not include line ending
Buflen = Lrecl + Ending + ((Bin) ? 1 : 0) + 1;
Buflen = Lrecl + Ending + ((Bin) ? 1 : 0) + 1; // Sergei
if (trace)
htrc("SubAllocating a buffer of %d bytes\n", Buflen);
@ -551,6 +690,21 @@ bool DOSFAM::RecordPos(PGLOBAL g)
return false;
} // end of RecordPos
/***********************************************************************/
/* Initialize Fpos and the current position for indexed DELETE. */
/***********************************************************************/
int DOSFAM::InitDelete(PGLOBAL g, int fpos, int spos)
{
Fpos = fpos;
if (fseek(Stream, spos, SEEK_SET)) {
sprintf(g->Message, MSG(FSETPOS_ERROR), Fpos);
return RC_FX;
} // endif
return RC_OK;
} // end of InitDelete
/***********************************************************************/
/* Skip one record in file. */
/***********************************************************************/
@ -713,7 +867,6 @@ int DOSFAM::WriteBuffer(PGLOBAL g)
if (OpenTempFile(g))
return RC_FX;
Indxd = Tdbp->To_Kindex != NULL;
} else
T_Stream = Stream;
@ -735,20 +888,13 @@ int DOSFAM::WriteBuffer(PGLOBAL g)
if (UseTemp) {
/*****************************************************************/
/* We are using a temporary file. */
/* Before writing the updated record, we must eventually copy */
/* all the intermediate records that have not been updated. */
/*****************************************************************/
if (Indxd) {
// Copying will be done later, must be done in sequential order
(void)AddListValue(g, TYPE_INT, &Fpos, &To_Pos);
(void)AddListValue(g, TYPE_INT, &curpos, &To_Sos);
} else {
// Before writing the updated record, we must eventually copy
// all the intermediate records that have not been updated.
if (MoveIntermediateLines(g, &moved))
return RC_FX;
Spos = curpos; // New start position
} // endif Indxd
if (MoveIntermediateLines(g, &moved))
return RC_FX;
Spos = curpos; // New start position
} else
// Update is directly written back into the file,
// with this (fast) method, record size cannot change.
@ -762,28 +908,24 @@ int DOSFAM::WriteBuffer(PGLOBAL g)
/*********************************************************************/
/* Prepare the write the updated line. */
/*********************************************************************/
if (!Indxd) {
strcat(strcpy(To_Buf, Tdbp->To_Line), (Bin) ? CrLf : "\n");
strcat(strcpy(To_Buf, Tdbp->To_Line), (Bin) ? CrLf : "\n");
/*******************************************************************/
/* Now start the writing process. */
/*******************************************************************/
if ((fputs(To_Buf, T_Stream)) == EOF) {
sprintf(g->Message, MSG(FPUTS_ERROR), strerror(errno));
/*********************************************************************/
/* Now start the writing process. */
/*********************************************************************/
if ((fputs(To_Buf, T_Stream)) == EOF) {
sprintf(g->Message, MSG(FPUTS_ERROR), strerror(errno));
return RC_FX;
} // endif EOF
if (Tdbp->Mode == MODE_UPDATE && moved)
if (fseek(Stream, curpos, SEEK_SET)) {
sprintf(g->Message, MSG(FSEEK_ERROR), strerror(errno));
return RC_FX;
} // endif EOF
} // endif
if (Tdbp->Mode == MODE_UPDATE && moved)
if (fseek(Stream, curpos, SEEK_SET)) {
sprintf(g->Message, MSG(FSEEK_ERROR), strerror(errno));
return RC_FX;
} // endif
if (trace)
htrc("write done\n");
} else // Add this updated line to the updated line list
(void)AddListValue(g, TYPE_STRING, Tdbp->To_Line, &To_Upd);
if (trace)
htrc("write done\n");
return RC_OK;
} // end of WriteBuffer
@ -840,18 +982,12 @@ int DOSFAM::DeleteRecords(PGLOBAL g, int irc)
Spos = Tpos = Fpos;
} // endif UseTemp
Indxd = Tdbp->To_Kindex != NULL;
} // endif Tpos == Spos
/*********************************************************************/
/* Move any intermediate lines. */
/*********************************************************************/
if (Indxd) {
// Moving will be done later, must be done in sequential order
(void)AddListValue(g, TYPE_INT, &Fpos, &To_Pos);
(void)AddListValue(g, TYPE_INT, &curpos, &To_Sos);
moved = false;
} else if (MoveIntermediateLines(g, &moved))
if (MoveIntermediateLines(g, &moved))
return RC_FX;
if (irc == RC_OK) {
@ -874,9 +1010,6 @@ int DOSFAM::DeleteRecords(PGLOBAL g, int irc)
/* Last call after EOF has been reached. */
/* The UseTemp case is treated in CloseTableFile. */
/*******************************************************************/
if (Indxd)
Abort = MakeDeletedFile(g);
if (!UseTemp & !Abort) {
/*****************************************************************/
/* Because the chsize functionality is only accessible with a */
@ -1000,136 +1133,6 @@ bool DOSFAM::MoveIntermediateLines(PGLOBAL g, bool *b)
return false;
} // end of MoveIntermediate Lines
/***********************************************************************/
/* MakeUpdatedFile. When updating using indexing, the issue is that */
/* record are not necessarily updated in sequential order. */
/* Moving intermediate lines cannot be done while making them because */
/* this can cause extra wrong records to be included in the new file. */
/* What we do here is to reorder the updated record and make the new */
/* updated file from the ordered updated records. */
/***********************************************************************/
bool DOSFAM::MakeUpdatedFile(PGLOBAL g)
{
const char *crlf = "\n", *mode = UseTemp ? "rb" : "r+b";
int *ix, i;
bool moved, b = false;
/*********************************************************************/
/* Open the temporary file, Spos is at the beginning of file. */
/*********************************************************************/
if (!(Stream = PlugReopenFile(g, To_Fb, mode))) {
goto err;
} else if (!(Posar = MakeValueArray(g, To_Pos))) {
strcpy(g->Message, "Position array is null");
goto err;
} else if (!(Sosar = MakeValueArray(g, To_Sos))) {
strcpy(g->Message, "Start position array is null");
goto err;
} else if (!(Updar = MakeValueArray(g, To_Upd))) {
strcpy(g->Message, "Updated line array is null");
goto err;
} else if (!(ix = (int*)Posar->GetSortIndex(g))) {
strcpy(g->Message, "Error getting array sort index");
goto err;
} // endif's
Spos = 0;
for (i = 0; i < Posar->GetNval(); i++) {
Fpos = Posar->GetIntValue(ix[i]);
if (i || UseTemp) {
// Copy all not updated lines preceding this one
if (MoveIntermediateLines(g, &moved))
goto err;
} else
Tpos = Fpos;
// Now write the updated line.
strcat(strcpy(To_Buf, Updar->GetStringValue(ix[i])), CrLf);
if ((fputs(To_Buf, T_Stream)) == EOF) {
sprintf(g->Message, MSG(FPUTS_ERROR), strerror(errno));
goto err;
} // endif EOF
// New start position
Spos = Sosar->GetIntValue(ix[i]);
} // endfor i
// Copy eventually remaining lines
fseek(Stream, 0, SEEK_END);
Fpos = ftell(Stream);
b = MoveIntermediateLines(g, &moved) != RC_OK;
if (!PlugCloseFile(g, To_Fbt) && !PlugCloseFile(g, To_Fb) && !b)
return false;
err:
if (trace)
htrc("%s\n", g->Message);
PlugCloseFile(g, To_Fbt);
return true;
} // end of MakeUpdatedFile
/***********************************************************************/
/* MakeDeletedFile. When deleting using indexing, the issue is that */
/* record are not necessarily deleted in sequential order. Moving */
/* intermediate lines cannot be done while deleing them because */
/* this can cause extra wrong records to be included in the new file. */
/* What we do here is to reorder the deleted record and make the new */
/* deleted file from the ordered deleted records. */
/***********************************************************************/
bool DOSFAM::MakeDeletedFile(PGLOBAL g)
{
const char *crlf = "\n", *mode = UseTemp ? "rb" : "r+b";
int *ix, i;
bool moved;
/*********************************************************************/
/* Open the temporary file, Spos is at the beginning of file. */
/*********************************************************************/
if (!(Posar = MakeValueArray(g, To_Pos))) {
strcpy(g->Message, "Position array is null");
goto err;
} else if (!(Sosar = MakeValueArray(g, To_Sos))) {
strcpy(g->Message, "Start position array is null");
goto err;
} else if (!(ix = (int*)Posar->GetSortIndex(g))) {
strcpy(g->Message, "Error getting array sort index");
goto err;
} // endif's
Spos = 0;
for (i = 0; i < Posar->GetNval(); i++) {
Fpos = Posar->GetIntValue(ix[i]);
if (i || UseTemp) {
// Copy all not updated lines preceding this one
if (MoveIntermediateLines(g, &moved))
goto err;
} else
Tpos = Fpos;
// New start position
Spos = Sosar->GetIntValue(ix[i]);
} // endfor i
if (!PlugCloseFile(g, To_Fbt) && !PlugCloseFile(g, To_Fb))
return false;
err:
if (trace)
htrc("%s\n", g->Message);
PlugCloseFile(g, To_Fbt);
return true;
} // end of MakeDeletedFile
/***********************************************************************/
/* Delete the old file and rename the new temp file. */
/* If aborting just delete the new temp file. */
@ -1148,22 +1151,10 @@ int DOSFAM::RenameTempFile(PGLOBAL g)
// This loop is necessary because, in case of join,
// To_File can have been open several times.
for (PFBLOCK fb = PlgGetUser(g)->Openlist; fb; fb = fb->Next)
if (fb == To_Fb || (fb == To_Fbt && !Indxd))
if (fb == To_Fb || (fb == To_Fbt))
rc = PlugCloseFile(g, fb);
if (!Abort) {
// If indexed the temp file must be made
if (Indxd) {
Abort = (Tdbp->Mode == MODE_UPDATE) ? MakeUpdatedFile(g)
: MakeDeletedFile(g);
if (Abort) {
remove(tempname);
return RC_FX;
} // endif Abort
} // endif Indxd
PlugSetPath(filename, To_File, Tdbp->GetPath());
strcat(PlugRemoveType(filetemp, filename), ".ttt");
remove(filetemp); // May still be there from previous error
@ -1199,7 +1190,7 @@ void DOSFAM::CloseTableFile(PGLOBAL g, bool abort)
Abort = abort;
if (UseTemp && T_Stream) {
if (Tdbp->Mode == MODE_UPDATE && !Indxd && !Abort) {
if (Tdbp->Mode == MODE_UPDATE && !Abort) {
// Copy eventually remaining lines
bool b;

View File

@ -69,10 +69,13 @@ class DllExport TXTFAM : public BLOCK {
virtual int DeleteRecords(PGLOBAL g, int irc) = 0;
virtual void CloseTableFile(PGLOBAL g, bool abort) = 0;
virtual void Rewind(void) = 0;
virtual int InitDelete(PGLOBAL g, int fpos, int spos);
bool AddListValue(PGLOBAL g, int type, void *val, PPARM *top);
int StoreValues(PGLOBAL g, bool upd);
int UpdateSortedRows(PGLOBAL g);
int DeleteSortedRows(PGLOBAL g);
protected:
bool AddListValue(PGLOBAL g, int type, void *val, PPARM *top);
// Members
PTDBDOS Tdbp; // To table class
PSZ To_File; // Points to table file name
@ -107,9 +110,11 @@ class DllExport TXTFAM : public BLOCK {
int Modif; // Number of modified lines in block
int Blksize; // Size of padded blocks
int Ending; // Length of line end
int Fpos; // Position of last read record
int Spos; // Start position for update/delete move
int Tpos; // Target Position for delete move
bool Padded; // true if fixed size blocks are padded
bool Eof; // true if an EOF (0xA) character exists
bool Indxd; // True for indexed UPDATE/DELETE
bool Abort; // To abort on error
char *CrLf; // End of line character(s)
}; // end of class TXTFAM
@ -154,16 +159,12 @@ class DllExport DOSFAM : public TXTFAM {
virtual bool OpenTempFile(PGLOBAL g);
virtual bool MoveIntermediateLines(PGLOBAL g, bool *b);
virtual int RenameTempFile(PGLOBAL g);
virtual bool MakeUpdatedFile(PGLOBAL g);
virtual bool MakeDeletedFile(PGLOBAL g);
virtual int InitDelete(PGLOBAL g, int fpos, int spos);
// Members
FILE *Stream; // Points to Dos file structure
FILE *T_Stream; // Points to temporary file structure
PFBLOCK To_Fbt; // Pointer to temp file block
int Fpos; // Position of last read record
int Tpos; // Target Position for delete move
int Spos; // Start position for update/delete move
bool UseTemp; // True to use a temporary file in Upd/Del
bool Bin; // True to force binary mode
}; // end of class DOSFAM

View File

@ -93,11 +93,6 @@ typedef struct _vecheader {
PVBLK AllocValBlock(PGLOBAL, void *, int, int, int, int,
bool check = true, bool blank = true, bool un = false);
/***********************************************************************/
/* Routine called externally by VCTFAM MakeUpdatedFile function. */
/***********************************************************************/
PARRAY MakeValueArray(PGLOBAL g, PPARM pp);
/* -------------------------- Class VCTFAM --------------------------- */
/***********************************************************************/
@ -670,10 +665,7 @@ int VCTFAM::WriteBuffer(PGLOBAL g)
// Mode Update is done in ReadDB, we just initialize it here
if (!T_Stream) {
if (UseTemp) {
if ((Indxd = Tdbp->GetKindex() != NULL)) {
strcpy(g->Message, "VCT indexed udate using temp file NIY");
return RC_FX;
} else if (OpenTempFile(g))
if (OpenTempFile(g))
return RC_FX;
// Most of the time, not all table columns are updated.
@ -792,17 +784,12 @@ int VCTFAM::DeleteRecords(PGLOBAL g, int irc)
Spos = Tpos = Fpos;
} // endif UseTemp
Indxd = Tdbp->GetKindex() != NULL;
} // endif Tpos == Spos
/*********************************************************************/
/* Move any intermediate lines. */
/*********************************************************************/
if (Indxd) {
// Moving will be done later, must be done in sequential order
(void)AddListValue(g, TYPE_INT, &Fpos, &To_Pos);
Spos = Fpos;
} else if (MoveIntermediateLines(g, &eof))
if (MoveIntermediateLines(g, &eof))
return RC_FX;
if (irc == RC_OK) {
@ -822,11 +809,6 @@ int VCTFAM::DeleteRecords(PGLOBAL g, int irc)
/* Last call after EOF has been reached. */
/* Update the Block and Last values. */
/*******************************************************************/
if (Indxd && (Abort = MakeDeletedFile(g)))
return RC_FX;
else
Indxd = false; // Not to be redone by RenameTempFile
Block = (Tpos > 0) ? (Tpos + Nrec - 1) / Nrec : 0;
Last = (Tpos + Nrec - 1) % Nrec + 1;
@ -1026,63 +1008,6 @@ bool VCTFAM::MoveIntermediateLines(PGLOBAL g, bool *b)
return false;
} // end of MoveIntermediateLines
/***********************************************************************/
/* MakeDeletedFile. When deleting using indexing, the issue is that */
/* record are not necessarily deleted in sequential order. Moving */
/* intermediate lines cannot be done while deleing them because */
/* this can cause extra wrong records to be included in the new file. */
/* What we do here is to reorder the deleted record and make the new */
/* deleted file from the ordered deleted records. */
/***********************************************************************/
bool VCTFAM::MakeDeletedFile(PGLOBAL g)
{
//char *crlf = "\n", *mode = UseTemp ? "rb" : "r+b";
int *ix, i, n;
bool eof = false;
/*********************************************************************/
/* Open the temporary file, Spos is at the beginning of file. */
/*********************************************************************/
if (!(Posar = MakeValueArray(g, To_Pos))) {
strcpy(g->Message, "Position array is null");
goto err;
} else if (!(ix = (int*)Posar->GetSortIndex(g))) {
strcpy(g->Message, "Error getting array sort index");
goto err;
} // endif's
n = Posar->GetNval();
Spos = 0;
for (i = 0; i < n; i++) {
if (i == n - 1 && !MaxBlk && UseTemp)
eof = true;
Fpos = Posar->GetIntValue(ix[i]);
if (i || UseTemp) {
// Copy all not updated lines preceding this one
if (MoveIntermediateLines(g, &eof))
goto err;
} else
Tpos = Fpos;
// New start position
Spos = Fpos + 1;
} // endfor i
if (!PlugCloseFile(g, To_Fbt))
return false;
err:
if (trace)
htrc("%s\n", g->Message);
PlugCloseFile(g, To_Fbt);
return true;
} // end of MakeDeletedFile
/***********************************************************************/
/* Clean deleted space in a VCT or Vec table file. */
/***********************************************************************/
@ -1701,13 +1626,7 @@ int VCMFAM::DeleteRecords(PGLOBAL g, int irc)
/* not required here, just setting of future Spos and Tpos. */
/*******************************************************************/
Tpos = Spos = Fpos;
Indxd = Tdbp->GetKindex() != NULL;
} // endif Tpos
if (Indxd)
// Moving will be done later, must be done in sequential order
(void)AddListValue(g, TYPE_INT, &Fpos, &To_Pos);
else
} else
(void)MoveIntermediateLines(g);
if (irc == RC_OK) {
@ -1716,7 +1635,7 @@ int VCMFAM::DeleteRecords(PGLOBAL g, int irc)
if (trace)
htrc("after: Tpos=%p Spos=%p\n", Tpos, Spos);
} else if (!(Abort = (Indxd && MakeDeletedFile(g)))) {
} else {
/*******************************************************************/
/* Last call after EOF has been reached. */
/*******************************************************************/
@ -1786,8 +1705,7 @@ int VCMFAM::DeleteRecords(PGLOBAL g, int irc)
// Reset Last and Block values in the catalog
PlugCloseFile(g, To_Fb); // in case of Header
ResetTableSize(g, Block, Last);
} else
return RC_FX;
} // endif irc
return RC_OK; // All is correct
} // end of DeleteRecords
@ -1841,49 +1759,6 @@ bool VCMFAM::MoveIntermediateLines(PGLOBAL g, bool *b)
return false;
} // end of MoveIntermediate Lines
/***********************************************************************/
/* MakeDeletedFile. When deleting using indexing, the issue is that */
/* record are not necessarily deleted in sequential order. Moving */
/* intermediate lines cannot be done while deleting them. */
/* What we do here is to reorder the deleted records and move the */
/* intermediate files from the ordered deleted record positions. */
/***********************************************************************/
bool VCMFAM::MakeDeletedFile(PGLOBAL g)
{
int *ix, i;
/*********************************************************************/
/* Make and order the arrays from the saved values. */
/*********************************************************************/
if (!(Posar = MakeValueArray(g, To_Pos))) {
strcpy(g->Message, "Position array is null");
goto err;
} else if (!(ix = (int*)Posar->GetSortIndex(g))) {
strcpy(g->Message, "Error getting array sort index");
goto err;
} // endif's
for (i = 0; i < Posar->GetNval(); i++) {
Fpos = Posar->GetIntValue(ix[i]);
if (!i) {
Tpos = Fpos;
} else
(void)MoveIntermediateLines(g);
// New start position
Spos = Fpos + 1;
} // endfor i
return false;
err:
if (trace)
htrc("%s\n", g->Message);
return true;
} // end of MakeDeletedFile
/***********************************************************************/
/* Data Base close routine for VMP access method. */
/***********************************************************************/
@ -2309,10 +2184,7 @@ int VECFAM::WriteBuffer(PGLOBAL g)
} else // Mode Update
// Writing updates being done in ReadDB we do initialization only.
if (InitUpdate) {
if ((Indxd = Tdbp->GetKindex() != NULL)) {
strcpy(g->Message, "VEC indexed udate using temp file NIY");
return RC_FX;
} else if (OpenTempFile(g))
if (OpenTempFile(g))
return RC_FX;
InitUpdate = false; // Done
@ -2360,17 +2232,12 @@ int VECFAM::DeleteRecords(PGLOBAL g, int irc)
/*****************************************************************/
Spos = Tpos = Fpos;
Indxd = Tdbp->GetKindex() != NULL;
} // endif Tpos == Spos
/*********************************************************************/
/* Move any intermediate lines. */
/*********************************************************************/
if (Indxd) {
// Moving will be done later, must be done in sequential order
(void)AddListValue(g, TYPE_INT, &Fpos, &To_Pos);
Spos = Fpos;
} else if (MoveIntermediateLines(g))
if (MoveIntermediateLines(g))
return RC_FX;
if (irc == RC_OK) {
@ -2386,11 +2253,6 @@ int VECFAM::DeleteRecords(PGLOBAL g, int irc)
/*******************************************************************/
/* Last call after EOF has been reached. */
/*******************************************************************/
if (Indxd && (Abort = MakeDeletedFile(g)))
return RC_FX;
// else
// Indxd = false; // Not to be redone by RenameTempFile
if (!UseTemp) {
/*****************************************************************/
/* Because the chsize functionality is only accessible with a */
@ -2560,56 +2422,6 @@ bool VECFAM::MoveIntermediateLines(PGLOBAL g, bool *bn)
return false;
} // end of MoveIntermediate Lines
/***********************************************************************/
/* MakeDeletedFile. When deleting using indexing, the issue is that */
/* record are not necessarily deleted in sequential order. Moving */
/* intermediate lines cannot be done while deleing them because */
/* this can cause extra wrong records to be included in the new file. */
/* What we do here is to reorder the deleted record and make the new */
/* deleted file from the ordered deleted records. */
/***********************************************************************/
bool VECFAM::MakeDeletedFile(PGLOBAL g)
{
int *ix, i, n;
/*********************************************************************/
/* Open the temporary file, Spos is at the beginning of file. */
/*********************************************************************/
if (!(Posar = MakeValueArray(g, To_Pos))) {
strcpy(g->Message, "Position array is null");
goto err;
} else if (!(ix = (int*)Posar->GetSortIndex(g))) {
strcpy(g->Message, "Error getting array sort index");
goto err;
} // endif's
n = Posar->GetNval();
Spos = 0;
for (i = 0; i < n; i++) {
Fpos = Posar->GetIntValue(ix[i]);
if (i || UseTemp) {
// Copy all not updated lines preceding this one
if (MoveIntermediateLines(g))
goto err;
} else
Tpos = Fpos;
// New start position
Spos = Fpos + 1;
} // endfor i
return false;
err:
if (trace)
htrc("%s\n", g->Message);
return true;
} // end of MakeDeletedFile
/***********************************************************************/
/* Delete the old files and rename the new temporary files. */
/***********************************************************************/
@ -3109,13 +2921,7 @@ int VMPFAM::DeleteRecords(PGLOBAL g, int irc)
/* not required here, just setting of future Spos and Tpos. */
/*******************************************************************/
Tpos = Fpos; // Spos is set below
Indxd = Tdbp->GetKindex() != NULL;
} // endif Tpos
if (Indxd)
// Moving will be done later, must be done in sequential order
(void)AddListValue(g, TYPE_INT, &Fpos, &To_Pos);
else if ((n = Fpos - Spos) > 0) {
} else if ((n = Fpos - Spos) > 0) {
/*******************************************************************/
/* Non consecutive line to delete. Move intermediate lines. */
/*******************************************************************/
@ -3137,7 +2943,7 @@ int VMPFAM::DeleteRecords(PGLOBAL g, int irc)
if (trace)
htrc("after: Tpos=%p Spos=%p\n", Tpos, Spos);
} else if (!(Abort = (Indxd && MakeDeletedFile(g)))) {
} else {
/*******************************************************************/
/* Last call after EOF has been reached. */
/* We must firstly Unmap the view and use the saved file handle */
@ -3198,55 +3004,6 @@ int VMPFAM::DeleteRecords(PGLOBAL g, int irc)
return RC_OK; // All is correct
} // end of DeleteRecords
/***********************************************************************/
/* MakeDeletedFile. When deleting using indexing, the issue is that */
/* record are not necessarily deleted in sequential order. Moving */
/* intermediate lines cannot be done while deleting them. */
/* What we do here is to reorder the deleted records and move the */
/* intermediate files from the ordered deleted record positions. */
/***********************************************************************/
bool VMPFAM::MakeDeletedFile(PGLOBAL g)
{
int *ix, i, j, m, n;
/*********************************************************************/
/* Make and order the arrays from the saved values. */
/*********************************************************************/
if (!(Posar = MakeValueArray(g, To_Pos))) {
strcpy(g->Message, "Position array is null");
goto err;
} else if (!(ix = (int*)Posar->GetSortIndex(g))) {
strcpy(g->Message, "Error getting array sort index");
goto err;
} // endif's
for (i = 0; i < Posar->GetNval(); i++) {
Fpos = Posar->GetIntValue(ix[i]);
if (!i) {
Tpos = Fpos;
} else if ((n = Fpos - Spos) > 0) {
for (j = 0; j < Ncol; j++) {
m = Clens[j];
memmove(Memcol[j] + Tpos * m, Memcol[j] + Spos * m, m * n);
} // endif j
Tpos += n;
} // endif n
// New start position
Spos = Fpos + 1;
} // endfor i
return false;
err:
if (trace)
htrc("%s\n", g->Message);
return true;
} // end of MakeDeletedFile
/***********************************************************************/
/* Data Base close routine for VMP access method. */
/***********************************************************************/
@ -3969,10 +3726,7 @@ int BGVFAM::WriteBuffer(PGLOBAL g)
// Mode Update is done in ReadDB, we just initialize it here
if (Tfile == INVALID_HANDLE_VALUE) {
if (UseTemp) {
if ((Indxd = Tdbp->GetKindex() != NULL)) {
strcpy(g->Message, "VEC indexed udate using temp file NIY");
return RC_FX;
} else if (OpenTempFile(g))
if (OpenTempFile(g))
return RC_FX;
// Most of the time, not all table columns are updated.
@ -4099,17 +3853,12 @@ int BGVFAM::DeleteRecords(PGLOBAL g, int irc)
Spos = Tpos = Fpos;
} // endif UseTemp
Indxd = Tdbp->GetKindex() != NULL;
} // endif Tpos == Spos
/*********************************************************************/
/* Move any intermediate lines. */
/*********************************************************************/
if (Indxd) {
// Moving will be done later, must be done in sequential order
(void)AddListValue(g, TYPE_INT, &Fpos, &To_Pos);
Spos = Fpos;
} else if (MoveIntermediateLines(g, &eof))
if (MoveIntermediateLines(g, &eof))
return RC_FX;
if (irc == RC_OK) {
@ -4125,11 +3874,6 @@ int BGVFAM::DeleteRecords(PGLOBAL g, int irc)
/*******************************************************************/
/* Last call after EOF has been reached. */
/*******************************************************************/
if (Indxd && (Abort = MakeDeletedFile(g)))
return RC_FX;
else
Indxd = false; // Not to be redone by RenameTempFile
Block = (Tpos > 0) ? (Tpos + Nrec - 1) / Nrec : 0;
Last = (Tpos + Nrec - 1) % Nrec + 1;

View File

@ -66,7 +66,6 @@ class DllExport VCTFAM : public FIXFAM {
virtual bool MoveLines(PGLOBAL g) {return false;}
virtual bool MoveIntermediateLines(PGLOBAL g, bool *b = NULL);
virtual bool CleanUnusedSpace(PGLOBAL g);
virtual bool MakeDeletedFile(PGLOBAL g);
virtual int GetBlockInfo(PGLOBAL g);
virtual bool SetBlockInfo(PGLOBAL g);
bool ResetTableSize(PGLOBAL g, int block, int last);
@ -116,7 +115,6 @@ class DllExport VCMFAM : public VCTFAM {
protected:
// Specific functions
virtual bool MoveIntermediateLines(PGLOBAL g, bool *b = NULL);
virtual bool MakeDeletedFile(PGLOBAL g);
virtual bool ReadBlock(PGLOBAL g, PVCTCOL colp);
virtual bool WriteBlock(PGLOBAL g, PVCTCOL colp);
@ -162,7 +160,6 @@ class DllExport VECFAM : public VCTFAM {
virtual bool MoveLines(PGLOBAL g);
virtual bool MoveIntermediateLines(PGLOBAL g, bool *b = NULL);
virtual int RenameTempFile(PGLOBAL g);
virtual bool MakeDeletedFile(PGLOBAL g);
bool OpenColumnFile(PGLOBAL g, char *opmode, int i);
// Members
@ -199,7 +196,6 @@ class DllExport VMPFAM : public VCMFAM {
virtual void CloseTableFile(PGLOBAL g, bool abort);
protected:
virtual bool MakeDeletedFile(PGLOBAL g);
bool MapColumnFile(PGLOBAL g, MODE mode, int i);
// Members

View File

@ -170,8 +170,8 @@
#define SZWMIN 4194304 // Minimum work area size 4M
extern "C" {
char version[]= "Version 1.03.0002 July 17, 2014";
char compver[]= "Version 1.03.0002 " __DATE__ " " __TIME__;
char version[]= "Version 1.03.0003 August 22, 2014";
char compver[]= "Version 1.03.0003 " __DATE__ " " __TIME__;
#if defined(WIN32)
char slash= '\\';
@ -185,11 +185,13 @@ extern "C" {
int trace= 0; // The general trace value
int xconv= 0; // The type conversion option
int zconv= SZCONV; // The text conversion size
USETEMP Use_Temp= TMP_AUTO; // The temporary file use
} // extern "C"
#if defined(XMAP)
bool xmap= false;
#endif // XMAP
bool xinfo= false;
uint worksize= SZWORK;
ulong ha_connect::num= 0;
@ -200,9 +202,11 @@ static int xtrace= 0;
static int conv_size= SZCONV;
static uint work_size= SZWORK;
static ulong type_conv= 0;
static ulong use_tempfile= 1;
#if defined(XMAP)
static my_bool indx_map= 0;
#endif // XMAP
static my_bool exact_info= 0;
/***********************************************************************/
/* Utility functions. */
@ -224,11 +228,14 @@ static int connect_assisted_discovery(handlerton *hton, THD* thd,
TABLE_SHARE *table_s,
HA_CREATE_INFO *info);
/***********************************************************************/
/* Global variables update functions. */
/***********************************************************************/
static void update_connect_xtrace(MYSQL_THD thd,
struct st_mysql_sys_var *var,
void *var_ptr, const void *save)
{
xtrace= *(int *)var_ptr= *(int *)save;
trace= *(int *)var_ptr= *(int *)save;
} // end of update_connect_xtrace
static void update_connect_zconv(MYSQL_THD thd,
@ -252,6 +259,13 @@ static void update_connect_worksize(MYSQL_THD thd,
worksize= (uint)(*(ulong *)var_ptr= *(ulong *)save);
} // end of update_connect_worksize
static void update_connect_usetemp(MYSQL_THD thd,
struct st_mysql_sys_var *var,
void *var_ptr, const void *save)
{
Use_Temp= (USETEMP)(*(ulong *)var_ptr= *(ulong *)save);
} // end of update_connect_usetemp
#if defined(XMAP)
static void update_connect_xmap(MYSQL_THD thd,
struct st_mysql_sys_var *var,
@ -261,6 +275,13 @@ static void update_connect_xmap(MYSQL_THD thd,
} // end of update_connect_xmap
#endif // XMAP
static void update_connect_xinfo(MYSQL_THD thd,
struct st_mysql_sys_var *var,
void *var_ptr, const void *save)
{
xinfo= (bool)(*(my_bool *)var_ptr= *(my_bool *)save);
} // end of update_connect_xinfo
/***********************************************************************/
/* The CONNECT handlerton object. */
/***********************************************************************/
@ -542,6 +563,11 @@ ha_connect::ha_connect(handlerton *hton, TABLE_SHARE *table_arg)
xp= (table) ? GetUser(ha_thd(), NULL) : NULL;
if (xp)
xp->SetHandler(this);
#if defined(WIN32)
datapath= ".\\";
#else // !WIN32
datapath= "./";
#endif // !WIN32
tdbp= NULL;
sdvalin= NULL;
sdvalout= NULL;
@ -555,7 +581,7 @@ ha_connect::ha_connect(handlerton *hton, TABLE_SHARE *table_arg)
stop= false;
alter= false;
mrr= false;
nox= false;
nox= true;
abort= false;
indexing= -1;
locked= 0;
@ -1381,6 +1407,14 @@ void ha_connect::AddColName(char *cp, Field *fp)
} // end of AddColName
#endif // 0
/***********************************************************************/
/* This function sets the current database path. */
/***********************************************************************/
void ha_connect::SetDataPath(PGLOBAL g, const char *path)
{
datapath= SetPath(g, path);
} // end of SetDataPath
/****************************************************************************/
/* Get the table description block of a CONNECT table. */
/****************************************************************************/
@ -1590,7 +1624,7 @@ int ha_connect::CloseTable(PGLOBAL g)
sdvalout=NULL;
valid_info= false;
indexing= -1;
nox= false;
nox= true;
abort= false;
return rc;
} // end of CloseTable
@ -1697,10 +1731,10 @@ int ha_connect::MakeRecord(char *buf)
// Store functions returns 1 on overflow and -1 on fatal error
if (rc > 0) {
char buf[128];
char buf[256];
THD *thd= ha_thd();
sprintf(buf, "Out of range value %s for column '%s' at row %ld",
sprintf(buf, "Out of range value %.140s for column '%s' at row %ld",
value->GetCharString(val),
fp->field_name,
thd->get_stmt_da()->current_row_for_warning());
@ -2642,7 +2676,6 @@ int ha_connect::open(const char *name, int mode, uint test_if_locked)
int ha_connect::optimize(THD* thd, HA_CHECK_OPT* check_opt)
{
int rc= 0;
bool dop= (check_opt != NULL);
PGLOBAL& g= xp->g;
PDBUSER dup= PlgGetUser(g);
@ -2652,9 +2685,10 @@ int ha_connect::optimize(THD* thd, HA_CHECK_OPT* check_opt)
dup->Check |= CHK_OPT;
if (tdbp) {
bool b= (((PTDBASE)tdbp)->GetDef()->Indexable() == 1);
bool dop= IsTypeIndexable(GetRealType(NULL));
bool dox= (((PTDBASE)tdbp)->GetDef()->Indexable() == 1);
if ((rc= ((PTDBASE)tdbp)->ResetTableOpt(g, dop, b))) {
if ((rc= ((PTDBASE)tdbp)->ResetTableOpt(g, dop, dox))) {
if (rc == RC_INFO) {
push_warning(thd, Sql_condition::WARN_LEVEL_WARN, 0, g->Message);
rc= 0;
@ -2739,7 +2773,8 @@ int ha_connect::write_row(uchar *buf)
DBUG_RETURN(0); // Alter table on an outward partition table
xmod= MODE_INSERT;
} // endif xmod
} else if (xmod == MODE_ANY)
DBUG_RETURN(0); // Probably never met
// Open the table if it was not opened yet (locked)
if (!IsOpened() || xmod != tdbp->GetMode()) {
@ -2751,9 +2786,6 @@ int ha_connect::write_row(uchar *buf)
} // endif isopened
if (tdbp->GetMode() == MODE_ANY)
DBUG_RETURN(0);
#if 0 // AUTO_INCREMENT NIY
if (table->next_number_field && buf == table->record[0]) {
int error;
@ -2773,7 +2805,8 @@ int ha_connect::write_row(uchar *buf)
DBUG_PRINT("write_row", ("%s", g->Message));
htrc("write_row: %s\n", g->Message);
rc= HA_ERR_INTERNAL_ERROR;
} // endif RC
} else // Table is modified
nox= false; // Indexes to be remade
DBUG_RETURN(rc);
} // end of write_row
@ -2818,7 +2851,8 @@ int ha_connect::update_row(const uchar *old_data, uchar *new_data)
DBUG_PRINT("update_row", ("%s", g->Message));
htrc("update_row CONNECT: %s\n", g->Message);
rc= HA_ERR_INTERNAL_ERROR;
} // endif RC
} else
nox= false; // Table is modified
DBUG_RETURN(rc);
} // end of update_row
@ -2851,7 +2885,8 @@ int ha_connect::delete_row(const uchar *buf)
if (CntDeleteRow(xp->g, tdbp, false)) {
rc= HA_ERR_INTERNAL_ERROR;
htrc("delete_row CONNECT: %s\n", xp->g->Message);
} // endif DeleteRow
} else
nox= false; // To remake indexes
DBUG_RETURN(rc);
} // end of delete_row
@ -2898,7 +2933,7 @@ int ha_connect::index_init(uint idx, bool sorted)
DBUG_RETURN(0);
} // endif locked
indexing= CntIndexInit(g, tdbp, (signed)idx);
indexing= CntIndexInit(g, tdbp, (signed)idx, sorted);
if (indexing <= 0) {
DBUG_PRINT("index_init", ("%s", g->Message));
@ -2911,8 +2946,10 @@ int ha_connect::index_init(uint idx, bool sorted)
((PTDBDOX)tdbp)->GetTxfp()->ResetBuffer(g);
active_index= idx;
} else // Void table
indexing= 0;
// } else { // Void table
// active_index= MAX_KEY;
// indexing= 0;
} // endif Num
rc= 0;
} // endif indexing
@ -3418,8 +3455,10 @@ int ha_connect::info(uint flag)
} // endif xmod
// This is necessary for getting file length
if (cat && table)
cat->SetDataPath(g, table->s->db.str);
// if (cat && table)
// cat->SetDataPath(g, table->s->db.str);
if (table)
SetDataPath(g, table->s->db.str);
else
DBUG_RETURN(HA_ERR_INTERNAL_ERROR); // Should never happen
@ -3535,7 +3574,8 @@ int ha_connect::delete_all_rows()
if (CntDeleteRow(g, tdbp, true)) {
htrc("%s\n", g->Message);
rc= HA_ERR_INTERNAL_ERROR;
} // endif
} else
nox= false;
} // endif rc
@ -4741,7 +4781,7 @@ static int connect_assisted_discovery(handlerton *hton, THD* thd,
const char *fncn= "?";
const char *user, *fn, *db, *host, *pwd, *sep, *tbl, *src;
const char *col, *ocl, *rnk, *pic, *fcl, *skc;
char *tab, *dsn, *shm;
char *tab, *dsn, *shm, *dpath;
#if defined(WIN32)
char *nsp= NULL, *cls= NULL;
#endif // WIN32
@ -4935,7 +4975,7 @@ static int connect_assisted_discovery(handlerton *hton, THD* thd,
} else if (!user)
user= "root";
if (CheckSelf(g, table_s, host, db, tab, src, port))
if (ok && CheckSelf(g, table_s, host, db, tab, src, port))
ok= false;
break;
@ -4986,10 +5026,12 @@ static int connect_assisted_discovery(handlerton *hton, THD* thd,
char *cnm, *rem, *dft, *xtra;
int i, len, prec, dec, typ, flg;
if (cat)
cat->SetDataPath(g, table_s->db.str);
else
return HA_ERR_INTERNAL_ERROR; // Should never happen
// if (cat)
// cat->SetDataPath(g, table_s->db.str);
// else
// return HA_ERR_INTERNAL_ERROR; // Should never happen
dpath= SetPath(g, table_s->db.str);
if (src && ttp != TAB_PIVOT && ttp != TAB_ODBC) {
qrp= SrcColumns(g, host, db, user, pwd, src, port);
@ -5002,7 +5044,7 @@ static int connect_assisted_discovery(handlerton *hton, THD* thd,
} else switch (ttp) {
case TAB_DBF:
qrp= DBFColumns(g, fn, fnc == FNC_COL);
qrp= DBFColumns(g, dpath, fn, fnc == FNC_COL);
break;
#if defined(ODBC_SUPPORT)
case TAB_ODBC:
@ -5039,7 +5081,7 @@ static int connect_assisted_discovery(handlerton *hton, THD* thd,
break;
#endif // MYSQL_SUPPORT
case TAB_CSV:
qrp= CSVColumns(g, fn, spc, qch, hdr, mxe, fnc == FNC_COL);
qrp= CSVColumns(g, dpath, fn, spc, qch, hdr, mxe, fnc == FNC_COL);
break;
#if defined(WIN32)
case TAB_WMI:
@ -5705,8 +5747,10 @@ int ha_connect::create(const char *name, TABLE *table_arg,
PDBUSER dup= PlgGetUser(g);
PCATLG cat= (dup) ? dup->Catalog : NULL;
SetDataPath(g, table_arg->s->db.str);
if (cat) {
cat->SetDataPath(g, table_arg->s->db.str);
// cat->SetDataPath(g, table_arg->s->db.str);
#if defined(WITH_PARTITION_STORAGE_ENGINE)
if (part_info)
@ -6196,6 +6240,9 @@ Item *ha_connect::idx_cond_push(uint keyno_arg, Item* idx_cond_arg)
struct st_mysql_storage_engine connect_storage_engine=
{ MYSQL_HANDLERTON_INTERFACE_VERSION };
/***********************************************************************/
/* CONNECT global variables definitions. */
/***********************************************************************/
// Tracing: 0 no, 1 yes, >1 more tracing
static MYSQL_SYSVAR_INT(xtrace, xtrace,
PLUGIN_VAR_RQCMDARG, "Console trace value.",
@ -6233,6 +6280,35 @@ static MYSQL_SYSVAR_ENUM(
0, // def (no)
&xconv_typelib); // typelib
/**
Temporary file usage:
no: Not using temporary file
auto: Using temporary file when needed
yes: Allways using temporary file
force: Force using temporary file (no MAP)
test: Reserved
*/
const char *usetemp_names[]=
{
"NO", "AUTO", "YES", "FORCE", "TEST", NullS
};
TYPELIB usetemp_typelib=
{
array_elements(usetemp_names) - 1, "usetemp_typelib",
usetemp_names, NULL
};
static MYSQL_SYSVAR_ENUM(
use_tempfile, // name
use_tempfile, // varname
PLUGIN_VAR_RQCMDARG, // opt
"Temporary file use.", // comment
NULL, // check
update_connect_usetemp, // update function
1, // def (AUTO)
&usetemp_typelib); // typelib
#if defined(XMAP)
// Using file mapping for indexes if true
static MYSQL_SYSVAR_BOOL(indx_map, indx_map, PLUGIN_VAR_RQCMDARG,
@ -6245,6 +6321,11 @@ static MYSQL_SYSVAR_UINT(work_size, work_size,
PLUGIN_VAR_RQCMDARG, "Size of the CONNECT work area.",
NULL, update_connect_worksize, SZWORK, SZWMIN, UINT_MAX, 1);
// Getting exact info values
static MYSQL_SYSVAR_BOOL(exact_info, exact_info, PLUGIN_VAR_RQCMDARG,
"Getting exact info values",
NULL, update_connect_xinfo, 0);
static struct st_mysql_sys_var* connect_system_variables[]= {
MYSQL_SYSVAR(xtrace),
MYSQL_SYSVAR(conv_size),
@ -6253,6 +6334,8 @@ static struct st_mysql_sys_var* connect_system_variables[]= {
MYSQL_SYSVAR(indx_map),
#endif // XMAP
MYSQL_SYSVAR(work_size),
MYSQL_SYSVAR(use_tempfile),
MYSQL_SYSVAR(exact_info),
NULL
};

View File

@ -210,7 +210,9 @@ public:
bool IsSameIndex(PIXDEF xp1, PIXDEF xp2);
bool IsPartitioned(void);
bool IsUnique(uint n);
char *GetDataPath(void) {return (char*)datapath;}
void SetDataPath(PGLOBAL g, const char *path);
PTDB GetTDB(PGLOBAL g);
int OpenTable(PGLOBAL g, bool del= false);
bool CheckColumnList(PGLOBAL g);
@ -521,6 +523,7 @@ protected:
ulong hnum; // The number of this handler
query_id_t valid_query_id; // The one when tdbp was allocated
query_id_t creat_query_id; // The one when handler was allocated
char *datapath; // Is the Path of DB data directory
PTDB tdbp; // To table class object
PVAL sdvalin; // Used to convert date values
PVAL sdvalout; // Used to convert date values

View File

@ -154,7 +154,7 @@ HANDLE CreateFileMap(PGLOBAL g, LPCSTR fileName,
} // endswitch
// Try to open the addressed file.
fd= global_open(g, MSGID_NONE, fileName, openMode);
fd= global_open(g, MSGID_NONE, fileName, openMode);
if (fd != INVALID_HANDLE_VALUE && mode != MODE_INSERT) {
/* We must know about the size of the file. */
@ -164,17 +164,19 @@ HANDLE CreateFileMap(PGLOBAL g, LPCSTR fileName,
return INVALID_HANDLE_VALUE;
} // endif fstat
filesize = st.st_size;
// Now we are ready to load the file. If mmap() is available we try
// this first. If not available or it failed we try to load it.
mm->memory = mmap(NULL, filesize, protmode, MAP_SHARED, fd, 0);
if ((filesize = st.st_size))
// Now we are ready to load the file. If mmap() is available we try
// this first. If not available or it failed we try to load it.
mm->memory = mmap(NULL, filesize, protmode, MAP_SHARED, fd, 0);
else
mm->memory = 0;
if (mm->memory != MAP_FAILED) {
mm->lenL = (mm->memory != 0) ? filesize : 0;
mm->lenH = 0;
} else {
strcpy(g->Message, "Memory mapping failed");
close(fd);
return INVALID_HANDLE_VALUE;
} // endif memory

View File

@ -405,9 +405,9 @@ PQRYRES OEMColumns(PGLOBAL g, PTOS topt, char *tab, char *db, bool info)
CATALOG::CATALOG(void)
{
#if defined(WIN32)
DataPath= ".\\";
//DataPath= ".\\";
#else // !WIN32
DataPath= "./";
//DataPath= "./";
#endif // !WIN32
memset(&Ctb, 0, sizeof(CURTAB));
Cbuf= NULL;
@ -433,6 +433,7 @@ void MYCAT::Reset(void)
{
} // end of Reset
#if 0
/***********************************************************************/
/* This function sets the current database path. */
/***********************************************************************/
@ -463,6 +464,7 @@ void MYCAT::SetPath(PGLOBAL g, LPCSTR *datapath, const char *path)
} // endif path
} // end of SetDataPath
#endif // 0
/***********************************************************************/
/* GetTableDesc: retrieve a table descriptor. */
@ -560,7 +562,7 @@ PTDB MYCAT::GetTable(PGLOBAL g, PTABLE tablep, MODE mode, LPCSTR type)
printf("tdb=%p type=%s\n", tdp, tdp->GetType());
if (tablep->GetQualifier())
SetPath(g, &tdp->Database, tablep->GetQualifier());
tdp->Database = SetPath(g, tablep->GetQualifier());
tdbp= tdp->GetTable(g, mode);
} // endif tdp

View File

@ -56,8 +56,8 @@ class MYCAT : public CATALOG {
// Methods
void Reset(void);
void SetDataPath(PGLOBAL g, const char *path)
{SetPath(g, &DataPath, path);}
//void SetDataPath(PGLOBAL g, const char *path)
// {SetPath(g, &DataPath, path);}
bool StoreIndex(PGLOBAL g, PTABDEF defp) {return false;} // Temporary
PRELDEF GetTableDesc(PGLOBAL g, LPCSTR name,
LPCSTR type, PRELDEF *prp = NULL);
@ -67,7 +67,7 @@ class MYCAT : public CATALOG {
protected:
PRELDEF MakeTableDesc(PGLOBAL g, LPCSTR name, LPCSTR am);
void SetPath(PGLOBAL g, LPCSTR *datapath, const char *path);
//void SetPath(PGLOBAL g, LPCSTR *datapath, const char *path);
// Members
ha_connect *Hc; // The Connect handler

View File

@ -1,3 +1,4 @@
set @@global.connect_exact_info=ON;
# This will be used to see what data files are created
CREATE TABLE dr1 (
fname VARCHAR(256) NOT NULL FLAG=2,
@ -342,3 +343,4 @@ part2 .txt
part3 .txt
DROP TABLE t1;
DROP TABLE dr1;
set @@global.connect_exact_info=OFF;

View File

@ -1,3 +1,4 @@
set @@global.connect_exact_info=ON;
CREATE TABLE xt1 (
id INT KEY NOT NULL,
msg VARCHAR(32))
@ -193,3 +194,4 @@ DROP TABLE t1;
DROP TABLE xt1;
DROP TABLE xt2;
DROP TABLE xt3;
set @@global.connect_exact_info=OFF;

File diff suppressed because it is too large Load Diff

View File

@ -1,6 +1,8 @@
--source include/have_partition.inc
let $MYSQLD_DATADIR= `select @@datadir`;
set @@global.connect_exact_info=ON;
--echo # This will be used to see what data files are created
CREATE TABLE dr1 (
fname VARCHAR(256) NOT NULL FLAG=2,
@ -153,6 +155,8 @@ DROP TABLE dr1;
#
# Clean up
#
set @@global.connect_exact_info=OFF;
--remove_file $MYSQLD_DATADIR/test/part1.txt
--remove_file $MYSQLD_DATADIR/test/part2.txt
--remove_file $MYSQLD_DATADIR/test/part3.txt

View File

@ -1,6 +1,8 @@
--source include/not_embedded.inc
--source include/have_partition.inc
set @@global.connect_exact_info=ON;
#
# These will be used by the t1 table partition table
#
@ -83,3 +85,8 @@ DROP TABLE t1;
DROP TABLE xt1;
DROP TABLE xt2;
DROP TABLE xt3;
#
# Clean up
#
set @@global.connect_exact_info=OFF;

View File

@ -0,0 +1,25 @@
DELETE FROM t1;
INSERT INTO t1 VALUES(4, 'four'),(7,'seven'),(10,'ten'),(40,'forty'),(60,'sixty'),(81,'eighty one'),(72,'seventy two'),(11,'eleven'),(1,'one'),(35,'thirty five'),(8,'eight');
SELECT * FROM t1;
UPDATE t1 SET msg = 'bof' WHERE id = 35;
SELECT * FROM t1;
UPDATE t1 SET msg = 'big' WHERE id > 50;
SELECT * FROM t1;
UPDATE t1 SET msg = 'updated' WHERE id IN (8,35,60,72);
SELECT * FROM t1;
UPDATE t1 SET msg = 'twin' WHERE id IN (81,10);
SELECT * FROM t1;
UPDATE t1 SET msg = 'sixty' WHERE id = 60;
SELECT * FROM t1 WHERE id = 60;
DELETE FROM t1 WHERE id = 4;
SELECT * FROM t1;
DELETE FROM t1 WHERE id IN (40,11,35);
SELECT * FROM t1;
DELETE FROM t1 WHERE id IN (4,60,1);
SELECT msg FROM t1;
DELETE FROM t1 WHERE id IN (81,72);
SELECT id FROM t1;
DELETE FROM t1 WHERE id IN (7,10);
SELECT * FROM t1;
DELETE FROM t1 WHERE id = 8;
SELECT * FROM t1;

View File

@ -0,0 +1,96 @@
-- source include/not_embedded.inc
let $MYSQLD_DATADIR= `select @@datadir`;
--echo #
--echo # Testing indexed UPDATE and DELETE for all table types
--echo #
--echo # CSV table
CREATE TABLE t1 (
id INT KEY NOT NULL,
msg VARCHAR(32))
ENGINE=CONNECT TABLE_TYPE=CSV AVG_ROW_LENGTH=6;
-- source updelx.inc
ALTER TABLE t1 MAPPED=YES;
-- source updelx.inc
ALTER TABLE t1 MAPPED=NO BLOCK_SIZE=6;
-- source updelx.inc
ALTER TABLE t1 MAPPED=YES;
-- source updelx.inc
DROP TABLE t1;
--echo # DOS table
CREATE TABLE t1 (
id INT(4) KEY NOT NULL,
msg VARCHAR(16))
ENGINE=CONNECT TABLE_TYPE=DOS;
-- source updelx.inc
ALTER TABLE t1 MAPPED=YES;
-- source updelx.inc
ALTER TABLE t1 MAPPED=NO BLOCK_SIZE=4;
-- source updelx.inc
ALTER TABLE t1 MAPPED=YES;
-- source updelx.inc
DROP TABLE t1;
--echo # FIX table
CREATE TABLE t1 (
id INT(4) KEY NOT NULL,
msg VARCHAR(16) CHARSET BINARY DISTRIB=CLUSTERED)
ENGINE=CONNECT TABLE_TYPE=FIX BLOCK_SIZE=4;
-- source updelx.inc
ALTER TABLE t1 MAPPED=YES;
-- source updelx.inc
ALTER TABLE t1 MAPPED=NO HUGE=YES;
-- source updelx.inc
DROP TABLE t1;
--echo # BIN table
CREATE TABLE t1 (
id INT(4) KEY NOT NULL,
msg VARCHAR(16) CHARSET BINARY DISTRIB=CLUSTERED)
ENGINE=CONNECT TABLE_TYPE=BIN BLOCK_SIZE=8;
-- source updelx.inc
ALTER TABLE t1 MAPPED=YES;
-- source updelx.inc
ALTER TABLE t1 MAPPED=NO HUGE=YES;
-- source updelx.inc
DROP TABLE t1;
--echo # DBF table
CREATE TABLE t1 (
id INT(4) KEY NOT NULL,
msg VARCHAR(16))
ENGINE=CONNECT TABLE_TYPE=DBF BLOCK_SIZE=12;
-- source updelx.inc
ALTER TABLE t1 MAPPED=YES;
-- source updelx.inc
#ALTER TABLE t1 MAPPED=NO HUGE=YES;
#-- source updelx.inc
DROP TABLE t1;
--echo # VEC table
CREATE TABLE t1 (
id INT(4) KEY NOT NULL,
msg VARCHAR(16))
ENGINE=CONNECT TABLE_TYPE=VEC BLOCK_SIZE=6 MAX_ROWS=16;
-- source updelx.inc
ALTER TABLE t1 MAPPED=YES;
-- source updelx.inc
ALTER TABLE t1 MAPPED=NO HUGE=YES;
-- source updelx.inc
DROP TABLE t1;
--echo # Split VEC table (outward)
CREATE TABLE t1 (
id INT(4) KEY NOT NULL,
msg VARCHAR(16))
ENGINE=CONNECT TABLE_TYPE=VEC BLOCK_SIZE=6 FILE_NAME='tx.vec';
-- source updelx.inc
ALTER TABLE t1 MAPPED=YES;
-- source updelx.inc
DROP TABLE t1;
# Cleanup
--remove_file $MYSQLD_DATADIR/test/tx1.vec
--remove_file $MYSQLD_DATADIR/test/tx2.vec

View File

@ -423,7 +423,7 @@ typedef struct { /* User application block */
int Maxbmp; /* Maximum XDB2 bitmap size */
int Check; /* General level of checking */
int Numlines; /* Number of lines involved */
USETEMP UseTemp; /* Use temporary file */
//USETEMP UseTemp; /* Use temporary file */
int Vtdbno; /* Used for TDB number setting */
bool Remote; /* true: if remotely called */
bool Proginfo; /* true: return progress info */
@ -549,7 +549,8 @@ typedef struct _colres {
PPARM Vcolist(PGLOBAL, PTDB, PSZ, bool);
void PlugPutOut(PGLOBAL, FILE *, short, void *, uint);
void PlugLineDB(PGLOBAL, PSZ, short, void *, uint);
char *PlgGetDataPath(PGLOBAL g);
//ar *PlgGetDataPath(PGLOBAL g);
char *SetPath(PGLOBAL g, const char *path);
char *ExtractFromPath(PGLOBAL, char *, char *, OPVAL);
void AddPointer(PTABS, void *);
PDTP MakeDateFormat(PGLOBAL, PSZ, bool, bool, int);

View File

@ -337,7 +337,7 @@ PDBUSER PlgMakeUser(PGLOBAL g)
memset(dbuserp, 0, sizeof(DBUSERBLK));
dbuserp->Maxbmp = MAXBMP;
dbuserp->UseTemp = TMP_AUTO;
//dbuserp->UseTemp = TMP_AUTO;
dbuserp->Check = CHK_ALL;
strcpy(dbuserp->Server, "CONNECT");
return dbuserp;
@ -373,6 +373,7 @@ PCATLG PlgGetCatalog(PGLOBAL g, bool jump)
return cat;
} // end of PlgGetCatalog
#if 0
/***********************************************************************/
/* PlgGetDataPath: returns the default data path. */
/***********************************************************************/
@ -382,6 +383,39 @@ char *PlgGetDataPath(PGLOBAL g)
return (cat) ? cat->GetDataPath() : NULL;
} // end of PlgGetDataPath
#endif // 0
/***********************************************************************/
/* This function returns a database path. */
/***********************************************************************/
char *SetPath(PGLOBAL g, const char *path)
{
char *buf= NULL;
if (path) {
size_t len= strlen(path) + (*path != '.' ? 4 : 1);
buf= (char*)PlugSubAlloc(g, NULL, len);
if (PlugIsAbsolutePath(path)) {
strcpy(buf, path);
return buf;
} // endif path
if (*path != '.') {
#if defined(WIN32)
char *s= "\\";
#else // !WIN32
char *s= "/";
#endif // !WIN32
strcat(strcat(strcat(strcpy(buf, "."), s), path), s);
} else
strcpy(buf, path);
} // endif path
return buf;
} // end of SetPath
/***********************************************************************/
/* Extract from a path name the required component. */

View File

@ -49,6 +49,8 @@
#include "tabmul.h"
#include "ha_connect.h"
extern "C" int trace;
extern "C" USETEMP Use_Temp;
/* --------------------------- Class RELDEF -------------------------- */
@ -225,6 +227,14 @@ bool TABDEF::Define(PGLOBAL g, PCATLG cat, LPCSTR name, LPCSTR am)
return DefineAM(g, am, poff);
} // end of Define
/***********************************************************************/
/* This function returns the database data path. */
/***********************************************************************/
PSZ TABDEF::GetPath(void)
{
return (Database) ? (PSZ)Database : Hc->GetDataPath();
} // end of GetPath
/***********************************************************************/
/* This function returns column table information. */
/***********************************************************************/
@ -561,7 +571,7 @@ PTDB OEMDEF::GetTable(PGLOBAL g, MODE mode)
PTXF txfp = NULL;
PDOSDEF defp = (PDOSDEF)Pxdef;
bool map = defp->Mapped && mode != MODE_INSERT &&
!(PlgGetUser(g)->UseTemp == TMP_FORCE &&
!(Use_Temp == TMP_FORCE &&
(mode == MODE_UPDATE || mode == MODE_DELETE));
int cmpr = defp->Compressed;

View File

@ -1,5 +1,5 @@
/*************** RelDef H Declares Source Code File (.H) ***************/
/* Name: RELDEF.H Version 1.4 */
/* Name: RELDEF.H Version 1.5 */
/* */
/* (C) Copyright to the author Olivier BERTRAND 2004-2014 */
/* */
@ -79,8 +79,9 @@ class DllExport TABDEF : public RELDEF { /* Logical table descriptor */
void SetNext(PTABDEF tdfp) {Next = tdfp;}
int GetMultiple(void) {return Multiple;}
int GetPseudo(void) {return Pseudo;}
PSZ GetPath(void)
{return (Database) ? (PSZ)Database : Cat->GetDataPath();}
PSZ GetPath(void);
//PSZ GetPath(void)
// {return (Database) ? (PSZ)Database : Cat->GetDataPath();}
bool SepIndex(void) {return GetBoolCatInfo("SepIndex", false);}
bool IsReadOnly(void) {return Read_Only;}
virtual AMT GetDefType(void) {return TYPE_AM_TAB;}

View File

@ -64,7 +64,10 @@
/* DB static variables. */
/***********************************************************************/
int num_read, num_there, num_eq[2]; // Statistics
extern "C" int trace;
extern "C" int trace;
extern "C" USETEMP Use_Temp;
extern bool xinfo;
/***********************************************************************/
/* Size of optimize file header. */
@ -75,8 +78,8 @@ extern "C" int trace;
/* Min and Max blocks contains zero ended fields (blank = false). */
/* No conversion of block values (check = true). */
/***********************************************************************/
PVBLK AllocValBlock(PGLOBAL, void *, int, int, int len = 0, int prec = 0,
bool check = true, bool blank = false, bool un = false);
PVBLK AllocValBlock(PGLOBAL, void *, int, int, int len= 0, int prec= 0,
bool check= true, bool blank= false, bool un= false);
/* --------------------------- Class DOSDEF -------------------------- */
@ -313,7 +316,7 @@ bool DOSDEF::InvalidateIndex(PGLOBAL g)
PTDB DOSDEF::GetTable(PGLOBAL g, MODE mode)
{
// Mapping not used for insert
USETEMP tmp = PlgGetUser(g)->UseTemp;
USETEMP tmp = Use_Temp;
bool map = Mapped && mode != MODE_INSERT &&
!(tmp != TMP_NO && Recfm == RECFM_VAR
&& mode == MODE_UPDATE) &&
@ -432,6 +435,7 @@ TDBDOS::TDBDOS(PDOSDEF tdp, PTXF txfp) : TDBASE(tdp)
//Xeval = 0;
Beval = 0;
Abort = false;
Indxd = false;
} // end of TDBDOS standard constructor
TDBDOS::TDBDOS(PGLOBAL g, PTDBDOS tdbp) : TDBASE(tdbp)
@ -446,6 +450,8 @@ TDBDOS::TDBDOS(PGLOBAL g, PTDBDOS tdbp) : TDBASE(tdbp)
SavFil = tdbp->SavFil;
//Xeval = tdbp->Xeval;
Beval = tdbp->Beval;
Abort = tdbp->Abort;
Indxd = tdbp->Indxd;
} // end of TDBDOS copy constructor
// Method
@ -542,8 +548,8 @@ int TDBDOS::ResetTableOpt(PGLOBAL g, bool dop, bool dox)
if (dox && (rc == RC_OK || rc == RC_INFO)) {
// Remake eventual indexes
if (Mode != MODE_UPDATE)
To_SetCols = NULL; // Only used on Update
// if (Mode != MODE_UPDATE)
To_SetCols = NULL; // Positions are changed
Columns = NULL; // Not used anymore
Txfp->Reset(); // New start
@ -659,6 +665,13 @@ int TDBDOS::MakeBlockValues(PGLOBAL g)
cdp->SetMin(PlugSubAlloc(g, NULL, block * lg));
cdp->SetMax(PlugSubAlloc(g, NULL, block * lg));
// Valgrind complains if there are uninitialised bytes
// after the null character ending
if (IsTypeChar(cdp->GetType())) {
memset(cdp->GetMin(), 0, block * lg);
memset(cdp->GetMax(), 0, block * lg);
} // endif Type
if (trace)
htrc("min(%p) max(%p) col(%d) %s Block=%d lg=%d\n",
cdp->GetMin(), cdp->GetMax(), i, cdp->GetName(), block, lg);
@ -837,6 +850,8 @@ bool TDBDOS::SaveBlockValues(PGLOBAL g)
return true;
} // endif opfile
memset(n, 0, sizeof(n)); // To avoid valgrind warning
if (Ftype == RECFM_VAR || defp->Compressed == 2) {
/*******************************************************************/
/* Write block starting positions into the opt file. */
@ -1722,7 +1737,7 @@ err:
/***********************************************************************/
/* Make a dynamic index. */
/***********************************************************************/
bool TDBDOS::InitialyzeIndex(PGLOBAL g, PIXDEF xdp)
bool TDBDOS::InitialyzeIndex(PGLOBAL g, PIXDEF xdp, bool sorted)
{
int k, rc;
bool brc, dynamic;
@ -1811,6 +1826,12 @@ bool TDBDOS::InitialyzeIndex(PGLOBAL g, PIXDEF xdp)
} // endif AmType
To_Kindex= kxp;
if (!(sorted && To_Kindex->IsSorted()) &&
((Mode == MODE_UPDATE && IsUsingTemp(g)) ||
(Mode == MODE_DELETE && Txfp->GetAmType() != TYPE_AM_DBF)))
Indxd = true;
} // endif brc
} else
@ -1887,7 +1908,7 @@ int TDBDOS::Cardinality(PGLOBAL g)
} // endif Mode
if (Mode == MODE_ANY) {
if (Mode == MODE_ANY && xinfo) {
// Using index impossible or failed, do it the hard way
Mode = MODE_READ;
To_Line = (char*)PlugSubAlloc(g, NULL, Lrecl + 1);
@ -2000,10 +2021,8 @@ int TDBDOS::EstimatedLength(PGLOBAL g)
/***********************************************************************/
bool TDBDOS::IsUsingTemp(PGLOBAL g)
{
USETEMP usetemp = PlgGetUser(g)->UseTemp;
return (usetemp == TMP_YES || usetemp == TMP_FORCE ||
(usetemp == TMP_AUTO && Mode == MODE_UPDATE));
return (Use_Temp == TMP_YES || Use_Temp == TMP_FORCE ||
(Use_Temp == TMP_AUTO && Mode == MODE_UPDATE));
} // end of IsUsingTemp
/***********************************************************************/
@ -2043,7 +2062,7 @@ bool TDBDOS::OpenDB(PGLOBAL g)
Txfp = new(g) DOSFAM((PDOSDEF)To_Def);
Txfp->SetTdbp(this);
} else if (Txfp->Blocked && (Mode == MODE_DELETE ||
(Mode == MODE_UPDATE && PlgGetUser(g)->UseTemp != TMP_NO))) {
(Mode == MODE_UPDATE && Use_Temp != TMP_NO))) {
/*******************************************************************/
/* Delete is not currently handled in block mode neither Update */
/* when using a temporary file. */
@ -2156,13 +2175,10 @@ int TDBDOS::ReadDB(PGLOBAL g)
} // end of ReadDB
/***********************************************************************/
/* WriteDB: Data Base write routine for DOS access method. */
/* PrepareWriting: Prepare the line to write. */
/***********************************************************************/
int TDBDOS::WriteDB(PGLOBAL g)
bool TDBDOS::PrepareWriting(PGLOBAL g)
{
if (trace > 1)
htrc("DOS WriteDB: R%d Mode=%d \n", Tdb_No, Mode);
if (!Ftype && (Mode == MODE_INSERT || Txfp->GetUseTemp())) {
char *p;
@ -2177,6 +2193,20 @@ int TDBDOS::WriteDB(PGLOBAL g)
*(++p) = '\0';
} // endif Mode
return false;
} // end of WriteDB
/***********************************************************************/
/* WriteDB: Data Base write routine for DOS access method. */
/***********************************************************************/
int TDBDOS::WriteDB(PGLOBAL g)
{
if (trace > 1)
htrc("DOS WriteDB: R%d Mode=%d \n", Tdb_No, Mode);
// Make the line to write
(void)PrepareWriting(g);
if (trace > 1)
htrc("Write: line is='%s'\n", To_Line);
@ -2204,6 +2234,7 @@ void TDBDOS::CloseDB(PGLOBAL g)
} // endif
Txfp->CloseTableFile(g, Abort);
RestoreNrec();
} // end of CloseDB
// ------------------------ DOSCOL functions ----------------------------
@ -2232,8 +2263,8 @@ DOSCOL::DOSCOL(PGLOBAL g, PCOLDEF cdp, PTDB tp, PCOL cp, int i, PSZ am)
Deplac = cdp->GetOffset();
Long = cdp->GetLong();
To_Val = NULL;
Clustered = 0;
Sorted = 0;
Clustered = cdp->GetOpt();
Sorted = (cdp->GetOpt() == 2) ? 1 : 0;
Ndv = 0; // Currently used only for XDB2
Nbm = 0; // Currently used only for XDB2
Min = NULL;

View File

@ -136,6 +136,7 @@ class DllExport TDBDOS : public TDBASE {
virtual PTDB CopyOne(PTABS t);
virtual void ResetDB(void) {Txfp->Reset();}
virtual bool IsUsingTemp(PGLOBAL g);
virtual bool IsIndexed(void) {return Indxd;}
virtual void ResetSize(void) {MaxSize = Cardinal = -1;}
virtual int ResetTableOpt(PGLOBAL g, bool dop, bool dox);
virtual int MakeBlockValues(PGLOBAL g);
@ -171,11 +172,12 @@ class DllExport TDBDOS : public TDBASE {
// Optimization routines
virtual int MakeIndex(PGLOBAL g, PIXDEF pxdf, bool add);
bool InitialyzeIndex(PGLOBAL g, PIXDEF xdp);
bool InitialyzeIndex(PGLOBAL g, PIXDEF xdp, bool sorted);
void ResetBlockFilter(PGLOBAL g);
bool GetDistinctColumnValues(PGLOBAL g, int nrec);
protected:
virtual bool PrepareWriting(PGLOBAL g);
PBF CheckBlockFilari(PGLOBAL g, PXOB *arg, int op, bool *cnv);
// Members
@ -185,6 +187,7 @@ class DllExport TDBDOS : public TDBASE {
PFIL SavFil; // Saved hidden filter
char *To_Line; // Points to current processed line
bool Abort; // TRUE when aborting UPDATE/DELETE
bool Indxd; // TRUE for indexed UPDATE/DELETE
int Lrecl; // Logical Record Length
int AvgLen; // Logical Record Average Length
//int Xeval; // BlockTest return value

View File

@ -51,7 +51,9 @@
/***********************************************************************/
/* DB static variables. */
/***********************************************************************/
extern "C" int trace;
extern "C" int trace;
extern "C" USETEMP Use_Temp;
extern int num_read, num_there, num_eq[2]; // Statistics
static const longlong M2G = 0x80000000;
static const longlong M4G = (longlong)2 * M2G;
@ -135,6 +137,10 @@ int TDBFIX::ResetTableOpt(PGLOBAL g, bool dop, bool dox)
MaxSize = -1; // Size must be recalculated
Cardinal = -1; // as well as Cardinality
// After the table was modified the indexes
// are invalid and we should mark them as such...
rc = ((PDOSDEF)To_Def)->InvalidateIndex(g);
if (dop) {
Columns = NULL; // Not used anymore
Txfp->Reset();
@ -153,12 +159,8 @@ int TDBFIX::ResetTableOpt(PGLOBAL g, bool dop, bool dox)
Mode = MODE_READ; // New mode
prc = rc;
if (!(PlgGetUser(g)->Check & CHK_OPT)) {
// After the table was modified the indexes
// are invalid and we should mark them as such...
rc = ((PDOSDEF)To_Def)->InvalidateIndex(g);
} else
// ... or we should remake them.
if (PlgGetUser(g)->Check & CHK_OPT)
// We must remake indexes.
rc = MakeIndex(g, NULL, FALSE);
rc = (rc == RC_INFO) ? prc : rc;
@ -269,9 +271,11 @@ int TDBFIX::RowNumber(PGLOBAL g, bool b)
/***********************************************************************/
bool TDBFIX::IsUsingTemp(PGLOBAL g)
{
USETEMP usetemp = PlgGetUser(g)->UseTemp;
return (usetemp == TMP_YES || usetemp == TMP_FORCE);
// Not ready yet to handle using a temporary file with mapping
// or while deleting from DBF files.
return ((Use_Temp == TMP_YES && Txfp->GetAmType() != TYPE_AM_MAP &&
!(Mode == MODE_DELETE && Txfp->GetAmType() == TYPE_AM_DBF)) ||
Use_Temp == TMP_FORCE || Use_Temp == TMP_TEST);
} // end of IsUsingTemp
/***********************************************************************/
@ -302,8 +306,9 @@ bool TDBFIX::OpenDB(PGLOBAL g)
return false;
} // endif use
if (Mode == MODE_DELETE && !Next && Txfp->GetAmType() == TYPE_AM_MAP) {
// Delete all lines. Not handled in MAP mode
if (Mode == MODE_DELETE && Txfp->GetAmType() == TYPE_AM_MAP &&
(!Next || Use_Temp == TMP_FORCE)) {
// Delete all lines or using temp. Not handled in MAP mode
Txfp = new(g) FIXFAM((PDOSDEF)To_Def);
Txfp->SetTdbp(this);
} // endif Mode

View File

@ -51,6 +51,8 @@ class DllExport TDBFIX : public TDBDOS {
virtual int WriteDB(PGLOBAL g);
protected:
virtual bool PrepareWriting(PGLOBAL g) {return false;}
// Members are inherited from TDBDOS
}; // end of class TDBFIX
@ -89,7 +91,8 @@ class TDBDCL : public TDBCAT {
protected:
// Specific routines
virtual PQRYRES GetResult(PGLOBAL g) {return DBFColumns(g, Fn, false);}
virtual PQRYRES GetResult(PGLOBAL g)
{return DBFColumns(g, ((PTABDEF)To_Def)->GetPath(), Fn, false);}
// Members
char *Fn; // The DBF file (path) name

View File

@ -66,7 +66,8 @@
#define MAXCOL 200 /* Default max column nb in result */
#define TYPE_UNKNOWN 10 /* Must be greater than other types */
extern "C" int trace;
extern "C" int trace;
extern "C" USETEMP Use_Temp;
/***********************************************************************/
/* CSVColumns: constructs the result blocks containing the description */
@ -75,8 +76,8 @@ extern "C" int trace;
/* of types (TYPE_STRING < TYPE_DOUBLE < TYPE_INT) (1 < 2 < 7). */
/* If these values are changed, this will have to be revisited. */
/***********************************************************************/
PQRYRES CSVColumns(PGLOBAL g, const char *fn, char sep, char q,
int hdr, int mxr, bool info)
PQRYRES CSVColumns(PGLOBAL g, char *dp, const char *fn, char sep,
char q, int hdr, int mxr, bool info)
{
static int buftyp[] = {TYPE_STRING, TYPE_SHORT, TYPE_STRING,
TYPE_INT, TYPE_INT, TYPE_SHORT};
@ -130,7 +131,7 @@ PQRYRES CSVColumns(PGLOBAL g, const char *fn, char sep, char q,
/*********************************************************************/
/* Open the input file. */
/*********************************************************************/
PlugSetPath(filename, fn, PlgGetDataPath(g));
PlugSetPath(filename, fn, dp);
if (!(infile= global_fopen(g, MSGID_CANNOT_OPEN, filename, "r")))
return NULL;
@ -441,7 +442,7 @@ PTDB CSVDEF::GetTable(PGLOBAL g, MODE mode)
PTDBASE tdbp;
if (Catfunc != FNC_COL) {
USETEMP tmp = PlgGetUser(g)->UseTemp;
USETEMP tmp = Use_Temp;
bool map = Mapped && mode != MODE_INSERT &&
!(tmp != TMP_NO && mode == MODE_UPDATE) &&
!(tmp == TMP_FORCE &&
@ -479,6 +480,36 @@ PTDB CSVDEF::GetTable(PGLOBAL g, MODE mode)
if (Multiple)
tdbp = new(g) TDBMUL(tdbp);
else
/*****************************************************************/
/* For block tables, get eventually saved optimization values. */
/*****************************************************************/
if (tdbp->GetBlockValues(g)) {
PushWarning(g, tdbp);
// return NULL; // causes a crash when deleting index
} else {
if (IsOptimized()) {
if (map) {
txfp = new(g) MBKFAM(this);
} else if (Compressed) {
#if defined(ZIP_SUPPORT)
if (Compressed == 1)
txfp = new(g) ZBKFAM(this);
else {
txfp->SetBlkPos(To_Pos);
((PZLBFAM)txfp)->SetOptimized(To_Pos != NULL);
} // endelse
#else
sprintf(g->Message, MSG(NO_FEAT_SUPPORT), "ZIP");
return NULL;
#endif
} else
txfp = new(g) BLKFAM(this);
((PTDBDOS)tdbp)->SetTxfp(txfp);
} // endif Optimized
} // endelse
} else
tdbp = new(g)TDBCCL(this);
@ -605,14 +636,12 @@ int TDBCSV::EstimatedLength(PGLOBAL g)
#if 0
/***********************************************************************/
/* CSV tables favor the use temporary files for Update. */
/* CSV tables needs the use temporary files for Update. */
/***********************************************************************/
bool TDBCSV::IsUsingTemp(PGLOBAL g)
{
USETEMP usetemp = PlgGetUser(g)->UseTemp;
return (usetemp == TMP_YES || usetemp == TMP_FORCE ||
(usetemp == TMP_AUTO && Mode == MODE_UPDATE));
return (Use_Temp == TMP_YES || Use_Temp == TMP_FORCE ||
(Use_Temp == TMP_AUTO && Mode == MODE_UPDATE));
} // end of IsUsingTemp
#endif // 0 (Same as TDBDOS one)
@ -899,9 +928,9 @@ int TDBCSV::ReadBuffer(PGLOBAL g)
} // end of ReadBuffer
/***********************************************************************/
/* Data Base write routine CSV file access method. */
/* Prepare the line to write. */
/***********************************************************************/
int TDBCSV::WriteDB(PGLOBAL g)
bool TDBCSV::PrepareWriting(PGLOBAL g)
{
char sep[2], qot[2];
int i, nlen, oldlen = strlen(To_Line);
@ -912,7 +941,7 @@ int TDBCSV::WriteDB(PGLOBAL g)
// Before writing the line we must check its length
if ((nlen = CheckWrite(g)) < 0)
return RC_FX;
return true;
// Before writing the line we must make it
sep[0] = Sep;
@ -975,6 +1004,18 @@ int TDBCSV::WriteDB(PGLOBAL g)
if (trace > 1)
htrc("Write: line is=%s", To_Line);
return false;
} // end of PrepareWriting
/***********************************************************************/
/* Data Base write routine CSV file access method. */
/***********************************************************************/
int TDBCSV::WriteDB(PGLOBAL g)
{
// Before writing the line we must check and prepare it
if (PrepareWriting(g))
return RC_FX;
/*********************************************************************/
/* Now start the writing process. */
/*********************************************************************/
@ -1430,7 +1471,8 @@ TDBCCL::TDBCCL(PCSVDEF tdp) : TDBCAT(tdp)
/***********************************************************************/
PQRYRES TDBCCL::GetResult(PGLOBAL g)
{
return CSVColumns(g, Fn, Sep, Qtd, Hdr, Mxr, false);
return CSVColumns(g, ((PTABDEF)To_Def)->GetPath(),
Fn, Sep, Qtd, Hdr, Mxr, false);
} // end of GetResult
/* ------------------------ End of TabFmt ---------------------------- */

View File

@ -1,188 +1,193 @@
/*************** TabFmt H Declares Source Code File (.H) ***************/
/* Name: TABFMT.H Version 2.4 */
/* */
/* (C) Copyright to the author Olivier BERTRAND 2001-2014 */
/* */
/* This file contains the CSV and FMT classes declares. */
/***********************************************************************/
#include "xtable.h" // Base class declares
#include "tabdos.h"
typedef class TDBFMT *PTDBFMT;
/***********************************************************************/
/* Functions used externally. */
/***********************************************************************/
PQRYRES CSVColumns(PGLOBAL g, const char *fn, char sep, char q,
int hdr, int mxr, bool info);
/***********************************************************************/
/* CSV table. */
/***********************************************************************/
class DllExport CSVDEF : public DOSDEF { /* Logical table description */
friend class TDBCSV;
friend class TDBCCL;
public:
// Constructor
CSVDEF(void);
// Implementation
virtual const char *GetType(void) {return "CSV";}
char GetSep(void) {return Sep;}
char GetQot(void) {return Qot;}
// Methods
virtual bool DefineAM(PGLOBAL g, LPCSTR am, int poff);
virtual PTDB GetTable(PGLOBAL g, MODE mode);
protected:
// Members
bool Fmtd; /* true for formatted files */
//bool Accept; /* true if wrong lines are accepted */
bool Header; /* true if first line contains headers */
//int Maxerr; /* Maximum number of bad records */
int Quoted; /* Quoting level for quoted fields */
char Sep; /* Separator for standard CSV files */
char Qot; /* Character for quoted strings */
}; // end of CSVDEF
/***********************************************************************/
/* This is the DOS/UNIX Access Method class declaration for files */
/* that are CSV files with columns separated by the Sep character. */
/***********************************************************************/
class TDBCSV : public TDBDOS {
friend class CSVCOL;
public:
// Constructor
TDBCSV(PCSVDEF tdp, PTXF txfp);
TDBCSV(PGLOBAL g, PTDBCSV tdbp);
// Implementation
virtual AMT GetAmType(void) {return TYPE_AM_CSV;}
virtual PTDB Duplicate(PGLOBAL g)
{return (PTDB)new(g) TDBCSV(g, this);}
// Methods
virtual PTDB CopyOne(PTABS t);
//virtual bool IsUsingTemp(PGLOBAL g);
virtual int GetBadLines(void) {return (int)Nerr;}
// Database routines
virtual PCOL MakeCol(PGLOBAL g, PCOLDEF cdp, PCOL cprec, int n);
virtual bool OpenDB(PGLOBAL g);
virtual int WriteDB(PGLOBAL g);
virtual int CheckWrite(PGLOBAL g);
virtual int ReadBuffer(PGLOBAL g); // Physical file read
// Specific routines
virtual int EstimatedLength(PGLOBAL g);
virtual bool SkipHeader(PGLOBAL g);
virtual bool CheckErr(void);
protected:
// Members
PSZ *Field; // Field to write to current line
int *Offset; // Column offsets for current record
int *Fldlen; // Column field length for current record
bool *Fldtyp; // true for numeric fields
int Fields; // Number of fields to handle
int Nerr; // Number of bad records
int Maxerr; // Maximum number of bad records
int Quoted; // Quoting level for quoted fields
bool Accept; // true if bad lines are accepted
bool Header; // true if first line contains column headers
char Sep; // Separator
char Qot; // Quoting character
}; // end of class TDBCSV
/***********************************************************************/
/* Class CSVCOL: CSV access method column descriptor. */
/* This A.M. is used for Comma Separated V(?) files. */
/***********************************************************************/
class CSVCOL : public DOSCOL {
friend class TDBCSV;
friend class TDBFMT;
public:
// Constructors
CSVCOL(PGLOBAL g, PCOLDEF cdp, PTDB tdbp, PCOL cprec, int i);
CSVCOL(CSVCOL *colp, PTDB tdbp); // Constructor used in copy process
// Implementation
virtual int GetAmType() {return TYPE_AM_CSV;}
// Methods
virtual bool VarSize(void);
virtual void ReadColumn(PGLOBAL g);
virtual void WriteColumn(PGLOBAL g);
protected:
// Default constructor not to be used
CSVCOL(void) {}
// Members
int Fldnum; // Field ordinal number (0 based)
}; // end of class CSVCOL
/***********************************************************************/
/* This is the DOS/UNIX Access Method class declaration for files */
/* whose record format is described by a Format keyword. */
/***********************************************************************/
class TDBFMT : public TDBCSV {
friend class CSVCOL;
//friend class FMTCOL;
public:
// Standard constructor
TDBFMT(PCSVDEF tdp, PTXF txfp) : TDBCSV(tdp, txfp)
{FldFormat = NULL; To_Fld = NULL; FmtTest = NULL; Linenum = 0;}
// Copy constructor
TDBFMT(PGLOBAL g, PTDBFMT tdbp);
// Implementation
virtual AMT GetAmType(void) {return TYPE_AM_FMT;}
virtual PTDB Duplicate(PGLOBAL g)
{return (PTDB)new(g) TDBFMT(g, this);}
// Methods
virtual PTDB CopyOne(PTABS t);
// Database routines
virtual PCOL MakeCol(PGLOBAL g, PCOLDEF cdp, PCOL cprec, int n);
//virtual int GetMaxSize(PGLOBAL g);
virtual bool OpenDB(PGLOBAL g);
virtual int WriteDB(PGLOBAL g);
//virtual int CheckWrite(PGLOBAL g);
virtual int ReadBuffer(PGLOBAL g); // Physical file read
// Specific routines
virtual int EstimatedLength(PGLOBAL g);
protected:
// Members
PSZ *FldFormat; // Field read format
void *To_Fld; // To field test buffer
int *FmtTest; // Test on ending by %n or %m
int Linenum; // Last read line
}; // end of class TDBFMT
/***********************************************************************/
/* This is the class declaration for the CSV catalog table. */
/***********************************************************************/
class TDBCCL : public TDBCAT {
public:
// Constructor
TDBCCL(PCSVDEF tdp);
protected:
// Specific routines
virtual PQRYRES GetResult(PGLOBAL g);
// Members
char *Fn; // The CSV file (path) name
bool Hdr; // true if first line contains headers
int Mxr; // Maximum number of bad records
int Qtd; // Quoting level for quoted fields
char Sep; // Separator for standard CSV files
}; // end of class TDBCCL
/* ------------------------- End of TabFmt.H ------------------------- */
/*************** TabFmt H Declares Source Code File (.H) ***************/
/* Name: TABFMT.H Version 2.4 */
/* */
/* (C) Copyright to the author Olivier BERTRAND 2001-2014 */
/* */
/* This file contains the CSV and FMT classes declares. */
/***********************************************************************/
#include "xtable.h" // Base class declares
#include "tabdos.h"
typedef class TDBFMT *PTDBFMT;
/***********************************************************************/
/* Functions used externally. */
/***********************************************************************/
PQRYRES CSVColumns(PGLOBAL g, char *dp, const char *fn, char sep,
char q, int hdr, int mxr, bool info);
/***********************************************************************/
/* CSV table. */
/***********************************************************************/
class DllExport CSVDEF : public DOSDEF { /* Logical table description */
friend class TDBCSV;
friend class TDBCCL;
public:
// Constructor
CSVDEF(void);
// Implementation
virtual const char *GetType(void) {return "CSV";}
char GetSep(void) {return Sep;}
char GetQot(void) {return Qot;}
// Methods
virtual bool DefineAM(PGLOBAL g, LPCSTR am, int poff);
virtual PTDB GetTable(PGLOBAL g, MODE mode);
protected:
// Members
bool Fmtd; /* true for formatted files */
//bool Accept; /* true if wrong lines are accepted */
bool Header; /* true if first line contains headers */
//int Maxerr; /* Maximum number of bad records */
int Quoted; /* Quoting level for quoted fields */
char Sep; /* Separator for standard CSV files */
char Qot; /* Character for quoted strings */
}; // end of CSVDEF
/***********************************************************************/
/* This is the DOS/UNIX Access Method class declaration for files */
/* that are CSV files with columns separated by the Sep character. */
/***********************************************************************/
class TDBCSV : public TDBDOS {
friend class CSVCOL;
public:
// Constructor
TDBCSV(PCSVDEF tdp, PTXF txfp);
TDBCSV(PGLOBAL g, PTDBCSV tdbp);
// Implementation
virtual AMT GetAmType(void) {return TYPE_AM_CSV;}
virtual PTDB Duplicate(PGLOBAL g)
{return (PTDB)new(g) TDBCSV(g, this);}
// Methods
virtual PTDB CopyOne(PTABS t);
//virtual bool IsUsingTemp(PGLOBAL g);
virtual int GetBadLines(void) {return (int)Nerr;}
// Database routines
virtual PCOL MakeCol(PGLOBAL g, PCOLDEF cdp, PCOL cprec, int n);
virtual bool OpenDB(PGLOBAL g);
virtual int WriteDB(PGLOBAL g);
virtual int CheckWrite(PGLOBAL g);
virtual int ReadBuffer(PGLOBAL g); // Physical file read
// Specific routines
virtual int EstimatedLength(PGLOBAL g);
virtual bool SkipHeader(PGLOBAL g);
virtual bool CheckErr(void);
protected:
virtual bool PrepareWriting(PGLOBAL g);
// Members
PSZ *Field; // Field to write to current line
int *Offset; // Column offsets for current record
int *Fldlen; // Column field length for current record
bool *Fldtyp; // true for numeric fields
int Fields; // Number of fields to handle
int Nerr; // Number of bad records
int Maxerr; // Maximum number of bad records
int Quoted; // Quoting level for quoted fields
bool Accept; // true if bad lines are accepted
bool Header; // true if first line contains column headers
char Sep; // Separator
char Qot; // Quoting character
}; // end of class TDBCSV
/***********************************************************************/
/* Class CSVCOL: CSV access method column descriptor. */
/* This A.M. is used for Comma Separated V(?) files. */
/***********************************************************************/
class CSVCOL : public DOSCOL {
friend class TDBCSV;
friend class TDBFMT;
public:
// Constructors
CSVCOL(PGLOBAL g, PCOLDEF cdp, PTDB tdbp, PCOL cprec, int i);
CSVCOL(CSVCOL *colp, PTDB tdbp); // Constructor used in copy process
// Implementation
virtual int GetAmType() {return TYPE_AM_CSV;}
// Methods
virtual bool VarSize(void);
virtual void ReadColumn(PGLOBAL g);
virtual void WriteColumn(PGLOBAL g);
protected:
// Default constructor not to be used
CSVCOL(void) {}
// Members
int Fldnum; // Field ordinal number (0 based)
}; // end of class CSVCOL
/***********************************************************************/
/* This is the DOS/UNIX Access Method class declaration for files */
/* whose record format is described by a Format keyword. */
/***********************************************************************/
class TDBFMT : public TDBCSV {
friend class CSVCOL;
//friend class FMTCOL;
public:
// Standard constructor
TDBFMT(PCSVDEF tdp, PTXF txfp) : TDBCSV(tdp, txfp)
{FldFormat = NULL; To_Fld = NULL; FmtTest = NULL; Linenum = 0;}
// Copy constructor
TDBFMT(PGLOBAL g, PTDBFMT tdbp);
// Implementation
virtual AMT GetAmType(void) {return TYPE_AM_FMT;}
virtual PTDB Duplicate(PGLOBAL g)
{return (PTDB)new(g) TDBFMT(g, this);}
// Methods
virtual PTDB CopyOne(PTABS t);
// Database routines
virtual PCOL MakeCol(PGLOBAL g, PCOLDEF cdp, PCOL cprec, int n);
//virtual int GetMaxSize(PGLOBAL g);
virtual bool OpenDB(PGLOBAL g);
virtual int WriteDB(PGLOBAL g);
//virtual int CheckWrite(PGLOBAL g);
virtual int ReadBuffer(PGLOBAL g); // Physical file read
// Specific routines
virtual int EstimatedLength(PGLOBAL g);
protected:
virtual bool PrepareWriting(PGLOBAL g)
{strcpy(g->Message, "FMT is read only"); return true;}
// Members
PSZ *FldFormat; // Field read format
void *To_Fld; // To field test buffer
int *FmtTest; // Test on ending by %n or %m
int Linenum; // Last read line
}; // end of class TDBFMT
/***********************************************************************/
/* This is the class declaration for the CSV catalog table. */
/***********************************************************************/
class TDBCCL : public TDBCAT {
public:
// Constructor
TDBCCL(PCSVDEF tdp);
protected:
// Specific routines
virtual PQRYRES GetResult(PGLOBAL g);
// Members
char *Fn; // The CSV file (path) name
bool Hdr; // true if first line contains headers
int Mxr; // Maximum number of bad records
int Qtd; // Quoting level for quoted fields
char Sep; // Separator for standard CSV files
}; // end of class TDBCCL
/* ------------------------- End of TabFmt.H ------------------------- */

View File

@ -216,10 +216,11 @@ PCOL TDBASE::ColDB(PGLOBAL g, PSZ name, int num)
/* Also find where to insert the new block. */
/*****************************************************************/
for (cp = Columns; cp; cp = cp->GetNext())
if (cp->GetIndex() < i)
if ((num && cp->GetIndex() == i) ||
(name && !stricmp(cp->GetName(), name)))
break; // Found
else if (cp->GetIndex() < i)
cprec = cp;
else if (cp->GetIndex() == i)
break;
if (trace)
htrc("cdp(%d).Name=%s cp=%p\n", i, cdp->GetName(), cp);

View File

@ -680,7 +680,7 @@ char* TDBDIR::Path(PGLOBAL g)
#if defined(WIN32)
if (!*Drive) {
PlugSetPath(Fpath, To_File, cat->GetDataPath());
PlugSetPath(Fpath, To_File, ((PTABDEF)To_Def)->GetPath());
_splitpath(Fpath, Drive, Direc, Fname, Ftype);
} else
_makepath(Fpath, Drive, Direc, Fname, Ftype); // Usefull ???
@ -688,7 +688,7 @@ char* TDBDIR::Path(PGLOBAL g)
return Fpath;
#else // !WIN32
if (!Done) {
PlugSetPath(Fpath, To_File, cat->GetDataPath());
PlugSetPath(Fpath, To_File, ((PTABDEF)To_Def)->GetPath());
_splitpath(Fpath, NULL, Direc, Fname, Ftype);
strcat(strcpy(Pattern, Fname), Ftype);
Done = true;

View File

@ -68,6 +68,7 @@ void PrintResult(PGLOBAL, PSEM, PQRYRES);
#endif // _CONSOLE
extern "C" int trace;
extern bool xinfo;
// Used to check whether a MYSQL table is created on itself
bool CheckSelf(PGLOBAL g, TABLE_SHARE *s, const char *host,
@ -754,7 +755,7 @@ int TDBMYSQL::Cardinality(PGLOBAL g)
if (!g)
return (Mode == MODE_ANY && !Srcdef) ? 1 : 0;
if (Cardinal < 0 && Mode == MODE_ANY && !Srcdef) {
if (Cardinal < 0 && Mode == MODE_ANY && !Srcdef && xinfo) {
// Info command, we must return the exact table row number
char query[96];
MYSQLC myc;

View File

@ -1,11 +1,11 @@
/************* Tabodbc C++ Program Source Code File (.CPP) *************/
/* PROGRAM NAME: TABODBC */
/* ------------- */
/* Version 2.7 */
/* Version 2.8 */
/* */
/* COPYRIGHT: */
/* ---------- */
/* (C) Copyright to the author Olivier BERTRAND 2000-2013 */
/* (C) Copyright to the author Olivier BERTRAND 2000-2014 */
/* */
/* WHAT THIS PROGRAM DOES: */
/* ----------------------- */
@ -76,6 +76,7 @@
#include "sql_string.h"
extern "C" int trace;
extern bool xinfo;
/***********************************************************************/
/* DB static variables. */
@ -671,7 +672,7 @@ int TDBODBC::Cardinality(PGLOBAL g)
if (!g)
return (Mode == MODE_ANY && !Srcdef) ? 1 : 0;
if (Cardinal < 0 && Mode == MODE_ANY && !Srcdef) {
if (Cardinal < 0 && Mode == MODE_ANY && !Srcdef && xinfo) {
// Info command, we must return the exact table row number
char qry[96], tbn[64];
ODBConn *ocp = new(g) ODBConn(g, this);

View File

@ -76,7 +76,8 @@
char *strerror(int num);
#endif // UNIX
extern "C" int trace;
extern "C" int trace;
extern "C" USETEMP Use_Temp;
/***********************************************************************/
/* Char VCT column blocks are right filled with blanks (blank = true) */
@ -208,7 +209,7 @@ PTDB VCTDEF::GetTable(PGLOBAL g, MODE mode)
// Mapping not used for insert (except for true VEC not split tables)
// or when UseTemp is forced
bool map = Mapped && (Estimate || mode != MODE_INSERT) &&
!(PlgGetUser(g)->UseTemp == TMP_FORCE &&
!(Use_Temp == TMP_FORCE &&
(mode == MODE_UPDATE || mode == MODE_DELETE));
PTXF txfp;
PTDB tdbp;
@ -284,6 +285,15 @@ PCOL TDBVCT::MakeCol(PGLOBAL g, PCOLDEF cdp, PCOL cprec, int n)
return new(g) VCTCOL(g, cdp, this, cprec, n);
} // end of MakeCol
/***********************************************************************/
/* VEC tables are not ready yet to use temporary files. */
/***********************************************************************/
bool TDBVCT::IsUsingTemp(PGLOBAL g)
{
// For developpers
return (Use_Temp == TMP_TEST);
} // end of IsUsingTemp
/***********************************************************************/
/* VCT Access Method opening routine. */
/* New method now that this routine is called recursively (last table */

View File

@ -1,123 +1,124 @@
/*************** TabVct H Declares Source Code File (.H) ***************/
/* Name: TABVCT.H Version 3.4 */
/* */
/* (C) Copyright to the author Olivier BERTRAND 1999-2011 */
/* */
/* This file contains the TDBVCT class declares. */
/***********************************************************************/
#ifndef __TABVCT__
#define __TABVCT__
#include "tabfix.h"
#if defined(UNIX)
//#include <string.h.SUNWCCh>
#endif
typedef class TDBVCT *PTDBVCT;
typedef class VCTCOL *PVCTCOL;
/***********************************************************************/
/* VCT table. */
/***********************************************************************/
class DllExport VCTDEF : public DOSDEF { /* Logical table description */
friend class TDBVCT;
friend class VCTFAM;
friend class VECFAM;
friend class VMPFAM;
public:
// Constructor
VCTDEF(void) {Split = false; Estimate = Header = 0;}
// Implementation
virtual const char *GetType(void) {return "VCT";}
int GetEstimate(void) {return Estimate;}
// Methods
virtual bool DefineAM(PGLOBAL g, LPCSTR am, int poff);
virtual PTDB GetTable(PGLOBAL g, MODE mode);
protected:
int MakeFnPattern(char *fpat);
// Members
bool Split; /* Columns in separate files */
int Estimate; /* Estimated maximum size of table */
int Header; /* 0: no, 1: separate, 2: in data file */
}; // end of VCTDEF
/***********************************************************************/
/* This is the DOS/UNIX Access Method class declaration for files */
/* in blocked vector format. In each block containing "Elements" */
/* records, values of each columns are consecutively stored (vector). */
/***********************************************************************/
class DllExport TDBVCT : public TDBFIX {
friend class VCTCOL;
friend class VCTFAM;
friend class VCMFAM;
friend class VECFAM;
friend class VMPFAM;
public:
// Constructors
TDBVCT(PVCTDEF tdp, PTXF txfp);
TDBVCT(PGLOBAL g, PTDBVCT tdbp);
// Implementation
virtual AMT GetAmType(void) {return TYPE_AM_VCT;}
virtual PTDB Duplicate(PGLOBAL g)
{return (PTDB)new(g) TDBVCT(g, this);}
bool IsSplit(void) {return ((VCTDEF*)To_Def)->Split;}
// Methods
virtual PTDB CopyOne(PTABS t);
// Database routines
virtual PCOL MakeCol(PGLOBAL g, PCOLDEF cdp, PCOL cprec, int n);
virtual bool OpenDB(PGLOBAL g);
virtual int ReadDB(PGLOBAL g);
virtual void CloseDB(PGLOBAL g);
protected:
// Members
}; // end of class TDBVCT
/***********************************************************************/
/* Class VCTCOL: VCT access method column descriptor. */
/* This A.M. is used for file having column wise organization. */
/***********************************************************************/
class DllExport VCTCOL : public DOSCOL {
friend class TDBVCT;
friend class VCTFAM;
friend class VCMFAM;
friend class VECFAM;
friend class VMPFAM;
friend class BGVFAM;
public:
// Constructors
VCTCOL(PGLOBAL g, PCOLDEF cdp, PTDB tdbp, PCOL cprec, int i);
VCTCOL(VCTCOL *colp, PTDB tdbp); // Constructor used in copy process
// Implementation
virtual int GetAmType(void) {return TYPE_AM_VCT;}
// Methods
virtual void ReadColumn(PGLOBAL g);
virtual void WriteColumn(PGLOBAL g);
virtual bool SetBuffer(PGLOBAL g, PVAL value, bool ok, bool check);
virtual void SetOk(void);
protected:
virtual void ReadBlock(PGLOBAL g);
virtual void WriteBlock(PGLOBAL g);
VCTCOL(void) {} // Default constructor not to be used
// Members
PVBLK Blk; // Block buffer
int Clen; // Internal length in table
int ColBlk; // Block pointed by column
int ColPos; // Last position read
int Modif; // Number of modified lines in block
}; // end of class VCTCOL
#endif // __TABVCT__
/*************** TabVct H Declares Source Code File (.H) ***************/
/* Name: TABVCT.H Version 3.4 */
/* */
/* (C) Copyright to the author Olivier BERTRAND 1999-2011 */
/* */
/* This file contains the TDBVCT class declares. */
/***********************************************************************/
#ifndef __TABVCT__
#define __TABVCT__
#include "tabfix.h"
#if defined(UNIX)
//#include <string.h.SUNWCCh>
#endif
typedef class TDBVCT *PTDBVCT;
typedef class VCTCOL *PVCTCOL;
/***********************************************************************/
/* VCT table. */
/***********************************************************************/
class DllExport VCTDEF : public DOSDEF { /* Logical table description */
friend class TDBVCT;
friend class VCTFAM;
friend class VECFAM;
friend class VMPFAM;
public:
// Constructor
VCTDEF(void) {Split = false; Estimate = Header = 0;}
// Implementation
virtual const char *GetType(void) {return "VCT";}
int GetEstimate(void) {return Estimate;}
// Methods
virtual bool DefineAM(PGLOBAL g, LPCSTR am, int poff);
virtual PTDB GetTable(PGLOBAL g, MODE mode);
protected:
int MakeFnPattern(char *fpat);
// Members
bool Split; /* Columns in separate files */
int Estimate; /* Estimated maximum size of table */
int Header; /* 0: no, 1: separate, 2: in data file */
}; // end of VCTDEF
/***********************************************************************/
/* This is the DOS/UNIX Access Method class declaration for files */
/* in blocked vector format. In each block containing "Elements" */
/* records, values of each columns are consecutively stored (vector). */
/***********************************************************************/
class DllExport TDBVCT : public TDBFIX {
friend class VCTCOL;
friend class VCTFAM;
friend class VCMFAM;
friend class VECFAM;
friend class VMPFAM;
public:
// Constructors
TDBVCT(PVCTDEF tdp, PTXF txfp);
TDBVCT(PGLOBAL g, PTDBVCT tdbp);
// Implementation
virtual AMT GetAmType(void) {return TYPE_AM_VCT;}
virtual PTDB Duplicate(PGLOBAL g)
{return (PTDB)new(g) TDBVCT(g, this);}
bool IsSplit(void) {return ((VCTDEF*)To_Def)->Split;}
// Methods
virtual PTDB CopyOne(PTABS t);
virtual bool IsUsingTemp(PGLOBAL g);
// Database routines
virtual PCOL MakeCol(PGLOBAL g, PCOLDEF cdp, PCOL cprec, int n);
virtual bool OpenDB(PGLOBAL g);
virtual int ReadDB(PGLOBAL g);
virtual void CloseDB(PGLOBAL g);
protected:
// Members
}; // end of class TDBVCT
/***********************************************************************/
/* Class VCTCOL: VCT access method column descriptor. */
/* This A.M. is used for file having column wise organization. */
/***********************************************************************/
class DllExport VCTCOL : public DOSCOL {
friend class TDBVCT;
friend class VCTFAM;
friend class VCMFAM;
friend class VECFAM;
friend class VMPFAM;
friend class BGVFAM;
public:
// Constructors
VCTCOL(PGLOBAL g, PCOLDEF cdp, PTDB tdbp, PCOL cprec, int i);
VCTCOL(VCTCOL *colp, PTDB tdbp); // Constructor used in copy process
// Implementation
virtual int GetAmType(void) {return TYPE_AM_VCT;}
// Methods
virtual void ReadColumn(PGLOBAL g);
virtual void WriteColumn(PGLOBAL g);
virtual bool SetBuffer(PGLOBAL g, PVAL value, bool ok, bool check);
virtual void SetOk(void);
protected:
virtual void ReadBlock(PGLOBAL g);
virtual void WriteBlock(PGLOBAL g);
VCTCOL(void) {} // Default constructor not to be used
// Members
PVBLK Blk; // Block buffer
int Clen; // Internal length in table
int ColBlk; // Block pointed by column
int ColPos; // Last position read
int Modif; // Number of modified lines in block
}; // end of class VCTCOL
#endif // __TABVCT__

View File

@ -827,12 +827,12 @@ void CHRBLK::SetValue(PVBLK pv, int n1, int n2)
longjmp(g->jumper[g->jump_level], Type);
} // endif Type
if (!(b = pv->IsNull(n2) && Nullable))
if (!(b = pv->IsNull(n2)))
memcpy(Chrp + n1 * Long, ((CHRBLK*)pv)->Chrp + n2 * Long, Long);
else
Reset(n1);
SetNull(n1, b);
SetNull(n1, b && Nullable);
} // end of SetValue
/***********************************************************************/

View File

@ -52,6 +52,7 @@ DllExport PVAL AllocateValue(PGLOBAL, int, int len = 0, int prec = 0,
bool uns = false, PSZ fmt = NULL);
DllExport ulonglong CharToNumber(char *, int, ulonglong, bool,
bool *minus = NULL, bool *rc = NULL);
DllExport BYTE OpBmp(PGLOBAL g, OPVAL opc);
/***********************************************************************/
/* Class VALUE represents a constant or variable of any valid type. */

View File

@ -50,7 +50,7 @@
/***********************************************************************/
/* Macro or external routine definition */
/***********************************************************************/
#define NZ 7
#define NZ 8
#define NW 5
#define MAX_INDX 10
#ifndef INVALID_SET_FILE_POINTER
@ -264,9 +264,6 @@ void XINDEX::Close(void)
kcp->FreeData();
} // endfor kcp
if (Tdbp)
Tdbp->RestoreNrec();
} // end of Close
/***********************************************************************/
@ -547,7 +544,7 @@ bool XINDEX::Make(PGLOBAL g, PIXDEF sxp)
if ((Ndif = Qsort(g, Num_K)) < 0)
goto err; // Error during sort
// if (trace)
if (trace)
htrc("Make: Nk=%d n=%d Num_K=%d Ndif=%d addcolp=%p BlkFil=%p X=%p\n",
Nk, n, Num_K, Ndif, addcolp, Tdbp->To_BlkFil, X);
@ -820,11 +817,11 @@ bool XINDEX::SaveIndex(PGLOBAL g, PIXDEF sxp)
bool sep, rc = false;
PXCOL kcp = To_KeyCol;
PDOSDEF defp = (PDOSDEF)Tdbp->To_Def;
PDBUSER dup = PlgGetUser(g);
//PDBUSER dup = PlgGetUser(g);
dup->Step = STEP(SAVING_INDEX);
dup->ProgMax = 15 + 16 * Nk;
dup->ProgCur = 0;
//dup->Step = STEP(SAVING_INDEX);
//dup->ProgMax = 15 + 16 * Nk;
//dup->ProgCur = 0;
switch (Tdbp->Ftype) {
case RECFM_VAR: ftype = ".dnx"; break;
@ -869,31 +866,32 @@ bool XINDEX::SaveIndex(PGLOBAL g, PIXDEF sxp)
/*********************************************************************/
/* Write the index values on the index file. */
/*********************************************************************/
n[0] = ID; // To check validity
n[0] = ID + MAX_INDX; // To check validity
n[1] = Nk; // The number of indexed columns
n[2] = nof; // The offset array size or 0
n[3] = Num_K; // The index size
n[4] = Incr; // Increment of record positions
n[5] = Nblk; n[6] = Sblk;
n[7] = Srtd ? 1 : 0; // Values are sorted in the file
if (trace) {
htrc("Saving index %s\n", Xdp->GetName());
htrc("ID=%d Nk=%d nof=%d Num_K=%d Incr=%d Nblk=%d Sblk=%d\n",
ID, Nk, nof, Num_K, Incr, Nblk, Sblk);
htrc("ID=%d Nk=%d nof=%d Num_K=%d Incr=%d Nblk=%d Sblk=%d Srtd=%d\n",
ID, Nk, nof, Num_K, Incr, Nblk, Sblk, Srtd);
} // endif trace
size = X->Write(g, n, NZ, sizeof(int), rc);
dup->ProgCur = 1;
//dup->ProgCur = 1;
if (Mul) // Write the offset array
size += X->Write(g, Pof, nof, sizeof(int), rc);
dup->ProgCur = 5;
//dup->ProgCur = 5;
if (!Incr) // Write the record position array(s)
size += X->Write(g, To_Rec, Num_K, sizeof(int), rc);
dup->ProgCur = 15;
//dup->ProgCur = 15;
for (; kcp; kcp = kcp->Next) {
n[0] = kcp->Ndf; // Number of distinct sub-values
@ -903,20 +901,20 @@ bool XINDEX::SaveIndex(PGLOBAL g, PIXDEF sxp)
n[4] = kcp->Type; // To be checked later
size += X->Write(g, n, NW, sizeof(int), rc);
dup->ProgCur += 1;
// dup->ProgCur += 1;
if (n[2])
size += X->Write(g, kcp->To_Bkeys, Nblk, kcp->Klen, rc);
dup->ProgCur += 5;
// dup->ProgCur += 5;
size += X->Write(g, kcp->To_Keys, n[0], kcp->Klen, rc);
dup->ProgCur += 5;
// dup->ProgCur += 5;
if (n[1])
size += X->Write(g, kcp->Kof, n[1], sizeof(int), rc);
dup->ProgCur += 5;
// dup->ProgCur += 5;
} // endfor kcp
if (trace)
@ -1019,12 +1017,22 @@ bool XINDEX::Init(PGLOBAL g)
goto err; // No saved values
// Now start the reading process.
if (X->Read(g, nv, NZ, sizeof(int)))
if (X->Read(g, nv, NZ - 1, sizeof(int)))
goto err;
if (nv[0] >= MAX_INDX) {
// New index format
if (X->Read(g, nv + 7, 1, sizeof(int)))
goto err;
Srtd = nv[7] != 0;
nv[0] -= MAX_INDX;
} else
Srtd = false;
if (trace)
htrc("nv=%d %d %d %d %d %d %d\n",
nv[0], nv[1], nv[2], nv[3], nv[4], nv[5], nv[6]);
htrc("nv=%d %d %d %d %d %d %d (%d)\n",
nv[0], nv[1], nv[2], nv[3], nv[4], nv[5], nv[6], Srtd);
// The test on ID was suppressed because MariaDB can change an index ID
// when other indexes are added or deleted
@ -1271,11 +1279,20 @@ bool XINDEX::MapInit(PGLOBAL g)
// Now start the mapping process.
nv = (int*)mbase;
mbase += NZ * sizeof(int);
if (nv[0] >= MAX_INDX) {
// New index format
Srtd = nv[7] != 0;
nv[0] -= MAX_INDX;
mbase += NZ * sizeof(int);
} else {
Srtd = false;
mbase += (NZ - 1) * sizeof(int);
} // endif nv
if (trace)
htrc("nv=%d %d %d %d %d %d %d\n",
nv[0], nv[1], nv[2], nv[3], nv[4], nv[5], nv[6]);
htrc("nv=%d %d %d %d %d %d %d %d\n",
nv[0], nv[1], nv[2], nv[3], nv[4], nv[5], nv[6], Srtd);
// The test on ID was suppressed because MariaDB can change an index ID
// when other indexes are added or deleted
@ -2453,7 +2470,7 @@ void *XFILE::FileView(PGLOBAL g, char *fn)
/***********************************************************************/
bool XHUGE::Open(PGLOBAL g, char *filename, int id, MODE mode)
{
IOFF noff[MAX_INDX];
IOFF noff[MAX_INDX];
if (Hfile != INVALID_HANDLE_VALUE) {
sprintf(g->Message, MSG(FILE_OPEN_YET), filename);
@ -2461,7 +2478,7 @@ bool XHUGE::Open(PGLOBAL g, char *filename, int id, MODE mode)
} // endif
if (trace)
htrc(" Xopen: filename=%s mode=%d\n", filename, mode);
htrc(" Xopen: filename=%s id=%d mode=%d\n", filename, id, mode);
#if defined(WIN32)
LONG high = 0;
@ -2553,7 +2570,7 @@ bool XHUGE::Open(PGLOBAL g, char *filename, int id, MODE mode)
#else // UNIX
int oflag = O_LARGEFILE; // Enable file size > 2G
mode_t pmod = 0;
mode_t pmod = S_IRUSR | S_IWUSR | S_IRGRP | S_IWGRP | S_IROTH | S_IWOTH;
/*********************************************************************/
/* Create the file object according to access mode */
@ -2564,7 +2581,7 @@ bool XHUGE::Open(PGLOBAL g, char *filename, int id, MODE mode)
break;
case MODE_WRITE:
oflag |= O_WRONLY | O_CREAT | O_TRUNC;
pmod = S_IREAD | S_IWRITE;
// pmod = S_IREAD | S_IWRITE;
break;
case MODE_INSERT:
oflag |= (O_WRONLY | O_APPEND);
@ -2597,6 +2614,9 @@ bool XHUGE::Open(PGLOBAL g, char *filename, int id, MODE mode)
return true;
} // endif
if (trace)
htrc("INSERT: NewOff=%lld\n", NewOff.Val);
} else if (mode == MODE_WRITE) {
if (id >= 0) {
// New not sep index file. Write the header.
@ -2604,18 +2624,26 @@ bool XHUGE::Open(PGLOBAL g, char *filename, int id, MODE mode)
NewOff.Low = write(Hfile, &noff, sizeof(noff));
} // endif id
if (trace)
htrc("WRITE: NewOff=%lld\n", NewOff.Val);
} else if (mode == MODE_READ && id >= 0) {
// Get offset from the header
if (read(Hfile, noff, sizeof(noff)) != sizeof(noff)) {
sprintf(g->Message, MSG(READ_ERROR), "Index file", strerror(errno));
return true;
} // endif MAX_INDX
} // endif read
if (trace)
htrc("noff[%d]=%lld\n", id, noff[id].Val);
// Position the cursor at the offset of this index
if (!lseek64(Hfile, noff[id].Val, SEEK_SET)) {
sprintf(g->Message, MSG(FUNC_ERRNO), errno, "Hseek");
if (lseek64(Hfile, noff[id].Val, SEEK_SET) < 0) {
sprintf(g->Message, "(XHUGE)lseek64: %s (%lld)", strerror(errno), noff[id].Val);
printf("%s\n", g->Message);
// sprintf(g->Message, MSG(FUNC_ERRNO), errno, "Hseek");
return true;
} // endif
} // endif lseek64
} // endif mode
#endif // UNIX
@ -2749,6 +2777,9 @@ int XHUGE::Write(PGLOBAL g, void *buf, int n, int size, bool& rc)
/***********************************************************************/
void XHUGE::Close(char *fn, int id)
{
if (trace)
htrc("XHUGE::Close: fn=%s id=%d NewOff=%lld\n", fn, id, NewOff.Val);
#if defined(WIN32)
if (id >= 0 && fn) {
CloseFileHandle(Hfile);
@ -2766,10 +2797,18 @@ void XHUGE::Close(char *fn, int id)
} // endif id
#else // !WIN32
if (id >= 0 && fn) {
fcntl(Hfile, F_SETFD, O_WRONLY);
if (lseek(Hfile, id * sizeof(IOFF), SEEK_SET))
write(Hfile, &NewOff, sizeof(IOFF));
if (Hfile != INVALID_HANDLE_VALUE) {
if (lseek64(Hfile, id * sizeof(IOFF), SEEK_SET) >= 0) {
ssize_t nbw = write(Hfile, &NewOff, sizeof(IOFF));
if (nbw != (signed)sizeof(IOFF))
htrc("Error writing index file header: %s\n", strerror(errno));
} else
htrc("(XHUGE::Close)lseek64: %s (%d)\n", strerror(errno), id);
} else
htrc("(XHUGE)error reopening %s: %s\n", fn, strerror(errno));
} // endif id
#endif // !WIN32
@ -2795,6 +2834,7 @@ void *XHUGE::FileView(PGLOBAL g, char *fn)
/***********************************************************************/
XXROW::XXROW(PTDBDOS tdbp) : XXBASE(tdbp, false)
{
Srtd = true;
Tdbp = tdbp;
Valp = NULL;
} // end of XXROW constructor

View File

@ -192,6 +192,7 @@ class DllExport XXBASE : public CSORT, public BLOCK {
void SetNth(int n) {Nth = n;}
int *GetPof(void) {return Pof;}
int *GetPex(void) {return Pex;}
bool IsSorted(void) {return Srtd;}
void FreeIndex(void) {PlgDBfree(Index);}
// Methods

View File

@ -147,6 +147,7 @@ class DllExport TDBASE : public TDB {
inline PKXBASE GetKindex(void) {return To_Kindex;}
inline PCOL GetSetCols(void) {return To_SetCols;}
inline void SetSetCols(PCOL colp) {To_SetCols = colp;}
inline void SetKey_Col(PCOL *cpp) {To_Key_Col = cpp;}
inline void SetXdp(PIXDEF xdp) {To_Xdp = xdp;}
inline void SetKindex(PKXBASE kxp) {To_Kindex = kxp;}
@ -156,6 +157,7 @@ class DllExport TDBASE : public TDB {
// Methods
virtual bool IsUsingTemp(PGLOBAL g) {return false;}
virtual bool IsIndexed(void) {return false;}
virtual PCATLG GetCat(void);
virtual PSZ GetPath(void);
virtual void PrintAM(FILE *f, char *m);
@ -190,6 +192,9 @@ class DllExport TDBASE : public TDB {
{assert(false); return true;}
protected:
virtual bool PrepareWriting(PGLOBAL g) {strcpy(g->Message,
"This function should not be called for this table"); return true;}
// Members
PTABDEF To_Def; // Points to catalog description block
PXOB *To_Link; // Points to column of previous relations