for (pdb = tablist; ;) { if ((p = strchr(pdb, ',')))
*p = 0;
// Analyze the table name, it may have the format: // [dbname.]tabname if ((pn = strchr(pdb, '.'))) {
*pn++ = 0;
} else {
pn = pdb;
pdb = dbname;
} // endif p
// Allocate the TBLIST block for that table
tbl = new(g) XTAB(pn, def);
tbl->SetSchema(pdb);
if (trace(1))
htrc("TBL: Name=%s db=%s\n", tbl->GetName(), tbl->GetSchema());
// Link the blocks if (Tablep)
Tablep->Link(tbl); else
Tablep = tbl;
/***********************************************************************/ /* Allocate TBL column description block. */ /***********************************************************************/
PCOL TDBTBL::MakeCol(PGLOBAL g, PCOLDEF cdp, PCOL cprec, int n)
{ returnnew(g) PRXCOL(cdp, this, cprec, n);
} // end of MakeCol
/***********************************************************************/ /* InsertSpecialColumn: Put a special column ahead of the column list.*/ /***********************************************************************/
PCOL TDBTBL::InsertSpecialColumn(PCOL scp)
{
PCOL colp;
if (!scp->IsSpecial()) return NULL;
if (scp->GetAmType() == TYPE_AM_TABID) // This special column is handled locally
colp = new((TIDBLK*)scp) TBTBLK(scp->GetValue()); else// Other special columns are treated normally
colp = scp;
colp->SetNext(Columns);
Columns = colp; return colp;
} // end of InsertSpecialColumn
for (tp = tdp->Tablep; tp; tp = tp->GetNext()) { if (TestFil(g, To_CondFil, tp)) {
tabp = new(g) XTAB(tp);
if (tabp->GetSrc()) { // Table list is a list of connections
hc->option_struct->connect= (char*)tabp->GetName();
} // endif Src
// Get the table description block of this table if (!(Tdbp = GetSubTable(g, tabp))) { if (++Nbc > Maxerr) returnTRUE; // Error return else continue; // Skip this table
} else
RemoveNext(tabp); // To avoid looping
// We must allocate subtable columns before GetMaxSize is called // because some (PLG, ODBC?) need to have their columns attached. // Real initialization will be done later. for (colp = Columns; colp; colp = colp->GetNext()) if (!colp->IsSpecial()) if (((PPRXCOL)colp)->Init(g, NULL) && !Accept) returnTRUE;
if (Tablist)
Tablist->Link(tabp); else
Tablist = tabp;
} // endif filp
} // endfor tp
hc->option_struct->connect = (char*)scs;
//NumTables = n;
To_CondFil = NULL; // To avoid doing it several times returnFALSE;
} // end of InitTableList
/***********************************************************************/ /* Test the tablename against the pseudo "local" filter. */ /***********************************************************************/ bool TDBTBL::TestFil(PGLOBAL g, PCFIL filp, PTABLE tabp)
{ char *body, *fil, op[8], tn[NAME_LEN]; bool neg;
if (!filp) returnTRUE; else
body = filp->Body;
if (strstr(body, " OR ") || strstr(body, " AND ")) returnTRUE; // Not handled yet else
fil = body + (*body == '(' ? 1 : 0);
if (neg)
n = sscanf(fil, "TABID NOT IN (%[^)])", tnl); else
n = sscanf(fil, "TABID IN (%[^)])", tnl);
if (n != 1) returnTRUE; // ignore invalid filter
while (tnl) { if ((p = strchr(tnl, ',')))
*p++ = 0;
if (sscanf(tnl, "'%[^']'", tn) != 1) returnTRUE; // ignore invalid filter elseif (!stricmp(tn, tabp->GetName())) return !neg; // Found
tnl = p;
} // endwhile
return neg; // Not found
} // endif op
returnTRUE; // invalid operator
} // end of TestFil
/***********************************************************************/ /* Sum up the cardinality of all sub-tables. */ /***********************************************************************/ int TDBTBL::Cardinality(PGLOBAL g)
{ if (!g) return0; // Cannot make the table list elseif (Cardinal < 0) { int tsz;
if (!Tablist && InitTableList(g)) return0; // Cannot be calculated at this stage
/***********************************************************************/ /* Sum up the maximum sizes of all sub-tables. */ /***********************************************************************/ int TDBTBL::GetMaxSize(PGLOBAL g)
{ if (MaxSize < 0) { int mxsz;
if (!Tablist && InitTableList(g)) return0; // Cannot be calculated at this stage
/***********************************************************************/ /* Reset read/write position values. */ /***********************************************************************/ void TDBTBL::ResetDB(void)
{ for (PCOL colp = Columns; colp; colp = colp->GetNext()) if (colp->GetAmType() == TYPE_AM_TABID ||
colp->GetAmType() == TYPE_AM_SRVID)
colp->COLBLK::Reset();
for (PTABLE tabp = Tablist; tabp; tabp = tabp->GetNext())
tabp->GetTo_Tdb()->ResetDB();
Tdbp = Tablist->GetTo_Tdb();
Crp = 0;
} // end of ResetDB
/***********************************************************************/ /* Returns RowId if b is false or Rownum if b is true. */ /***********************************************************************/ int TDBTBL::RowNumber(PGLOBAL g, bool b)
{ return Tdbp->RowNumber(g) + ((b) ? 0 : Rows);
} // end of RowNumber
/***********************************************************************/ /* TBL Access Method opening routine. */ /* Open first file, other will be opened sequencially when reading. */ /***********************************************************************/ bool TDBTBL::OpenDB(PGLOBAL g)
{ if (trace(1))
htrc("TBL OpenDB: tdbp=%p tdb=R%d use=%d key=%p mode=%d\n", this, Tdb_No, Use, To_Key_Col, Mode);
if (Use == USE_OPEN) { /*******************************************************************/ /* Table already open, replace it at its beginning. */ /*******************************************************************/
ResetDB(); return Tdbp->OpenDB(g); // Re-open fist table
} // endif use
/*********************************************************************/ /* When GetMaxsize was called, To_CondFil was not set yet. */ /*********************************************************************/ if (To_CondFil && Tablist) {
Tablist = NULL;
Nbc = 0;
} // endif To_CondFil
/*********************************************************************/ /* Open the first table of the list. */ /*********************************************************************/ if (!Tablist && InitTableList(g)) // done in GetMaxSize returnTRUE;
// Check and initialize the subtable columns for (PCOL cp = Columns; cp; cp = cp->GetNext()) if (cp->GetAmType() == TYPE_AM_TABID)
cp->COLBLK::Reset(); elseif (((PPRXCOL)cp)->Init(g, NULL) && !Accept) returnTRUE;
if (trace(1))
htrc("Opening subtable %s\n", Tdbp->GetName());
// Now we can safely open the table if (Tdbp->OpenDB(g)) returnTRUE;
} // endif *Tablist
Use = USE_OPEN; returnFALSE;
} // end of OpenDB
/***********************************************************************/ /* ReadDB: Data Base read routine for MUL access method. */ /***********************************************************************/ int TDBTBL::ReadDB(PGLOBAL g)
{ int rc;
if (!CurTable) return RC_EF; elseif (To_Kindex) { /*******************************************************************/ /* Reading is by an index table. */ /*******************************************************************/
strcpy(g->Message, MSG(NO_INDEX_READ));
rc = RC_FX;
} else { /*******************************************************************/ /* Now start the reading process. */ /*******************************************************************/
retry:
rc = Tdbp->ReadDB(g);
if (rc == RC_EF) { // Total number of rows met so far
Rows += Tdbp->RowNumber(g) - 1;
Crp += Tdbp->GetProgMax(g);
if ((CurTable = CurTable->GetNext())) { /***************************************************************/ /* Continue reading from next table file. */ /***************************************************************/
Tdbp->CloseDB(g);
Tdbp = CurTable->GetTo_Tdb();
// Check and initialize the subtable columns for (PCOL cp = Columns; cp; cp = cp->GetNext()) if (cp->GetAmType() == TYPE_AM_TABID ||
cp->GetAmType() == TYPE_AM_SRVID)
cp->COLBLK::Reset(); elseif (((PPRXCOL)cp)->Init(g, NULL) && !Accept) return RC_FX;
if (trace(1))
htrc("Opening subtable %s\n", Tdbp->GetName());
// Now we can safely open the table if (Tdbp->OpenDB(g)) // Open next table return RC_FX;
/***********************************************************************/ /* TDBTBM constructors. */ /***********************************************************************/
TDBTBM::TDBTBM(PTBLDEF tdp) : TDBTBL(tdp)
{
Tmp = NULL; // To data table TBMT structures
Cmp = NULL; // Current data table TBMT
Bmp = NULL; // To bad (unconnected) TBMT structures
Done = false; // TRUE after first GetAllResults
Nrc = 0; // Number of remote connections
Nlc = 0; // Number of local connections
} // end of TDBTBL standard constructor
/***********************************************************************/ /* Reset read/write position values. */ /***********************************************************************/ void TDBTBM::ResetDB(void)
{ for (PCOL colp = Columns; colp; colp = colp->GetNext()) if (colp->GetAmType() == TYPE_AM_TABID)
colp->COLBLK::Reset();
// Local tables for (PTABLE tabp = Tablist; tabp; tabp = tabp->GetNext())
tabp->GetTo_Tdb()->ResetDB();
Tdbp = (Tablist) ? Tablist->GetTo_Tdb() : NULL;
Crp = 0;
} // end of ResetDB
/***********************************************************************/ /* Returns RowId if b is false or Rownum if b is true. */ /***********************************************************************/ int TDBTBM::RowNumber(PGLOBAL g, bool b)
{ return Tdbp->RowNumber(g) + ((b) ? 0 : Rows);
} // end of RowNumber
/***********************************************************************/ /* Returns true if this MYSQL table refers to a local table. */ /***********************************************************************/ bool TDBTBM::IsLocal(PTABLE tbp)
{
TDBMYSQL *tdbp = (TDBMYSQL*)tbp->GetTo_Tdb();
return ((!stricmp(tdbp->Host, "localhost") ||
!strcmp(tdbp->Host, "127.0.0.1")) &&
(int) tdbp->Port == (int)GetDefaultPort());
} // end of IsLocal
// Allocates the TBMT blocks for the tables for (tabp = Tablist; tabp; tabp = tabp->Next) if (tabp->GetTo_Tdb()->GetAmType() == TYPE_AM_MYSQL && !IsLocal(tabp)) { // Remove remote table from the local list
*ptabp = tabp->Next;
if (trace(1))
htrc("=====> New remote table %s\n", tabp->GetName());
// Create the thread that will do the table opening.
pthread_attr_init(&tp->attr); // pthread_attr_setdetachstate(&tp->attr, PTHREAD_CREATE_JOINABLE);
if ((k = pthread_create(&tp->Tid, &tp->attr, ThreadOpen, tp))) {
snprintf(g->Message, sizeof(g->Message), "pthread_create error %d", k);
Nbc++; continue;
} // endif k
// Add it to the remote list
*ptp = tp;
ptp = &tp->Next;
Nrc++; // Number of remote connections
} else { if (trace(1))
htrc("=====> Local table %s\n", tabp->GetName());
ptabp = &tabp->Next;
Nlc++; // Number of local connections
} // endif Type
returnfalse;
} // end of OpenTables
/***********************************************************************/ /* TBL Access Method opening routine. */ /* Open first file, other will be opened sequencially when reading. */ /***********************************************************************/ bool TDBTBM::OpenDB(PGLOBAL g)
{ if (trace(1))
htrc("TBM OpenDB: tdbp=%p tdb=R%d use=%d key=%p mode=%d\n", this, Tdb_No, Use, To_Key_Col, Mode);
if (Use == USE_OPEN) { /*******************************************************************/ /* Table already open, replace it at its beginning. */ /*******************************************************************/
ResetDB(); return (Tdbp) ? Tdbp->OpenDB(g) : false; // Re-open fist table
} // endif use
#if0 /*********************************************************************/ /* When GetMaxsize was called, To_CondFil was not set yet. */ /*********************************************************************/ if (To_CondFil && Tablist) {
Tablist = NULL;
Nbc = 0;
} // endif To_CondFil #endif// 0
/*********************************************************************/ /* Make the table list. */ /*********************************************************************/ if (/*!Tablist &&*/ InitTableList(g)) returnTRUE;
/*********************************************************************/ /* Open all remote tables of the list. */ /*********************************************************************/ if (OpenTables(g)) returnTRUE;
/*********************************************************************/ /* Proceed with local tables. */ /*********************************************************************/ if ((CurTable = Tablist)) {
Tdbp = CurTable->GetTo_Tdb(); // Tdbp->SetMode(Mode);
// Check and initialize the subtable columns for (PCOL cp = Columns; cp; cp = cp->GetNext()) if (cp->GetAmType() == TYPE_AM_TABID)
cp->COLBLK::Reset(); elseif (((PPRXCOL)cp)->Init(g, NULL) && !Accept) returnTRUE;
if (trace(1))
htrc("Opening subtable %s\n", Tdbp->GetName());
// Now we can safely open the table if (Tdbp->OpenDB(g)) returnTRUE;
} // endif *Tablist
Use = USE_OPEN; returnFALSE;
} // end of OpenDB
/***********************************************************************/ /* ReadDB: Data Base read routine for MUL access method. */ /***********************************************************************/ int TDBTBM::ReadDB(PGLOBAL g)
{ int rc;
if (!Done) { // Get result from local tables if ((rc = TDBTBL::ReadDB(g)) != RC_EF) return rc; elseif ((rc = ReadNextRemote(g)) != RC_OK) return rc;
Done = true;
} // endif Done
/*********************************************************************/ /* Now start the reading process of remote tables. */ /*********************************************************************/
retry:
rc = Tdbp->ReadDB(g);
if (rc == RC_EF) { // Total number of rows met so far
Rows += Tdbp->RowNumber(g) - 1;
Crp += Tdbp->GetProgMax(g);
Cmp->Complete = true;
if ((rc = ReadNextRemote(g)) == RC_OK) goto retry;
/***********************************************************************/ /* ReadNext: Continue reading from next table. */ /***********************************************************************/ int TDBTBM::ReadNextRemote(PGLOBAL g)
{ bool b;
if (Tdbp)
Tdbp->CloseDB(g);
Cmp = NULL;
retry:
b = false;
// Search for a remote table having its result set
pthread_mutex_lock(&tblmut); for (PTBMT tp = Tmp; tp; tp = tp->Next) if (tp->Rc != RC_FX) { if (tp->Ready) { if (!tp->Complete) {
Cmp = tp; break;
} // endif Complete
} else
b = true;
} // endif Rc
pthread_mutex_unlock(&tblmut);
if (!Cmp) { if (b) { // more result to come // sleep(20); goto retry;
} else return RC_EF;
} // endif Curtable
Tdbp = Cmp->Tap->GetTo_Tdb();
// Check and initialize the subtable columns for (PCOL cp = Columns; cp; cp = cp->GetNext()) if (cp->GetAmType() == TYPE_AM_TABID)
cp->COLBLK::Reset(); elseif (((PPRXCOL)cp)->Init(g, NULL) && !Accept) return RC_FX;
if (trace(1))
htrc("Reading subtable %s\n", Tdbp->GetName());
return RC_OK;
} // end of ReadNextRemote #endif// DEVELOPMENT
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.