YoushouldhavereceivedacopyoftheGNUGeneralPublicLicense alongwiththisprogram;ifnot,writetotheFreeSoftware
Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1335 USA */
/***********************************************************************/ /* Author Olivier BERTRAND bertrandop@gmail.com 2004-2019 */ /* */ /* WHAT THIS PROGRAM DOES: */ /* ----------------------- */ /* This program are the CONNECT general purpose semantic routines. */ /***********************************************************************/
/***********************************************************************/ /* Include application header files */ /* */ /* global.h is header containing all global declarations. */ /* plgdbsem.h is header containing the DB applic. declarations. */ /***********************************************************************/ #define DONT_DEFINE_VOID #include <my_global.h> #include"handler.h" #undef OFFSET
/***********************************************************************/ /* MySQL routines called externally by semantic routines. */ /***********************************************************************/ int rename_file_ext(constchar *from, constchar *to,constchar *ext);
/***********************************************************************/ /* CntCheckDB: Initialize a DB application session. */ /* Note: because MySQL does not call a storage handler when a user */ /* executes a use db command, a check must be done before an SQL */ /* command is executed to check whether we are still working on the */ /* current database, and if not to load the newly used database. */ /***********************************************************************/ bool CntCheckDB(PGLOBAL g, PHC handler, constchar *pathname)
{ bool rc= false;
PDBUSER dbuserp= PlgGetUser(g);
if (trace(1)) {
printf("CntCheckDB: dbuserp=%p\n", dbuserp);
} // endif trace
// Set the database path for this table if (handler->SetDataPath(g, pathname)) returntrue;
if (dbuserp->Catalog) { returnfalse; // Nothing else to do
} // endif Catalog
// Copy new database name in dbuser block
strncpy(dbuserp->Name, "???", sizeof(dbuserp->Name) - 1);
dbuserp->Vtdbno= 0; // Init of TDB numbers
/*********************************************************************/ /* Now allocate and initialize the Database Catalog. */ /*********************************************************************/
dbuserp->Step= MSG(READY);
if (!(dbuserp->Catalog= new MYCAT(handler))) returntrue;
/*********************************************************************/ /* All is correct. */ /*********************************************************************/
snprintf(g->Message, sizeof(g->Message), MSG(DATABASE_LOADED), "???");
if (trace(1))
printf("msg=%s\n", g->Message);
return rc;
} // end of CntCheckDB
/***********************************************************************/ /* CntInfo: Get table info. */ /* Returns valid: true if this is a table info. */ /***********************************************************************/ bool CntInfo(PGLOBAL g, PTDB tp, PXF info)
{ if (tp) { bool b = (tp->GetFtype() == RECFM_NAF);
PTDBDOS tdbp = b ? NULL : (PTDBDOS)tp;
try { if (!c1) { // if (mode == MODE_INSERT) or CHECK TABLE // Allocate all column blocks for that table
tdbp->ColDB(g, NULL, 0);
} elsefor (p = c1; *p; p += n) { // Allocate only used column blocks if (trace(1))
printf("Allocating column %s\n", p);
g->Message[0] = 0; // To check whether ColDB made an error message
colp = tdbp->ColDB(g, p, 0);
if (!colp && !(mode == MODE_INSERT && tdbp->IsSpecial(p))) { if (g->Message[0] == 0)
snprintf(g->Message, sizeof(g->Message), MSG(COL_ISNOT_TABLE), p, tdbp->GetName());
throw1;
} // endif colp
n = strlen(p) + 1;
} // endfor p
for (colp = tdbp->GetColumns(); colp; colp = colp->GetNext()) { if (colp->InitValue(g)) throw2;
if (mode == MODE_INSERT) // Allow type conversion if (colp->SetBuffer(g, colp->GetValue(), true, false)) throw3;
colp->AddColUse(U_P); // For PLG tables
} // endfor colp
/*******************************************************************/ /* In Update mode, the updated column blocks must be distinct from */ /* the read column blocks. So make a copy of the TDB and allocate */ /* its column blocks in mode write (required by XML tables). */ /*******************************************************************/ if (mode == MODE_UPDATE) {
PTDB utp;
if (!(utp = tdbp->Duplicate(g))) { /* If table type is of type virtual retrieve global parameter as it was.*/ if (tdbp->GetAmType() == TYPE_AM_VIR) { if (tdbp->OpenDB(g)) {
printf("%s\n", g->Message); throw7;
}
}
snprintf(g->Message, sizeof(g->Message), MSG(INV_UPDT_TABLE), tdbp->GetName()); throw4;
} // endif tp
if (!c2) // Allocate all column blocks for that table
utp->ColDB(g, NULL, 0); elsefor (p = c2; *p; p += n) { // Allocate only used column blocks
colp = utp->ColDB(g, p, 0);
n = strlen(p) + 1;
} // endfor p
for (colp = utp->GetColumns(); colp; colp = colp->GetNext()) { if (colp->InitValue(g)) throw5;
if (colp->SetBuffer(g, colp->GetValue(), true, false)) throw6;
} // endfor colp
// Attach the updated columns list to the main table
tdbp->SetSetCols(utp->GetColumns());
} elseif (tdbp && mode == MODE_INSERT)
tdbp->SetSetCols(tdbp->GetColumns());
// Now do open the physical table if (trace(1))
printf("Opening table %s in mode %d tdbp=%p\n",
tdbp->GetName(), mode, tdbp);
//tdbp->SetMode(mode);
if (del/* && (tdbp->GetFtype() != RECFM_NAF*/) { // To avoid erasing the table when doing a partial delete // make a fake Next // PDOSDEF ddp= new(g) DOSDEF; // PTDB tp= new(g) TDBDOS(ddp, NULL);
tdbp->SetNext((PTDB)1);
dup->Check &= ~CHK_DELETE;
} // endif del
if (trace(1))
printf("About to open the table: tdbp=%p\n", tdbp);
if (mode != MODE_ANY && mode != MODE_ALTER) { if (tdbp->OpenDB(g)) {
printf("%s\n", g->Message); throw7;
} else
tdbp->SetNext(NULL);
} // endif mode
rcop = false;
} catch (int n) { if (trace(1))
htrc("Exception %d: %s\n", n, g->Message);
} catch (constchar *msg) {
strcpy(g->Message, msg);
} // end catch
return rcop;
} // end of CntOpenTable
/***********************************************************************/ /* Rewind a table by reopening it. */ /***********************************************************************/ bool CntRewindTable(PGLOBAL g, PTDB tdbp)
{ if (!tdbp) returntrue;
tdbp->OpenDB(g); returnfalse;
} // end of CntRewindTable
/***********************************************************************/ /* Evaluate all columns after a record is read. */ /***********************************************************************/
RCODE EvalColumns(PGLOBAL g, PTDB tdbp, bool reset, bool mrr)
{
RCODE rc= RC_OK;
PCOL colp;
try { for (colp = tdbp->GetColumns(); rc == RC_OK && colp;
colp = colp->GetNext()) {
xtrc(2, "Going to read column %s of table %s\n",
colp->GetName(), tdbp->GetName());
if (reset)
colp->Reset();
// Virtual columns are computed by MariaDB if (!colp->GetColUse(U_VIRTUAL) && (!mrr || colp->GetKcol())) if (colp->Eval(g))
rc = RC_FX;
} // endfor colp
} catch (int n) { if (trace(1))
printf("Error %d reading columns: %s\n", n, g->Message);
/***********************************************************************/ /* ReadNext: Read next record sequentially. */ /***********************************************************************/
RCODE CntReadNext(PGLOBAL g, PTDB tdbp)
{
RCODE rc;
if (!tdbp) return RC_FX; elseif (tdbp->GetKindex()) { // Reading sequencially an indexed table. This happens after the // handler function records_in_range was called and MySQL decides // to quit using the index (!!!) Drop the index. // for (PCOL colp= tdbp->GetColumns(); colp; colp= colp->GetNext()) // colp->SetKcol(NULL);
((PTDBASE)tdbp)->ResetKindex(g, NULL);
} // endif index
try { // Do it now to avoid double eval when filtering for (PCOL colp = tdbp->GetColumns(); colp; colp = colp->GetNext())
colp->Reset();
do { if ((rc = (RCODE)tdbp->ReadDB(g)) == RC_OK) if (!ApplyFilter(g, tdbp->GetFilter()))
rc = RC_NF;
} while (rc == RC_NF);
if (rc == RC_OK)
rc = EvalColumns(g, tdbp, false);
/***********************************************************************/ /* WriteRow: Insert a new row into a table. */ /***********************************************************************/
RCODE CntWriteRow(PGLOBAL g, PTDB tdbp)
{
RCODE rc;
PCOL colp; //PTDBASE tp= (PTDBASE)tdbp;
if (!tdbp) return RC_FX;
try { // Store column values in table write buffer(s) for (colp = tdbp->GetSetCols(); colp; colp = colp->GetNext()) if (!colp->GetColUse(U_VIRTUAL))
colp->WriteColumn(g);
if (tdbp->IsIndexed()) // Index values must be sorted before updating
rc = (RCODE)((PTDBDOS)tdbp)->GetTxfp()->StoreValues(g, true); else // Return result code from write operation
rc = (RCODE)tdbp->WriteDB(g);
if (all) { if (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 (tdbp->GetKindex() && !((PTDBASE)tdbp)->GetKindex()->IsSorted() && // ((PTDBASE)tdbp)->Txfp->GetAmType() != TYPE_AM_DBF) {
} elseif(tdbp->IsIndexed()) { // Index values must be sorted before updating
rc= (RCODE)((PTDBDOS)tdbp)->GetTxfp()->StoreValues(g, false);
} else// Return result code from delete operation
rc= (RCODE)tdbp->DeleteDB(g, RC_OK);
return rc;
} // end of CntDeleteRow
/***********************************************************************/ /* CLOSETAB: Close a table. */ /***********************************************************************/ int CntCloseTable(PGLOBAL g, PTDB tdbp, bool nox, bool abort)
{ int rc = RC_OK; //TDBASE *tbxp= (PTDBASE)tdbp;
if (!tdbp) return rc; // Nothing to do elseif (tdbp->GetUse() != USE_OPEN) { if (tdbp->GetAmType() == TYPE_AM_XML ||
tdbp->GetAmType() == TYPE_AM_JSN)
tdbp->CloseDB(g); // Opened by GetMaxSize
switch (rc) { case RC_FX:
abort = true; break; case RC_INFO:
PushWarning(g, tdbp); break;
} // endswitch rc
try { // This will close the table file(s) and also finalize write // operations such as Insert, Update, or Delete.
tdbp->SetAbort(abort);
tdbp->CloseDB(g);
tdbp->SetAbort(false);
if (trace(2))
printf("Table %s closed\n", tdbp->GetName());
if (!nox && tdbp->GetMode() != MODE_READ && tdbp->GetMode() != MODE_ANY) { if (trace(2))
printf("About to reset opt\n");
if (!tdbp->IsRemote()) { // Make all the eventual indexes
PTDBASE tbxp = (PTDBASE)tdbp;
tbxp->ResetKindex(g, NULL);
tbxp->SetKey_Col(NULL);
rc = tbxp->ResetTableOpt(g, true, tbxp->GetDef()->Indexable() == 1);
} // endif remote
return (rc == RC_OK || rc == RC_INFO) ? 0 : rc;
} // end of CntCloseTable
/***********************************************************************/ /* Load and initialize the use of an index. */ /* 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, bool sorted)
{
PIXDEF xdp;
PTDBDOS tdbp;
DOSDEF *dfp;
//if (!(k= colp->GetKey())) // if (colp->GetOpt() >= 2) { // strcpy(g->Message, "Not a valid indexed column"); // return -1; // } else // This is a pseudo indexed sorted block optimized column // return 0;
if (tdbp->GetKindex())
{ if (((XXBASE*)tdbp->GetKindex())->GetID() == id) {
tdbp->GetKindex()->Reset(); // Same index return (tdbp->GetKindex()->IsMul()) ? 2 : 1;
} else {
tdbp->GetKindex()->Close();
tdbp->SetKindex(NULL);
} // endif colp
}
for (xdp= dfp->GetIndx(); xdp; xdp= xdp->GetNext()) if (xdp->GetID() == id) break;
if (!xdp) {
snprintf(g->Message, sizeof(g->Message), "Wrong index ID %d", id); return0;
} // endif xdp
#if0 if (xdp->IsDynamic()) { // This is a dynamically created index (KINDEX) // It should not be created now, if called by index range
tdbp->SetXdp(xdp); return (xdp->IsUnique()) ? 1 : 2;
} // endif dynamic #endif// 0
// Static indexes must be initialized now for records_in_range if (tdbp->InitialyzeIndex(g, xdp, sorted)) return0;
return (tdbp->GetKindex()->IsMul()) ? 2 : 1;
} // end of CntIndexInit
#ifdefined(WORDS_BIGENDIAN) /***********************************************************************/ /* Swap bytes of the key that are written in little endian order. */ /***********************************************************************/ staticvoid SetSwapValue(PVAL valp, char *kp)
{ if (valp->IsTypeNum() && valp->GetType() != TYPE_DECIM) {
uchar buf[8]; int i, k= valp->GetClen();
/***********************************************************************/ /* IndexRead: fetch a record having the index value. */ /***********************************************************************/
RCODE CntIndexRead(PGLOBAL g, PTDB ptdb, OPVAL op, const key_range *kr, bool mrr)
{ int n, x;
RCODE rc;
XXBASE *xbp;
PTDBDOS tdbp;
if (!ptdb) return RC_FX; else
x= ptdb->GetDef()->Indexable();
if (!x) {
snprintf(g->Message, sizeof(g->Message), MSG(TABLE_NO_INDEX), ptdb->GetName()); return RC_FX;
} elseif (x == 2) { // Remote index. Only used in read mode if ((ptdb->GetMode() == MODE_READ || ptdb->GetMode() == MODE_READX)
&& op != OP_SAME && ptdb->ReadKey(g, op, kr)) return RC_FX;
// Set reference values and index operator if (!tdbp->GetLink() || !tdbp->GetKindex()) { // if (!tdbp->To_Xdp) {
snprintf(g->Message, sizeof(g->Message), "Index not initialized for table %s", tdbp->GetName()); return RC_FX; #if0
} // endif !To_Xdp // Now it's time to make the dynamic index if (tdbp->InitialyzeIndex(g, NULL, false)) {
snprintf(g->Message, sizeof(g->Message), "Fail to make dynamic index %s",
tdbp->To_Xdp->GetName()); return RC_FX;
} // endif MakeDynamicIndex #endif// 0
} // endif !To_Kindex
xbp= (XXBASE*)tdbp->GetKindex();
if (kr) { char *kp= (char*)kr->key; int len= kr->length; short lg; bool rcb;
PVAL valp;
PCOL colp;
for (n= 0; n < tdbp->GetKnum(); n++) {
colp= (PCOL)tdbp->Key(n);
if (colp->GetColUse(U_NULLS))
kp++; // Skip null byte
if (rcb) { if (tdbp->RowNumber(g))
snprintf(g->Message, sizeof(g->Message), "Out of range value for column %s at row %d",
colp->GetName(), tdbp->RowNumber(g)); else
snprintf(g->Message, sizeof(g->Message), "Out of range value for column %s",
colp->GetName());
if (!tdbp->GetKindex() || !tdbp->GetLink()) { if (!tdbp->GetXdp()) {
snprintf(g->Message, sizeof(g->Message), "Index not initialized for table %s", tdbp->GetName());
DBUG_PRINT("Range", ("%s", g->Message)); return -1;
} else// Dynamic index return tdbp->GetXdp()->GetMaxSame(); // TODO a better estimate
} else
xbp= (XXBASE*)tdbp->GetKindex();
for (b= false, i= 0; i < 2; i++) {
p= kp= key[i];
if (kp) { for (n= 0; n < tdbp->GetKnum(); n++) { if (kmap[i] & (key_part_map)(1 << n)) { if (b == true) // Cannot do indexing with missing intermediate key return -1;
colp= (PCOL)tdbp->Key(n);
if (colp->GetColUse(U_NULLS))
p++; // Skip null byte ???
if (rcb) { if (tdbp->RowNumber(g))
snprintf(g->Message, sizeof(g->Message), "Out of range value for column %s at row %d",
colp->GetName(), tdbp->RowNumber(g)); else
snprintf(g->Message, sizeof(g->Message), "Out of range value for column %s",
colp->GetName());
if (trace(1))
printf("k1=%d k0=%d\n", k[1], k[0]);
return k[1] - k[0];
} // end of CntIndexRange
Messung V0.5 in Prozent
¤ Diese beiden folgenden Angebotsgruppen bietet das Unternehmen0.21Angebot
(Wie Sie bei der Firma Beratungs- und Dienstleistungen beauftragen können 2026-10-08)
¤
Die Informationen auf dieser Webseite wurden
nach bestem Wissen sorgfältig zusammengestellt. Es wird jedoch weder Vollständigkeit, noch Richtigkeit,
noch Qualität der bereit gestellten Informationen zugesichert.
Bemerkung:
Die farbliche Syntaxdarstellung und die Messung sind noch experimentell.