mariadb/storage/connect/tabtbl.cpp
Sergei Golubchik 5ae2656b69 Squashed commit of connect/10.0:
commit c545d544378483bf68c4fb713cd4ec872d0df2c4
Author: Olivier Bertrand <bertrandop@gmail.com>
Date:   Tue Mar 27 23:13:14 2018 +0200

    - Fix MDEV-15577 CONNECT engine JDBC remote index prevents UPDATE
      Fixed in TDBJDBC::OpenDB because query can be null for updates
      modified:   storage/connect/tabjdbc.cpp

commit c4f1fe2e8e74566e9c3296f435448d9f5c718b23
Author: Olivier Bertrand <bertrandop@gmail.com>
Date:   Wed Mar 14 12:21:17 2018 +0100

    - Fix MDEV-15429 CONNECT engine JDBC handling Postgresql UUID type
      Also handle Postgresql sending type VARCHAR for TEXT column and
      setting length to b x7FFFFFF when the length is unknown.
      modified:   storage/connect/Client.java
      modified:   storage/connect/JavaWrappers.jar
      modified:   storage/connect/JdbcInterface.java
      modified:   storage/connect/PostgresqlInterface.java
      modified:   storage/connect/global.h
      modified:   storage/connect/ha_connect.cc
      modified:   storage/connect/jdbconn.cpp
      modified:   storage/connect/jdbconn.h
      modified:   storage/connect/mysql-test/connect/r/jdbc_postgresql.result
      modified:   storage/connect/mysql-test/connect/t/jdbc_postgresql.test
      modified:   storage/connect/mysql-test/connect/t/jdbconn.inc
      modified:   storage/connect/plgdbsem.h
      modified:   storage/connect/tabjdbc.cpp
      modified:   storage/connect/tabjdbc.h
      added:      storage/connect/mysql-test/connect/std_data/JavaWrappers.jar

commit 3068bb4882a316c6c32c624609db2bf24ae3ad40
Author: Olivier Bertrand <bertrandop@gmail.com>
Date:   Mon Feb 26 19:40:27 2018 +0100

    Revert to old cmake file to avoid compile error

commit da8c1c0bd6a327fd03bd321be3170f468122ef67
Author: Olivier Bertrand <bertrandop@gmail.com>
Date:   Mon Feb 26 16:13:39 2018 +0100

    - Remove warning on not used tabtyp variable in connect_assisted_discovery
      modified:   storage/connect/ha_connect.cc

    - Fix a bug causing CONNECT to loop when expanding a JSON column
      when the expanded column value is null or void array.
    - Adding the FullArray option to JSON tables.
    - Skipping expanded JSON lines when the expanded column value is null.
      modified:   storage/connect/connect.cc
      modified:   storage/connect/tabdos.h
      modified:   storage/connect/tabjson.cpp
      modified:   storage/connect/tabjson.h

    - Fix MDEV-13353 No file privilege for ODBC, JDBC, MONGO, MAC, WMI file types.
      modified:   storage/connect/ha_connect.cc

    - Make some Json UDFs  to accept a non JSON item as 1st parameter.
      modified:   storage/connect/json.cpp
      modified:   storage/connect/json.h
      modified:   storage/connect/jsonudf.cpp
      modified:   storage/connect/jsonudf.h

    - Update Json UDF tests to cope with above changes.
      modified:   storage/connect/mysql-test/connect/r/json_udf.result
      modified:   storage/connect/mysql-test/connect/r/json_udf_bin.result
      modified:   storage/connect/mysql-test/connect/r/vcol.result
      modified:   storage/connect/mysql-test/connect/t/json_udf.test
      modified:   storage/connect/mysql-test/connect/t/vcol.test

    - Fix some compiler warning treated as error
      PlugSubAlloc no more exported because it does throw.
      modified:   storage/connect/global.h
      modified:   storage/connect/ha_connect.cc
      modified:   storage/connect/jsonudf.cpp
      modified:   storage/connect/tabjson.cpp
      modified:   storage/connect/tabjson.h

    - Other files modified (?) when going back to wrong merge
      modified:   storage/connect/CMakeLists.txt
      modified:   storage/connect/array.cpp
      modified:   storage/connect/colblk.cpp
      modified:   storage/connect/connect.cc
      modified:   storage/connect/csort.cpp
      modified:   storage/connect/domdoc.cpp
      modified:   storage/connect/filamap.cpp
      modified:   storage/connect/filamgz.cpp
      modified:   storage/connect/filamtxt.cpp
      modified:   storage/connect/filamzip.cpp
      modified:   storage/connect/filter.cpp
      modified:   storage/connect/fmdlex.c
      modified:   storage/connect/jdbconn.cpp
      modified:   storage/connect/macutil.cpp
      modified:   storage/connect/myconn.cpp
      modified:   storage/connect/odbconn.cpp
      modified:   storage/connect/plgdbutl.cpp
      modified:   storage/connect/plugutil.cpp
      modified:   storage/connect/preparse.h
      modified:   storage/connect/rcmsg.c
      modified:   storage/connect/rcmsg.h
      modified:   storage/connect/reldef.cpp
      modified:   storage/connect/tabdos.cpp
      modified:   storage/connect/tabfmt.cpp
      modified:   storage/connect/tabmac.cpp
      modified:   storage/connect/tabmul.cpp
      modified:   storage/connect/tabmysql.cpp
      modified:   storage/connect/tabmysql.h
      modified:   storage/connect/tabodbc.cpp
      modified:   storage/connect/tabtbl.cpp
      modified:   storage/connect/tabxml.cpp
      modified:   storage/connect/value.cpp
      modified:   storage/connect/xobject.cpp

commit 5095628b31ed8c94bd7c794c6b0162894a9040b1
Author: Olivier Bertrand <bertrandop@gmail.com>
Date:   Tue Feb 13 14:29:00 2018 +0100

    - Fix a bug causing CONNECT to loop when expanding a JSON column
      when the expanded column value is null or void array.
    - Adding the FullArray option to JSON tables.
    - Skipping expanded JSON lines when the expanded column value is null.
      modified:   storage/connect/connect.cc
      modified:   storage/connect/tabdos.h
      modified:   storage/connect/tabjson.cpp
      modified:   storage/connect/tabjson.h

commit 9896174328da42016735630c893fd09eb128b48e
Author: Olivier Bertrand <bertrandop@gmail.com>
Date:   Fri Feb 2 15:48:57 2018 +0100

    - Remove warning on not used tabtyp variable in connect_assisted_discovery
      modified:   storage/connect/ha_connect.cc

commit d7e254c05f88173eb04d8dafc813013eb42ccdbe
Author: Olivier Bertrand <bertrandop@gmail.com>
Date:   Wed Jan 31 14:42:45 2018 +0100

    - Use delayed load for the MongoDB C Drive on Windows
      modified:   storage/connect/CMakeLists.txt
      modified:   storage/connect/cmgoconn.cpp
      modified:   storage/connect/ha_connect.cc

    - Add FORCE to the connect_type_conv enum values
      This will translate binary values to TYPE_STRING
      modified:   storage/connect/checklvl.h
      modified:   storage/connect/ha_connect.cc
      modified:   storage/connect/odbconn.cpp

    - Change the connect_xtrace variable to from int to set
      modified:   storage/connect/array.cpp
      modified:   storage/connect/blkfil.cpp
      modified:   storage/connect/block.h
      modified:   storage/connect/cmgoconn.cpp
      modified:   storage/connect/colblk.cpp
      modified:   storage/connect/connect.cc
      modified:   storage/connect/filamap.cpp
      modified:   storage/connect/filamdbf.cpp
      modified:   storage/connect/filamfix.cpp
      modified:   storage/connect/filamgz.cpp
      modified:   storage/connect/filamtxt.cpp
      modified:   storage/connect/filamvct.cpp
      modified:   storage/connect/filamzip.cpp
      modified:   storage/connect/filter.cpp
      modified:   storage/connect/global.h
      modified:   storage/connect/ha_connect.cc
      modified:   storage/connect/inihandl.cpp
      modified:   storage/connect/javaconn.cpp
      modified:   storage/connect/jdbconn.cpp
      modified:   storage/connect/jmgfam.cpp
      modified:   storage/connect/jmgoconn.cpp
      modified:   storage/connect/json.cpp
      modified:   storage/connect/jsonudf.cpp
      modified:   storage/connect/libdoc.cpp
      modified:   storage/connect/mongo.cpp
      modified:   storage/connect/mycat.cc
      modified:   storage/connect/myconn.cpp
      modified:   storage/connect/odbconn.cpp
      modified:   storage/connect/plgdbutl.cpp
      modified:   storage/connect/plugutil.cpp
      modified:   storage/connect/reldef.cpp
      modified:   storage/connect/tabcol.cpp
      modified:   storage/connect/tabdos.cpp
      modified:   storage/connect/tabext.cpp
      modified:   storage/connect/tabfix.cpp
      modified:   storage/connect/tabfmt.cpp
      modified:   storage/connect/tabjdbc.cpp
      modified:   storage/connect/tabjson.cpp
      modified:   storage/connect/table.cpp
      modified:   storage/connect/tabmul.cpp
      modified:   storage/connect/tabmysql.cpp
      modified:   storage/connect/tabodbc.cpp
      modified:   storage/connect/tabpivot.cpp
      modified:   storage/connect/tabsys.cpp
      modified:   storage/connect/tabtbl.cpp
      modified:   storage/connect/tabutil.cpp
      modified:   storage/connect/tabvct.cpp
      modified:   storage/connect/tabwmi.cpp
      modified:   storage/connect/tabxml.cpp
      modified:   storage/connect/user_connect.cc
      modified:   storage/connect/valblk.cpp
      modified:   storage/connect/value.cpp
      modified:   storage/connect/xindex.cpp

    - Restore connect_enable_mongo variable (but undocumented)
      modified:   storage/connect/ha_connect.cc
      modified:   storage/connect/mycat.cc
      modified:   storage/connect/mysql-test/connect/r/json_java_2.result
      modified:   storage/connect/mysql-test/connect/r/json_java_3.result
      modified:   storage/connect/mysql-test/connect/r/json_mongo_c.result
      modified:   storage/connect/mysql-test/connect/r/mongo_c.result
      modified:   storage/connect/mysql-test/connect/r/mongo_java_2.result
      modified:   storage/connect/mysql-test/connect/r/mongo_java_3.result
      modified:   storage/connect/mysql-test/connect/r/tbl_thread.result
      modified:   storage/connect/mysql-test/connect/t/mongo.inc
      modified:   storage/connect/mysql-test/connect/t/mongo_test.inc
      modified:   storage/connect/mysql-test/connect/t/tbl_thread.test
2018-04-26 14:15:18 +02:00

876 lines
28 KiB
C++

/************* TabTbl C++ Program Source Code File (.CPP) **************/
/* PROGRAM NAME: TABTBL */
/* ------------- */
/* Version 1.9 */
/* */
/* Author: Olivier BERTRAND 2008-2018 */
/* */
/* WHAT THIS PROGRAM DOES: */
/* ----------------------- */
/* This program are the TDBTBL class DB routines. */
/* */
/* WHAT YOU NEED TO COMPILE THIS PROGRAM: */
/* -------------------------------------- */
/* */
/* REQUIRED FILES: */
/* --------------- */
/* TABTBL.CPP - Source code */
/* PLGDBSEM.H - DB application declaration file */
/* TABDOS.H - TABDOS classes declaration file */
/* TABTBL.H - TABTBL classes declaration file */
/* GLOBAL.H - Global declaration file */
/* */
/* REQUIRED LIBRARIES: */
/* ------------------- */
/* Large model C library */
/* */
/* REQUIRED PROGRAMS: */
/* ------------------ */
/* IBM, Borland, GNU or Microsoft C++ Compiler and Linker */
/* */
/***********************************************************************/
/***********************************************************************/
/* Include relevant section of system dependant header files. */
/***********************************************************************/
//#include "sql_base.h"
#include "my_global.h"
#include "table.h" // MySQL table definitions
#if defined(__WIN__)
#include <stdlib.h>
#include <stdio.h>
#if defined(__BORLANDC__)
#define __MFC_COMPAT__ // To define min/max as macro
#endif
//#include <windows.h>
#else
#if defined(UNIX)
#include <fnmatch.h>
#include <errno.h>
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#include "osutil.h"
#else
//#include <io.h>
#endif
//#include <fcntl.h>
#endif
/***********************************************************************/
/* Include application header files: */
/***********************************************************************/
#include "global.h" // global declarations
#include "plgdbsem.h" // DB application declarations
#include "reldef.h" // DB definition declares
#include "filamtxt.h"
#include "tabcol.h"
#include "tabdos.h" // TDBDOS and DOSCOL class dcls
#include "tabtbl.h"
#include "tabext.h"
#include "tabmysql.h"
#include "ha_connect.h"
#if defined(__WIN__)
#if defined(__BORLANDC__)
#define SYSEXIT void _USERENTRY
#else
#define SYSEXIT void
#endif
#else // !__WIN__
#define SYSEXIT void *
#endif // !__WIN__
extern pthread_mutex_t tblmut;
/* ---------------------------- Class TBLDEF ---------------------------- */
/**************************************************************************/
/* Constructor. */
/**************************************************************************/
TBLDEF::TBLDEF(void)
{
//To_Tables = NULL;
Accept = false;
Thread = false;
Maxerr = 0;
Ntables = 0;
Pseudo = 3;
} // end of TBLDEF constructor
/**************************************************************************/
/* DefineAM: define specific AM block values from XDB file. */
/**************************************************************************/
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(1))
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
/***********************************************************************/
/* GetTable: makes a new Table Description Block. */
/***********************************************************************/
PTDB TBLDEF::GetTable(PGLOBAL g, MODE)
{
if (Catfunc == FNC_COL)
return new(g) TDBTBC(this);
else if (Thread) {
#if defined(DEVELOPMENT)
return new(g) TDBTBM(this);
#else
strcpy(g->Message, "Option THREAD is no more supported");
return NULL;
#endif // DEVELOPMENT
} else
return new(g) TDBTBL(this);
} // end of GetTable
/* ------------------------- Class TDBTBL ---------------------------- */
/***********************************************************************/
/* TDBTBL constructors. */
/***********************************************************************/
TDBTBL::TDBTBL(PTBLDEF tdp) : TDBPRX(tdp)
{
Tablist = NULL;
CurTable = NULL;
//Tdbp = NULL;
Accept = tdp->Accept;
Maxerr = tdp->Maxerr;
Nbc = 0;
Rows = 0;
Crp = 0;
// NTables = 0;
// iTable = 0;
} // end of TDBTBL standard constructor
/***********************************************************************/
/* Allocate TBL column description block. */
/***********************************************************************/
PCOL TDBTBL::MakeCol(PGLOBAL g, PCOLDEF cdp, PCOL cprec, int n)
{
return new(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
/***********************************************************************/
/* Initializes the table table list. */
/***********************************************************************/
bool TDBTBL::InitTableList(PGLOBAL g)
{
int n;
uint sln;
char *scs;
PTABLE tp, tabp;
PCOL colp;
PTBLDEF tdp = (PTBLDEF)To_Def;
PCATLG cat = To_Def->GetCat();
PHC hc = ((MYCAT*)cat)->GetHandler();
scs = hc->get_table()->s->connect_string.str;
sln = hc->get_table()->s->connect_string.length;
// PlugSetPath(filename, Tdbp->GetFile(g), Tdbp->GetPath());
for (n = 0, 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->get_table()->s->connect_string.str = (char*)tabp->GetName();
hc->get_table()->s->connect_string.length = strlen(tabp->GetName());
} // endif Src
// Get the table description block of this table
if (!(Tdbp = GetSubTable(g, tabp))) {
if (++Nbc > Maxerr)
return TRUE; // 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)
return TRUE;
if (Tablist)
Tablist->Link(tabp);
else
Tablist = tabp;
n++;
} // endif filp
} // endfor tp
hc->get_table()->s->connect_string.str = scs;
hc->get_table()->s->connect_string.length = sln;
//NumTables = n;
To_CondFil = NULL; // To avoid doing it several times
return FALSE;
} // 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)
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
/***********************************************************************/
/* Sum up the cardinality of all sub-tables. */
/***********************************************************************/
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
/***********************************************************************/
/* Sum up the maximum sizes of all sub-tables. */
/***********************************************************************/
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
/***********************************************************************/
/* 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
return TRUE;
if ((CurTable = Tablist)) {
Tdbp = CurTable->GetTo_Tdb();
// Tdbp->SetMode(Mode);
// Tdbp->ResetDB();
// Tdbp->ResetSize();
// Check and initialize the subtable columns
for (PCOL cp = Columns; cp; cp = cp->GetNext())
if (cp->GetAmType() == TYPE_AM_TABID)
cp->COLBLK::Reset();
else if (((PPRXCOL)cp)->Init(g, NULL) && !Accept)
return TRUE;
if (trace(1))
htrc("Opening subtable %s\n", Tdbp->GetName());
// Now we can safely open the table
if (Tdbp->OpenDB(g))
return TRUE;
} // endif *Tablist
Use = USE_OPEN;
return FALSE;
} // end of OpenDB
/***********************************************************************/
/* ReadDB: Data Base read routine for MUL access method. */
/***********************************************************************/
int TDBTBL::ReadDB(PGLOBAL g)
{
int rc;
if (!CurTable)
return RC_EF;
else if (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();
else if (((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;
goto retry;
} // endif iFile
} else if (rc == RC_FX)
strcat(strcat(strcat(g->Message, " ("), Tdbp->GetName()), ")");
} // endif To_Kindex
return rc;
} // end of ReadDB
/* ---------------------------- TBTBLK ------------------------------- */
/***********************************************************************/
/* ReadColumn: */
/***********************************************************************/
void TBTBLK::ReadColumn(PGLOBAL)
{
if (trace(1))
htrc("TBT ReadColumn: name=%s\n", Name);
Value->SetValue_psz((char*)((PTDBTBL)To_Tdb)->Tdbp->GetName());
} // end of ReadColumn
#if defined(DEVELOPMENT)
/* ------------------------- Class TDBTBM ---------------------------- */
/***********************************************************************/
/* Thread routine that check and open one remote connection. */
/***********************************************************************/
pthread_handler_t ThreadOpen(void *p)
{
PTBMT cmp = (PTBMT)p;
if (!my_thread_init()) {
set_current_thd(cmp->Thd);
if (trace(1))
htrc("ThreadOpen: Thd=%d\n", cmp->Thd);
// Try to open the connection
pthread_mutex_lock(&tblmut);
if (!cmp->Tap->GetTo_Tdb()->OpenDB(cmp->G)) {
// pthread_mutex_lock(&tblmut);
if (trace(1))
htrc("Table %s ready\n", cmp->Tap->GetName());
cmp->Ready = true;
// pthread_mutex_unlock(&tblmut);
} else {
// pthread_mutex_lock(&tblmut);
if (trace(1))
htrc("Opening %s failed\n", cmp->Tap->GetName());
cmp->Rc = RC_FX;
// pthread_mutex_unlock(&tblmut);
} // endif OpenDB
pthread_mutex_unlock(&tblmut);
my_thread_end();
} else
cmp->Rc = RC_FX;
return NULL;
} // end of ThreadOpen
/***********************************************************************/
/* 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();
// Remote tables
for (PTBMT tp = Tmp; tp; tp = tp->Next)
tp->Tap->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
/***********************************************************************/
/* Initialyze table parallel processing. */
/***********************************************************************/
bool TDBTBM::OpenTables(PGLOBAL g)
{
int k;
THD *thd = current_thd;
PTABLE tabp, *ptabp = &Tablist;
PTBMT tp, *ptp = &Tmp;
// 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());
// Make the remote table block
tp = (PTBMT)PlugSubAlloc(g, NULL, sizeof(TBMT));
memset(tp, 0, sizeof(TBMT));
tp->G = g;
tp->Ready = false;
tp->Tap = tabp;
tp->Thd = thd;
// 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))) {
sprintf(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
return false;
} // 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
#if 0
/*********************************************************************/
/* 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))
return TRUE;
/*********************************************************************/
/* Open all remote tables of the list. */
/*********************************************************************/
if (OpenTables(g))
return TRUE;
/*********************************************************************/
/* 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();
else if (((PPRXCOL)cp)->Init(g, NULL) && !Accept)
return TRUE;
if (trace(1))
htrc("Opening subtable %s\n", Tdbp->GetName());
// Now we can safely open the table
if (Tdbp->OpenDB(g))
return TRUE;
} // endif *Tablist
Use = USE_OPEN;
return FALSE;
} // 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;
else if ((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;
} else if (rc == RC_FX)
strcat(strcat(strcat(g->Message, " ("), Tdbp->GetName()), ")");
return rc;
} // end of ReadDB
/***********************************************************************/
/* 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();
else if (((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
/* ------------------------------------------------------------------- */