diff options
Diffstat (limited to 'storage')
-rw-r--r-- | storage/connect/CMakeLists.txt | 4 | ||||
-rw-r--r-- | storage/connect/ha_connect.cc | 252 | ||||
-rw-r--r-- | storage/connect/ha_connect.h | 58 | ||||
-rw-r--r-- | storage/connect/mycat.cc | 20 | ||||
-rw-r--r-- | storage/connect/myconn.cpp | 4 | ||||
-rw-r--r-- | storage/connect/mysql-test/connect/r/xml.result | 2 | ||||
-rw-r--r-- | storage/connect/plgdbsem.h | 14 | ||||
-rw-r--r-- | storage/connect/tabmysql.cpp | 12 | ||||
-rw-r--r-- | storage/connect/taboccur.cpp | 375 | ||||
-rw-r--r-- | storage/connect/taboccur.h | 145 | ||||
-rw-r--r-- | storage/connect/tabtbl.cpp | 166 | ||||
-rw-r--r-- | storage/connect/tabtbl.h | 49 | ||||
-rw-r--r-- | storage/connect/tabutil.cpp | 596 | ||||
-rw-r--r-- | storage/connect/tabutil.h | 181 | ||||
-rw-r--r-- | storage/connect/tabxcl.cpp | 376 | ||||
-rw-r--r-- | storage/connect/tabxcl.h | 133 | ||||
-rw-r--r-- | storage/connect/valblk.cpp | 66 | ||||
-rw-r--r-- | storage/connect/valblk.h | 4 |
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); |