int TDBTBL::Cardinality(PGLOBAL g) { if (!g) return 0; // Cannot make the table list else if (Cardinal < 0) { int tsz; if (!Tablist && InitTableList(g)) return 0; // Cannot be calculated at this stage Cardinal = 0; for (PTABLE tabp = Tablist; tabp; tabp = tabp->GetNext()) { if ((tsz = tabp->GetTo_Tdb()->Cardinality(g)) < 0) { Cardinal = -1; return tsz; } // endif mxsz Cardinal += tsz; } // endfor i } // endif Cardinal return Cardinal; } // end of Cardinality
bool TDBTBL::TestFil(PGLOBAL g, PCFIL filp, PTABLE tabp) { char *body, *fil, op[8], tn[NAME_LEN]; bool neg; if (!filp) return TRUE; else body = filp->Body; if (strstr(body, " OR ") || strstr(body, " AND ")) return TRUE; // Not handled yet else fil = body + (*body == '(' ? 1 : 0); if (sscanf(fil, "TABID %s", op) != 1) return TRUE; // ignore invalid filter if ((neg = !strcmp(op, "NOT"))) strcpy(op, "IN"); if (!strcmp(op, "=")) { // Temporarily, filter must be "TABID = 'value'" only if (sscanf(fil, "TABID = '%[^']'", tn) != 1) return TRUE; // ignore invalid filter return !stricmp(tn, tabp->GetName()); } else if (!strcmp(op, "IN")) { char *p, *tnl = (char*)PlugSubAlloc(g, NULL, strlen(fil) - 10); int n; if (neg) n = sscanf(fil, "TABID NOT IN (%[^)])", tnl); else n = sscanf(fil, "TABID IN (%[^)])", tnl); if (n != 1) return TRUE; // ignore invalid filter while (tnl) { if ((p = strchr(tnl, ','))) *p++ = 0; if (sscanf(tnl, "'%[^']'", tn) != 1) return TRUE; // ignore invalid filter else if (!stricmp(tn, tabp->GetName())) return !neg; // Found tnl = p; } // endwhile return neg; // Not found } // endif op return TRUE; // invalid operator } // end of TestFil
bool TBLDEF::DefineAM(PGLOBAL g, LPCSTR, int) { char *tablist, *dbname, *def = NULL; Desc = "Table list table"; tablist = GetStringCatInfo(g, "Tablist", ""); dbname = GetStringCatInfo(g, "Dbname", "*"); def = GetStringCatInfo(g, "Srcdef", NULL); Ntables = 0; if (*tablist) { char *p, *pn, *pdb; PTABLE tbl; 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) htrc("TBL: Name=%s db=%s\n", tbl->GetName(), tbl->GetSchema()); // Link the blocks if (Tablep) Tablep->Link(tbl); else Tablep = tbl; Ntables++; if (p) pdb = pn + strlen(pn) + 1; else break; } // endfor pdb Maxerr = GetIntCatInfo("Maxerr", 0); Accept = GetBoolCatInfo("Accept", false); Thread = GetBoolCatInfo("Thread", false); } // endif tablist return FALSE; } // end of DefineAM
void TDBTBM::ResetDB(void) { for (PCOL colp = Columns; colp; colp = colp->GetNext()) if (colp->GetAmType() == TYPE_AM_TABID) colp->COLBLK::Reset(); for (PTABLE tabp = Tablist; tabp; tabp = tabp->GetNext()) ((PTDBASE)tabp->GetTo_Tdb())->ResetDB(); Tdbp = (Tablist) ? (PTDBASE)Tablist->GetTo_Tdb() : NULL; Crp = 0; } // end of ResetDB
int TDBTBL::GetMaxSize(PGLOBAL g) { if (MaxSize < 0) { int mxsz; if (!Tablist && InitTableList(g)) return 0; // Cannot be calculated at this stage MaxSize = 0; for (PTABLE tabp = Tablist; tabp; tabp = tabp->GetNext()) { if ((mxsz = tabp->GetTo_Tdb()->GetMaxSize(g)) < 0) { MaxSize = -1; return mxsz; } // endif mxsz MaxSize += mxsz; } // endfor i } // endif MaxSize return MaxSize; } // end of GetMaxSize
bool TDBPIVOT::GetSourceTable(PGLOBAL g) { if (Tdbp) return false; // Already done if (!Tabsrc && Tabname) { // Get the table description block of this table if (!(Tdbp = GetSubTable(g, ((PPIVOTDEF)To_Def)->Tablep, true))) return true; if (!GBdone) { char *colist; PCOLDEF cdp; if (FindDefaultColumns(g)) return true; // Locate the suballocated colist (size is not known yet) *(colist = (char*)PlugSubAlloc(g, NULL, 0)) = 0; // Make the column list for (cdp = To_Def->GetCols(); cdp; cdp = cdp->GetNext()) if (!cdp->GetOffset()) strcat(strcat(colist, cdp->GetName()), ", "); // Add the Pivot column at the end of the list strcat(colist, Picol); // Now we know how much was suballocated PlugSubAlloc(g, NULL, strlen(colist) + 1); // Locate the source string (size is not known yet) Tabsrc = (char*)PlugSubAlloc(g, NULL, 0); // Start making the definition strcat(strcat(strcpy(Tabsrc, "SELECT "), colist), ", "); // Make it suitable for Pivot by doing the group by strcat(strcat(Tabsrc, Function), "("); strcat(strcat(strcat(Tabsrc, Fncol), ") "), Fncol); strcat(strcat(Tabsrc, " FROM "), Tabname); strcat(strcat(Tabsrc, " GROUP BY "), colist); if (Tdbp->IsView()) // Until MariaDB bug is fixed strcat(strcat(Tabsrc, " ORDER BY "), colist); // Now we know how much was suballocated PlugSubAlloc(g, NULL, strlen(Tabsrc) + 1); } // endif !GBdone } else if (!Tabsrc) { strcpy(g->Message, MSG(SRC_TABLE_UNDEF)); return true; } // endif if (Tabsrc) { // Get the new table description block of this source table PTABLE tablep = new(g) XTAB("whatever", Tabsrc); tablep->SetQualifier(Database); if (!(Tdbp = GetSubTable(g, tablep, true))) return true; } // endif Tabsrc return false; } // end of GetSourceTable
PTDBASE TDBPRX::GetSubTable(PGLOBAL g, PTABLE tabp, bool b) { const char *sp = NULL; char *db, *name; bool mysql = true; PTDB tdbp = NULL; TABLE_SHARE *s = NULL; Field* *fp = NULL; PCATLG cat = To_Def->GetCat(); PHC hc = ((MYCAT*)cat)->GetHandler(); LPCSTR cdb, curdb = hc->GetDBName(NULL); THD *thd = (hc->GetTable())->in_use; db = (char*)tabp->GetQualifier(); name = (char*)tabp->GetName(); // Check for eventual loop for (PTABLE tp = To_Table; tp; tp = tp->Next) { cdb = (tp->Qualifier) ? tp->Qualifier : curdb; if (!stricmp(name, tp->Name) && !stricmp(db, cdb)) { sprintf(g->Message, "Table %s.%s pointing on itself", db, name); return NULL; } // endif } // endfor tp if (!tabp->GetSrc()) { if (!(s = GetTableShare(g, thd, db, name, mysql))) return NULL; if (s->is_view && !b) s->field = hc->get_table()->s->field; hc->tshp = s; } else if (b) { // Don't use caller's columns fp = hc->get_table()->field; hc->get_table()->field = NULL; // Make caller use the source definition sp = hc->get_table()->s->option_struct->srcdef; hc->get_table()->s->option_struct->srcdef = tabp->GetSrc(); } // endif srcdef if (mysql) { #if defined(MYSQL_SUPPORT) // Access sub-table via MySQL API if (!(tdbp= cat->GetTable(g, tabp, Mode, "MYPRX"))) { char buf[MAX_STR]; strcpy(buf, g->Message); sprintf(g->Message, "Error accessing %s.%s: %s", db, name, buf); hc->tshp = NULL; goto err; } // endif Define if (db) ((PTDBMY)tdbp)->SetDatabase(tabp->GetQualifier()); if (Mode == MODE_UPDATE || Mode == MODE_DELETE) tdbp->SetName(Name); // For Make_Command #else // !MYSQL_SUPPORT sprintf(g->Message, "%s.%s is not a CONNECT table", db, tblp->Name); goto err; #endif // MYSQL_SUPPORT } else { // Sub-table is a CONNECT table tabp->Next = To_Table; // For loop checking tdbp = cat->GetTable(g, tabp, Mode); } // endif mysql if (s) { if (s->is_view && !b) s->field = NULL; hc->tshp = NULL; } else if (b) { // Restore s structure that can be in cache hc->get_table()->field = fp; hc->get_table()->s->option_struct->srcdef = sp; } // endif s if (trace && tdbp) htrc("Subtable %s in %s\n", name, SVP(((PTDBASE)tdbp)->GetDef()->GetDB())); err: if (s) free_table_share(s); return (PTDBASE)tdbp; } // end of GetSubTable