summaryrefslogtreecommitdiff
path: root/storage
diff options
context:
space:
mode:
Diffstat (limited to 'storage')
-rw-r--r--storage/connect/CMakeLists.txt4
-rw-r--r--storage/connect/ha_connect.cc252
-rw-r--r--storage/connect/ha_connect.h58
-rw-r--r--storage/connect/mycat.cc20
-rw-r--r--storage/connect/myconn.cpp4
-rw-r--r--storage/connect/mysql-test/connect/r/xml.result2
-rw-r--r--storage/connect/plgdbsem.h14
-rw-r--r--storage/connect/tabmysql.cpp12
-rw-r--r--storage/connect/taboccur.cpp375
-rw-r--r--storage/connect/taboccur.h145
-rw-r--r--storage/connect/tabtbl.cpp166
-rw-r--r--storage/connect/tabtbl.h49
-rw-r--r--storage/connect/tabutil.cpp596
-rw-r--r--storage/connect/tabutil.h181
-rw-r--r--storage/connect/tabxcl.cpp376
-rw-r--r--storage/connect/tabxcl.h133
-rw-r--r--storage/connect/valblk.cpp66
-rw-r--r--storage/connect/valblk.h4
18 files changed, 2211 insertions, 246 deletions
diff --git a/storage/connect/CMakeLists.txt b/storage/connect/CMakeLists.txt
index 63943aaa03b..41930c71aa4 100644
--- a/storage/connect/CMakeLists.txt
+++ b/storage/connect/CMakeLists.txt
@@ -25,12 +25,14 @@ filamap.cpp filamdbf.cpp filamfix.cpp filamtxt.cpp filamvct.cpp
tabdos.cpp tabfix.cpp tabfmt.cpp tabmul.cpp tabsys.cpp tabvct.cpp
valblk.cpp value.cpp xindex.cpp xobject.cpp
filamzip.cpp tabtbl.cpp myutil.cpp
+tabutil.cpp tabxcl.cpp taboccur.cpp
block.h catalog.h checklvl.h colblk.h connect.h csort.h engmsg.h
filamap.h filamdbf.h filamfix.h filamtxt.h filamvct.h filamzip.h
global.h ha_connect.h maputil.h msgid.h mycat.h myutil.h os.h
osutil.h plgcnx.h plgdbsem.h preparse.h reldef.h resource.h tabcol.h
tabdos.h tabfix.h tabfmt.h tabmul.h tabsys.h tabtbl.h tabvct.h
-user_connect.h valblk.h value.h xindex.h xobject.h xtable.h)
+user_connect.h valblk.h value.h xindex.h xobject.h xtable.h
+tabutil.h tabxcl.h taboccur.h)
#
# Definitions that are shared for all OSes
diff --git a/storage/connect/ha_connect.cc b/storage/connect/ha_connect.cc
index 8136e6d0263..99f81905f0c 100644
--- a/storage/connect/ha_connect.cc
+++ b/storage/connect/ha_connect.cc
@@ -122,6 +122,7 @@
#include "tabmysql.h"
#endif // MYSQL_SUPPORT
#include "filamdbf.h"
+#include "tabxcl.h"
#include "tabfmt.h"
#include "reldef.h"
#include "tabcol.h"
@@ -156,7 +157,7 @@ extern "C" char nmfile[];
extern "C" char pdebug[];
extern "C" {
- char version[]= "Version 1.01.0004 April 10, 2013";
+ char version[]= "Version 1.01.0005 April 27, 2013";
#if defined(XMSG)
char msglang[]; // Default message language
@@ -187,44 +188,13 @@ static int connect_assisted_discovery(handlerton *hton, THD* thd,
handlerton *connect_hton;
/**
- structure for CREATE TABLE options (table options)
+ CREATE TABLE option list (table options)
These can be specified in the CREATE TABLE:
CREATE TABLE ( ... ) {...here...}
*/
-struct ha_table_option_struct {
- const char *type;
- const char *filename;
- const char *optname;
- const char *tabname;
- const char *tablist;
- const char *dbname;
- const char *separator;
-//const char *connect;
- const char *qchar;
- const char *module;
- const char *subtype;
- const char *catfunc;
- const char *oplist;
- const char *data_charset;
- ulonglong lrecl;
- ulonglong elements;
-//ulonglong estimate;
- ulonglong multiple;
- ulonglong header;
- ulonglong quoted;
- ulonglong ending;
- ulonglong compressed;
- bool mapped;
- bool huge;
- bool split;
- bool readonly;
- bool sepindex;
- };
-
ha_create_table_option connect_table_option_list[]=
{
- // These option are for stand alone Connect tables
HA_TOPTION_STRING("TABLE_TYPE", type),
HA_TOPTION_STRING("FILE_NAME", filename),
HA_TOPTION_STRING("XFILE_NAME", optname),
@@ -258,22 +228,11 @@ ha_create_table_option connect_table_option_list[]=
/**
- structure for CREATE TABLE options (field options)
+ CREATE TABLE option list (field options)
These can be specified in the CREATE TABLE per field:
CREATE TABLE ( field ... {...here...}, ... )
*/
-struct ha_field_option_struct
-{
- ulonglong offset;
- ulonglong freq; // Not used by this version
- ulonglong opt; // Not used by this version
- ulonglong fldlen;
- const char *dateformat;
- const char *fieldformat;
- char *special;
-};
-
ha_create_table_option connect_field_option_list[]=
{
HA_FOPTION_NUMBER("FLAG", offset, -1, 0, INT_MAX32, 1),
@@ -345,9 +304,8 @@ static void init_connect_psi_keys() {}
delete_table method in handler.cc
*/
static const char *ha_connect_exts[]= {
- ".tbl", ".dnx", ".fnx", ".bnx", ".vnx", ".dbx", ".dos", ".fix", ".csv",
- ".fmt", ".dbf", ".xml", ".ini", ".vec", ".odbc", ".mysql", ".dir",
- ".mac", ".wmi", ".bin", ".oem",
+ ".dos", ".fix", ".csv",".bin", ".fmt", ".dbf", ".xml", ".ini", ".vec",
+ ".dnx", ".fnx", ".bnx", ".vnx", ".dbx",
NULL
};
@@ -708,6 +666,10 @@ char *ha_connect::GetStringOption(char *opname, char *sdef)
// Return the handler default value
if (!stricmp(opname, "Dbname") || !stricmp(opname, "Database"))
opval= (char*)GetDBName(NULL); // Current database
+ else if (!stricmp(opname, "User")) // Connected user
+ opval= table->in_use->main_security_ctx.user;
+ else if (!stricmp(opname, "Host")) // Connected user host
+ opval= table->in_use->main_security_ctx.host;
else
opval= sdef; // Caller default
@@ -773,9 +735,9 @@ bool ha_connect::SetBooleanOption(char *opname, bool b)
/****************************************************************************/
int ha_connect::GetIntegerOption(char *opname)
{
- int opval= NO_IVAL;
- char *pv;
- PTOS options= GetTableOptionStruct(table);
+ ulonglong opval= NO_IVAL;
+ char *pv;
+ PTOS options= GetTableOptionStruct(table);
if (!options)
;
@@ -801,9 +763,9 @@ int ha_connect::GetIntegerOption(char *opname)
if (opval == NO_IVAL && options && options->oplist)
if ((pv= GetListOption(xp->g, opname, options->oplist)))
- opval= atoi(pv);
+ opval= (unsigned)atoll(pv);
- return opval;
+ return (int)opval;
} // end of GetIntegerOption
/****************************************************************************/
@@ -885,13 +847,13 @@ void *ha_connect::GetColumnOption(void *field, PCOLINFO pcf)
pcf->Name= (char*)fp->field_name;
pcf->Prec= 0;
- pcf->Opt= (fop) ? fop->opt : 0;
+ pcf->Opt= (fop) ? (int)fop->opt : 0;
if ((pcf->Length= fp->field_length) < 0)
pcf->Length= 256; // BLOB?
if (fop) {
- pcf->Offset= fop->offset;
+ pcf->Offset= (int)fop->offset;
// pcf->Freq= fop->freq;
pcf->Datefmt= (char*)fop->dateformat;
pcf->Fieldfmt= (char*)fop->fieldformat;
@@ -905,6 +867,7 @@ void *ha_connect::GetColumnOption(void *field, PCOLINFO pcf)
switch (fp->type()) {
case MYSQL_TYPE_BLOB:
case MYSQL_TYPE_VARCHAR:
+ case MYSQL_TYPE_VAR_STRING:
pcf->Flags |= U_VAR;
case MYSQL_TYPE_STRING:
pcf->Type= TYPE_STRING;
@@ -941,7 +904,7 @@ void *ha_connect::GetColumnOption(void *field, PCOLINFO pcf)
// Field_length is only used for DATE columns
if (fop->fldlen)
- pcf->Length= fop->fldlen;
+ pcf->Length= (int)fop->fldlen;
else {
int len;
@@ -2688,13 +2651,18 @@ int ha_connect::delete_all_rows()
bool ha_connect::check_privileges(THD *thd, PTOS options)
{
- if (!options->type)
- options->type= "DOS";
+ if (!options->type) {
+ if (options->tabname)
+ options->type= "PROXY";
+ else
+ options->type= "DOS";
+
+ } // endif type
switch (GetTypeID(options->type))
{
case TAB_UNDEF:
- case TAB_CATLG:
+// case TAB_CATLG:
case TAB_PLG:
case TAB_JCT:
case TAB_DMY:
@@ -2733,13 +2701,17 @@ bool ha_connect::check_privileges(THD *thd, PTOS options)
case TAB_OEM:
return check_access(thd, FILE_ACL, NULL, NULL, NULL, 0, 0);
+ // This is temporary until a solution is found
case TAB_TBL:
+ case TAB_XCL:
+ case TAB_PRX:
+ case TAB_OCCUR:
return false;
}
my_printf_error(ER_UNKNOWN_ERROR, "check_privileges failed", MYF(0));
return true;
-}
+} // end of check_privileges
// Check that two indexes are equivalent
bool ha_connect::IsSameIndex(PIXDEF xp1, PIXDEF xp2)
@@ -3272,8 +3244,9 @@ bool add_field(String *sql, const char *field_name, const char *type,
{
bool error= false;
+ error|= sql->append('`');
error|= sql->append(field_name);
- error|= sql->append(' ');
+ error|= sql->append("` ");
error|= sql->append(type);
if (len) {
error|= sql->append('(');
@@ -3289,7 +3262,7 @@ bool add_field(String *sql, const char *field_name, const char *type,
error|= sql->append(STRING_WITH_LEN(" NOT NULL"), system_charset_info);
if (rem && *rem) {
- error|= sql->append(" COMMENT='");
+ error|= sql->append(" COMMENT '");
error|= sql->append_for_single_quote(rem, strlen(rem));
error|= sql->append("'");
}
@@ -3314,12 +3287,12 @@ static int connect_assisted_discovery(handlerton *hton, THD* thd,
{
char spc= ',', qch= 0;
const char *fncn= "?";
- const char *user, *fn, *tab, *db, *host, *pwd, *prt, *sep; // *csn;
- char *dsn;
+ const char *user, *fn, *db, *host, *pwd, *prt, *sep, *tbl; // *csn;
+ char *tab, *dsn;
#if defined(WIN32)
char *nsp= NULL, *cls= NULL;
#endif // WIN32
- int port= MYSQL_PORT, hdr= 0, mxr= 0, b= 0;
+ int port= 0, hdr= 0, mxr= 0, b= 0;
uint tm, fnc= FNC_NO, supfnc= (FNC_NO | FNC_COL);
bool ok= false, dbf= false;
TABTYPE ttp= TAB_UNDEF;
@@ -3338,51 +3311,101 @@ static int connect_assisted_discovery(handlerton *hton, THD* thd,
sql.copy(STRING_WITH_LEN("CREATE TABLE whatever ("), system_charset_info);
- user= host= pwd= prt= dsn= NULL;
+ user= host= pwd= prt= tbl= dsn= NULL;
// Get the useful create options
ttp= GetTypeID(topt->type);
fn= topt->filename;
- tab= topt->tabname;
+ tab= (char*)topt->tabname;
db= topt->dbname;
fncn= topt->catfunc;
fnc= GetFuncID(fncn);
sep= topt->separator;
spc= (!sep || !strcmp(sep, "\\t")) ? '\t' : *sep;
qch= topt->qchar ? *topt->qchar : topt->quoted >= 0 ? '"' : 0;
- hdr= topt->header;
+ hdr= (int)topt->header;
+ tbl= topt->tablist;
+
if (topt->oplist) {
- host= GetListOption(g,"host", topt->oplist, "localhost");
- user= GetListOption(g,"user", topt->oplist, "root");
- // Default value db can come from the DBNAME=xxx option.
- db= GetListOption(g,"database", topt->oplist, db);
- pwd= GetListOption(g,"password", topt->oplist);
- prt= GetListOption(g,"port", topt->oplist);
- port= (prt) ? atoi(prt) : MYSQL_PORT;
+ host= GetListOption(g,"host", topt->oplist, "localhost");
+ user= GetListOption(g,"user", topt->oplist, "root");
+ // Default value db can come from the DBNAME=xxx option.
+ db= GetListOption(g,"database", topt->oplist, db);
+ pwd= GetListOption(g,"password", topt->oplist);
+ prt= GetListOption(g,"port", topt->oplist);
+ port= (prt) ? atoi(prt) : MYSQL_PORT;
#if defined(WIN32)
- nsp= GetListOption(g,"namespace", topt->oplist);
- cls= GetListOption(g,"class", topt->oplist);
+ nsp= GetListOption(g,"namespace", topt->oplist);
+ cls= GetListOption(g,"class", topt->oplist);
#endif // WIN32
- mxr= atoi(GetListOption(g,"maxerr", topt->oplist, "0"));
- } // endelse option_list
+ mxr= atoi(GetListOption(g,"maxerr", topt->oplist, "0"));
+ } // endif option_list
if (!db)
db= thd->db; // Default value
// Check table type
if (ttp == TAB_UNDEF) {
- strcpy(g->Message, "No table_type. Was set to DOS");
- push_warning(thd, MYSQL_ERROR::WARN_LEVEL_WARN, 0, g->Message);
- ttp= TAB_DOS;
- topt->type= "DOS";
+ if (!tab) {
+ strcpy(g->Message, "No table_type. Was set to DOS");
+ push_warning(thd, MYSQL_ERROR::WARN_LEVEL_WARN, 0, g->Message);
+ ttp= TAB_DOS;
+ topt->type= "DOS";
+ } else {
+ strcpy(g->Message, "No table_type. Was set to PROXY");
+ push_warning(thd, MYSQL_ERROR::WARN_LEVEL_WARN, 0, g->Message);
+ ttp= TAB_PRX;
+ topt->type= "PROXY";
+ } // endif fnc
+
} else if (ttp == TAB_NIY) {
sprintf(g->Message, "Unsupported table type %s", topt->type);
my_message(ER_UNKNOWN_ERROR, g->Message, MYF(0));
return HA_ERR_INTERNAL_ERROR;
} // endif ttp
- if (!tab && !(fnc & (FNC_TABLE | FNC_COL)))
- tab= (char*)create_info->alias;
+ if (!tab) {
+ if (ttp == TAB_TBL) {
+ // Make tab the first table of the list
+ char *p;
+
+ if (!tbl) {
+ strcpy(g->Message, "Missing table list");
+ my_message(ER_UNKNOWN_ERROR, g->Message, MYF(0));
+ return HA_ERR_INTERNAL_ERROR;
+ } // endif tbl
+
+ tab= (char*)PlugSubAlloc(g, NULL, strlen(tbl) + 1);
+ strcpy(tab, tbl);
+
+ if ((p= strchr(tab, ',')))
+ *p= 0;
+
+ if ((p=strchr(tab, '.'))) {
+ *p= 0;
+ db= tab;
+ tab= p + 1;
+ } // endif p
+
+ } else if (ttp != TAB_ODBC || !(fnc & (FNC_TABLE | FNC_COL)))
+ tab= (char*)create_info->alias;
+
+ } // endif tab
+
+ // Check whether a table is defined on itself
+ switch (ttp) {
+ case TAB_PRX:
+ case TAB_XCL:
+ case TAB_TBL:
+ case TAB_OCCUR:
+ if (!stricmp(tab, create_info->alias) &&
+ !stricmp(db, thd->db)) {
+ sprintf(g->Message, "A %s table cannot refer to itself", topt->type);
+ my_message(ER_UNKNOWN_ERROR, g->Message, MYF(0));
+ return HA_ERR_INTERNAL_ERROR;
+ } // endif tab
+
+ } // endswitch ttp
switch (ttp) {
#if defined(ODBC_SUPPORT)
@@ -3433,7 +3456,7 @@ static int connect_assisted_discovery(handlerton *hton, THD* thd,
ok= false;
} else if (!user)
- user= "root"; // Avoid crash
+ user= thd->main_security_ctx.user;
break;
#endif // MYSQL_SUPPORT
@@ -3442,6 +3465,11 @@ static int connect_assisted_discovery(handlerton *hton, THD* thd,
ok= true;
break;
#endif // WIN32
+ case TAB_PRX:
+ case TAB_TBL:
+ case TAB_XCL:
+ ok= true;
+ break;
default:
sprintf(g->Message, "Cannot get column info for table type %s", topt->type);
} // endif ttp
@@ -3453,6 +3481,9 @@ static int connect_assisted_discovery(handlerton *hton, THD* thd,
ok= false;
} // endif supfnc
+ // Here we should test the flag column options when
+ // this function is called in case of CREATE .. SELECT
+
if (ok) {
char *cnm, *rem;
int i, len, dec, typ;
@@ -3505,6 +3536,11 @@ static int connect_assisted_discovery(handlerton *hton, THD* thd,
qrp= WMIColumns(g, nsp, cls, fnc == FNC_COL);
break;
#endif // WIN32
+ case TAB_PRX:
+ case TAB_TBL:
+ case TAB_XCL:
+ qrp= TabColumns(g, thd, db, tab, fnc == FNC_COL);
+ break;
default:
strcpy(g->Message, "System error during assisted discovery");
break;
@@ -3587,11 +3623,16 @@ static int connect_assisted_discovery(handlerton *hton, THD* thd,
} // endif ttp
#endif // ODBC_SUPPORT
+ // Make the arguments as required by add_fields
type= PLGtoMYSQLtype(typ, true);
+
if (typ == TYPE_DATE)
len= 0;
+
+ // Now add the field
if (add_field(&sql, cnm, type, len, dec, tm, rem))
b= HA_ERR_OUT_OF_MEM;
+
} // endfor i
sql.length(sql.length()-1); // remove the trailing comma
@@ -3602,59 +3643,76 @@ static int connect_assisted_discovery(handlerton *hton, THD* thd,
ulonglong vull;
const char *vstr;
bool oom= false;
+
switch (opt->type) {
case HA_OPTION_TYPE_ULL:
- vull= *(ulonglong*)(((char*)topt) + opt->offset);
+ vull= *(ulonglong*)(((char*)topt) + opt->offset);
+
if (vull != opt->def_value) {
oom|= sql.append(' ');
oom|= sql.append(opt->name);
oom|= sql.append('=');
oom|= sql.append_ulonglong(vull);
- }
+ } // endif vull
+
break;
case HA_OPTION_TYPE_STRING:
- vstr= *(char**)(((char*)topt) + opt->offset);
+ vstr= *(char**)(((char*)topt) + opt->offset);
+
if (vstr) {
oom|= sql.append(' ');
oom|= sql.append(opt->name);
oom|= sql.append("='");
oom|= sql.append_for_single_quote(vstr, strlen(vstr));
oom|= sql.append('\'');
- }
+ } // endif vstr
+
break;
case HA_OPTION_TYPE_BOOL:
- vull= *(bool*)(((char*)topt) + opt->offset);
+ vull= *(bool*)(((char*)topt) + opt->offset);
+
if (vull != opt->def_value) {
oom|= sql.append(' ');
oom|= sql.append(opt->name);
oom|= sql.append('=');
oom|= sql.append(vull ? "ON" : "OFF");
- }
+ } // endif vull
+
break;
default: // no enums here, good :)
break;
- }
+ } // endswitch type
+
if (oom)
b= HA_ERR_OUT_OF_MEM;
- }
+
+ } // endfor opt
if (create_info->connect_string.length) {
bool oom= false;
+
oom|= sql.append(' ');
oom|= sql.append("CONNECTION='");
oom|= sql.append_for_single_quote(create_info->connect_string.str,
create_info->connect_string.length);
oom|= sql.append('\'');
+
if (oom)
b= HA_ERR_OUT_OF_MEM;
- }
+
+ } // endif string
if (create_info->default_table_charset) {
bool oom= false;
+
oom|= sql.append(' ');
oom|= sql.append("CHARSET=");
oom|= sql.append(create_info->default_table_charset->csname);
- }
+
+ if (oom)
+ b= HA_ERR_OUT_OF_MEM;
+
+ } // endif charset
if (!b)
b= table_s->init_from_sql_statement_string(thd, true,
@@ -3664,7 +3722,7 @@ static int connect_assisted_discovery(handlerton *hton, THD* thd,
my_message(ER_UNKNOWN_ERROR, g->Message, MYF(0));
return HA_ERR_INTERNAL_ERROR;
-} // end of pre_create
+} // end of connect_assisted_discovery
/**
@brief
diff --git a/storage/connect/ha_connect.h b/storage/connect/ha_connect.h
index b8c92479543..53339d168d0 100644
--- a/storage/connect/ha_connect.h
+++ b/storage/connect/ha_connect.h
@@ -1,4 +1,4 @@
-/* Copyright (C) Olivier Bertrand 2004 - 2011
+/* Copyright (C) Olivier Bertrand 2004 - 2013
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
@@ -64,6 +64,59 @@ typedef struct ha_field_option_struct FOS, *PFOS;
extern handlerton *connect_hton;
+/**
+ structure for CREATE TABLE options (table options)
+
+ These can be specified in the CREATE TABLE:
+ CREATE TABLE ( ... ) {...here...}
+*/
+struct ha_table_option_struct {
+ const char *type;
+ const char *filename;
+ const char *optname;
+ const char *tabname;
+ const char *tablist;
+ const char *dbname;
+ const char *separator;
+//const char *connect;
+ const char *qchar;
+ const char *module;
+ const char *subtype;
+ const char *catfunc;
+ const char *oplist;
+ const char *data_charset;
+ ulonglong lrecl;
+ ulonglong elements;
+//ulonglong estimate;
+ ulonglong multiple;
+ ulonglong header;
+ ulonglong quoted;
+ ulonglong ending;
+ ulonglong compressed;
+ bool mapped;
+ bool huge;
+ bool split;
+ bool readonly;
+ bool sepindex;
+ };
+
+/**
+ structure for CREATE TABLE options (field options)
+
+ These can be specified in the CREATE TABLE per field:
+ CREATE TABLE ( field ... {...here...}, ... )
+*/
+struct ha_field_option_struct
+{
+ ulonglong offset;
+ ulonglong freq; // Not used by this version
+ ulonglong opt; // Not used by this version
+ ulonglong fldlen;
+ const char *dateformat;
+ const char *fieldformat;
+ char *special;
+};
+
/** @brief
CONNECT_SHARE is a structure that will be shared among all open handlers.
This example implements the minimum of what you will probably need.
@@ -143,8 +196,7 @@ public:
{
return (HA_NO_TRANSACTIONS | HA_REC_NOT_IN_SEQ | HA_HAS_RECORDS |
HA_NO_AUTO_INCREMENT | HA_NO_PREFIX_CHAR_KEYS |
- HA_NO_COPY_ON_ALTER |
- HA_CAN_VIRTUAL_COLUMNS |
+ HA_NO_COPY_ON_ALTER | HA_CAN_VIRTUAL_COLUMNS |
HA_NULL_IN_KEY | HA_BINLOG_ROW_CAPABLE | HA_BINLOG_STMT_CAPABLE);
}
diff --git a/storage/connect/mycat.cc b/storage/connect/mycat.cc
index 4db70efe27f..5a7f53977c7 100644
--- a/storage/connect/mycat.cc
+++ b/storage/connect/mycat.cc
@@ -68,7 +68,10 @@
#include "tabmac.h"
#include "tabwmi.h"
#endif // WIN32
+//#include "tabtbl.h"
+#include "tabxcl.h"
#include "tabtbl.h"
+#include "taboccur.h"
#if defined(XML_SUPPORT)
#include "tabxml.h"
#endif // XML_SUPPORT
@@ -124,6 +127,10 @@ TABTYPE GetTypeID(const char *type)
: (!stricmp(type, "WMI")) ? TAB_WMI
#endif
: (!stricmp(type, "TBL")) ? TAB_TBL
+ : (!stricmp(type, "XCOL")) ? TAB_XCL
+ : (!stricmp(type, "OCCUR")) ? TAB_OCCUR
+ : (!stricmp(type, "CATLG")) ? TAB_PRX // Legacy
+ : (!stricmp(type, "PROXY")) ? TAB_PRX
: (!stricmp(type, "OEM")) ? TAB_OEM : TAB_NIY;
} // end of GetTypeID
@@ -186,7 +193,6 @@ bool IsTypeNullable(TABTYPE type)
break;
} // endswitch type
-
return nullable;
} // end of IsTypeNullable
@@ -414,7 +420,7 @@ int MYCAT::GetColCatInfo(PGLOBAL g, PTABDEF defp)
PCOLINFO pcf= (PCOLINFO)PlugSubAlloc(g, NULL, sizeof(COLINFO));
// Get a unique char identifier for type
- tc= (defp->Catfunc == FNC_NO) ? GetTypeID(type) : TAB_CATLG;
+ tc= (defp->Catfunc == FNC_NO) ? GetTypeID(type) : TAB_PRX;
// Take care of the column definitions
i= poff= nof= nlg= 0;
@@ -443,6 +449,9 @@ int MYCAT::GetColCatInfo(PGLOBAL g, PTABDEF defp)
case TAB_INI:
case TAB_MAC:
case TAB_TBL:
+ case TAB_XCL:
+ case TAB_OCCUR:
+ case TAB_PRX:
case TAB_OEM:
poff = 0; // Offset represents an independant flag
break;
@@ -592,7 +601,7 @@ PRELDEF MYCAT::GetTableDesc(PGLOBAL g, LPCSTR name,
// If not specified get the type of this table
if (!type && !(type= Hc->GetStringOption("Type")))
- type= "DOS";
+ type= (Hc->GetStringOption("Tabname")) ? "PROXY" : "DOS";
return MakeTableDesc(g, name, type);
} // end of GetTableDesc
@@ -636,6 +645,9 @@ PRELDEF MYCAT::MakeTableDesc(PGLOBAL g, LPCSTR name, LPCSTR am)
#endif // WIN32
case TAB_OEM: tdp= new(g) OEMDEF; break;
case TAB_TBL: tdp= new(g) TBLDEF; break;
+ case TAB_XCL: tdp= new(g) XCLDEF; break;
+ case TAB_PRX: tdp= new(g) PRXDEF; break;
+ case TAB_OCCUR: tdp= new(g) OCCURDEF; break;
#if defined(MYSQL_SUPPORT)
case TAB_MYSQL: tdp= new(g) MYSQLDEF; break;
#endif // MYSQL_SUPPORT
@@ -646,7 +658,7 @@ PRELDEF MYCAT::MakeTableDesc(PGLOBAL g, LPCSTR name, LPCSTR am)
sprintf(g->Message, MSG(BAD_TABLE_TYPE), am, name);
} // endswitch
- // Do make the table/view definition from XDB file information
+ // Do make the table/view definition
if (tdp && tdp->Define(g, this, name, am))
tdp= NULL;
diff --git a/storage/connect/myconn.cpp b/storage/connect/myconn.cpp
index 3edf07004ea..53a2496b197 100644
--- a/storage/connect/myconn.cpp
+++ b/storage/connect/myconn.cpp
@@ -62,6 +62,7 @@ static char *server_groups[] = {
#endif // EMBEDDED
extern "C" int trace;
+extern MYSQL_PLUGIN_IMPORT uint mysqld_port;
/************************************************************************/
/* MyColumns: constructs the result blocks containing all columns */
@@ -90,6 +91,9 @@ PQRYRES MyColumns(PGLOBAL g, const char *host, const char *db,
PCOLRES crp;
MYSQLC myc;
+ if (!port)
+ port = mysqld_port;
+
if (!info) {
/********************************************************************/
/* Open the connection with the MySQL server. */
diff --git a/storage/connect/mysql-test/connect/r/xml.result b/storage/connect/mysql-test/connect/r/xml.result
index e7dcf8f4c73..554039dc3f1 100644
--- a/storage/connect/mysql-test/connect/r/xml.result
+++ b/storage/connect/mysql-test/connect/r/xml.result
@@ -507,7 +507,7 @@ DROP TABLE t1;
SET @a=LOAD_FILE('test/t1.xml');
SELECT CAST(@a AS CHAR CHARACTER SET latin1);
CAST(@a AS CHAR CHARACTER SET latin1) <?xml version="1.0" encoding="iso-8859-1"?>
-<!-- Created by CONNECT Version 1.01.0004 April 10, 2013 -->
+<!-- Created by CONNECT Version 1.01.0005 April 27, 2013 -->
<t1>
<line>
<node>ÀÁÂÃ</node>
diff --git a/storage/connect/plgdbsem.h b/storage/connect/plgdbsem.h
index 611b0067e18..a1eaf97bd10 100644
--- a/storage/connect/plgdbsem.h
+++ b/storage/connect/plgdbsem.h
@@ -69,12 +69,14 @@ enum TABTYPE {TAB_UNDEF = 0, /* Table of undefined type */
TAB_WMI = 14, /* WMI tables (Windows only) */
TAB_TBL = 15, /* Collection of CONNECT tables */
TAB_OEM = 16, /* OEM implemented table */
- TAB_CATLG = 17, /* Catalog table */
- TAB_PLG = 18, /* PLG NIY */
- TAB_PIVOT = 19, /* PIVOT NIY */
- TAB_JCT = 20, /* Junction tables NIY */
- TAB_DMY = 21, /* DMY Dummy tables NIY */
- TAB_NIY = 22}; /* Table not implemented yet */
+ TAB_XCL = 17, /* XCL table */
+ TAB_OCCUR = 18, /* OCCUR table */
+ TAB_PRX = 19, /* Proxy (catalog) table */
+ TAB_PLG = 20, /* PLG NIY */
+ TAB_PIVOT = 21, /* PIVOT NIY */
+ TAB_JCT = 22, /* Junction tables NIY */
+ TAB_DMY = 23, /* DMY Dummy tables NIY */
+ TAB_NIY = 24}; /* Table not implemented yet */
enum AMT {TYPE_AM_ERROR = 0, /* Type not defined */
TYPE_AM_ROWID = 1, /* ROWID type (special column) */
diff --git a/storage/connect/tabmysql.cpp b/storage/connect/tabmysql.cpp
index 7b38cc8ab1b..495324b74f7 100644
--- a/storage/connect/tabmysql.cpp
+++ b/storage/connect/tabmysql.cpp
@@ -63,6 +63,7 @@ void PrintResult(PGLOBAL, PSEM, PQRYRES);
#endif // _CONSOLE
extern "C" int trace;
+extern MYSQL_PLUGIN_IMPORT uint mysqld_port;
/* -------------- Implementation of the MYSQLDEF class --------------- */
@@ -243,10 +244,13 @@ bool MYSQLDEF::ParseURL(PGLOBAL g, char *url)
if ((sport = strchr(Hostname, ':')))
*sport++ = 0;
- Portnumber = (sport && sport[0]) ? atoi(sport) : MYSQL_PORT;
+ Portnumber = (sport && sport[0]) ? atoi(sport) : mysqld_port;
+
+ if (Username[0] == 0)
+ Username = Cat->GetStringCatInfo(g, "User", "*");
if (Hostname[0] == 0)
- Hostname = "localhost";
+ Hostname = Cat->GetStringCatInfo(g, "Host", "localhost");
if (!Database || !*Database)
Database = Cat->GetStringCatInfo(g, "Database", "*");
@@ -282,9 +286,9 @@ bool MYSQLDEF::DefineAM(PGLOBAL g, LPCSTR am, int poff)
Database = Cat->GetStringCatInfo(g, "Database", "*");
Tabname = Cat->GetStringCatInfo(g, "Name", Name); // Deprecated
Tabname = Cat->GetStringCatInfo(g, "Tabname", Tabname);
- Username = Cat->GetStringCatInfo(g, "User", "root");
+ Username = Cat->GetStringCatInfo(g, "User", "*");
Password = Cat->GetStringCatInfo(g, "Password", NULL);
- Portnumber = Cat->GetIntCatInfo("Port", MYSQL_PORT);
+ Portnumber = Cat->GetIntCatInfo("Port", mysqld_port);
} else if (ParseURL(g, url))
return TRUE;
diff --git a/storage/connect/taboccur.cpp b/storage/connect/taboccur.cpp
new file mode 100644
index 00000000000..e1b83c06422
--- /dev/null
+++ b/storage/connect/taboccur.cpp
@@ -0,0 +1,375 @@
+/************ TabOccur CPP Declares Source Code File (.CPP) ************/
+/* Name: TABOCCUR.CPP Version 1.0 */
+/* */
+/* (C) Copyright to the author Olivier BERTRAND 2013 */
+/* */
+/* OCCUR: Table that provides a view of a source table where the */
+/* contain of several columns of the source table is placed in only */
+/* one column, the OCCUR column, this resulting into several rows. */
+/***********************************************************************/
+
+/***********************************************************************/
+/* Include relevant section of system dependant header files. */
+/***********************************************************************/
+#include "my_global.h"
+#if defined(WIN32)
+#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 "table.h" // MySQL table definitions
+#include "global.h"
+#include "plgdbsem.h"
+#include "reldef.h"
+#include "filamtxt.h"
+#include "tabdos.h"
+#include "tabcol.h"
+#include "taboccur.h"
+#include "xtable.h"
+#if defined(MYSQL_SUPPORT)
+#include "tabmysql.h"
+#endif // MYSQL_SUPPORT
+#include "ha_connect.h"
+#include "mycat.h"
+
+extern "C" int trace;
+
+/* -------------- Implementation of the OCCUR classes ---------------- */
+
+/***********************************************************************/
+/* DefineAM: define specific AM block values from OCCUR table. */
+/***********************************************************************/
+bool OCCURDEF::DefineAM(PGLOBAL g, LPCSTR am, int poff)
+ {
+//Tabname = Cat->GetStringCatInfo(g, "SrcTable", "");
+ Xcol = Cat->GetStringCatInfo(g, "OccurCol", "");
+ Rcol = Cat->GetStringCatInfo(g, "RankCol", "");
+ Colist = Cat->GetStringCatInfo(g, "Colist", "");
+ return PRXDEF::DefineAM(g, am, poff);
+ } // end of DefineAM
+
+/***********************************************************************/
+/* GetTable: makes a new TDB of the proper type. */
+/***********************************************************************/
+PTDB OCCURDEF::GetTable(PGLOBAL g, MODE m)
+ {
+ if (Catfunc != FNC_COL) {
+ PTDB tdbp;
+ PTDBOCCUR tocp = new(g) TDBOCCUR(this);
+
+ // Check that the source table is available
+ if (!tocp || !(tdbp = tocp->GetSubTable(g, Tablep)))
+ return NULL;
+
+ // Set Tdbp now
+ tocp->SetTdbp((PTDBASE)tdbp);
+
+ if (tocp->MakeColumnList(g) < 0)
+ return NULL;
+
+ return tocp;
+ } else
+ return new(g) TDBTBC(this);
+
+ } // end of GetTable
+
+/* ------------------------------------------------------------------- */
+
+/***********************************************************************/
+/* Implementation of the TDBOCCUR class. */
+/***********************************************************************/
+TDBOCCUR::TDBOCCUR(POCCURDEF tdp) : TDBPRX(tdp)
+ {
+//Tdbp = NULL; // Source table
+ Tabname = tdp->Tablep->GetName(); // Name of source table
+ Colist = tdp->Colist; // List of source columns
+ Xcolumn = tdp->Xcol; // Occur column name
+ Rcolumn = tdp->Rcol; // Rank column name
+ Xcolp = NULL; // To the OCCURCOL column
+ Col = NULL; // To source column blocks array
+ Mult = -1; // Multiplication factor
+ N = 0; // The current table index
+ M = 0; // The occurence rank
+ RowFlag = 0; // 0: Ok, 1: Same, 2: Skip
+ } // end of TDBOCCUR constructor
+
+/***********************************************************************/
+/* Allocate OCCUR/SRC column description block. */
+/***********************************************************************/
+PCOL TDBOCCUR::MakeCol(PGLOBAL g, PCOLDEF cdp, PCOL cprec, int n)
+ {
+ PCOL colp = NULL;
+
+ if (!stricmp(cdp->GetName(), Rcolumn)) {
+ // Allocate a RANK column
+ colp = new(g) RANKCOL(cdp, this, n);
+ } else if (!stricmp(cdp->GetName(), Xcolumn)) {
+ // Allocate the OCCUR column
+ colp = Xcolp = new(g) OCCURCOL(cdp, this, n);
+ } else {
+ colp = new(g) PRXCOL(cdp, this, cprec, n);
+
+ if (((PPRXCOL)colp)->Init(g))
+ return NULL;
+
+ return colp;
+ } //endif name
+
+ if (cprec) {
+ colp->SetNext(cprec->GetNext());
+ cprec->SetNext(colp);
+ } else {
+ colp->SetNext(Columns);
+ Columns = colp;
+ } // endif cprec
+
+ return colp;
+ } // end of MakeCol
+
+/***********************************************************************/
+/* Allocate OCCUR column description block. */
+/***********************************************************************/
+int TDBOCCUR::MakeColumnList(PGLOBAL g)
+ {
+ if (Mult < 0) {
+ char *p, *pn;
+ int i;
+ int n = 0;
+
+ // Count the number of columns and change separator into null char
+ for (pn = Colist; ; pn += (strlen(pn) + 1))
+ if ((p = strchr(pn, ';'))) {
+ *p++ = '\0';
+ n++;
+ } else {
+ if (*pn)
+ n++;
+
+ break;
+ } // endif p
+
+ Col = (PCOL*)PlugSubAlloc(g, NULL, n * sizeof(PCOL));
+
+ for (i = 0, pn = Colist; i < n; i++, pn += (strlen(pn) + 1)) {
+ if (!(Col[i] = Tdbp->ColDB(g, pn, 0))) {
+ // Column not found in table
+ sprintf(g->Message, MSG(COL_ISNOT_TABLE), pn, Tabname);
+ return -1;
+ } // endif Col
+
+ if (Col[i]->InitValue(g)) {
+ strcpy(g->Message, "OCCUR InitValue failed");
+ return -1;
+ } // endif InitValue
+
+ } // endfor i
+
+ // OCCUR column name defaults to the name of the list first column
+ if (!Xcolumn)
+ Xcolumn = Colist;
+
+ Mult = n;
+ } // endif Mult
+
+ return Mult;
+ } // end of MakeColumnList
+
+/***********************************************************************/
+/* OCCUR GetMaxSize: returns the maximum number of rows in the table. */
+/***********************************************************************/
+int TDBOCCUR::GetMaxSize(PGLOBAL g)
+ {
+ if (MaxSize < 0) {
+// Mult = MakeColumnList(g);
+ MaxSize = Mult * Tdbp->GetMaxSize(g);
+ } // endif MaxSize
+
+ return MaxSize;
+ } // end of GetMaxSize
+
+/***********************************************************************/
+/* In this sample, ROWID will be the (virtual) row number, */
+/* while ROWNUM will be the occurence rank in the multiple column. */
+/***********************************************************************/
+int TDBOCCUR::RowNumber(PGLOBAL g, bool b)
+ {
+ return (b) ? M : N;
+ } // end of RowNumber
+
+/***********************************************************************/
+/* OCCUR Access Method opening routine. */
+/***********************************************************************/
+bool TDBOCCUR::OpenDB(PGLOBAL g)
+ {
+ if (Use == USE_OPEN) {
+ /*******************************************************************/
+ /* Table already open, just replace it at its beginning. */
+ /*******************************************************************/
+ N = M = 0;
+ RowFlag = 0;
+
+ if (Xcolp)
+ Xcolp->Xreset();
+
+ return Tdbp->OpenDB(g);
+ } // endif use
+
+ /*********************************************************************/
+ /* Do it here if not done yet. */
+ /*********************************************************************/
+// if (MakeColumnList(g) < 0)
+// return TRUE;
+
+ if (Mode != MODE_READ) {
+ /*******************************************************************/
+ /* Currently OCCUR tables cannot be modified. */
+ /*******************************************************************/
+ strcpy(g->Message, "OCCUR tables are read only");
+ return TRUE;
+ } // endif Mode
+
+#if 0
+ /*********************************************************************/
+ /* Be sure OCCUR column exist. */
+ /*********************************************************************/
+ if (!Xcolp) {
+ if (!(Xcolp = (POCCURCOL)ColDB(g, Xcolumn, 0))) {
+ sprintf(g->Message, "OCCUR column %s definition error", Xcolumn);
+ return TRUE;
+ } else if (Xcolp->InitValue(g)) {
+ strcpy(g->Message, "OCCUR InitValue failed");
+ return TRUE;
+ } // endif's Xcolp
+
+ } // endif Xcolp
+#endif // 0
+
+ if (Xcolp)
+ // Lock this column so it is evaluated by its table only
+ Xcolp->AddStatus(BUF_READ);
+
+ if (To_Key_Col || To_Kindex) {
+ /*******************************************************************/
+ /* Direct access of OCCUR tables is not implemented yet. */
+ /*******************************************************************/
+ strcpy(g->Message, "No direct access to OCCUR tables");
+ return TRUE;
+ } // endif To_Key_Col
+
+ /*********************************************************************/
+ /* Do open the source table. */
+ /*********************************************************************/
+ return Tdbp->OpenDB(g);
+ } // end of OpenDB
+
+/***********************************************************************/
+/* Data Base read routine for OCCUR access method. */
+/***********************************************************************/
+int TDBOCCUR::ReadDB(PGLOBAL g)
+ {
+ int rc = RC_OK;
+
+ /*********************************************************************/
+ /* Now start the multi reading process. */
+ /*********************************************************************/
+ do {
+ if (RowFlag != 1)
+ if ((rc = Tdbp->ReadDB(g)) != RC_OK)
+ break;
+
+ if (Xcolp) {
+ RowFlag = 0;
+ Xcolp->ReadColumn(g);
+ M = Xcolp->GetI();
+ } // endif Xcolp
+
+ } while (RowFlag == 2);
+
+ N++;
+ return rc;
+ } // end of ReadDB
+
+// ------------------------ OCCURCOL functions ----------------------------
+
+/***********************************************************************/
+/* OCCURCOL public constructor. */
+/***********************************************************************/
+OCCURCOL::OCCURCOL(PCOLDEF cdp, PTDBOCCUR tdbp, int n)
+ : COLBLK(cdp, tdbp, n)
+ {
+ // Set additional OCCUR access method information for column.
+ I = 0;
+ } // end of OCCURCOL constructor
+
+/***********************************************************************/
+/* ReadColumn: what this routine does is to access the columns of */
+/* list, extract their value and convert it to buffer type. */
+/***********************************************************************/
+void OCCURCOL::ReadColumn(PGLOBAL g)
+ {
+ PTDBOCCUR tdbp = (PTDBOCCUR)To_Tdb;
+ PCOL *col = tdbp->Col;
+
+ for (; I < tdbp->Mult; I++) {
+ col[I]->ReadColumn(g);
+
+ if (Nullable || !col[I]->GetValue()->IsZero())
+ break;
+
+ } // endfor I
+
+ if (I == tdbp->Mult) {
+ // No more values, go to next source row
+ tdbp->RowFlag = 2;
+ I = 0;
+ return;
+ } // endif I
+
+ // Set the OCCUR column value from the Ith source column value
+ Value->SetValue_pval(col[I++]->GetValue());
+ tdbp->RowFlag = 1;
+ } // end of ReadColumn
+
+
+// ------------------------ RANKCOL functions ---------------------------
+
+/***********************************************************************/
+/* ReadColumn: what this routine does is to access the Mth columns of */
+/* list, extract its name and set to it the rank column value. */
+/***********************************************************************/
+void RANKCOL::ReadColumn(PGLOBAL g)
+ {
+ PTDBOCCUR tdbp = (PTDBOCCUR)To_Tdb;
+ PCOL *col = tdbp->Col;
+
+ // Set the RANK column value from the Mth source column name
+ if (tdbp->M)
+ Value->SetValue_psz(col[tdbp->M - 1]->GetName());
+ else {
+ Value->Reset();
+
+ if (Nullable)
+ Value->SetNull(true);
+
+ } // endelse
+
+ } // end of ReadColumn
diff --git a/storage/connect/taboccur.h b/storage/connect/taboccur.h
new file mode 100644
index 00000000000..0cfabf87793
--- /dev/null
+++ b/storage/connect/taboccur.h
@@ -0,0 +1,145 @@
+// TABOCCUR.H Olivier Bertrand 2013
+// Defines the OCCUR tables
+
+#include "tabutil.h"
+
+#define TYPE_AM_OCCUR (AMT)128
+
+typedef class OCCURDEF *POCCURDEF;
+typedef class TDBOCCUR *PTDBOCCUR;
+typedef class OCCURCOL *POCCURCOL;
+typedef class RANKCOL *PRANKCOL;
+typedef class SRTCOL *PSRTCOL;
+
+/* -------------------------- OCCUR classes -------------------------- */
+
+/***********************************************************************/
+/* OCCUR: OEM table that provides a view of a source table where the */
+/* contain of several columns of the source table is placed in only */
+/* one column, the OCCUR column, this resulting into several rows. */
+/***********************************************************************/
+
+/***********************************************************************/
+/* OCCUR table. */
+/***********************************************************************/
+class OCCURDEF : public PRXDEF { /* Logical table description */
+ friend class TDBOCCUR;
+ public:
+ // Constructor
+ OCCURDEF(void) {Pseudo = 3; Colist = Xcol = NULL;}
+
+ // Implementation
+ virtual const char *GetType(void) {return "OCCUR";}
+
+ // Methods
+ virtual bool DefineAM(PGLOBAL g, LPCSTR am, int poff);
+ virtual PTDB GetTable(PGLOBAL g, MODE m);
+
+ protected:
+ // Members
+//char *Tabname; /* The source table name */
+ char *Colist; /* The source column list */
+ char *Xcol; /* The multiple occurence column */
+ char *Rcol; /* The rank column */
+ }; // end of OCCURDEF
+
+/***********************************************************************/
+/* This is the class declaration for the OCCUR table. */
+/***********************************************************************/
+class TDBOCCUR : public TDBPRX {
+ friend class OCCURCOL;
+ friend class RANKCOL;
+ friend class SRTCOL;
+ public:
+ // Constructor
+ TDBOCCUR(POCCURDEF tdp);
+
+ // Implementation
+ virtual AMT GetAmType(void) {return TYPE_AM_OCCUR;}
+ void SetTdbp(PTDBASE tdbp) {Tdbp = tdbp;}
+
+ // Methods
+//virtual int GetRecpos(void) {return N;}
+ virtual void ResetDB(void) {N = 0; Tdbp->ResetDB();}
+ virtual int RowNumber(PGLOBAL g, bool b = FALSE);
+ PTDB GetSourceTable(PGLOBAL g);
+ int MakeColumnList(PGLOBAL g);
+
+ // Database routines
+//virtual PCOL ColDB(PGLOBAL g, PSZ colname, int num);
+ virtual PCOL MakeCol(PGLOBAL g, PCOLDEF cdp, PCOL cprec, int n);
+ virtual int GetMaxSize(PGLOBAL g);
+ virtual bool OpenDB(PGLOBAL g);
+ virtual int ReadDB(PGLOBAL g);
+
+ protected:
+ // Members
+//PTDBASE Tdbp; // To the source table or view
+ LPCSTR Tabname; // Name of source table
+ char *Colist; // Source column list
+ char *Xcolumn; // Occurence column name
+ char *Rcolumn; // Rank column name
+ POCCURCOL Xcolp; // To the OCCURCOL column
+ PCOL *Col; // To source multiple columns
+ int Mult; // Multiplication factor
+ int N; // The current table index
+ int M; // The occurence rank
+ BYTE RowFlag; // 0: Ok, 1: Same, 2: Skip
+ }; // end of class TDBOCCUR
+
+/***********************************************************************/
+/* Class OCCURCOL: for the multiple occurence column. */
+/***********************************************************************/
+class OCCURCOL : public COLBLK {
+ public:
+ // Constructors
+ OCCURCOL(PCOLDEF cdp, PTDBOCCUR tdbp, int n);
+//OCCURCOL(OCCURCOL *colp, PTDB tdbp); // Constructor used in copy process
+
+ // Implementation
+ virtual int GetAmType(void) {return TYPE_AM_OCCUR;}
+ int GetI(void) {return I;}
+
+ // Methods
+ virtual void Reset(void) {} // Evaluated only by TDBOCCUR
+ virtual void ReadColumn(PGLOBAL g);
+ void Xreset(void) {I = 0;};
+
+ protected:
+ // Default constructor not to be used
+ OCCURCOL(void) {}
+
+ // Members
+ int I;
+ }; // end of class OCCURCOL
+
+/***********************************************************************/
+/* Class RANKCOL: for the multiple occurence column ranking. */
+/***********************************************************************/
+class RANKCOL : public COLBLK {
+ public:
+ // Constructors
+ RANKCOL(PCOLDEF cdp, PTDBOCCUR tdbp, int n) : COLBLK(cdp, tdbp, n) {}
+//RANKCOL(RANKCOL *colp, PTDB tdbp); // Constructor used in copy process
+
+ // Implementation
+ virtual int GetAmType(void) {return TYPE_AM_OCCUR;}
+
+ // Methods
+ virtual void ReadColumn(PGLOBAL g);
+
+ protected:
+ // Default constructor not to be used
+ RANKCOL(void) {}
+
+ // Members
+ }; // end of class RANKCOL
+
+/***********************************************************************/
+/* Definition of class XCOLDEF. */
+/* This class purpose is just to access COLDEF protected items! */
+/***********************************************************************/
+class XCOLDEF: public COLDEF {
+ friend class TDBOCCUR;
+ }; // end of class XCOLDEF
+
diff --git a/storage/connect/tabtbl.cpp b/storage/connect/tabtbl.cpp
index b194da3fc09..c1286785d73 100644
--- a/storage/connect/tabtbl.cpp
+++ b/storage/connect/tabtbl.cpp
@@ -1,7 +1,7 @@
/************* TabTbl C++ Program Source Code File (.CPP) **************/
/* PROGRAM NAME: TABTBL */
/* ------------- */
-/* Version 1.4 */
+/* Version 1.5 */
/* */
/* COPYRIGHT: */
/* ---------- */
@@ -70,7 +70,7 @@
#include "filamtxt.h"
#include "tabcol.h"
#include "tabdos.h" // TDBDOS and DOSCOL class dcls
-#include "tabtbl.h" // TDBTBL and TBLCOL classes dcls
+#include "tabtbl.h"
#if defined(MYSQL_SUPPORT)
#include "tabmysql.h"
#endif // MYSQL_SUPPORT
@@ -86,7 +86,7 @@ extern "C" int trace;
/**************************************************************************/
TBLDEF::TBLDEF(void)
{
- To_Tables = NULL;
+//To_Tables = NULL;
Ntables = 0;
Pseudo = 3;
} // end of TBLDEF constructor
@@ -100,18 +100,18 @@ bool TBLDEF::DefineAM(PGLOBAL g, LPCSTR am, int poff)
Desc = "Table list table";
tablist = Cat->GetStringCatInfo(g, "Tablist", "");
- dbname = Cat->GetStringCatInfo(g, "Database", NULL);
+ dbname = Cat->GetStringCatInfo(g, "Dbname", "*");
Ntables = 0;
if (*tablist) {
- char *p, *pn, *pdb;
- PTBL *ptbl = &To_Tables, tbl;
+ char *p, *pn, *pdb;
+ PTABLE tbl;
for (pdb = tablist; ;) {
if ((p = strchr(pdb, ',')))
*p = 0;
- // Analyze the table name, it has the format:
+ // Analyze the table name, it may have the format:
// [dbname.]tabname
if ((pn = strchr(pdb, '.'))) {
*pn++ = 0;
@@ -121,17 +121,18 @@ bool TBLDEF::DefineAM(PGLOBAL g, LPCSTR am, int poff)
} // endif p
// Allocate the TBLIST block for that table
- tbl = (PTBL)PlugSubAlloc(g, NULL, sizeof(TBLIST));
- tbl->Next = NULL;
- tbl->Name = pn;
- tbl->DB = pdb;
+ tbl = new(g) XTAB(pn);
+ tbl->SetQualifier(pdb);
if (trace)
- htrc("TBL: Name=%s db=%s\n", tbl->Name, SVP(tbl->DB));
+ htrc("TBL: Name=%s db=%s\n", tbl->GetName(), tbl->GetQualifier());
// Link the blocks
- *ptbl = tbl;
- ptbl = &tbl->Next;
+ if (Tablep)
+ Tablep->Link(tbl);
+ else
+ Tablep = tbl;
+
Ntables++;
if (p)
@@ -153,15 +154,11 @@ bool TBLDEF::DefineAM(PGLOBAL g, LPCSTR am, int poff)
/***********************************************************************/
PTDB TBLDEF::GetTable(PGLOBAL g, MODE m)
{
- PTDB tdbp;
-
- /*********************************************************************/
- /* Allocate a TDB of the proper type. */
- /* Column blocks will be allocated only when needed. */
- /*********************************************************************/
- tdbp = new(g) TDBTBL(this);
+ if (Catfunc == FNC_COL)
+ return new(g) TDBTBC(this);
+ else
+ return new(g) TDBTBL(this);
- return tdbp;
} // end of GetTable
/* ------------------------- Class TDBTBL ---------------------------- */
@@ -169,11 +166,11 @@ PTDB TBLDEF::GetTable(PGLOBAL g, MODE m)
/***********************************************************************/
/* TDBTBL constructors. */
/***********************************************************************/
-TDBTBL::TDBTBL(PTBLDEF tdp) : TDBASE(tdp)
+TDBTBL::TDBTBL(PTBLDEF tdp) : TDBPRX(tdp)
{
Tablist = NULL;
CurTable = NULL;
- Tdbp = NULL;
+//Tdbp = NULL;
Accept = tdp->Accept;
Maxerr = tdp->Maxerr;
Nbf = 0;
@@ -188,7 +185,7 @@ TDBTBL::TDBTBL(PTBLDEF tdp) : TDBASE(tdp)
/***********************************************************************/
PCOL TDBTBL::MakeCol(PGLOBAL g, PCOLDEF cdp, PCOL cprec, int n)
{
- return new(g) TBLCOL(cdp, this, cprec, n);
+ return new(g) PRXCOL(cdp, this, cprec, n);
} // end of MakeCol
/***********************************************************************/
@@ -212,13 +209,14 @@ PCOL TDBTBL::InsertSpecialColumn(PGLOBAL g, PCOL scp)
return colp;
} // end of InsertSpecialColumn
+#if 0
/***********************************************************************/
/* Get the PTDB of a table of the list. */
/***********************************************************************/
PTDB TDBTBL::GetSubTable(PGLOBAL g, PTBL tblp, PTABLE tabp)
{
- char *db, key[256];
- uint k;
+//char *db;
+ bool mysql;
PTDB tdbp = NULL;
TABLE_SHARE *s;
PCATLG cat = To_Def->GetCat();
@@ -228,54 +226,47 @@ PTDB TDBTBL::GetSubTable(PGLOBAL g, PTBL tblp, PTABLE tabp)
if (!thd)
return NULL; // Should not happen anymore
- if (tblp->DB)
- db = tblp->DB;
- else
- db = (char*)hc->GetDBName(NULL);
-
- k = sprintf(key, "%s", db) + 1;
- k += sprintf(key + k, "%s", tblp->Name);
- key[++k] = 0;
+//if (tblp->DB)
+// db = tblp->DB;
+//else
+// db = (char*)hc->GetDBName(NULL);
- if (!(s = alloc_table_share(db, tblp->Name, key, ++k))) {
- strcpy(g->Message, "Error allocating share\n");
- return NULL;
- } // endif s
+//if (!(s = GetTableShare(g, thd, db, tblp->Name, mysql)))
+ if (!(s = GetTableShare(g, thd, tblp->DB, tblp->Name, mysql)))
+ return NULL;
- if (!open_table_def(thd, s)) {
- if (plugin_data(s->db_plugin, handlerton*) != connect_hton) {
+ if (mysql) {
#if defined(MYSQL_SUPPORT)
- // Access sub-table via MySQL API
- if (!(tdbp= cat->GetTable(g, tabp, MODE_READ, "MYSQL"))) {
- sprintf(g->Message, "Cannot access %s.%s", db, tblp->Name);
- return NULL;
- } // endif Define
+ // Access sub-table via MySQL API
+ if (!(tdbp= cat->GetTable(g, tabp, MODE_READ, "MYSQL"))) {
+ sprintf(g->Message, "Cannot access %s.%s", tblp->DB, tblp->Name);
+ goto err;
+ } // endif Define
- if (tabp->GetQualifier())
- ((PTDBMY)tdbp)->SetDatabase(tabp->GetQualifier());
+ if (tabp->GetQualifier())
+ ((PTDBMY)tdbp)->SetDatabase(tabp->GetQualifier());
#else // !MYSQL_SUPPORT
- sprintf(g->Message, "%s.%s is not a CONNECT table",
- db, tblp->Name);
- return NULL;
+ 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
- hc->tshp = s;
- tdbp = cat->GetTable(g, tabp);
- hc->tshp = NULL;
- } // endif plugin
-
- } else
- sprintf(g->Message, "Error %d opening share\n", s->error);
+ } else {
+ // Sub-table is a CONNECT table
+ hc->tshp = s;
+ tdbp = cat->GetTable(g, tabp);
+ hc->tshp = NULL;
+ } // endif plugin
if (trace && tdbp)
htrc("Subtable %s in %s\n",
tblp->Name, SVP(((PTDBASE)tdbp)->GetDef()->GetDB()));
-
+
+ err:
free_table_share(s);
return tdbp;
} // end of GetSubTable
+#endif // 0
/***********************************************************************/
/* Initializes the table table list. */
@@ -284,28 +275,25 @@ bool TDBTBL::InitTableList(PGLOBAL g)
{
char *colname;
int n, colpos;
- PTBL tblp;
- PTABLE tabp;
+ PTABLE tp, tabp;
PTDB tdbp;
PCOL colp;
PTBLDEF tdp = (PTBLDEF)To_Def;
// PlugSetPath(filename, Tdbp->GetFile(g), Tdbp->GetPath());
- for (n = 0, tblp = tdp->GetTables(); tblp; tblp = tblp->Next) {
- if (TestFil(g, To_Filter, tblp)) {
- // Table or named view
- tabp = new(g) XTAB(tblp->Name);
- tabp->SetQualifier(tblp->DB);
+ for (n = 0, tp = tdp->Tablep; tp; tp = tp->GetNext()) {
+ if (TestFil(g, To_Filter, tp)) {
+ tabp = new(g) XTAB(tp);
// Get the table description block of this table
- if (!(tdbp = GetSubTable(g, tblp, tabp))) {
+ if (!(tdbp = GetSubTable(g, tabp))) {
if (++Nbf > Maxerr)
return TRUE; // Error return
else
continue; // Skip this table
- } // endif tdbp
+ } // endif tdbp
// We must allocate subtable columns before GetMaxSize is called
// because some (PLG, ODBC?) need to have their columns attached.
@@ -313,7 +301,7 @@ bool TDBTBL::InitTableList(PGLOBAL g)
for (PCOL cp = Columns; cp; cp = cp->GetNext())
if (!cp->IsSpecial()) {
colname = cp->GetName();
- colpos = ((PTBLCOL)cp)->Colnum;
+ colpos = ((PPRXCOL)cp)->Colnum;
// We try first to get the column by name
if (!(colp = tdbp->ColDB(g, colname, 0)) && colpos)
@@ -328,7 +316,7 @@ bool TDBTBL::InitTableList(PGLOBAL g)
return TRUE; // Error return
} // endif !Accept
- } else // this is needed in particular by PLG tables
+ } else // this is needed by some tables (which?)
colp->SetColUse(cp->GetColUse());
} // endif !special
@@ -351,7 +339,7 @@ bool TDBTBL::InitTableList(PGLOBAL g)
/***********************************************************************/
/* Test the tablename against the pseudo "local" filter. */
/***********************************************************************/
-bool TDBTBL::TestFil(PGLOBAL g, PFIL filp, PTBL tblp)
+bool TDBTBL::TestFil(PGLOBAL g, PFIL filp, PTABLE tabp)
{
char *fil, op[8], tn[NAME_LEN];
bool neg;
@@ -374,7 +362,7 @@ bool TDBTBL::TestFil(PGLOBAL g, PFIL filp, PTBL tblp)
if (sscanf(fil, "TABID = '%[^']'", tn) != 1)
return TRUE; // ignore invalid filter
- return !stricmp(tn, tblp->Name);
+ return !stricmp(tn, tabp->GetName());
} else if (!strcmp(op, "IN")) {
char *p, *tnl = (char*)PlugSubAlloc(g, NULL, strlen(fil) - 10);
int n;
@@ -393,7 +381,7 @@ bool TDBTBL::TestFil(PGLOBAL g, PFIL filp, PTBL tblp)
if (sscanf(tnl, "'%[^']'", tn) != 1)
return TRUE; // ignore invalid filter
- else if (!stricmp(tn, tblp->Name))
+ else if (!stricmp(tn, tabp->GetName()))
return !neg; // Found
tnl = p;
@@ -405,19 +393,19 @@ bool TDBTBL::TestFil(PGLOBAL g, PFIL filp, PTBL tblp)
return TRUE; // invalid operator
} // end of TestFil
+#if 0
/***********************************************************************/
/* TBL GetProgMax: get the max value for progress information. */
/***********************************************************************/
int TDBTBL::GetProgMax(PGLOBAL g)
{
- PTABLE tblp;
- int n, pmx = 0;
+ int n, pmx = 0;
if (!Tablist && InitTableList(g))
return -1;
- for (tblp = Tablist; tblp; tblp = tblp->GetNext())
- if ((n = tblp->GetTo_Tdb()->GetProgMax(g)) > 0)
+ for (PTABLE tabp = Tablist; tabp; tblp = tabp->GetNext())
+ if ((n = tabp->GetTo_Tdb()->GetProgMax(g)) > 0)
pmx += n;
return pmx;
@@ -431,7 +419,6 @@ int TDBTBL::GetProgCur(void)
return Crp + Tdbp->GetProgCur();
} // end of GetProgCur
-#if 0
/***********************************************************************/
/* TBL Cardinality: returns table cardinality in number of rows. */
/* This function can be called with a null argument to test the */
@@ -470,7 +457,6 @@ int TDBTBL::Cardinality(PGLOBAL g)
int TDBTBL::GetMaxSize(PGLOBAL g)
{
if (MaxSize < 0) {
- PTABLE tblp;
int mxsz;
if (!Tablist && InitTableList(g))
@@ -482,8 +468,8 @@ int TDBTBL::GetMaxSize(PGLOBAL g)
// } else
MaxSize = 0;
- for (tblp = Tablist; tblp; tblp = tblp->GetNext()) {
- if ((mxsz = tblp->GetTo_Tdb()->GetMaxSize(g)) < 0) {
+ for (PTABLE tabp = Tablist; tabp; tabp = tabp->GetNext()) {
+ if ((mxsz = tabp->GetTo_Tdb()->GetMaxSize(g)) < 0) {
MaxSize = -1;
return mxsz;
} // endif mxsz
@@ -505,8 +491,8 @@ void TDBTBL::ResetDB(void)
if (colp->GetAmType() == TYPE_AM_TABID)
colp->COLBLK::Reset();
- for (PTABLE tblp = Tablist; tblp; tblp = tblp->GetNext())
- ((PTDBASE)tblp->GetTo_Tdb())->ResetDB();
+ for (PTABLE tabp = Tablist; tabp; tabp = tabp->GetNext())
+ ((PTDBASE)tabp->GetTo_Tdb())->ResetDB();
Tdbp = (PTDBASE)Tablist->GetTo_Tdb();
Crp = 0;
@@ -573,7 +559,7 @@ bool TDBTBL::OpenDB(PGLOBAL g)
for (PCOL cp = Columns; cp; cp = cp->GetNext())
if (cp->GetAmType() == TYPE_AM_TABID)
cp->COLBLK::Reset();
- else if (((PTBLCOL)cp)->Init(g))
+ else if (((PPRXCOL)cp)->Init(g))
return TRUE;
if (trace)
@@ -627,7 +613,7 @@ int TDBTBL::ReadDB(PGLOBAL g)
for (PCOL cp = Columns; cp; cp = cp->GetNext())
if (cp->GetAmType() == TYPE_AM_TABID)
cp->COLBLK::Reset();
- else if (((PTBLCOL)cp)->Init(g))
+ else if (((PPRXCOL)cp)->Init(g))
return RC_FX;
if (trace)
@@ -648,6 +634,7 @@ int TDBTBL::ReadDB(PGLOBAL g)
return rc;
} // end of ReadDB
+#if 0
/***********************************************************************/
/* Data Base write routine for MUL access method. */
/***********************************************************************/
@@ -675,9 +662,11 @@ void TDBTBL::CloseDB(PGLOBAL g)
Tdbp->CloseDB(g);
} // end of CloseDB
+#endif // 0
/* ---------------------------- TBLCOL ------------------------------- */
+#if 0
/***********************************************************************/
/* TBLCOL public constructor. */
/***********************************************************************/
@@ -705,7 +694,6 @@ TBLCOL::TBLCOL(PCOLDEF cdp, PTDB tdbp, PCOL cprec, int i, PSZ am)
} // end of TBLCOL constructor
-#if 0
/***********************************************************************/
/* TBLCOL public constructor. */
/***********************************************************************/
@@ -733,7 +721,6 @@ TBLCOL::TBLCOL(TBLCOL *col1, PTDB tdbp) : COLBLK(col1, tdbp)
To_Val = col1->To_Val;
Pseudo = col1->Pseudo;
} // end of TBLCOL copy constructor
-#endif
/***********************************************************************/
/* TBLCOL initialization routine. */
@@ -783,6 +770,7 @@ void TBLCOL::ReadColumn(PGLOBAL g)
} // endif Colp
} // end of ReadColumn
+#endif // 0
/* ---------------------------- TBTBLK ------------------------------- */
diff --git a/storage/connect/tabtbl.h b/storage/connect/tabtbl.h
index 07a20bb2867..d241b00743e 100644
--- a/storage/connect/tabtbl.h
+++ b/storage/connect/tabtbl.h
@@ -1,41 +1,30 @@
/*************** TabTbl H Declares Source Code File (.H) ***************/
/* Name: TABTBL.H Version 1.2 */
/* */
-/* (C) Copyright to the author Olivier BERTRAND 2008-2012 */
+/* (C) Copyright to the author Olivier BERTRAND 2008-2013 */
/* */
/* This file contains the TDBTBL classes declares. */
/***********************************************************************/
-//#include "osutil.h"
#include "block.h"
#include "colblk.h"
+#include "tabutil.h"
typedef class TBLDEF *PTBLDEF;
typedef class TDBTBL *PTDBTBL;
-typedef class TBLCOL *PTBLCOL;
-
-/***********************************************************************/
-/* Defines the structure used for multiple tables. */
-/***********************************************************************/
-typedef struct _tablist *PTBL;
-
-typedef struct _tablist {
- PTBL Next;
- char *Name;
- char *DB;
- } TBLIST;
/***********************************************************************/
/* TBL table. */
/***********************************************************************/
-class DllExport TBLDEF : public TABDEF { /* Logical table description */
+class DllExport TBLDEF : public PRXDEF { /* Logical table description */
friend class TDBTBL;
+ friend class TDBTBC;
public:
// Constructor
TBLDEF(void);
// Implementation
virtual const char *GetType(void) {return "TBL";}
- PTBL GetTables(void) {return To_Tables;}
+//PTABLE GetTables(void) {return Tablep;}
//int GetNtables(void) {return Ntables;}
// Methods
@@ -44,7 +33,7 @@ class DllExport TBLDEF : public TABDEF { /* Logical table description */
protected:
// Members
- PTBL To_Tables; /* To the list of tables */
+//PTABLE To_Tables; /* To the list of tables */
bool Accept; /* TRUE if bad tables are accepted */
int Maxerr; /* Maximum number of bad tables */
int Ntables; /* Number of tables */
@@ -53,50 +42,46 @@ class DllExport TBLDEF : public TABDEF { /* Logical table description */
/***********************************************************************/
/* This is the TBL Access Method class declaration. */
/***********************************************************************/
-class DllExport TDBTBL : public TDBASE {
- friend class TBLCOL;
+class DllExport TDBTBL : public TDBPRX {
+//friend class TBLCOL;
friend class TBTBLK;
friend class TDBPLG;
public:
// Constructor
TDBTBL(PTBLDEF tdp = NULL);
-//TDBTBL(PTDBTBL tdbp);
// Implementation
virtual AMT GetAmType(void) {return TYPE_AM_TBL;}
-//virtual PTDB Duplicate(PGLOBAL g)
-// {return (PTDB)new(g) TDBTBL(this);}
// Methods
virtual void ResetDB(void);
//virtual PTABLE GetTablist(void) {return (PSZ)Tablist;}
-//virtual PTDB CopyOne(PTABS t);
virtual int GetRecpos(void) {return Rows;}
virtual int GetBadLines(void) {return (int)Nbf;}
// Database routines
virtual PCOL MakeCol(PGLOBAL g, PCOLDEF cdp, PCOL cprec, int n);
virtual int GetMaxSize(PGLOBAL g);
- virtual int GetProgMax(PGLOBAL g);
- virtual int GetProgCur(void);
+//virtual int GetProgMax(PGLOBAL g);
+//virtual int GetProgCur(void);
virtual int RowNumber(PGLOBAL g, bool b = FALSE);
virtual PCOL InsertSpecialColumn(PGLOBAL g, PCOL scp);
virtual bool OpenDB(PGLOBAL g);
virtual int ReadDB(PGLOBAL g);
- virtual int WriteDB(PGLOBAL g);
- virtual int DeleteDB(PGLOBAL g, int irc);
- virtual void CloseDB(PGLOBAL g);
+//virtual int WriteDB(PGLOBAL g);
+//virtual int DeleteDB(PGLOBAL g, int irc);
+//virtual void CloseDB(PGLOBAL g);
protected:
// Internal functions
- PTDB GetSubTable(PGLOBAL g, PTBL tblp, PTABLE tabp);
+//PTDB GetSubTable(PGLOBAL g, PTBL tblp, PTABLE tabp);
bool InitTableList(PGLOBAL g);
- bool TestFil(PGLOBAL g, PFIL filp, PTBL tblp);
+ bool TestFil(PGLOBAL g, PFIL filp, PTABLE tabp);
// Members
PTABLE Tablist; // Points to the table list
PTABLE CurTable; // Points to the current table
- PTDBASE Tdbp; // Current table PTDB
+//PTDBASE Tdbp; // Current table PTDB
bool Accept; // TRUE if bad tables are accepted
int Maxerr; // Maximum number of bad tables
int Nbf; // Number of bad connections
@@ -104,6 +89,7 @@ class DllExport TDBTBL : public TDBASE {
int Crp; // Used for CurPos
}; // end of class TDBTBL
+#if 0
/***********************************************************************/
/* Class TBLCOL: TBL access method column descriptor. */
/* This A.M. is used for TBL tables. */
@@ -136,6 +122,7 @@ class DllExport TBLCOL : public COLBLK {
bool Pseudo; // TRUE for special columns
int Colnum; // Used when retrieving columns by number
}; // end of class TBLCOL
+#endif // 0
/***********************************************************************/
/* Class TBTBLK: TDBPLG TABID special column descriptor. */
diff --git a/storage/connect/tabutil.cpp b/storage/connect/tabutil.cpp
new file mode 100644
index 00000000000..5706ca7aeba
--- /dev/null
+++ b/storage/connect/tabutil.cpp
@@ -0,0 +1,596 @@
+/************* Tabutil cpp Declares Source Code File (.H) **************/
+/* Name: TABUTIL.CPP Version 1.0 */
+/* */
+/* (C) Copyright to the author Olivier BERTRAND 2013 */
+/* */
+/* Utility function used by TBL and PRX tables. */
+/***********************************************************************/
+
+/***********************************************************************/
+/* Include relevant section of system dependant header files. */
+/***********************************************************************/
+#include "my_global.h"
+#include "sql_class.h"
+#include "table.h"
+#include "field.h"
+#if defined(WIN32)
+#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 "table.h" // MySQL table definitions
+#include "global.h"
+#include "plgdbsem.h"
+#include "plgcnx.h" // For DB types
+#include "myutil.h"
+#include "mycat.h"
+#include "valblk.h"
+#include "resource.h"
+#include "reldef.h"
+#include "xtable.h"
+#if defined(MYSQL_SUPPORT)
+#include "tabmysql.h"
+#endif // MYSQL_SUPPORT
+#include "tabcol.h"
+#include "tabutil.h"
+#include "ha_connect.h"
+
+extern "C" int trace;
+
+/************************************************************************/
+/* GetTableShare: allocates and open a table share. */
+/************************************************************************/
+TABLE_SHARE *GetTableShare(PGLOBAL g, THD *thd, const char *db,
+ const char *name, bool& mysql)
+{
+ char key[256];
+ uint k;
+//TABLE_LIST table_list;
+ TABLE_SHARE *s;
+
+//table_list.init_one_table(db, strlen(db), name, strlen(name),
+// NULL, TL_IGNORE);
+ k = sprintf(key, "%s", db);
+ k += sprintf(key + ++k, "%s", name);
+ key[++k] = 0;
+
+ if (!(s = alloc_table_share(db, name, key, ++k))) {
+ strcpy(g->Message, "Error allocating share\n");
+ return NULL;
+ } // endif s
+
+// 1 2 4 8
+//flags = GTS_TABLE | GTS_VIEW | GTS_NOLOCK | GTS_FORCE_DISCOVERY;
+
+ if (!open_table_def(thd, s, GTS_TABLE)) {
+#ifdef DBUG_OFF
+ if (stricmp(s->db_plugin->name.str, "connect")) {
+#else
+ if (stricmp((*s->db_plugin)->name.str, "connect")) {
+#endif
+#if defined(MYSQL_SUPPORT)
+ mysql = true;
+#else // !MYSQL_SUPPORT
+ sprintf(g->Message, "%s.%s is not a CONNECT table", db, name);
+ return NULL;
+#endif // MYSQL_SUPPORT
+ } else
+ mysql = false;
+
+ } else {
+ sprintf(g->Message, "Error %d opening share\n", s->error);
+ free_table_share(s);
+ return NULL;
+ } // endif open_table_def
+
+ return s;
+} // end of GetTableShare
+
+/************************************************************************/
+/* TabColumns: constructs the result blocks containing all the columns */
+/* of the object table that will be retrieved by GetData commands. */
+/* key = TRUE when called from Create Table to get key informations. */
+/************************************************************************/
+PQRYRES TabColumns(PGLOBAL g, THD *thd, const char *db,
+ const char *name, bool info)
+ {
+ static int dbtype[] = {DB_CHAR, DB_SHORT, DB_CHAR, DB_INT,
+ DB_INT, DB_SHORT, DB_SHORT, DB_SHORT,
+ DB_CHAR, DB_CHAR, DB_CHAR};
+ static int buftyp[] = {TYPE_STRING, TYPE_SHORT, TYPE_STRING, TYPE_INT,
+ TYPE_INT, TYPE_SHORT, TYPE_SHORT, TYPE_SHORT,
+ TYPE_STRING, TYPE_STRING, TYPE_STRING};
+ static XFLD fldtyp[] = {FLD_NAME, FLD_TYPE, FLD_TYPENAME, FLD_PREC,
+ FLD_LENGTH, FLD_SCALE, FLD_RADIX, FLD_NULL,
+ FLD_REM, FLD_NO, FLD_CHARSET};
+ static unsigned int length[] = {0, 4, 16, 4, 4, 4, 4, 4, 256, 32, 32};
+ char *fld, *fmt;
+ int i, n, ncol = sizeof(dbtype) / sizeof(int);
+ int len, type, prec;
+ bool mysql;
+ TABLE_SHARE *s;
+ Field* *field;
+ Field *fp;
+ PQRYRES qrp;
+ PCOLRES crp;
+
+ if (!info) {
+ if (!(s = GetTableShare(g, thd, db, name, mysql)))
+ return NULL;
+ else
+ n = s->fieldnames.count;
+
+ } else {
+ n = 0;
+ length[0] = 128;
+ } // endif info
+
+ /**********************************************************************/
+ /* Allocate the structures used to refer to the result set. */
+ /**********************************************************************/
+ qrp = PlgAllocResult(g, ncol, n, IDS_COLUMNS + 3,
+ dbtype, buftyp, fldtyp, length, true, true);
+
+ // Some columns must be renamed
+ for (i = 0, crp = qrp->Colresp; crp; crp = crp->Next)
+ switch (++i) {
+ case 10: crp->Name = "Date_fmt"; break;
+ case 11: crp->Name = "Collation"; break;
+ } // endswitch i
+
+ if (info)
+ return qrp;
+
+ /**********************************************************************/
+ /* Now get the results into blocks. */
+ /**********************************************************************/
+ for (i = 0, field= s->field; *field; i++, field++) {
+ fp= *field;
+
+ // Get column name
+ crp = qrp->Colresp; // Column_Name
+ fld = (char *)fp->field_name;
+ crp->Kdata->SetValue(fld, i);
+
+ if ((type = MYSQLtoPLG(fp->type())) == TYPE_ERROR) {
+ sprintf(g->Message, "Unsupported column type %s", GetTypeName(type));
+ qrp = NULL;
+ break;
+ } // endif type
+
+ crp = crp->Next; // Data_Type
+ crp->Kdata->SetValue(type, i);
+ crp = crp->Next; // Type_Name
+ crp->Kdata->SetValue(GetTypeName(type), i);
+
+ if (type == TYPE_DATE) {
+ // When creating tables we do need info about date columns
+ if (mysql) {
+ fmt = MyDateFmt(fp->type());
+ len = strlen(fmt);
+ } else {
+ fmt = (char*)fp->option_struct->dateformat;
+ len = fp->field_length;
+ } // endif mysql
+
+ } else {
+ fmt = NULL;
+ len = fp->char_length();
+ } // endif type
+
+ crp = crp->Next; // Precision
+ crp->Kdata->SetValue(len, i);
+
+ crp = crp->Next; // Length
+ len = fp->field_length;
+ crp->Kdata->SetValue(len, i);
+
+ prec = (type == TYPE_FLOAT) ? fp->decimals() : 0;
+ crp = crp->Next; // Scale
+ crp->Kdata->SetValue(prec, i);
+
+ crp = crp->Next; // Radix
+ crp->Kdata->SetValue(0, i);
+
+ crp = crp->Next; // Nullable
+ crp->Kdata->SetValue((fp->null_ptr != 0) ? 1 : 0, i);
+
+ crp = crp->Next; // Remark
+ fld = fp->comment.str;
+ crp->Kdata->SetValue(fld, fp->comment.length, i);
+
+ crp = crp->Next; // New
+ crp->Kdata->SetValue((fmt) ? fmt : (char*) "", i);
+
+ crp = crp->Next; // New (charset)
+ fld = (char *)fp->charset()->name;
+ crp->Kdata->SetValue(fld, i);
+
+ // Add this item
+ qrp->Nblin++;
+ } // endfor field
+
+ /**********************************************************************/
+ /* Return the result pointer for use by GetData routines. */
+ /**********************************************************************/
+ free_table_share(s);
+ return qrp;
+ } // end of TabColumns
+
+/* -------------- Implementation of the XCOL classes ---------------- */
+
+/***********************************************************************/
+/* PRXDEF constructor. */
+/***********************************************************************/
+PRXDEF::PRXDEF(void)
+ {
+ Tablep = NULL;
+ Pseudo = 3;
+} // end of PRXDEF constructor
+
+/***********************************************************************/
+/* DefineAM: define specific AM block values from XCOL file. */
+/***********************************************************************/
+bool PRXDEF::DefineAM(PGLOBAL g, LPCSTR am, int poff)
+ {
+ char *pn, *db, *tab;
+
+ db = Cat->GetStringCatInfo(g, "Dbname", "*");
+ tab = Cat->GetStringCatInfo(g, "Tabname", NULL);
+
+ // Analyze the table name, it may have the format: [dbname.]tabname
+ if ((pn = strchr(tab, '.'))) {
+ *pn++ = 0;
+ db = tab;
+ tab = pn;
+ } // endif pn
+
+ Tablep = new(g) XTAB(tab);
+ Tablep->SetQualifier(db);
+ return FALSE;
+ } // end of DefineAM
+
+/***********************************************************************/
+/* GetTable: makes a new TDB of the proper type. */
+/***********************************************************************/
+PTDB PRXDEF::GetTable(PGLOBAL g, MODE mode)
+ {
+ if (Catfunc == FNC_COL)
+ return new(g) TDBTBC(this);
+ else
+ return new(g) TDBPRX(this);
+
+ } // end of GetTable
+
+/* ------------------------------------------------------------------- */
+
+/***********************************************************************/
+/* Implementation of the TDBPRX class. */
+/***********************************************************************/
+TDBPRX::TDBPRX(PPRXDEF tdp) : TDBASE(tdp)
+ {
+ Tdbp = NULL; // The object table
+ } // end of TDBPRX constructor
+
+/***********************************************************************/
+/* Get the PTDB of the sub-table. */
+/***********************************************************************/
+PTDB TDBPRX::GetSubTable(PGLOBAL g, PTABLE tabp)
+ {
+ char *db, *name;
+ bool mysql;
+ PTDB tdbp = NULL;
+ TABLE_SHARE *s;
+ PCATLG cat = To_Def->GetCat();
+ PHC hc = ((MYCAT*)cat)->GetHandler();
+ THD *thd = (hc->GetTable())->in_use;
+
+ db = (char*)tabp->GetQualifier();
+ name = (char*)tabp->GetName();
+
+ if (!(s = GetTableShare(g, thd, db, name, mysql)))
+ return NULL;
+
+ hc->tshp = s;
+
+ if (mysql) {
+#if defined(MYSQL_SUPPORT)
+ // Access sub-table via MySQL API
+ if (!(tdbp= cat->GetTable(g, tabp, MODE_READ, "MYSQL"))) {
+ sprintf(g->Message, "Cannot access %s.%s", db, name);
+ goto err;
+ } // endif Define
+
+ if (db)
+ ((PTDBMY)tdbp)->SetDatabase(tabp->GetQualifier());
+
+#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
+ tdbp = cat->GetTable(g, tabp);
+
+ hc->tshp = NULL;
+
+ if (trace && tdbp)
+ htrc("Subtable %s in %s\n",
+ name, SVP(((PTDBASE)tdbp)->GetDef()->GetDB()));
+
+ err:
+ free_table_share(s);
+ return tdbp;
+ } // end of GetSubTable
+
+/***********************************************************************/
+/* Initializes the table. */
+/***********************************************************************/
+bool TDBPRX::InitTable(PGLOBAL g)
+ {
+ if (!Tdbp) {
+ // Get the table description block of this table
+ if (!(Tdbp = (PTDBASE)GetSubTable(g, ((PPRXDEF)To_Def)->Tablep)))
+ return TRUE;
+
+ } // endif Tdbp
+
+ return FALSE;
+ } // end of InitTable
+
+/***********************************************************************/
+/* Allocate PRX column description block. */
+/***********************************************************************/
+PCOL TDBPRX::MakeCol(PGLOBAL g, PCOLDEF cdp, PCOL cprec, int n)
+ {
+ return new(g) PRXCOL(cdp, this, cprec, n);
+ } // end of MakeCol
+
+/***********************************************************************/
+/* PRX GetMaxSize: returns the maximum number of rows in the table. */
+/***********************************************************************/
+int TDBPRX::GetMaxSize(PGLOBAL g)
+ {
+ if (MaxSize < 0) {
+ if (InitTable(g))
+ return NULL;
+
+ MaxSize = Tdbp->GetMaxSize(g);
+ } // endif MaxSize
+
+ return MaxSize;
+ } // end of GetMaxSize
+
+/***********************************************************************/
+/* In this sample, ROWID will be the (virtual) row number, */
+/* while ROWNUM will be the occurence rank in the multiple column. */
+/***********************************************************************/
+int TDBPRX::RowNumber(PGLOBAL g, bool b)
+ {
+ return Tdbp->RowNumber(g, b);
+ } // end of RowNumber
+
+/***********************************************************************/
+/* XCV Access Method opening routine. */
+/***********************************************************************/
+bool TDBPRX::OpenDB(PGLOBAL g)
+ {
+ if (Use == USE_OPEN) {
+ /*******************************************************************/
+ /* Table already open, just replace it at its beginning. */
+ /*******************************************************************/
+ return Tdbp->OpenDB(g);
+ } // endif use
+
+ if (Mode != MODE_READ) {
+ /*******************************************************************/
+ /* Currently XCOL tables cannot be modified. */
+ /*******************************************************************/
+ strcpy(g->Message, "PROXY tables are read only");
+ return TRUE;
+ } // endif Mode
+
+ if (InitTable(g))
+ return NULL;
+
+ /*********************************************************************/
+ /* Check and initialize the subtable columns. */
+ /*********************************************************************/
+ for (PCOL cp = Columns; cp; cp = cp->GetNext())
+ if (((PPRXCOL)cp)->Init(g))
+ return TRUE;
+
+ /*********************************************************************/
+ /* Physically open the object table. */
+ /*********************************************************************/
+ if (Tdbp->OpenDB(g))
+ return TRUE;
+
+ return FALSE;
+ } // end of OpenDB
+
+/***********************************************************************/
+/* Data Base read routine for XCV access method. */
+/***********************************************************************/
+int TDBPRX::ReadDB(PGLOBAL g)
+ {
+ /*********************************************************************/
+ /* Now start the reading process. */
+ /*********************************************************************/
+ return Tdbp->ReadDB(g);
+ } // end of ReadDB
+
+/***********************************************************************/
+/* WriteDB: Data Base write routine for XCV access methods. */
+/***********************************************************************/
+int TDBPRX::WriteDB(PGLOBAL g)
+ {
+ sprintf(g->Message, "%s tables are read only", To_Def->GetType());
+ return RC_FX;
+ } // end of WriteDB
+
+/***********************************************************************/
+/* Data Base delete line routine for XCV access methods. */
+/***********************************************************************/
+int TDBPRX::DeleteDB(PGLOBAL g, int irc)
+ {
+ sprintf(g->Message, "Delete not enabled for %s tables",
+ To_Def->GetType());
+ return RC_FX;
+ } // end of DeleteDB
+
+/* ---------------------------- PRXCOL ------------------------------- */
+
+/***********************************************************************/
+/* PRXCOL public constructor. */
+/***********************************************************************/
+PRXCOL::PRXCOL(PCOLDEF cdp, PTDB tdbp, PCOL cprec, int i, PSZ am)
+ : COLBLK(cdp, tdbp, i)
+ {
+ if (cprec) {
+ Next = cprec->GetNext();
+ cprec->SetNext(this);
+ } else {
+ Next = tdbp->GetColumns();
+ tdbp->SetColumns(this);
+ } // endif cprec
+
+ // Set additional Dos access method information for column.
+ Long = cdp->GetLong(); // Useful ???
+//strcpy(F_Date, cdp->F_Date);
+ Colp = NULL;
+ To_Val = NULL;
+ Pseudo = FALSE;
+ Colnum = cdp->GetOffset(); // If columns are retrieved by number
+
+ if (trace)
+ htrc(" making new %sCOL C%d %s at %p\n", am, Index, Name, this);
+
+ } // end of PRXCOL constructor
+
+/***********************************************************************/
+/* PRXCOL initialization routine. */
+/* Look for the matching column in the object table. */
+/***********************************************************************/
+bool PRXCOL::Init(PGLOBAL g)
+ {
+ PTDBPRX tdbp = (PTDBPRX)To_Tdb;
+
+ if (!(Colp = tdbp->Tdbp->ColDB(g, Name, 0)) && Colnum)
+ Colp = tdbp->Tdbp->ColDB(g, NULL, Colnum);
+
+ if (Colp) {
+ Colp->InitValue(g); // May not have been done elsewhere
+ To_Val = Colp->GetValue();
+ } else {
+ sprintf(g->Message, MSG(NO_MATCHING_COL), Name, tdbp->Tdbp->GetName());
+ return TRUE;
+ } // endif Colp
+
+ return FALSE;
+ } // end of Init
+
+/***********************************************************************/
+/* ReadColumn: */
+/***********************************************************************/
+void PRXCOL::ReadColumn(PGLOBAL g)
+ {
+ if (trace)
+ htrc("PRX ReadColumn: name=%s\n", Name);
+
+ if (Colp) {
+ Colp->ReadColumn(g);
+ Value->SetValue_pval(To_Val);
+
+ // Set null when applicable
+ if (Nullable)
+ Value->SetNull(Value->IsNull());
+
+ } // endif Colp
+
+ } // end of ReadColumn
+
+#if 0
+/* ---------------------------TBCDEF class --------------------------- */
+
+/***********************************************************************/
+/* DefineAM: define specific AM block values from CATLG table. */
+/***********************************************************************/
+bool TBCDEF::DefineAM(PGLOBAL g, LPCSTR am, int poff)
+ {
+ Desc = "Catalog Table";
+ Database = Cat->GetStringCatInfo(g, "Database", "*");
+ Tabname = Cat->GetStringCatInfo(g, "Tabname", Tabname);
+ return FALSE;
+ } // end of DefineAM
+
+/***********************************************************************/
+/* GetTable: makes a new TDB of the proper type. */
+/***********************************************************************/
+PTDB TBCDEF::GetTable(PGLOBAL g, MODE m)
+ {
+ return new(g) TDBTBC(this);
+ } // end of GetTable
+#endif // 0
+
+/* ---------------------------TDBTBC class --------------------------- */
+
+/***********************************************************************/
+/* TDBTBC class constructor. */
+/***********************************************************************/
+TDBTBC::TDBTBC(PPRXDEF tdp) : TDBCAT(tdp)
+ {
+// Db = tdp->Database;
+// Tab = tdp->Tabname;
+ Db = (PSZ)tdp->Tablep->GetQualifier();
+ Tab = (PSZ)tdp->Tablep->GetName();
+ } // end of TDBTBC constructor
+
+#if 0
+/***********************************************************************/
+/* TDBTBC class constructor from TBL table. */
+/***********************************************************************/
+TDBTBC::TDBTBC(PTBLDEF tdp) : TDBCAT(tdp)
+ {
+ Db = tdp->To_Tables->DB;
+ Tab = tdp->To_Tables->Name;
+ } // end of TDBTBC constructor
+
+/***********************************************************************/
+/* TDBTBC class constructor from PRX table. */
+/***********************************************************************/
+TDBTBC::TDBTBC(PXCLDEF tdp) : TDBCAT(tdp)
+ {
+ Db = (PSZ)tdp->Tablep->GetQualifier();
+ Tab = (PSZ)tdp->Tablep->GetName();
+ } // end of TDBTBC constructor
+#endif // 0
+
+/***********************************************************************/
+/* GetResult: Get the list the MYSQL table columns. */
+/***********************************************************************/
+PQRYRES TDBTBC::GetResult(PGLOBAL g)
+ {
+ return TabColumns(g, current_thd, Db, Tab, false);
+ } // end of GetResult
+
diff --git a/storage/connect/tabutil.h b/storage/connect/tabutil.h
new file mode 100644
index 00000000000..48e97bd49ec
--- /dev/null
+++ b/storage/connect/tabutil.h
@@ -0,0 +1,181 @@
+// TABUTIL.H Olivier Bertrand 2013
+// Defines the TAB catalog tables
+
+#ifndef TABUTIL
+#define TABUTIL 1
+
+//#include "tabtbl.h"
+
+#define TYPE_AM_PRX (AMT)129
+
+typedef class PRXDEF *PPRXDEF;
+typedef class TDBPRX *PTDBPRX;
+typedef class XXLCOL *PXXLCOL;
+typedef class PRXCOL *PPRXCOL;
+typedef class TBCDEF *PTBCDEF;
+typedef class TDBTBC *PTDBTBC;
+typedef class XTDBASE *PTDBX;
+typedef class XCOLBLK *PCOLX;
+
+TABLE_SHARE *GetTableShare(PGLOBAL g, THD *thd, const char *db,
+ const char *name, bool& mysql);
+PQRYRES TabColumns(PGLOBAL g, THD *thd, const char *db,
+ const char *name, bool info);
+
+/***********************************************************************/
+/* This class is used to access protected members of TDBASE. */
+/***********************************************************************/
+class XTDBASE : public TDBASE {
+ friend class TDBXCL;
+ }; // end of class XCOLBLK
+
+/***********************************************************************/
+/* This class is used to access protected members of COLBLK. */
+/***********************************************************************/
+class XCOLBLK : public COLBLK {
+ friend class TDBXCL;
+ }; // end of class XCOLBLK
+
+/* -------------------------- PROXY classes -------------------------- */
+
+/***********************************************************************/
+/* PROXY: table based on another table. Can be used to have a */
+/* different view on an existing table. */
+/* However, its real use is to be the base of TBL and PRX tables. */
+/***********************************************************************/
+
+/***********************************************************************/
+/* PRX table. */
+/***********************************************************************/
+class DllExport PRXDEF : public TABDEF { /* Logical table description */
+ friend class TDBPRX;
+ friend class TDBTBC;
+ public:
+ // Constructor
+ PRXDEF(void);
+
+ // Implementation
+ virtual const char *GetType(void) {return "PRX";}
+
+ // Methods
+ virtual bool DefineAM(PGLOBAL g, LPCSTR am, int poff);
+ virtual PTDB GetTable(PGLOBAL g, MODE mode);
+
+ protected:
+ // Members
+ PTABLE Tablep; /* The object table */
+ }; // end of PRXDEF
+
+/***********************************************************************/
+/* This is the class declaration for the XCSV table. */
+/***********************************************************************/
+class DllExport TDBPRX : public TDBASE {
+//friend class MULINDX;
+ friend class PRXDEF;
+ friend class PRXCOL;
+ public:
+ // Constructor
+ TDBPRX(PPRXDEF tdp);
+
+ // Implementation
+ virtual AMT GetAmType(void) {return TYPE_AM_PRX;}
+
+ // Methods
+ virtual int GetRecpos(void) {return Tdbp->GetRecpos();}
+ virtual void ResetDB(void) {Tdbp->ResetDB();}
+ virtual int RowNumber(PGLOBAL g, bool b = FALSE);
+
+ // Database routines
+ virtual PCOL MakeCol(PGLOBAL g, PCOLDEF cdp, PCOL cprec, int n);
+ virtual bool InitTable(PGLOBAL g);
+ virtual int GetMaxSize(PGLOBAL g);
+ virtual bool OpenDB(PGLOBAL g);
+ virtual int ReadDB(PGLOBAL g);
+ virtual int WriteDB(PGLOBAL g);
+ virtual int DeleteDB(PGLOBAL g, int irc);
+ virtual void CloseDB(PGLOBAL g) {if (Tdbp) Tdbp->CloseDB(g);}
+ PTDB GetSubTable(PGLOBAL g, PTABLE tabp);
+
+ protected:
+ // Members
+ PTDBASE Tdbp; // The object table
+ }; // end of class TDBPRX
+
+/***********************************************************************/
+/* Class PRXCOL: PRX access method column descriptor. */
+/* This A.M. is used for PRX tables. */
+/***********************************************************************/
+class DllExport PRXCOL : public COLBLK {
+ friend class TDBPRX;
+ friend class TDBTBL;
+ public:
+ // Constructors
+ PRXCOL(PCOLDEF cdp, PTDB tdbp, PCOL cprec, int i, PSZ am = "PRX");
+
+ // Implementation
+ virtual int GetAmType(void) {return TYPE_AM_PRX;}
+
+ // Methods
+ virtual bool IsSpecial(void) {return Pseudo;}
+ virtual void ReadColumn(PGLOBAL g);
+ bool Init(PGLOBAL g);
+
+ protected:
+ // Default constructor not to be used
+ PRXCOL(void) {}
+
+ // Members
+ PCOL Colp; // Points to matching table column
+ PVAL To_Val; // To the matching column value
+ bool Pseudo; // TRUE for special columns
+ int Colnum; // Used when retrieving columns by number
+ }; // end of class PRXCOL
+
+#if 0
+/***********************************************************************/
+/* TBC table. */
+/***********************************************************************/
+class TBCDEF : public TABDEF {/* Logical table description */
+ friend class TDBTBC;
+ friend class ha_connect;
+ public:
+ // Constructor
+ TBCDEF(void) {Database = NULL; Tabname = NULL;}
+
+
+ // Implementation
+ virtual const char *GetType(void) {return "TBC";}
+ inline PSZ GetDatabase(void) {return Database;};
+ inline PSZ GetTabname(void) {return Tabname;}
+
+ // Methods
+ virtual bool DefineAM(PGLOBAL g, LPCSTR am, int poff);
+ virtual PTDB GetTable(PGLOBAL g, MODE m);
+
+ protected:
+ // Members
+ PSZ Database; /* Database to be used by server */
+ PSZ Tabname; /* External table name */
+ }; // end of TBCDEF
+#endif // 0
+
+/***********************************************************************/
+/* This is the class declaration for the TBC column catalog table. */
+/***********************************************************************/
+class TDBTBC : public TDBCAT {
+ public:
+ // Constructors
+ TDBTBC(PPRXDEF tdp);
+//TDBTBC(PTBLDEF tdp);
+//TDBTBC(PXCLDEF tdp);
+
+ protected:
+ // Specific routines
+ virtual PQRYRES GetResult(PGLOBAL g);
+
+ // Members
+ PSZ Db; // Database of the table
+ PSZ Tab; // Table name
+ }; // end of class TDBMCL
+
+#endif // TABUTIL
diff --git a/storage/connect/tabxcl.cpp b/storage/connect/tabxcl.cpp
new file mode 100644
index 00000000000..337a6cefd1d
--- /dev/null
+++ b/storage/connect/tabxcl.cpp
@@ -0,0 +1,376 @@
+/************* TabXcl CPP Declares Source Code File (.CPP) *************/
+/* Name: TABXCL.CPP Version 1.0 */
+/* */
+/* (C) Copyright to the author Olivier BERTRAND 2013 */
+/* */
+/* XCOL: Table having one column containing several values */
+/* comma separated. When creating the table, the name of the X */
+/* column is given by the Name option. */
+/* This first version has one limitation: */
+/* - The X column has the same length than in the physical file. */
+/* This tables produces as many rows for a physical row than the */
+/* number of items in the X column (eventually 0). */
+/***********************************************************************/
+
+/***********************************************************************/
+/* Include relevant section of system dependant header files. */
+/***********************************************************************/
+#include "my_global.h"
+#if defined(WIN32)
+#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 "table.h" // MySQL table definitions
+#include "global.h"
+#include "plgdbsem.h"
+#include "plgcnx.h" // For DB types
+#include "resource.h"
+#include "reldef.h"
+#include "filamtxt.h"
+#include "tabdos.h"
+#include "tabcol.h"
+#include "tabxcl.h"
+#include "xtable.h"
+#if defined(MYSQL_SUPPORT)
+#include "tabmysql.h"
+#endif // MYSQL_SUPPORT
+#include "ha_connect.h"
+#include "mycat.h"
+
+extern "C" int trace;
+
+/* -------------- Implementation of the XCOL classes ---------------- */
+
+/***********************************************************************/
+/* XCLDEF constructor. */
+/***********************************************************************/
+XCLDEF::XCLDEF(void)
+ {
+ Pseudo = 3;
+ Xcol = NULL;
+ Sep = ',';
+ Mult = 10;
+} // end of XCLDEF constructor
+
+/***********************************************************************/
+/* DefineAM: define specific AM block values from XCOL file. */
+/***********************************************************************/
+bool XCLDEF::DefineAM(PGLOBAL g, LPCSTR am, int poff)
+ {
+ char buf[8];
+
+ Xcol = Cat->GetStringCatInfo(g, "Colname", "");
+ Cat->GetCharCatInfo("Separator", ",", buf, sizeof(buf));
+ Sep = (strlen(buf) == 2 && buf[0] == '\\' && buf[1] == 't') ? '\t' : *buf;
+ Mult = Cat->GetIntCatInfo("Mult", 10);
+ return PRXDEF::DefineAM(g, am, poff);
+ } // end of DefineAM
+
+/***********************************************************************/
+/* GetTable: makes a new TDB of the proper type. */
+/***********************************************************************/
+PTDB XCLDEF::GetTable(PGLOBAL g, MODE mode)
+ {
+ if (Catfunc == FNC_COL)
+ return new(g) TDBTBC(this);
+ else
+ return new(g) TDBXCL(this);
+
+ } // end of GetTable
+
+/* ------------------------------------------------------------------- */
+
+/***********************************************************************/
+/* Implementation of the TDBXCL class. */
+/***********************************************************************/
+TDBXCL::TDBXCL(PXCLDEF tdp) : TDBPRX(tdp)
+ {
+//Tdbp = NULL; // The physical table
+ Xcolumn = tdp->Xcol; // CSV column name
+ Xcolp = NULL; // To the XCVCOL column
+ Mult = tdp->Mult; // Multiplication factor
+ N = 0; // The current table index
+ M = 0; // The occurence rank
+ RowFlag = 0; // 0: Ok, 1: Same, 2: Skip
+ New = TRUE; // TRUE for new line
+ Sep = tdp->Sep; // The Xcol separator
+ } // end of TDBXCL constructor
+
+/***********************************************************************/
+/* Initializes the table. */
+/***********************************************************************/
+bool TDBXCL::InitTable(PGLOBAL g)
+ {
+ if (!Tdbp) {
+ PCOLDEF cdp;
+
+ // Get the table description block of this table
+ if (!(Tdbp = (PTDBASE)GetSubTable(g, ((PXCLDEF)To_Def)->Tablep)))
+ return TRUE;
+
+ for (cdp = Tdbp->GetDef()->GetCols(); cdp; cdp = cdp->GetNext())
+ if (!stricmp(cdp->GetName(), Xcolumn))
+ break;
+
+ if (!cdp) {
+ sprintf(g->Message, "%s is not a %s column",
+ Xcolumn, Tdbp->GetName());
+ return TRUE;
+ } // endif cdp
+
+ } // endif Tdbp
+
+ return FALSE;
+ } // end of InitTable
+
+/***********************************************************************/
+/* Allocate XCL column description block. */
+/***********************************************************************/
+PCOL TDBXCL::MakeCol(PGLOBAL g, PCOLDEF cdp, PCOL cprec, int n)
+ {
+ PCOL colp;
+
+ if (!stricmp(cdp->GetName(), Xcolumn)) {
+ Xcolp = new(g) XCLCOL(g, cdp, this, cprec, n);
+ colp = Xcolp;
+ } else
+ colp = new(g) PRXCOL(cdp, this, cprec, n);
+
+ return colp;
+ } // end of MakeCol
+
+/***********************************************************************/
+/* XCL GetMaxSize: returns the maximum number of rows in the table. */
+/***********************************************************************/
+int TDBXCL::GetMaxSize(PGLOBAL g)
+ {
+ if (MaxSize < 0) {
+ if (InitTable(g))
+ return NULL;
+
+ MaxSize = Mult * Tdbp->GetMaxSize(g);
+ } // endif MaxSize
+
+ return MaxSize;
+ } // end of GetMaxSize
+
+/***********************************************************************/
+/* In this sample, ROWID will be the (virtual) row number, */
+/* while ROWNUM will be the occurence rank in the multiple column. */
+/***********************************************************************/
+int TDBXCL::RowNumber(PGLOBAL g, bool b)
+ {
+ return (b) ? M : N;
+ } // end of RowNumber
+
+/***********************************************************************/
+/* XCV Access Method opening routine. */
+/***********************************************************************/
+bool TDBXCL::OpenDB(PGLOBAL g)
+ {
+ if (Use == USE_OPEN) {
+ /*******************************************************************/
+ /* Table already open, just replace it at its beginning. */
+ /*******************************************************************/
+ M = N = 0;
+ RowFlag = 0;
+ New = TRUE;
+ return Tdbp->OpenDB(g);
+ } // endif use
+
+ if (Mode != MODE_READ) {
+ /*******************************************************************/
+ /* Currently XCOL tables cannot be modified. */
+ /*******************************************************************/
+ strcpy(g->Message, "XCOL tables are read only");
+ return TRUE;
+ } // endif Mode
+
+ if (InitTable(g))
+ return NULL;
+
+ /*********************************************************************/
+ /* Check and initialize the subtable columns. */
+ /*********************************************************************/
+ for (PCOL cp = Columns; cp; cp = cp->GetNext())
+ if (((PXCLCOL)cp)->Init(g))
+ return TRUE;
+
+ /*********************************************************************/
+ /* Physically open the object table. */
+ /*********************************************************************/
+ if (Tdbp->OpenDB(g))
+ return TRUE;
+
+#if 0
+ /*********************************************************************/
+ /* Check for direct access. */
+ /*********************************************************************/
+ if (To_Key_Col)
+ if (!Tdbp->GetDef()->Indexable()) {
+ strcpy(g->Message, "Object table is not indexable");
+ return TRUE;
+ } else {
+ ((PTDBX)Tdbp)->To_Key_Col = To_Key_Col;
+ ((PTDBX)Tdbp)->To_Link = To_Link;
+ ((PTDBX)Tdbp)->Knum = Knum;
+ To_Kindex = (PKXBASE)new(g) KINDEX(Tdbp);
+
+ if (To_Kindex->Init(g))
+ return TRUE;
+
+ ((PKINDEX)To_Kindex)->SetMult(Mult);
+ Tdbp->SetKindex(To_Kindex);
+ } // endif Indexable
+#endif // 0
+
+ return FALSE;
+ } // end of OpenDB
+
+/***********************************************************************/
+/* Data Base read routine for XCV access method. */
+/***********************************************************************/
+int TDBXCL::ReadDB(PGLOBAL g)
+ {
+ int rc = RC_OK;
+
+ /*********************************************************************/
+ /* Now start the multi reading process. */
+ /*********************************************************************/
+ do {
+ if (RowFlag != 1) {
+ if ((rc = Tdbp->ReadDB(g)) != RC_OK)
+ break;
+
+ New = TRUE;
+ M = 1;
+ } else {
+ New = FALSE;
+ M++;
+ } // endif RowFlag
+
+ if (Xcolp) {
+ RowFlag = 0;
+ Xcolp->ReadColumn(g);
+ } // endif Xcolp
+
+ N++;
+ } while (RowFlag == 2);
+
+ return rc;
+ } // end of ReadDB
+
+
+// ------------------------ XCLCOL functions ----------------------------
+
+/***********************************************************************/
+/* XCLCOL public constructor. */
+/***********************************************************************/
+XCLCOL::XCLCOL(PGLOBAL g, PCOLDEF cdp, PTDB tdbp, PCOL cprec, int i)
+ : PRXCOL(cdp, tdbp, cprec, i, "XCL")
+ {
+ // Set additional XXL access method information for column.
+ Cbuf = (char*)PlugSubAlloc(g, NULL, Long + 1);
+ Cp = NULL; // Pointer to current position in Cbuf
+ Sep = ((PTDBXCL)tdbp)->Sep;
+ AddStatus(BUF_READ); // Only evaluated from TDBXCL::ReadDB
+ } // end of XCLCOL constructor
+
+/***********************************************************************/
+/* What this routine does is to get the comma-separated string */
+/* from the source table column, extract the single values and */
+/* set the flag for the table ReadDB function. */
+/***********************************************************************/
+void XCLCOL::ReadColumn(PGLOBAL g)
+ {
+ if (((PTDBXCL)To_Tdb)->New) {
+ Colp->ReadColumn(g);
+ strcpy(Cbuf, To_Val->GetCharValue());
+ Cp = Cbuf;
+ } // endif New
+
+ if (*Cp) {
+ PSZ p;
+
+ // Trim left
+ for (p = Cp; *p == ' '; p++) ;
+
+ if ((Cp = strchr(Cp, Sep)))
+ // Separator is found
+ *Cp++ = '\0';
+
+ Value->SetValue_psz(p);
+ } else if (Nullable) {
+ Value->Reset();
+ Value->SetNull(true);
+ } else
+ // Skip that row
+ ((PTDBXCL)To_Tdb)->RowFlag = 2;
+
+ if (Cp && *Cp)
+ // More to come from the same row
+ ((PTDBXCL)To_Tdb)->RowFlag = 1;
+
+ } // end of ReadColumn
+
+#if 0
+/* -------------- Implementation of the MULINDX class ---------------- */
+
+/***********************************************************************/
+/* Returns FALSE if Ok, TRUE if there are no more equal values. */
+/***********************************************************************/
+bool MULINDX::HaveSame(void)
+ {
+ return (Op == OP_SAME || Txlp->RowFlag == 1);
+ } // end of HaveSame
+
+/***********************************************************************/
+/* Returns FALSE if Ok, TRUE if there are no more equal values. */
+/***********************************************************************/
+bool MULINDX::NextVal(bool eq)
+ {
+ return (Pof) ? KINDEX::NextVal(eq) : TRUE;
+ } // end of NextVal
+
+/***********************************************************************/
+/* Returns TRUE if there are more same values. */
+/***********************************************************************/
+bool MULINDX::MoreVal(void)
+ {
+ Op = OP_SAME; // There may be more equal values
+ return (Pof) ? Pof[Val_K] : Val_K;
+ } // end of MoreVal
+
+/***********************************************************************/
+/* Change the index multiple status. */
+/***********************************************************************/
+bool MULINDX::Init(PGLOBAL g)
+ {
+ if (KINDEX::Init(g))
+ return TRUE;
+
+ Mul = TRUE;
+ MaxSame *= Txlp->Mult;
+ return FALSE;
+ } // end of Init
+#endif // 0
diff --git a/storage/connect/tabxcl.h b/storage/connect/tabxcl.h
new file mode 100644
index 00000000000..6db653d5709
--- /dev/null
+++ b/storage/connect/tabxcl.h
@@ -0,0 +1,133 @@
+// TABXCL.H Olivier Bertrand 2013
+// Defines the XCOL tables
+
+#include "tabutil.h"
+
+#define TYPE_AM_XCOL (AMT)124
+
+typedef class XCLDEF *PXCLDEF;
+typedef class TDBXCL *PTDBXCL;
+typedef class XCLCOL *PXCLCOL;
+//pedef class MULINDX *PMINDX;
+
+/* -------------------------- XCOL classes --------------------------- */
+
+/***********************************************************************/
+/* XCOL: table having one column containing several values comma */
+/* (or any other character) separated. When creating the table, the */
+/* name of the X column is given by the NAME option. */
+/* This sample has a limitation: */
+/* - The X column has the same length than in the physical file. */
+/* This tables produces as many rows for a physical row than the */
+/* number of items in the X column (eventually 0). */
+/***********************************************************************/
+
+/***********************************************************************/
+/* XCL table. */
+/***********************************************************************/
+class XCLDEF : public PRXDEF { /* Logical table description */
+ friend class TDBXCL;
+ public:
+ // Constructor
+ XCLDEF(void);
+
+ // Implementation
+ virtual const char *GetType(void) {return "XCL";}
+
+ // Methods
+ virtual bool DefineAM(PGLOBAL g, LPCSTR am, int poff);
+ virtual PTDB GetTable(PGLOBAL g, MODE mode);
+
+ protected:
+ // Members
+ char *Xcol; /* The column containing separated fields */
+ char Sep; /* The field separator, defaults to comma */
+ int Mult; /* Multiplication factor */
+ }; // end of XCLDEF
+
+/***********************************************************************/
+/* This is the class declaration for the XCSV table. */
+/***********************************************************************/
+class TDBXCL : public TDBPRX {
+//friend class MULINDX;
+ friend class XCLDEF;
+ friend class PRXCOL;
+ friend class XCLCOL;
+ public:
+ // Constructor
+ TDBXCL(PXCLDEF tdp);
+
+ // Implementation
+ virtual AMT GetAmType(void) {return TYPE_AM_XCOL;}
+
+ // Methods
+ virtual void ResetDB(void) {N = 0; Tdbp->ResetDB();}
+ virtual int RowNumber(PGLOBAL g, bool b = FALSE);
+//virtual bool HaveSame(void) {return RowFlag == 1;}
+
+ // Database routines
+ virtual PCOL MakeCol(PGLOBAL g, PCOLDEF cdp, PCOL cprec, int n);
+ virtual bool InitTable(PGLOBAL g);
+ virtual int GetMaxSize(PGLOBAL g);
+ virtual bool OpenDB(PGLOBAL g);
+ virtual int ReadDB(PGLOBAL g);
+
+ protected:
+ // Members
+ char *Xcolumn; // Multiple column name
+ PXCLCOL Xcolp; // To the XCVCOL column
+ int Mult; // Multiplication factor
+ int N; // The current table index
+ int M; // The occurence rank
+ BYTE RowFlag; // 0: Ok, 1: Same, 2: Skip
+ BOOL New; // TRUE for new line
+ char Sep; // The Xcol separator
+ }; // end of class TDBXCL
+
+/***********************************************************************/
+/* Class XCLCOL: for the multiple CSV column. */
+/***********************************************************************/
+class XCLCOL : public PRXCOL {
+ friend class TDBXCL;
+ public:
+ // Constructors
+ XCLCOL(PGLOBAL g, PCOLDEF cdp, PTDB tdbp, PCOL cprec, int i);
+
+ // Methods
+ virtual void Reset(void) {} // Evaluated only by TDBXCL
+ virtual void ReadColumn(PGLOBAL g);
+
+ protected:
+ // Default constructor not to be used
+ XCLCOL(void) {}
+
+ // Members
+ char *Cbuf; // The column buffer
+ char *Cp; // Pointer to current position
+ char Sep; // The separator
+ }; // end of class XCLCOL
+
+#if 0
+/* ------------------------- MULINDX classes ------------------------- */
+
+/***********************************************************************/
+/* This represents a KINDEX class for an XCOL table. */
+/***********************************************************************/
+class MULINDX : public KINDEX {
+ public:
+ // Constructor
+ MULINDX(PTDBXCL txlp) : KINDEX(txlp->Tdbp) {Txlp = txlp;}
+
+ // Implementation
+ virtual BOOL HaveSame(void);
+
+ // Methods
+ virtual BOOL Init(PGLOBAL g);
+ virtual BOOL NextVal(BOOL eq);
+ virtual int MoreVal(void);
+
+ protected:
+ //Member
+ PTDBXCL Txlp;
+}; // end of class MULINDX
+#endif // 0
diff --git a/storage/connect/valblk.cpp b/storage/connect/valblk.cpp
index a56841d8980..a96dec2565c 100644
--- a/storage/connect/valblk.cpp
+++ b/storage/connect/valblk.cpp
@@ -266,7 +266,7 @@ char TYPBLK<char>::GetTypedValue(PVAL valp)
{return valp->GetTinyValue();}
/***********************************************************************/
-/* Set one value in a block. */
+/* Set one value in a block from a zero terminated string. */
/***********************************************************************/
template <class TYPE>
void TYPBLK<TYPE>::SetValue(PSZ p, int n)
@@ -295,6 +295,22 @@ template <>
char TYPBLK<char>::GetTypedValue(PSZ p) {return (char)atoi(p);}
/***********************************************************************/
+/* Set one value in a block from an array of characters. */
+/***********************************************************************/
+template <class TYPE>
+void TYPBLK<TYPE>::SetValue(char *sp, uint len, int n)
+ {
+ PGLOBAL& g = Global;
+ PSZ spz = (PSZ)PlugSubAlloc(g, NULL, 0); // Temporary
+
+ if (sp)
+ memcpy(spz, sp, len);
+
+ spz[len] = 0;
+ SetValue(spz, n);
+ } // end of SetValue
+
+/***********************************************************************/
/* Set one value in a block from a value in another block. */
/***********************************************************************/
template <class TYPE>
@@ -552,11 +568,19 @@ void CHRBLK::SetValue(PVAL valp, int n)
} // end of SetValue
/***********************************************************************/
-/* Set one value in a block. */
+/* Set one value in a block from a zero terminated string. */
/***********************************************************************/
void CHRBLK::SetValue(PSZ sp, int n)
{
- size_t len = (sp) ? strlen(sp) : 0;
+ uint len = (sp) ? strlen(sp) : 0;
+ SetValue(sp, len, n);
+ } // end of SetValue
+
+/***********************************************************************/
+/* Set one value in a block from an array of characters. */
+/***********************************************************************/
+void CHRBLK::SetValue(char *sp, uint len, int n)
+ {
char *p = Chrp + n * Long;
#if defined(_DEBUG) || defined(DEBTRACE)
@@ -568,15 +592,16 @@ void CHRBLK::SetValue(PSZ sp, int n)
#endif
if (sp)
- strncpy(p, sp, Long);
- else
- *p = '\0';
+ memcpy(p, sp, len);
- if (Blanks)
+ if (Blanks) {
// Suppress eventual ending zero and right fill with blanks
for (register int i = len; i < Long; i++)
p[i] = ' ';
+ } else if ((signed)len < Long)
+ p[len] = 0;
+
SetNull(n, false);
} // end of SetValue
@@ -801,12 +826,33 @@ void STRBLK::SetValue(PVAL valp, int n)
} // end of SetValue
/***********************************************************************/
-/* Set one value in a block. */
+/* Set one value in a block from a zero terminated string. */
/***********************************************************************/
void STRBLK::SetValue(PSZ p, int n)
{
- Strp[n] = (PSZ)PlugSubAlloc(Global, NULL, strlen(p) + 1);
- strcpy(Strp[n], p);
+ if (p) {
+ Strp[n] = (PSZ)PlugSubAlloc(Global, NULL, strlen(p) + 1);
+ strcpy(Strp[n], p);
+ } else
+ Strp[n] = NULL;
+
+ } // end of SetValue
+
+/***********************************************************************/
+/* Set one value in a block from an array of characters. */
+/***********************************************************************/
+void STRBLK::SetValue(char *sp, uint len, int n)
+ {
+ PSZ p;
+
+ if (sp) {
+ p = (PSZ)PlugSubAlloc(Global, NULL, len + 1);
+ memcpy(p, sp, len);
+ p[len] = 0;
+ } else
+ p = NULL;
+
+ Strp[n] = p;
} // end of SetValue
/***********************************************************************/
diff --git a/storage/connect/valblk.h b/storage/connect/valblk.h
index 9a85577a104..a7b1b5046d7 100644
--- a/storage/connect/valblk.h
+++ b/storage/connect/valblk.h
@@ -64,6 +64,7 @@ class VALBLK : public BLOCK {
virtual void SetValue(double fval, int n) {assert(false);}
virtual void SetValue(char cval, int n) {assert(false);}
virtual void SetValue(PSZ sp, int n) {assert(false);}
+ virtual void SetValue(char *sp, uint len, int n) {assert(false);}
virtual void SetValue(PVAL valp, int n) = 0;
virtual void SetValue(PVBLK pv, int n1, int n2) = 0;
#if 0
@@ -120,6 +121,7 @@ class TYPBLK : public VALBLK {
// Methods
virtual void SetValue(PSZ sp, int n);
+ virtual void SetValue(char *sp, uint len, int n);
virtual void SetValue(short sval, int n)
{Typp[n] = (TYPE)sval; SetNull(n, false);}
virtual void SetValue(int lval, int n)
@@ -175,6 +177,7 @@ class CHRBLK : public VALBLK {
// Methods
virtual void SetValue(PSZ sp, int n);
+ virtual void SetValue(char *sp, uint len, int n);
virtual void SetValue(PVAL valp, int n);
virtual void SetValue(PVBLK pv, int n1, int n2);
//virtual void SetValues(PVBLK pv, int k, int n);
@@ -221,6 +224,7 @@ class STRBLK : public VALBLK {
// Methods
virtual void SetValue(PSZ sp, int n);
+ virtual void SetValue(char *sp, uint len, int n);
virtual void SetValue(PVAL valp, int n);
virtual void SetValue(PVBLK pv, int n1, int n2);
//virtual void SetValues(PVBLK pv, int k, int n);