10.0-connect merge
This commit is contained in:
commit
86957d414f
@ -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);
|
||||
|
@ -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
|
||||
|
@ -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_
|
||||
|
@ -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;
|
||||
|
@ -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
|
||||
|
@ -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. */
|
||||
/***********************************************************************/
|
||||
|
@ -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
|
||||
|
||||
|
@ -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) {
|
||||
|
@ -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
|
||||
|
@ -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
|
||||
|
@ -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
|
||||
|
@ -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;
|
||||
|
||||
|
@ -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
|
||||
|
@ -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;
|
||||
|
||||
|
@ -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
|
||||
|
@ -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
|
||||
};
|
||||
|
||||
|
@ -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
|
||||
|
@ -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
|
||||
|
||||
|
@ -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
|
||||
|
@ -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
|
||||
|
@ -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;
|
||||
|
@ -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;
|
||||
|
2570
storage/connect/mysql-test/connect/r/updelx.result
Normal file
2570
storage/connect/mysql-test/connect/r/updelx.result
Normal file
File diff suppressed because it is too large
Load Diff
@ -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
|
||||
|
@ -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;
|
||||
|
25
storage/connect/mysql-test/connect/t/updelx.inc
Normal file
25
storage/connect/mysql-test/connect/t/updelx.inc
Normal 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;
|
96
storage/connect/mysql-test/connect/t/updelx.test
Normal file
96
storage/connect/mysql-test/connect/t/updelx.test
Normal 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
|
@ -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);
|
||||
|
@ -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. */
|
||||
|
@ -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;
|
||||
|
||||
|
@ -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;}
|
||||
|
@ -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;
|
||||
|
@ -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
|
||||
|
@ -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
|
||||
|
@ -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
|
||||
|
@ -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 ---------------------------- */
|
||||
|
@ -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 ------------------------- */
|
||||
|
@ -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);
|
||||
|
@ -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;
|
||||
|
@ -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;
|
||||
|
@ -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);
|
||||
|
@ -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 */
|
||||
|
@ -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__
|
||||
|
||||
|
@ -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
|
||||
|
||||
/***********************************************************************/
|
||||
|
@ -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. */
|
||||
|
@ -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
|
||||
|
@ -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
|
||||
|
@ -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
|
||||
|
Loading…
x
Reference in New Issue
Block a user