From 4fd74200dd8ff357b7f870ea0407ef8f3c78ff11 Mon Sep 17 00:00:00 2001 From: Olivier Bertrand Date: Mon, 29 Apr 2013 13:50:20 +0200 Subject: [PATCH 01/47] - Adding 3 new table types: PROXY table base on another table. Used by several other types. XCOL proxy on a table having a colummn containing a list of values OCCUR proxy on a table having several columns containing the same type of values that can be put in a unique column and several rows. TBL Not new but now internally using the PROXY table class. - Fix 2 bugs in add_field: Change '=' to ' ' after the COMMENT keyword. Quote column names between '`' in the SQL string. - Update xml test result to the CONNECT version added: storage/connect/taboccur.cpp storage/connect/taboccur.h storage/connect/tabutil.cpp storage/connect/tabutil.h storage/connect/tabxcl.cpp storage/connect/tabxcl.h modified: storage/connect/CMakeLists.txt storage/connect/ha_connect.cc storage/connect/ha_connect.h storage/connect/mycat.cc storage/connect/myconn.cpp storage/connect/mysql-test/connect/r/xml.result storage/connect/plgdbsem.h storage/connect/tabmysql.cpp storage/connect/tabtbl.cpp storage/connect/tabtbl.h storage/connect/valblk.cpp storage/connect/valblk.h --- storage/connect/CMakeLists.txt | 4 +- storage/connect/ha_connect.cc | 252 +++++--- storage/connect/ha_connect.h | 58 +- storage/connect/mycat.cc | 20 +- storage/connect/myconn.cpp | 4 + .../connect/mysql-test/connect/r/xml.result | 2 +- storage/connect/plgdbsem.h | 14 +- storage/connect/tabmysql.cpp | 12 +- storage/connect/taboccur.cpp | 375 +++++++++++ storage/connect/taboccur.h | 145 +++++ storage/connect/tabtbl.cpp | 166 +++-- storage/connect/tabtbl.h | 49 +- storage/connect/tabutil.cpp | 596 ++++++++++++++++++ storage/connect/tabutil.h | 181 ++++++ storage/connect/tabxcl.cpp | 376 +++++++++++ storage/connect/tabxcl.h | 133 ++++ storage/connect/valblk.cpp | 66 +- storage/connect/valblk.h | 4 + 18 files changed, 2211 insertions(+), 246 deletions(-) create mode 100644 storage/connect/taboccur.cpp create mode 100644 storage/connect/taboccur.h create mode 100644 storage/connect/tabutil.cpp create mode 100644 storage/connect/tabutil.h create mode 100644 storage/connect/tabxcl.cpp create mode 100644 storage/connect/tabxcl.h 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) - + ÀÁÂÃ 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 +#include +#if defined(__BORLANDC__) +#define __MFC_COMPAT__ // To define min/max as macro +#endif +//#include +#else +#if defined(UNIX) +#include +#include +#include +#include +#include +#include "osutil.h" +#else +//#include +#endif +//#include +#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; + if (Catfunc == FNC_COL) + return new(g) TDBTBC(this); + else + return new(g) TDBTBL(this); - /*********************************************************************/ - /* Allocate a TDB of the proper type. */ - /* Column blocks will be allocated only when needed. */ - /*********************************************************************/ - tdbp = 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); +//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 (!(s = GetTableShare(g, thd, db, tblp->Name, mysql))) + if (!(s = GetTableShare(g, thd, tblp->DB, tblp->Name, mysql))) + return NULL; - if (!(s = alloc_table_share(db, tblp->Name, key, ++k))) { - strcpy(g->Message, "Error allocating share\n"); - return NULL; - } // endif s - - 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 +#include +#if defined(__BORLANDC__) +#define __MFC_COMPAT__ // To define min/max as macro +#endif +//#include +#else +#if defined(UNIX) +#include +#include +#include +#include +#include +#include "osutil.h" +#else +//#include +#endif +//#include +#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 +#include +#if defined(__BORLANDC__) +#define __MFC_COMPAT__ // To define min/max as macro +#endif +//#include +#else +#if defined(UNIX) +#include +#include +#include +#include +#include +#include "osutil.h" +#else +//#include +#endif +//#include +#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::GetTypedValue(PVAL valp) {return valp->GetTinyValue();} /***********************************************************************/ -/* Set one value in a block. */ +/* Set one value in a block from a zero terminated string. */ /***********************************************************************/ template void TYPBLK::SetValue(PSZ p, int n) @@ -294,6 +294,22 @@ double TYPBLK::GetTypedValue(PSZ p) {return atof(p);} template <> char TYPBLK::GetTypedValue(PSZ p) {return (char)atoi(p);} +/***********************************************************************/ +/* Set one value in a block from an array of characters. */ +/***********************************************************************/ +template +void TYPBLK::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. */ /***********************************************************************/ @@ -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); From 2a37f3e0308062f393decee9ab6935fb45f8be52 Mon Sep 17 00:00:00 2001 From: Olivier Bertrand Date: Mon, 29 Apr 2013 17:47:23 +0200 Subject: [PATCH 02/47] - Fix a bug causing a crash when using OEM tables based on BIN tables. modified: storage/connect/reldef.cpp --- storage/connect/reldef.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/storage/connect/reldef.cpp b/storage/connect/reldef.cpp index 77f2f43ec31..6d16dcde04a 100644 --- a/storage/connect/reldef.cpp +++ b/storage/connect/reldef.cpp @@ -304,7 +304,7 @@ PTDB OEMDEF::GetTable(PGLOBAL g, MODE mode) else txfp = new(g) DOSFAM(defp); - } else if (rfm == RECFM_FIX || rfm == RECFM_FIX) { + } else if (rfm == RECFM_FIX || rfm == RECFM_BIN) { if (map) txfp = new(g) MPXFAM(defp); else From 7461d8e30c085ec4936959ebd21c7ff07ba268e5 Mon Sep 17 00:00:00 2001 From: Olivier Bertrand Date: Tue, 30 Apr 2013 16:16:32 +0200 Subject: [PATCH 03/47] - Allow PROXY based tables to specify MySQL access parameters when the object table is not a CONNECT table. This was the case in previous versions but was no more possible with recent changes. modified: storage/connect/mycat.cc storage/connect/tabmysql.cpp storage/connect/tabutil.cpp --- storage/connect/mycat.cc | 1 + storage/connect/tabmysql.cpp | 8 ++++++++ storage/connect/tabutil.cpp | 11 ++++++++++- 3 files changed, 19 insertions(+), 1 deletion(-) diff --git a/storage/connect/mycat.cc b/storage/connect/mycat.cc index 5a7f53977c7..b46c014fba6 100644 --- a/storage/connect/mycat.cc +++ b/storage/connect/mycat.cc @@ -120,6 +120,7 @@ TABTYPE GetTypeID(const char *type) #endif #ifdef MYSQL_SUPPORT : (!stricmp(type, "MYSQL")) ? TAB_MYSQL + : (!stricmp(type, "MYPRX")) ? TAB_MYSQL #endif : (!stricmp(type, "DIR")) ? TAB_DIR #ifdef WIN32 diff --git a/storage/connect/tabmysql.cpp b/storage/connect/tabmysql.cpp index 495324b74f7..2af1055e8e1 100644 --- a/storage/connect/tabmysql.cpp +++ b/storage/connect/tabmysql.cpp @@ -65,6 +65,9 @@ void PrintResult(PGLOBAL, PSEM, PQRYRES); extern "C" int trace; extern MYSQL_PLUGIN_IMPORT uint mysqld_port; +// This function is located in tabutil.cpp +void Remove_tshp(PCATLG cat); + /* -------------- Implementation of the MYSQLDEF class --------------- */ /***********************************************************************/ @@ -280,6 +283,11 @@ bool MYSQLDEF::DefineAM(PGLOBAL g, LPCSTR am, int poff) Desc = "MySQL Table"; + if (!stricmp(am, "MYPRX")) + // MYSQL access from a PROXY table, + // we must get parms from the calling table + Remove_tshp(Cat); + if (!url || !*url) { // Not using the connection URL Hostname = Cat->GetStringCatInfo(g, "Host", "localhost"); diff --git a/storage/connect/tabutil.cpp b/storage/connect/tabutil.cpp index 5706ca7aeba..76885aeedce 100644 --- a/storage/connect/tabutil.cpp +++ b/storage/connect/tabutil.cpp @@ -56,6 +56,15 @@ extern "C" int trace; +/************************************************************************/ +/* Used by MYSQL tables to get MySQL parameters from the calling proxy */ +/* table (PROXY, TBL, XCL, or OCCUR) when used by one of these. */ +/************************************************************************/ +void Remove_tshp(PCATLG cat) +{ + ((MYCAT*)cat)->GetHandler()->tshp = NULL; +} // end of Remove_thsp + /************************************************************************/ /* GetTableShare: allocates and open a table share. */ /************************************************************************/ @@ -315,7 +324,7 @@ PTDB TDBPRX::GetSubTable(PGLOBAL g, PTABLE tabp) if (mysql) { #if defined(MYSQL_SUPPORT) // Access sub-table via MySQL API - if (!(tdbp= cat->GetTable(g, tabp, MODE_READ, "MYSQL"))) { + if (!(tdbp= cat->GetTable(g, tabp, MODE_READ, "MYPRX"))) { sprintf(g->Message, "Cannot access %s.%s", db, name); goto err; } // endif Define From 3d4adc3fdfa1238efb9cd1b6335a397527c24da2 Mon Sep 17 00:00:00 2001 From: Olivier Bertrand Date: Tue, 30 Apr 2013 17:48:18 +0200 Subject: [PATCH 04/47] - Change in connect_assisted_discovery the default value for port from MYSQL_PORT to 0. So it can be later set to mysqld_port if necessary. Doing so, it is no more required to specify port when using the current port and the current port is not equal to MYSQL_PORT (3306) modified: storage/connect/ha_connect.cc --- storage/connect/ha_connect.cc | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/storage/connect/ha_connect.cc b/storage/connect/ha_connect.cc index 99f81905f0c..b2303b07de8 100644 --- a/storage/connect/ha_connect.cc +++ b/storage/connect/ha_connect.cc @@ -3333,7 +3333,7 @@ static int connect_assisted_discovery(handlerton *hton, THD* thd, 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; + port= (prt) ? atoi(prt) : 0; #if defined(WIN32) nsp= GetListOption(g,"namespace", topt->oplist); cls= GetListOption(g,"class", topt->oplist); From f3e944099e1d7369bbf84e0b1087b45506279034 Mon Sep 17 00:00:00 2001 From: Olivier Bertrand Date: Thu, 2 May 2013 16:33:15 +0200 Subject: [PATCH 05/47] - Adding a loop test to prevent PROXY based table to loop when repointing on itself. - Fix bug causing PROXY on non CONNECT tables to sometimes use the wrong DB. - Making some more tests in create that were in pre_create not called anymore when columns are defined. - Updating some test results to reflect new warnings. modified: storage/connect/ha_connect.cc storage/connect/mysql-test/connect/r/tbl.result storage/connect/mysql-test/connect/r/upd.result storage/connect/tabcol.h storage/connect/tabmysql.cpp storage/connect/taboccur.cpp storage/connect/taboccur.h storage/connect/tabtbl.cpp storage/connect/tabtbl.h storage/connect/tabutil.cpp storage/connect/tabutil.h storage/connect/tabxcl.cpp storage/connect/tabxcl.h --- storage/connect/ha_connect.cc | 60 ++-- .../connect/mysql-test/connect/r/tbl.result | 3 + .../connect/mysql-test/connect/r/upd.result | 6 + storage/connect/tabcol.h | 3 +- storage/connect/tabmysql.cpp | 33 ++- storage/connect/taboccur.cpp | 65 ++-- storage/connect/taboccur.h | 6 +- storage/connect/tabtbl.cpp | 277 +----------------- storage/connect/tabtbl.h | 47 --- storage/connect/tabutil.cpp | 28 +- storage/connect/tabutil.h | 1 + storage/connect/tabxcl.cpp | 65 ---- storage/connect/tabxcl.h | 28 -- 13 files changed, 132 insertions(+), 490 deletions(-) diff --git a/storage/connect/ha_connect.cc b/storage/connect/ha_connect.cc index b2303b07de8..7422815223f 100644 --- a/storage/connect/ha_connect.cc +++ b/storage/connect/ha_connect.cc @@ -3392,21 +3392,6 @@ static int connect_assisted_discovery(handlerton *hton, THD* thd, } // 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) case TAB_ODBC: @@ -3758,7 +3743,8 @@ int ha_connect::create(const char *name, TABLE *table_arg, Field *fp; TABTYPE type; TABLE *st= table; // Probably unuseful - xp= GetUser(ha_thd(), xp); + THD *thd= ha_thd(); + xp= GetUser(thd, xp); PGLOBAL g= xp->g; DBUG_ENTER("ha_connect::create"); @@ -3768,7 +3754,27 @@ int ha_connect::create(const char *name, TABLE *table_arg, DBUG_ASSERT(options); type= GetTypeID(options->type); - if (check_privileges(ha_thd(), options)) + // Check table type + if (type == TAB_UNDEF) { + if (!options->tabname) { + strcpy(g->Message, "No table_type. Will be set to DOS"); + push_warning(thd, MYSQL_ERROR::WARN_LEVEL_WARN, 0, g->Message); + type= TAB_DOS; + options->type= "DOS"; + } else { + strcpy(g->Message, "No table_type. Will be set to PROXY"); + push_warning(thd, MYSQL_ERROR::WARN_LEVEL_WARN, 0, g->Message); + type= TAB_PRX; + options->type= "PROXY"; + } // endif fnc + + } else if (type == TAB_NIY) { + sprintf(g->Message, "Unsupported table type %s", options->type); + my_message(ER_UNKNOWN_ERROR, g->Message, MYF(0)); + DBUG_RETURN(HA_ERR_INTERNAL_ERROR); + } // endif ttp + + if (check_privileges(thd, options)) DBUG_RETURN(HA_ERR_INTERNAL_ERROR); if (options->data_charset) { @@ -3795,6 +3801,21 @@ int ha_connect::create(const char *name, TABLE *table_arg, } else dbf= (GetTypeID(options->type) == TAB_DBF && !options->catfunc); + // Check whether a table is defined on itself + switch (type) { + case TAB_PRX: + case TAB_XCL: + case TAB_OCCUR: + if (!stricmp(options->tabname, create_info->alias) && + (!options->dbname || !stricmp(options->dbname, thd->db))) { + sprintf(g->Message, "A %s table cannot refer to itself", + options->type); + my_message(ER_UNKNOWN_ERROR, g->Message, MYF(0)); + return HA_ERR_INTERNAL_ERROR; + } // endif tab + + } // endswitch ttp + if (type == TAB_XML) { bool dom; // True: MS-DOM, False libxml2 char *xsup= GetListOption(g, "Xmlsup", options->oplist, "*"); @@ -3964,8 +3985,7 @@ int ha_connect::create(const char *name, TABLE *table_arg, strcat(strcat(buf, "."), lwt); sprintf(g->Message, "No file name. Table will use %s", buf); - push_warning(table->in_use, - MYSQL_ERROR::WARN_LEVEL_WARN, 0, g->Message); + push_warning(thd, MYSQL_ERROR::WARN_LEVEL_WARN, 0, g->Message); strcat(strcat(strcpy(dbpath, "./"), table->s->db.str), "/"); PlugSetPath(fn, buf, dbpath); @@ -3994,7 +4014,7 @@ int ha_connect::create(const char *name, TABLE *table_arg, // We should be in CREATE TABLE if (table->in_use->lex->sql_command != SQLCOM_CREATE_TABLE) - push_warning(table->in_use, MYSQL_ERROR::WARN_LEVEL_WARN, 0, + push_warning(thd, MYSQL_ERROR::WARN_LEVEL_WARN, 0, "Wrong command in create, please contact CONNECT team"); // Get the index definitions diff --git a/storage/connect/mysql-test/connect/r/tbl.result b/storage/connect/mysql-test/connect/r/tbl.result index 01a6afcebe8..bc77516c22d 100644 --- a/storage/connect/mysql-test/connect/r/tbl.result +++ b/storage/connect/mysql-test/connect/r/tbl.result @@ -4,6 +4,9 @@ CREATE TABLE t1 ( a INT NOT NULL, message CHAR(10)) ENGINE=connect; +Warnings: +Warning 1105 No table_type. Will be set to DOS +Warning 1105 No file name. Table will use t1.dos INSERT INTO t1 VALUES (1,'Testing'),(2,'dos table'),(3,'t1'); SELECT * FROM t1; a message diff --git a/storage/connect/mysql-test/connect/r/upd.result b/storage/connect/mysql-test/connect/r/upd.result index 24cfdafaa9a..fa519c4b688 100644 --- a/storage/connect/mysql-test/connect/r/upd.result +++ b/storage/connect/mysql-test/connect/r/upd.result @@ -59,6 +59,9 @@ END// # Testing DOS table changes # CREATE TABLE t1 ENGINE=connect AS SELECT * FROM employee; +Warnings: +Warning 1105 No table_type. Will be set to DOS +Warning 1105 No file name. Table will use t1.dos CALL test.tst_up(); serialno name sex title manager department secretary salary 74200 BANCROFT 2 SALESMAN 70012 0318 24888 9600.00 @@ -154,6 +157,9 @@ serialno name sex title manager department secretary salary # Testing DOS table changes # CREATE TABLE t1 ENGINE=connect mapped=yes AS SELECT * FROM employee; +Warnings: +Warning 1105 No table_type. Will be set to DOS +Warning 1105 No file name. Table will use t1.dos CALL test.tst_up(); serialno name sex title manager department secretary salary 74200 BANCROFT 2 SALESMAN 70012 0318 24888 9600.00 diff --git a/storage/connect/tabcol.h b/storage/connect/tabcol.h index 5cc2050f872..8c21fe6d1b2 100644 --- a/storage/connect/tabcol.h +++ b/storage/connect/tabcol.h @@ -15,7 +15,8 @@ /***********************************************************************/ /* Definition of class XTAB with all its method functions. */ /***********************************************************************/ - class DllExport XTAB: public BLOCK { // Table Name-Owner-Correl block. +class DllExport XTAB: public BLOCK { // Table Name-Owner-Correl block. + friend class TDBPRX; public: // Constructors XTAB(LPCSTR name, LPCSTR correl = NULL); diff --git a/storage/connect/tabmysql.cpp b/storage/connect/tabmysql.cpp index 2af1055e8e1..b3401530c1b 100644 --- a/storage/connect/tabmysql.cpp +++ b/storage/connect/tabmysql.cpp @@ -283,25 +283,36 @@ bool MYSQLDEF::DefineAM(PGLOBAL g, LPCSTR am, int poff) Desc = "MySQL Table"; - if (!stricmp(am, "MYPRX")) - // MYSQL access from a PROXY table, - // we must get parms from the calling table - Remove_tshp(Cat); + if (!stricmp(am, "MYPRX")) { + // Normal case of specific MYSQL table + if (!url || !*url) { + // Not using the connection URL + Hostname = Cat->GetStringCatInfo(g, "Host", "localhost"); + Database = Cat->GetStringCatInfo(g, "Database", "*"); + Tabname = Cat->GetStringCatInfo(g, "Name", Name); // Deprecated + Tabname = Cat->GetStringCatInfo(g, "Tabname", Tabname); + Username = Cat->GetStringCatInfo(g, "User", "*"); + Password = Cat->GetStringCatInfo(g, "Password", NULL); + Portnumber = Cat->GetIntCatInfo("Port", mysqld_port); + } else if (ParseURL(g, url)) + return TRUE; - if (!url || !*url) { - // Not using the connection URL - Hostname = Cat->GetStringCatInfo(g, "Host", "localhost"); + Bind = !!Cat->GetIntCatInfo("Bind", 0); + Delayed = !!Cat->GetIntCatInfo("Delayed", 0); + } else { + // MYSQL access from a PROXY table, not using URL Database = Cat->GetStringCatInfo(g, "Database", "*"); Tabname = Cat->GetStringCatInfo(g, "Name", Name); // Deprecated Tabname = Cat->GetStringCatInfo(g, "Tabname", Tabname); + + // We must get connection parms from the calling table + Remove_tshp(Cat); + Hostname = Cat->GetStringCatInfo(g, "Host", "localhost"); Username = Cat->GetStringCatInfo(g, "User", "*"); Password = Cat->GetStringCatInfo(g, "Password", NULL); Portnumber = Cat->GetIntCatInfo("Port", mysqld_port); - } else if (ParseURL(g, url)) - return TRUE; + } // endif am - Bind = !!Cat->GetIntCatInfo("Bind", 0); - Delayed = !!Cat->GetIntCatInfo("Delayed", 0); return FALSE; } // end of DefineAM diff --git a/storage/connect/taboccur.cpp b/storage/connect/taboccur.cpp index e1b83c06422..8b7e10f2e34 100644 --- a/storage/connect/taboccur.cpp +++ b/storage/connect/taboccur.cpp @@ -60,7 +60,6 @@ extern "C" int trace; /***********************************************************************/ 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", ""); @@ -72,22 +71,9 @@ bool OCCURDEF::DefineAM(PGLOBAL g, LPCSTR am, int poff) /***********************************************************************/ 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 + if (Catfunc != FNC_COL) + return new(g) TDBOCCUR(this); + else return new(g) TDBTBC(this); } // end of GetTable @@ -145,6 +131,24 @@ PCOL TDBOCCUR::MakeCol(PGLOBAL g, PCOLDEF cdp, PCOL cprec, int n) return colp; } // end of MakeCol +/***********************************************************************/ +/* Initializes the table. */ +/***********************************************************************/ +bool TDBOCCUR::InitTable(PGLOBAL g) + { + if (!Tdbp) { + // Get the table description block of this table + if (!(Tdbp = (PTDBASE)GetSubTable(g, ((POCCURDEF)To_Def)->Tablep))) + return TRUE; + + if (MakeColumnList(g) < 0) + return TRUE; + + } // endif Tdbp + + return FALSE; + } // end of InitTable + /***********************************************************************/ /* Allocate OCCUR column description block. */ /***********************************************************************/ @@ -199,7 +203,9 @@ int TDBOCCUR::MakeColumnList(PGLOBAL g) int TDBOCCUR::GetMaxSize(PGLOBAL g) { if (MaxSize < 0) { -// Mult = MakeColumnList(g); + if (InitTable(g)) + return NULL; + MaxSize = Mult * Tdbp->GetMaxSize(g); } // endif MaxSize @@ -233,12 +239,7 @@ bool TDBOCCUR::OpenDB(PGLOBAL g) 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. */ @@ -247,21 +248,11 @@ bool TDBOCCUR::OpenDB(PGLOBAL g) return TRUE; } // endif Mode -#if 0 /*********************************************************************/ - /* Be sure OCCUR column exist. */ + /* Do it here if not done yet. */ /*********************************************************************/ - 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 (InitTable(g)) + return NULL; if (Xcolp) // Lock this column so it is evaluated by its table only diff --git a/storage/connect/taboccur.h b/storage/connect/taboccur.h index 0cfabf87793..c0077a0b33e 100644 --- a/storage/connect/taboccur.h +++ b/storage/connect/taboccur.h @@ -37,7 +37,6 @@ class OCCURDEF : public PRXDEF { /* Logical table description */ 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 */ @@ -59,15 +58,14 @@ class TDBOCCUR : public TDBPRX { 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 bool InitTable(PGLOBAL g); virtual int GetMaxSize(PGLOBAL g); virtual bool OpenDB(PGLOBAL g); virtual int ReadDB(PGLOBAL g); @@ -94,7 +92,6 @@ 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;} @@ -120,7 +117,6 @@ 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;} diff --git a/storage/connect/tabtbl.cpp b/storage/connect/tabtbl.cpp index c1286785d73..5a2089d04d6 100644 --- a/storage/connect/tabtbl.cpp +++ b/storage/connect/tabtbl.cpp @@ -209,65 +209,6 @@ 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; - bool mysql; - PTDB tdbp = NULL; - TABLE_SHARE *s; - PCATLG cat = To_Def->GetCat(); - PHC hc = ((MYCAT*)cat)->GetHandler(); - THD *thd = (hc->GetTable())->in_use; - - if (!thd) - return NULL; // Should not happen anymore - -//if (tblp->DB) -// db = tblp->DB; -//else -// db = (char*)hc->GetDBName(NULL); - -//if (!(s = GetTableShare(g, thd, db, tblp->Name, mysql))) - if (!(s = GetTableShare(g, thd, tblp->DB, tblp->Name, mysql))) - return NULL; - - 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", tblp->DB, tblp->Name); - goto err; - } // endif Define - - if (tabp->GetQualifier()) - ((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 - 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. */ /***********************************************************************/ @@ -293,7 +234,8 @@ bool TDBTBL::InitTableList(PGLOBAL g) else continue; // Skip this table - } // endif tdbp + } else + RemoveNext(tabp); // To avoid looping // We must allocate subtable columns before GetMaxSize is called // because some (PLG, ODBC?) need to have their columns attached. @@ -393,80 +335,18 @@ bool TDBTBL::TestFil(PGLOBAL g, PFIL filp, PTABLE tabp) return TRUE; // invalid operator } // end of TestFil -#if 0 -/***********************************************************************/ -/* TBL GetProgMax: get the max value for progress information. */ -/***********************************************************************/ -int TDBTBL::GetProgMax(PGLOBAL g) - { - int n, pmx = 0; - - if (!Tablist && InitTableList(g)) - return -1; - - for (PTABLE tabp = Tablist; tabp; tblp = tabp->GetNext()) - if ((n = tabp->GetTo_Tdb()->GetProgMax(g)) > 0) - pmx += n; - - return pmx; - } // end of GetProgMax - -/***********************************************************************/ -/* TBL GetProgCur: get the current value for progress information. */ -/***********************************************************************/ -int TDBTBL::GetProgCur(void) - { - return Crp + Tdbp->GetProgCur(); - } // end of GetProgCur - -/***********************************************************************/ -/* TBL Cardinality: returns table cardinality in number of rows. */ -/* This function can be called with a null argument to test the */ -/* availability of Cardinality implementation (1 yes, 0 no). */ -/* Can be used on Multiple FIX table only. */ -/***********************************************************************/ -int TDBTBL::Cardinality(PGLOBAL g) - { - if (!g) - return Tdbp->Cardinality(g); - - if (!Tablist && InitTableList(g)) - return -1; - - int n, card = 0; - - for (int i = 0; i < NumFiles; i++) { - Tdbp->SetFile(g, Filenames[i]); - Tdbp->ResetSize(); - - if ((n = Tdbp->Cardinality(g)) < 0) { -// strcpy(g->Message, MSG(BAD_CARDINALITY)); - return -1; - } // endif n - - card += n; - } // endfor i - - return card; - } // end of Cardinality -#endif // 0 - /***********************************************************************/ /* Sum up the sizes of all sub-tables. */ /***********************************************************************/ int TDBTBL::GetMaxSize(PGLOBAL g) { if (MaxSize < 0) { - int mxsz; + int mxsz; if (!Tablist && InitTableList(g)) return 0; // Cannot be calculated at this stage -// if (Use == USE_OPEN) { -// strcpy(g->Message, MSG(MAXSIZE_ERROR)); -// return -1; -// } else - MaxSize = 0; + MaxSize = 0; for (PTABLE tabp = Tablist; tabp; tabp = tabp->GetNext()) { if ((mxsz = tabp->GetTo_Tdb()->GetMaxSize(g)) < 0) { @@ -524,17 +404,6 @@ bool TDBTBL::OpenDB(PGLOBAL g) return Tdbp->OpenDB(g); // Re-open fist table } // endif use -#if 0 - /*********************************************************************/ - /* Direct access needed for join or sorting. */ - /*********************************************************************/ - if (NeedIndexing(g)) { - // Direct access of TBL tables is not implemented yet - strcpy(g->Message, MSG(NO_MUL_DIR_ACC)); - return TRUE; - } // endif NeedIndexing -#endif // 0 - /*********************************************************************/ /* When GetMaxsize was called, To_Filter was not set yet. */ /*********************************************************************/ @@ -634,144 +503,6 @@ int TDBTBL::ReadDB(PGLOBAL g) return rc; } // end of ReadDB -#if 0 -/***********************************************************************/ -/* Data Base write routine for MUL access method. */ -/***********************************************************************/ -int TDBTBL::WriteDB(PGLOBAL g) - { - strcpy(g->Message, MSG(TABMUL_READONLY)); - return RC_FX; // NIY - } // end of WriteDB - -/***********************************************************************/ -/* Data Base delete line routine for MUL access method. */ -/***********************************************************************/ -int TDBTBL::DeleteDB(PGLOBAL g, int irc) - { - strcpy(g->Message, MSG(TABMUL_READONLY)); - return RC_FX; // NIY - } // end of DeleteDB - -/***********************************************************************/ -/* Data Base close routine for MUL access method. */ -/***********************************************************************/ -void TDBTBL::CloseDB(PGLOBAL g) - { - if (Tdbp) - Tdbp->CloseDB(g); - - } // end of CloseDB -#endif // 0 - -/* ---------------------------- TBLCOL ------------------------------- */ - -#if 0 -/***********************************************************************/ -/* TBLCOL public constructor. */ -/***********************************************************************/ -TBLCOL::TBLCOL(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(); // ??? -//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 TBLCOL constructor - -/***********************************************************************/ -/* TBLCOL public constructor. */ -/***********************************************************************/ -TBLCOL::TBLCOL(SPCBLK *scp, PTDB tdbp) : COLBLK(scp->GetName(), tdbp, 0) - { - // Set additional TBL access method information for pseudo column. - Is_Key = Was_Key = scp->IsKey(); - Long = scp->GetLength(); - Buf_Type = scp->GetResultType(); - *Format.Type = (Buf_Type == TYPE_INT) ? 'N' : 'C'; - Format.Length = Long; - Colp = NULL; - To_Val = NULL; - Pseudo = TRUE; - } // end of TBLCOL constructor - -/***********************************************************************/ -/* TBLCOL constructor used for copying columns. */ -/* tdbp is the pointer to the new table descriptor. */ -/***********************************************************************/ -TBLCOL::TBLCOL(TBLCOL *col1, PTDB tdbp) : COLBLK(col1, tdbp) - { - Long = col1->Long; - Colp = col1->Colp; - To_Val = col1->To_Val; - Pseudo = col1->Pseudo; - } // end of TBLCOL copy constructor - -/***********************************************************************/ -/* TBLCOL initialization routine. */ -/* Look for the matching column in the current table. */ -/***********************************************************************/ -bool TBLCOL::Init(PGLOBAL g) - { - PTDBTBL tdbp = (PTDBTBL)To_Tdb; - - To_Val = NULL; - - 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 if (!tdbp->Accept) { - sprintf(g->Message, MSG(NO_MATCHING_COL), Name, tdbp->Tdbp->GetName()); - return TRUE; - } else { - if (Nullable) - Value->SetNull(true); - - Value->Reset(); - } // endif's - - return FALSE; - } // end of Init - -/***********************************************************************/ -/* ReadColumn: */ -/***********************************************************************/ -void TBLCOL::ReadColumn(PGLOBAL g) - { - if (trace) - htrc("TBL 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 -#endif // 0 - /* ---------------------------- TBTBLK ------------------------------- */ /***********************************************************************/ diff --git a/storage/connect/tabtbl.h b/storage/connect/tabtbl.h index d241b00743e..69b862ebe4e 100644 --- a/storage/connect/tabtbl.h +++ b/storage/connect/tabtbl.h @@ -24,8 +24,6 @@ class DllExport TBLDEF : public PRXDEF { /* Logical table description */ // Implementation virtual const char *GetType(void) {return "TBL";} -//PTABLE GetTables(void) {return Tablep;} -//int GetNtables(void) {return Ntables;} // Methods virtual bool DefineAM(PGLOBAL g, LPCSTR am, int poff); @@ -33,7 +31,6 @@ class DllExport TBLDEF : public PRXDEF { /* Logical table description */ protected: // Members -//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 */ @@ -43,7 +40,6 @@ class DllExport TBLDEF : public PRXDEF { /* Logical table description */ /* This is the TBL Access Method class declaration. */ /***********************************************************************/ class DllExport TDBTBL : public TDBPRX { -//friend class TBLCOL; friend class TBTBLK; friend class TDBPLG; public: @@ -55,33 +51,25 @@ class DllExport TDBTBL : public TDBPRX { // Methods virtual void ResetDB(void); -//virtual PTABLE GetTablist(void) {return (PSZ)Tablist;} 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 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); protected: // Internal functions -//PTDB GetSubTable(PGLOBAL g, PTBL tblp, PTABLE tabp); bool InitTableList(PGLOBAL g); 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 bool Accept; // TRUE if bad tables are accepted int Maxerr; // Maximum number of bad tables int Nbf; // Number of bad connections @@ -89,41 +77,6 @@ class DllExport TDBTBL : public TDBPRX { 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. */ -/***********************************************************************/ -class DllExport TBLCOL : public COLBLK { - friend class TDBTBL; - public: - // Constructors - TBLCOL(PCOLDEF cdp, PTDB tdbp, PCOL cprec, int i, PSZ am = "TBL"); - TBLCOL(TBLCOL *colp, PTDB tdbp); // Constructor used in copy process -//TBLCOL(SPCBLK *colp, PTDB tdbp); // Constructor used for pseudo columns - - // Implementation - virtual int GetAmType(void) {return TYPE_AM_TBL;} - - // Methods - virtual bool IsSpecial(void) {return Pseudo;} - virtual void ReadColumn(PGLOBAL g); -//virtual void WriteColumn(PGLOBAL g); -// void Print(PGLOBAL g, FILE *, UINT); - bool Init(PGLOBAL g); - - protected: - // Default constructor not to be used - TBLCOL(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 TBLCOL -#endif // 0 - /***********************************************************************/ /* Class TBTBLK: TDBPLG TABID special column descriptor. */ /***********************************************************************/ diff --git a/storage/connect/tabutil.cpp b/storage/connect/tabutil.cpp index 76885aeedce..3829e16b00b 100644 --- a/storage/connect/tabutil.cpp +++ b/storage/connect/tabutil.cpp @@ -245,7 +245,7 @@ PQRYRES TabColumns(PGLOBAL g, THD *thd, const char *db, return qrp; } // end of TabColumns -/* -------------- Implementation of the XCOL classes ---------------- */ +/* -------------- Implementation of the PROXY classes ---------------- */ /***********************************************************************/ /* PRXDEF constructor. */ @@ -311,11 +311,23 @@ PTDB TDBPRX::GetSubTable(PGLOBAL g, PTABLE tabp) TABLE_SHARE *s; PCATLG cat = To_Def->GetCat(); PHC hc = ((MYCAT*)cat)->GetHandler(); + LPCSTR cdb, curdb = hc->GetDBName(NULL); THD *thd = (hc->GetTable())->in_use; db = (char*)tabp->GetQualifier(); name = (char*)tabp->GetName(); + // Check for eventual loop + for (PTABLE tp = To_Table; tp; tp = tp->Next) { + cdb = (tp->Qualifier) ? tp->Qualifier : curdb; + + if (!stricmp(name, tp->Name) && !stricmp(db, cdb)) { + sprintf(g->Message, "Table %s.%s pointing on itself", db, name); + return NULL; + } // endif + + } // endfor tp + if (!(s = GetTableShare(g, thd, db, name, mysql))) return NULL; @@ -337,9 +349,11 @@ PTDB TDBPRX::GetSubTable(PGLOBAL g, PTABLE tabp) db, tblp->Name); goto err; #endif // MYSQL_SUPPORT - } else + } else { // Sub-table is a CONNECT table + tabp->Next = To_Table; // For loop checking tdbp = cat->GetTable(g, tabp); + } // endif mysql hc->tshp = NULL; @@ -420,7 +434,7 @@ bool TDBPRX::OpenDB(PGLOBAL g) } // endif Mode if (InitTable(g)) - return NULL; + return TRUE; /*********************************************************************/ /* Check and initialize the subtable columns. */ @@ -468,6 +482,14 @@ int TDBPRX::DeleteDB(PGLOBAL g, int irc) return RC_FX; } // end of DeleteDB +/***********************************************************************/ +/* Used by the TBL tables. */ +/***********************************************************************/ +void TDBPRX::RemoveNext(PTABLE tp) + { + tp->Next = NULL; + } // end of RemoveNext + /* ---------------------------- PRXCOL ------------------------------- */ /***********************************************************************/ diff --git a/storage/connect/tabutil.h b/storage/connect/tabutil.h index 48e97bd49ec..3a5946bae8f 100644 --- a/storage/connect/tabutil.h +++ b/storage/connect/tabutil.h @@ -95,6 +95,7 @@ class DllExport TDBPRX : public TDBASE { virtual int DeleteDB(PGLOBAL g, int irc); virtual void CloseDB(PGLOBAL g) {if (Tdbp) Tdbp->CloseDB(g);} PTDB GetSubTable(PGLOBAL g, PTABLE tabp); + void RemoveNext(PTABLE tp); protected: // Members diff --git a/storage/connect/tabxcl.cpp b/storage/connect/tabxcl.cpp index 337a6cefd1d..78998435aa6 100644 --- a/storage/connect/tabxcl.cpp +++ b/storage/connect/tabxcl.cpp @@ -105,7 +105,6 @@ PTDB XCLDEF::GetTable(PGLOBAL g, MODE mode) /***********************************************************************/ 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 @@ -222,28 +221,6 @@ bool TDBXCL::OpenDB(PGLOBAL g) 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 @@ -332,45 +309,3 @@ void XCLCOL::ReadColumn(PGLOBAL g) ((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 index 6db653d5709..79b890c9f55 100644 --- a/storage/connect/tabxcl.h +++ b/storage/connect/tabxcl.h @@ -8,7 +8,6 @@ typedef class XCLDEF *PXCLDEF; typedef class TDBXCL *PTDBXCL; typedef class XCLCOL *PXCLCOL; -//pedef class MULINDX *PMINDX; /* -------------------------- XCOL classes --------------------------- */ @@ -49,7 +48,6 @@ class XCLDEF : public PRXDEF { /* Logical table description */ /* 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; @@ -63,7 +61,6 @@ class TDBXCL : public TDBPRX { // 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); @@ -106,28 +103,3 @@ class XCLCOL : public PRXCOL { 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 From 5fc19f8db85af67efac58c3710933aa6c8925e29 Mon Sep 17 00:00:00 2001 From: Olivier Bertrand Date: Sat, 4 May 2013 00:47:55 +0200 Subject: [PATCH 06/47] - Add test for XCOL and OCCUR tables - Fix a bug causing a crash when doing an ALTER TABLE (because create_info->alias is NULL) added: storage/connect/mysql-test/connect/r/occur.result storage/connect/mysql-test/connect/r/xcol.result storage/connect/mysql-test/connect/t/occur.test storage/connect/mysql-test/connect/t/xcol.test modified: storage/connect/ha_connect.cc --- storage/connect/ha_connect.cc | 28 +- .../connect/mysql-test/connect/r/occur.result | 255 ++++++++++++++++++ .../connect/mysql-test/connect/r/xcol.result | 85 ++++++ .../connect/mysql-test/connect/t/occur.test | 59 ++++ .../connect/mysql-test/connect/t/xcol.test | 28 ++ 5 files changed, 442 insertions(+), 13 deletions(-) create mode 100644 storage/connect/mysql-test/connect/r/occur.result create mode 100644 storage/connect/mysql-test/connect/r/xcol.result create mode 100644 storage/connect/mysql-test/connect/t/occur.test create mode 100644 storage/connect/mysql-test/connect/t/xcol.test diff --git a/storage/connect/ha_connect.cc b/storage/connect/ha_connect.cc index 7422815223f..2eefd1e20d2 100644 --- a/storage/connect/ha_connect.cc +++ b/storage/connect/ha_connect.cc @@ -3801,20 +3801,22 @@ int ha_connect::create(const char *name, TABLE *table_arg, } else dbf= (GetTypeID(options->type) == TAB_DBF && !options->catfunc); - // Check whether a table is defined on itself - switch (type) { - case TAB_PRX: - case TAB_XCL: - case TAB_OCCUR: - if (!stricmp(options->tabname, create_info->alias) && - (!options->dbname || !stricmp(options->dbname, thd->db))) { - sprintf(g->Message, "A %s table cannot refer to itself", - options->type); - my_message(ER_UNKNOWN_ERROR, g->Message, MYF(0)); - return HA_ERR_INTERNAL_ERROR; - } // endif tab + // Can be null in ALTER TABLE + if (create_info->alias) + // Check whether a table is defined on itself + switch (type) { + case TAB_PRX: + case TAB_XCL: + case TAB_OCCUR: + if (!stricmp(options->tabname, create_info->alias) && + (!options->dbname || !stricmp(options->dbname, thd->db))) { + sprintf(g->Message, "A %s table cannot refer to itself", + options->type); + my_message(ER_UNKNOWN_ERROR, g->Message, MYF(0)); + return HA_ERR_INTERNAL_ERROR; + } // endif tab - } // endswitch ttp + } // endswitch ttp if (type == TAB_XML) { bool dom; // True: MS-DOM, False libxml2 diff --git a/storage/connect/mysql-test/connect/r/occur.result b/storage/connect/mysql-test/connect/r/occur.result new file mode 100644 index 00000000000..a497dfc9942 --- /dev/null +++ b/storage/connect/mysql-test/connect/r/occur.result @@ -0,0 +1,255 @@ +CREATE TABLE employee ( +serialno CHAR(5) NOT NULL, +name VARCHAR(12) NOT NULL FLAG=6, +sex TINYINT(1) NOT NULL, +title VARCHAR(15) NOT NULL FLAG=20, +manager CHAR(5) DEFAULT NULL, +department CHAR(4) NOT NULL FLAG=41, +secretary CHAR(5) DEFAULT NULL FLAG=46, +salary DOUBLE(8,2) NOT NULL FLAG=52 +) ENGINE=connect TABLE_TYPE=fix FILE_NAME='employee.dat' ENDING=1; +SELECT * FROM employee; +serialno name sex title manager department secretary salary +74200 BANCROFT 2 SALESMAN 70012 0318 24888 9600.00 +02345 SMITH 1 ENGINEER 31416 2452 11111 9000.00 +78943 MERCHANT 1 SALESMAN 70012 0318 24888 8700.00 +07654 FUNNIGUY 1 ADMINISTRATOR 40567 0319 33333 8500.00 +45678 BUGHAPPY 1 PROGRAMMER 40567 0319 12345 8500.00 +34567 BIGHEAD 1 SCIENTIST 31416 2452 11111 8000.00 +77777 SHRINKY 2 ADMINISTRATOR 70012 0318 27845 7500.00 +74234 WALTER 1 ENGINEER 70012 0318 24888 7400.00 +56789 FODDERMAN 1 SALESMAN 40567 0319 12345 7000.00 +73452 TONGHO 1 ENGINEER 70012 0318 24888 6800.00 +22222 SHORTSIGHT 2 SECRETARY 87777 0021 NULL 5500.00 +55555 MESSIFUL 2 SECRETARY 40567 0319 12345 5000.50 +27845 HONEY 2 SECRETARY 70012 0318 24888 4900.00 +98765 GOOSEPEN 1 ADMINISTRATOR 07654 0319 33333 4700.00 +11111 CHERRY 2 SECRETARY 31416 2452 NULL 4500.00 +33333 MONAPENNY 2 SECRETARY 07654 0319 NULL 3800.00 +12345 KITTY 2 TYPIST 40567 0319 NULL 3000.45 +24888 PLUMHEAD 2 TYPIST 27845 0318 NULL 2800.00 +87777 STRONG 1 DIRECTOR NULL 0021 22222 23000.00 +76543 BULLOZER 1 SALESMAN 40567 0319 12345 14800.00 +70012 WERTHER 1 DIRECTOR 87777 0318 27845 14500.00 +40567 QUINN 1 DIRECTOR 87777 0319 55555 14000.00 +31416 ORELLY 1 ENGINEER 87777 2452 11111 13400.00 +36666 BIGHORN 1 SCIENTIST 31416 2452 11111 11000.00 +00137 BROWNY 1 ENGINEER 40567 0319 12345 10500.00 +73111 WHEELFOR 1 SALESMAN 70012 0318 24888 10030.00 +00023 MARTIN 1 ENGINEER 40567 0319 12345 10000.00 +CREATE TABLE occurs (name CHAR(12), sex CHAR(1), title CHAR(15), department CHAR(4), salary DOUBLE(8,2), id_of CHAR(12), id CHAR(5) NOT NULL) ENGINE=CONNECT TABLE_TYPE=OCCUR TABNAME=employee OPTION_LIST='OccurCol=ID,RankCol=ID_OF,Colist=serialno;manager;secretary,port=PORT';; +SELECT * FROM occurs; +name sex title department salary id_of id +BANCROFT 2 SALESMAN 0318 9600.00 serialno 74200 +BANCROFT 2 SALESMAN 0318 9600.00 manager 70012 +BANCROFT 2 SALESMAN 0318 9600.00 secretary 24888 +SMITH 1 ENGINEER 2452 9000.00 serialno 02345 +SMITH 1 ENGINEER 2452 9000.00 manager 31416 +SMITH 1 ENGINEER 2452 9000.00 secretary 11111 +MERCHANT 1 SALESMAN 0318 8700.00 serialno 78943 +MERCHANT 1 SALESMAN 0318 8700.00 manager 70012 +MERCHANT 1 SALESMAN 0318 8700.00 secretary 24888 +FUNNIGUY 1 ADMINISTRATOR 0319 8500.00 serialno 07654 +FUNNIGUY 1 ADMINISTRATOR 0319 8500.00 manager 40567 +FUNNIGUY 1 ADMINISTRATOR 0319 8500.00 secretary 33333 +BUGHAPPY 1 PROGRAMMER 0319 8500.00 serialno 45678 +BUGHAPPY 1 PROGRAMMER 0319 8500.00 manager 40567 +BUGHAPPY 1 PROGRAMMER 0319 8500.00 secretary 12345 +BIGHEAD 1 SCIENTIST 2452 8000.00 serialno 34567 +BIGHEAD 1 SCIENTIST 2452 8000.00 manager 31416 +BIGHEAD 1 SCIENTIST 2452 8000.00 secretary 11111 +SHRINKY 2 ADMINISTRATOR 0318 7500.00 serialno 77777 +SHRINKY 2 ADMINISTRATOR 0318 7500.00 manager 70012 +SHRINKY 2 ADMINISTRATOR 0318 7500.00 secretary 27845 +WALTER 1 ENGINEER 0318 7400.00 serialno 74234 +WALTER 1 ENGINEER 0318 7400.00 manager 70012 +WALTER 1 ENGINEER 0318 7400.00 secretary 24888 +FODDERMAN 1 SALESMAN 0319 7000.00 serialno 56789 +FODDERMAN 1 SALESMAN 0319 7000.00 manager 40567 +FODDERMAN 1 SALESMAN 0319 7000.00 secretary 12345 +TONGHO 1 ENGINEER 0318 6800.00 serialno 73452 +TONGHO 1 ENGINEER 0318 6800.00 manager 70012 +TONGHO 1 ENGINEER 0318 6800.00 secretary 24888 +SHORTSIGHT 2 SECRETARY 0021 5500.00 serialno 22222 +SHORTSIGHT 2 SECRETARY 0021 5500.00 manager 87777 +MESSIFUL 2 SECRETARY 0319 5000.50 serialno 55555 +MESSIFUL 2 SECRETARY 0319 5000.50 manager 40567 +MESSIFUL 2 SECRETARY 0319 5000.50 secretary 12345 +HONEY 2 SECRETARY 0318 4900.00 serialno 27845 +HONEY 2 SECRETARY 0318 4900.00 manager 70012 +HONEY 2 SECRETARY 0318 4900.00 secretary 24888 +GOOSEPEN 1 ADMINISTRATOR 0319 4700.00 serialno 98765 +GOOSEPEN 1 ADMINISTRATOR 0319 4700.00 manager 07654 +GOOSEPEN 1 ADMINISTRATOR 0319 4700.00 secretary 33333 +CHERRY 2 SECRETARY 2452 4500.00 serialno 11111 +CHERRY 2 SECRETARY 2452 4500.00 manager 31416 +MONAPENNY 2 SECRETARY 0319 3800.00 serialno 33333 +MONAPENNY 2 SECRETARY 0319 3800.00 manager 07654 +KITTY 2 TYPIST 0319 3000.45 serialno 12345 +KITTY 2 TYPIST 0319 3000.45 manager 40567 +PLUMHEAD 2 TYPIST 0318 2800.00 serialno 24888 +PLUMHEAD 2 TYPIST 0318 2800.00 manager 27845 +STRONG 1 DIRECTOR 0021 23000.00 serialno 87777 +STRONG 1 DIRECTOR 0021 23000.00 secretary 22222 +BULLOZER 1 SALESMAN 0319 14800.00 serialno 76543 +BULLOZER 1 SALESMAN 0319 14800.00 manager 40567 +BULLOZER 1 SALESMAN 0319 14800.00 secretary 12345 +WERTHER 1 DIRECTOR 0318 14500.00 serialno 70012 +WERTHER 1 DIRECTOR 0318 14500.00 manager 87777 +WERTHER 1 DIRECTOR 0318 14500.00 secretary 27845 +QUINN 1 DIRECTOR 0319 14000.00 serialno 40567 +QUINN 1 DIRECTOR 0319 14000.00 manager 87777 +QUINN 1 DIRECTOR 0319 14000.00 secretary 55555 +ORELLY 1 ENGINEER 2452 13400.00 serialno 31416 +ORELLY 1 ENGINEER 2452 13400.00 manager 87777 +ORELLY 1 ENGINEER 2452 13400.00 secretary 11111 +BIGHORN 1 SCIENTIST 2452 11000.00 serialno 36666 +BIGHORN 1 SCIENTIST 2452 11000.00 manager 31416 +BIGHORN 1 SCIENTIST 2452 11000.00 secretary 11111 +BROWNY 1 ENGINEER 0319 10500.00 serialno 00137 +BROWNY 1 ENGINEER 0319 10500.00 manager 40567 +BROWNY 1 ENGINEER 0319 10500.00 secretary 12345 +WHEELFOR 1 SALESMAN 0318 10030.00 serialno 73111 +WHEELFOR 1 SALESMAN 0318 10030.00 manager 70012 +WHEELFOR 1 SALESMAN 0318 10030.00 secretary 24888 +MARTIN 1 ENGINEER 0319 10000.00 serialno 00023 +MARTIN 1 ENGINEER 0319 10000.00 manager 40567 +MARTIN 1 ENGINEER 0319 10000.00 secretary 12345 +DROP TABLE occurs; +DROP TABLE employee; +CREATE TABLE pets ( +name VARCHAR(12) NOT NULL, +dog INT NOT NULL DEFAULT 0, +cat INT NOT NULL DEFAULT 0, +rabbit INT NOT NULL DEFAULT 0, +bird INT NOT NULL DEFAULT 0, +fish INT NOT NULL DEFAULT 0) ENGINE=MYISAM; +INSERT INTO pets(name,dog) VALUES('John',2); +INSERT INTO pets(name,cat) VALUES('Bill',1); +INSERT INTO pets(name,dog,cat) VALUES('Mary',1,1); +INSERT INTO pets(name,rabbit) VALUES('Lisbeth',2); +INSERT INTO pets(name,cat,bird) VALUES('Kevin',2,6); +INSERT INTO pets(name,dog,fish) VALUES('Donald',1,3); +SELECT * FROM pets; +name dog cat rabbit bird fish +John 2 0 0 0 0 +Bill 0 1 0 0 0 +Mary 1 1 0 0 0 +Lisbeth 0 0 2 0 0 +Kevin 0 2 0 6 0 +Donald 1 0 0 0 3 +CREATE TABLE xpet (name VARCHAR(12) NOT NULL, race CHAR(6) NOT NULL, number INT) ENGINE=CONNECT TABLE_TYPE=OCCUR TABNAME=pets OPTION_LIST='OccurCol=number,RankCol=race,Colist=dog;cat;rabbit;bird;fish,port=PORT'; +SELECT * FROM xpet; +name race number +John dog 2 +John cat 0 +John rabbit 0 +John bird 0 +John fish 0 +Bill dog 0 +Bill cat 1 +Bill rabbit 0 +Bill bird 0 +Bill fish 0 +Mary dog 1 +Mary cat 1 +Mary rabbit 0 +Mary bird 0 +Mary fish 0 +Lisbeth dog 0 +Lisbeth cat 0 +Lisbeth rabbit 2 +Lisbeth bird 0 +Lisbeth fish 0 +Kevin dog 0 +Kevin cat 2 +Kevin rabbit 0 +Kevin bird 6 +Kevin fish 0 +Donald dog 1 +Donald cat 0 +Donald rabbit 0 +Donald bird 0 +Donald fish 3 +SELECT name FROM xpet; +name +John +Bill +Mary +Lisbeth +Kevin +Donald +SELECT name FROM xpet WHERE race = 'cat' AND number = 0; +name +John +Lisbeth +Donald +SELECT name, SUM(number) pets FROM xpet GROUP BY name; +name pets +Bill 1 +Donald 4 +John 2 +Kevin 8 +Lisbeth 2 +Mary 2 +ALTER TABLE xpet MODIFY number INT NOT NULL; +SELECT * FROM xpet; +name race number +John dog 2 +Bill cat 1 +Mary dog 1 +Mary cat 1 +Lisbeth rabbit 2 +Kevin cat 2 +Kevin bird 6 +Donald dog 1 +Donald fish 3 +SELECT * FROM xpet WHERE number > 1; +name race number +John dog 2 +Lisbeth rabbit 2 +Kevin cat 2 +Kevin bird 6 +Donald fish 3 +SELECT DISTINCT name FROM xpet WHERE number > 1; +name +John +Lisbeth +Kevin +Donald +SELECT name FROM xpet; +name +John +Bill +Mary +Lisbeth +Kevin +Donald +SELECT name, race FROM xpet; +name race +John +Bill +Mary +Lisbeth +Kevin +Donald +SELECT name, count(*) FROM xpet GROUP BY name, LEAST(number,1); +name count(*) +Bill 1 +Donald 2 +John 1 +Kevin 2 +Lisbeth 1 +Mary 2 +SELECT name, number, count(*) FROM xpet GROUP BY name, number; +name number count(*) +Bill 1 1 +Donald 1 1 +Donald 3 1 +John 2 1 +Kevin 2 1 +Kevin 6 1 +Lisbeth 2 1 +Mary 1 2 +DROP TABLE xpet; +DROP TABLE pets; diff --git a/storage/connect/mysql-test/connect/r/xcol.result b/storage/connect/mysql-test/connect/r/xcol.result new file mode 100644 index 00000000000..f6899b47504 --- /dev/null +++ b/storage/connect/mysql-test/connect/r/xcol.result @@ -0,0 +1,85 @@ +# +# Checking XCOL tables +# +CREATE TABLE chlist ( +mother char(12) NOT NULL COMMENT 'The mother of the listed children', +children varchar(30) DEFAULT NULL COMMENT 'The comma separated list of children' +) ENGINE=CONNECT; +Warnings: +Warning 1105 No table_type. Will be set to DOS +Warning 1105 No file name. Table will use chlist.dos +INSERT INTO chlist VALUES('Sophia','Vivian, Antony'); +INSERT INTO chlist VALUES('Lisbeth','Lucy,Charles,Diana'); +INSERT INTO chlist VALUES('Corinne',NULL); +INSERT INTO chlist VALUES('Claude','Marc'); +INSERT INTO chlist VALUES('Janet','Arthur,Sandra,Peter,John'); +SELECT * FROM chlist; +mother children +Sophia Vivian, Antony +Lisbeth Lucy,Charles,Diana +Corinne NULL +Claude Marc +Janet Arthur,Sandra,Peter,John +CREATE TABLE child ENGINE=CONNECT TABLE_TYPE=XCOL TABNAME=chlist OPTION_LIST='colname=children,port=PORT'; +SELECT * FROM child; +mother children +Sophia Vivian +Sophia Antony +Lisbeth Lucy +Lisbeth Charles +Lisbeth Diana +Corinne NULL +Claude Marc +Janet Arthur +Janet Sandra +Janet Peter +Janet John +SELECT * FROM child ORDER BY mother; +mother children +Claude Marc +Corinne NULL +Janet Peter +Janet Sandra +Janet Arthur +Janet John +Lisbeth Diana +Lisbeth Charles +Lisbeth Lucy +Sophia Antony +Sophia Vivian +SELECT * FROM child ORDER BY children; +mother children +Corinne NULL +Sophia Antony +Janet Arthur +Lisbeth Charles +Lisbeth Diana +Janet John +Lisbeth Lucy +Claude Marc +Janet Peter +Janet Sandra +Sophia Vivian +SELECT mother FROM child; +mother +Sophia +Lisbeth +Corinne +Claude +Janet +SELECT mother, COUNT(*) FROM child GROUP BY mother; +mother COUNT(*) +Claude 1 +Corinne 1 +Janet 1 +Lisbeth 1 +Sophia 1 +SELECT mother, COUNT(children) FROM child GROUP BY mother; +mother COUNT(children) +Claude 1 +Corinne 0 +Janet 4 +Lisbeth 3 +Sophia 2 +DROP TABLE child; +DROP TABLE chlist; diff --git a/storage/connect/mysql-test/connect/t/occur.test b/storage/connect/mysql-test/connect/t/occur.test new file mode 100644 index 00000000000..5b237742fd8 --- /dev/null +++ b/storage/connect/mysql-test/connect/t/occur.test @@ -0,0 +1,59 @@ +let $MYSQLD_DATADIR= `select @@datadir`; +let $PORT= `select @@port`; +--copy_file $MTR_SUITE_DIR/std_data/employee.dat $MYSQLD_DATADIR/test/employee.dat + +CREATE TABLE employee ( +serialno CHAR(5) NOT NULL, +name VARCHAR(12) NOT NULL FLAG=6, +sex TINYINT(1) NOT NULL, +title VARCHAR(15) NOT NULL FLAG=20, +manager CHAR(5) DEFAULT NULL, +department CHAR(4) NOT NULL FLAG=41, +secretary CHAR(5) DEFAULT NULL FLAG=46, +salary DOUBLE(8,2) NOT NULL FLAG=52 +) ENGINE=connect TABLE_TYPE=fix FILE_NAME='employee.dat' ENDING=1; +SELECT * FROM employee; + +--replace_result $PORT PORT +--eval CREATE TABLE occurs (name CHAR(12), sex CHAR(1), title CHAR(15), department CHAR(4), salary DOUBLE(8,2), id_of CHAR(12), id CHAR(5) NOT NULL) ENGINE=CONNECT TABLE_TYPE=OCCUR TABNAME=employee OPTION_LIST='OccurCol=ID,RankCol=ID_OF,Colist=serialno;manager;secretary,port=$PORT'; +SELECT * FROM occurs; + +DROP TABLE occurs; +DROP TABLE employee; + +CREATE TABLE pets ( +name VARCHAR(12) NOT NULL, +dog INT NOT NULL DEFAULT 0, +cat INT NOT NULL DEFAULT 0, +rabbit INT NOT NULL DEFAULT 0, +bird INT NOT NULL DEFAULT 0, +fish INT NOT NULL DEFAULT 0) ENGINE=MYISAM; +INSERT INTO pets(name,dog) VALUES('John',2); +INSERT INTO pets(name,cat) VALUES('Bill',1); +INSERT INTO pets(name,dog,cat) VALUES('Mary',1,1); +INSERT INTO pets(name,rabbit) VALUES('Lisbeth',2); +INSERT INTO pets(name,cat,bird) VALUES('Kevin',2,6); +INSERT INTO pets(name,dog,fish) VALUES('Donald',1,3); +SELECT * FROM pets; + +--replace_result $PORT PORT +--eval CREATE TABLE xpet (name VARCHAR(12) NOT NULL, race CHAR(6) NOT NULL, number INT) ENGINE=CONNECT TABLE_TYPE=OCCUR TABNAME=pets OPTION_LIST='OccurCol=number,RankCol=race,Colist=dog;cat;rabbit;bird;fish,port=$PORT' + +SELECT * FROM xpet; +SELECT name FROM xpet; +SELECT name FROM xpet WHERE race = 'cat' AND number = 0; +SELECT name, SUM(number) pets FROM xpet GROUP BY name; + +ALTER TABLE xpet MODIFY number INT NOT NULL; + +SELECT * FROM xpet; +SELECT * FROM xpet WHERE number > 1; +SELECT DISTINCT name FROM xpet WHERE number > 1; +SELECT name FROM xpet; +SELECT name, race FROM xpet; +SELECT name, count(*) FROM xpet GROUP BY name, LEAST(number,1); +SELECT name, number, count(*) FROM xpet GROUP BY name, number; + +DROP TABLE xpet; +DROP TABLE pets; +--remove_file $MYSQLD_DATADIR/test/employee.dat diff --git a/storage/connect/mysql-test/connect/t/xcol.test b/storage/connect/mysql-test/connect/t/xcol.test new file mode 100644 index 00000000000..b6998ee77e0 --- /dev/null +++ b/storage/connect/mysql-test/connect/t/xcol.test @@ -0,0 +1,28 @@ +let $MYSQLD_DATADIR= `select @@datadir`; +let $PORT= `select @@port`; + +--echo # +--echo # Checking XCOL tables +--echo # +CREATE TABLE chlist ( +mother char(12) NOT NULL COMMENT 'The mother of the listed children', +children varchar(30) DEFAULT NULL COMMENT 'The comma separated list of children' +) ENGINE=CONNECT; +INSERT INTO chlist VALUES('Sophia','Vivian, Antony'); +INSERT INTO chlist VALUES('Lisbeth','Lucy,Charles,Diana'); +INSERT INTO chlist VALUES('Corinne',NULL); +INSERT INTO chlist VALUES('Claude','Marc'); +INSERT INTO chlist VALUES('Janet','Arthur,Sandra,Peter,John'); +SELECT * FROM chlist; + +--replace_result $PORT PORT +--eval CREATE TABLE child ENGINE=CONNECT TABLE_TYPE=XCOL TABNAME=chlist OPTION_LIST='colname=children,port=$PORT' +SELECT * FROM child; +SELECT * FROM child ORDER BY mother; +SELECT * FROM child ORDER BY children; +SELECT mother FROM child; +SELECT mother, COUNT(*) FROM child GROUP BY mother; +SELECT mother, COUNT(children) FROM child GROUP BY mother; + +DROP TABLE child; +DROP TABLE chlist; From 495981141118e7b88b75526c494af12888ffcf12 Mon Sep 17 00:00:00 2001 From: Olivier Bertrand Date: Sun, 5 May 2013 12:45:26 +0200 Subject: [PATCH 07/47] - General code cleaning, eliminating a few potential bugs modified: storage/connect/catalog.h storage/connect/mycat.cc storage/connect/taboccur.cpp storage/connect/taboccur.h storage/connect/tabutil.cpp storage/connect/tabutil.h storage/connect/tabxcl.cpp storage/connect/tabxcl.h --- storage/connect/catalog.h | 4 +-- storage/connect/mycat.cc | 16 ++++----- storage/connect/taboccur.cpp | 2 +- storage/connect/taboccur.h | 6 ++-- storage/connect/tabutil.cpp | 66 +++++++----------------------------- storage/connect/tabutil.h | 28 --------------- storage/connect/tabxcl.cpp | 43 +++++------------------ storage/connect/tabxcl.h | 5 ++- 8 files changed, 34 insertions(+), 136 deletions(-) diff --git a/storage/connect/catalog.h b/storage/connect/catalog.h index 4f0584ef7bc..365169100d9 100644 --- a/storage/connect/catalog.h +++ b/storage/connect/catalog.h @@ -63,7 +63,7 @@ class DllExport CATALOG { // Implementation void *GetDescp(void) {return Descp;} - PRELDEF GetTo_Desc(void) {return To_Desc;} +//PRELDEF GetTo_Desc(void) {return To_Desc;} //PSZ GetDescFile(void) {return DescFile;} int GetCblen(void) {return Cblen;} bool GetDefHuge(void) {return DefHuge;} @@ -115,7 +115,7 @@ class DllExport CATALOG { virtual PRELDEF MakeTableDesc(PGLOBAL g, LPCSTR name, LPCSTR am) {return NULL;} // Members - PRELDEF To_Desc; /* To chain of relation desc. */ +//PRELDEF To_Desc; /* To chain of relation desc. */ void *Descp; /* To DB description area */ //AREADEF DescArea; /* Table desc. area size */ char *Cbuf; /* Buffer used for col section */ diff --git a/storage/connect/mycat.cc b/storage/connect/mycat.cc index b46c014fba6..badcdcb9514 100644 --- a/storage/connect/mycat.cc +++ b/storage/connect/mycat.cc @@ -253,7 +253,7 @@ uint GetFuncID(const char *func) /***********************************************************************/ CATALOG::CATALOG(void) { - To_Desc= NULL; +//To_Desc= NULL; //*DescFile= '\0'; #if defined(WIN32) DataPath= ".\\"; @@ -276,7 +276,7 @@ CATALOG::CATALOG(void) MYCAT::MYCAT(PHC hc) : CATALOG() { Hc= hc; - To_Desc= NULL; +//To_Desc= NULL; DefHuge= false; //SepIndex= true; // Temporay until we can store offet and size } // end of MYCAT constructor @@ -286,7 +286,7 @@ MYCAT::MYCAT(PHC hc) : CATALOG() /***********************************************************************/ void MYCAT::Reset(void) { - To_Desc= NULL; +//To_Desc= NULL; } // end of Reset /***********************************************************************/ @@ -586,9 +586,7 @@ bool MYCAT::GetIndexInfo(PGLOBAL g, PTABDEF defp) /***********************************************************************/ /* GetTableDesc: retrieve a table descriptor. */ -/* Look for a table descriptor matching the name and type. If found */ -/* in storage, return a pointer to it, else look in the XDB file. If */ -/* found, make and add the descriptor and return a pointer to it. */ +/* Look for a table descriptor matching the name and type. */ /***********************************************************************/ PRELDEF MYCAT::GetTableDesc(PGLOBAL g, LPCSTR name, LPCSTR type, PRELDEF *prp) @@ -597,8 +595,8 @@ PRELDEF MYCAT::GetTableDesc(PGLOBAL g, LPCSTR name, printf("GetTableDesc: name=%s am=%s\n", name, SVP(type)); // Firstly check whether this table descriptor is in memory - if (To_Desc) - return To_Desc; +//if (To_Desc) +// return To_Desc; // If not specified get the type of this table if (!type && !(type= Hc->GetStringOption("Type"))) @@ -707,7 +705,7 @@ PTDB MYCAT::GetTable(PGLOBAL g, PTABLE tablep, MODE mode, LPCSTR type) /***********************************************************************/ void MYCAT::ClearDB(PGLOBAL g) { - To_Desc= NULL; +//To_Desc= NULL; } // end of ClearDB /* ------------------------ End of MYCAT --------------------------- */ diff --git a/storage/connect/taboccur.cpp b/storage/connect/taboccur.cpp index 8b7e10f2e34..2f721c6a7cf 100644 --- a/storage/connect/taboccur.cpp +++ b/storage/connect/taboccur.cpp @@ -161,7 +161,7 @@ int TDBOCCUR::MakeColumnList(PGLOBAL g) // Count the number of columns and change separator into null char for (pn = Colist; ; pn += (strlen(pn) + 1)) - if ((p = strchr(pn, ';'))) { + if ((p = strchr(pn, ',')) || (p = strchr(pn, ';'))) { *p++ = '\0'; n++; } else { diff --git a/storage/connect/taboccur.h b/storage/connect/taboccur.h index c0077a0b33e..076202be477 100644 --- a/storage/connect/taboccur.h +++ b/storage/connect/taboccur.h @@ -9,12 +9,11 @@ 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 */ +/* 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. */ /***********************************************************************/ @@ -48,7 +47,6 @@ class OCCURDEF : public PRXDEF { /* Logical table description */ class TDBOCCUR : public TDBPRX { friend class OCCURCOL; friend class RANKCOL; - friend class SRTCOL; public: // Constructor TDBOCCUR(POCCURDEF tdp); @@ -116,7 +114,7 @@ class OCCURCOL : public COLBLK { class RANKCOL : public COLBLK { public: // Constructors - RANKCOL(PCOLDEF cdp, PTDBOCCUR tdbp, int n) : COLBLK(cdp, tdbp, n) {} + RANKCOL(PCOLDEF cdp, PTDBOCCUR tdbp, int n) : COLBLK(cdp, tdbp, n) {} // Implementation virtual int GetAmType(void) {return TYPE_AM_OCCUR;} diff --git a/storage/connect/tabutil.cpp b/storage/connect/tabutil.cpp index 3829e16b00b..2bd92ff9607 100644 --- a/storage/connect/tabutil.cpp +++ b/storage/connect/tabutil.cpp @@ -1,9 +1,9 @@ -/************* Tabutil cpp Declares Source Code File (.H) **************/ +/************* Tabutil cpp Declares Source Code File (.CPP) ************/ /* Name: TABUTIL.CPP Version 1.0 */ /* */ /* (C) Copyright to the author Olivier BERTRAND 2013 */ /* */ -/* Utility function used by TBL and PRX tables. */ +/* Utility function used by the PROXY, XCOL, OCCUR, and TBL tables. */ /***********************************************************************/ /***********************************************************************/ @@ -117,7 +117,6 @@ TABLE_SHARE *GetTableShare(PGLOBAL g, THD *thd, const char *db, /************************************************************************/ /* 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) @@ -264,7 +263,11 @@ bool PRXDEF::DefineAM(PGLOBAL g, LPCSTR am, int poff) char *pn, *db, *tab; db = Cat->GetStringCatInfo(g, "Dbname", "*"); - tab = Cat->GetStringCatInfo(g, "Tabname", NULL); + + if (!(tab = Cat->GetStringCatInfo(g, "Tabname", NULL))) { + strcpy(g->Message, "Missing object table name"); + return TRUE; + } // endif tab // Analyze the table name, it may have the format: [dbname.]tabname if ((pn = strchr(tab, '.'))) { @@ -414,7 +417,7 @@ int TDBPRX::RowNumber(PGLOBAL g, bool b) } // end of RowNumber /***********************************************************************/ -/* XCV Access Method opening routine. */ +/* PROXY Access Method opening routine. */ /***********************************************************************/ bool TDBPRX::OpenDB(PGLOBAL g) { @@ -453,7 +456,7 @@ bool TDBPRX::OpenDB(PGLOBAL g) } // end of OpenDB /***********************************************************************/ -/* Data Base read routine for XCV access method. */ +/* Data Base read routine for PROY access method. */ /***********************************************************************/ int TDBPRX::ReadDB(PGLOBAL g) { @@ -464,7 +467,7 @@ int TDBPRX::ReadDB(PGLOBAL g) } // end of ReadDB /***********************************************************************/ -/* WriteDB: Data Base write routine for XCV access methods. */ +/* WriteDB: Data Base write routine for PROXY access methods. */ /***********************************************************************/ int TDBPRX::WriteDB(PGLOBAL g) { @@ -473,7 +476,7 @@ int TDBPRX::WriteDB(PGLOBAL g) } // end of WriteDB /***********************************************************************/ -/* Data Base delete line routine for XCV access methods. */ +/* Data Base delete line routine for PROXY access methods. */ /***********************************************************************/ int TDBPRX::DeleteDB(PGLOBAL g, int irc) { @@ -496,7 +499,7 @@ void TDBPRX::RemoveNext(PTABLE tp) /* PRXCOL public constructor. */ /***********************************************************************/ PRXCOL::PRXCOL(PCOLDEF cdp, PTDB tdbp, PCOL cprec, int i, PSZ am) - : COLBLK(cdp, tdbp, i) + : COLBLK(cdp, tdbp, i) { if (cprec) { Next = cprec->GetNext(); @@ -561,29 +564,6 @@ void PRXCOL::ReadColumn(PGLOBAL g) } // 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 --------------------------- */ /***********************************************************************/ @@ -591,32 +571,10 @@ PTDB TBCDEF::GetTable(PGLOBAL g, MODE m) /***********************************************************************/ 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. */ /***********************************************************************/ diff --git a/storage/connect/tabutil.h b/storage/connect/tabutil.h index 3a5946bae8f..b99cf959bca 100644 --- a/storage/connect/tabutil.h +++ b/storage/connect/tabutil.h @@ -132,34 +132,6 @@ class DllExport PRXCOL : public COLBLK { 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. */ /***********************************************************************/ diff --git a/storage/connect/tabxcl.cpp b/storage/connect/tabxcl.cpp index 78998435aa6..d64a730beb0 100644 --- a/storage/connect/tabxcl.cpp +++ b/storage/connect/tabxcl.cpp @@ -73,7 +73,7 @@ XCLDEF::XCLDEF(void) } // end of XCLDEF constructor /***********************************************************************/ -/* DefineAM: define specific AM block values from XCOL file. */ +/* DefineAM: define specific AM block values from XCOL table. */ /***********************************************************************/ bool XCLDEF::DefineAM(PGLOBAL g, LPCSTR am, int poff) { @@ -106,7 +106,7 @@ PTDB XCLDEF::GetTable(PGLOBAL g, MODE mode) TDBXCL::TDBXCL(PXCLDEF tdp) : TDBPRX(tdp) { Xcolumn = tdp->Xcol; // CSV column name - Xcolp = NULL; // To the XCVCOL column + Xcolp = NULL; // To the XCLCOL column Mult = tdp->Mult; // Multiplication factor N = 0; // The current table index M = 0; // The occurence rank @@ -115,33 +115,6 @@ TDBXCL::TDBXCL(PXCLDEF tdp) : TDBPRX(tdp) 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. */ /***********************************************************************/ @@ -165,7 +138,7 @@ int TDBXCL::GetMaxSize(PGLOBAL g) { if (MaxSize < 0) { if (InitTable(g)) - return NULL; + return 0; MaxSize = Mult * Tdbp->GetMaxSize(g); } // endif MaxSize @@ -174,8 +147,8 @@ int TDBXCL::GetMaxSize(PGLOBAL g) } // end of GetMaxSize /***********************************************************************/ -/* In this sample, ROWID will be the (virtual) row number, */ -/* while ROWNUM will be the occurence rank in the multiple column. */ +/* For this table type, ROWID is the (virtual) row number, */ +/* while ROWNUM is be the occurence rank in the multiple column. */ /***********************************************************************/ int TDBXCL::RowNumber(PGLOBAL g, bool b) { @@ -183,7 +156,7 @@ int TDBXCL::RowNumber(PGLOBAL g, bool b) } // end of RowNumber /***********************************************************************/ -/* XCV Access Method opening routine. */ +/* XCL Access Method opening routine. */ /***********************************************************************/ bool TDBXCL::OpenDB(PGLOBAL g) { @@ -206,7 +179,7 @@ bool TDBXCL::OpenDB(PGLOBAL g) } // endif Mode if (InitTable(g)) - return NULL; + return TRUE; /*********************************************************************/ /* Check and initialize the subtable columns. */ @@ -225,7 +198,7 @@ bool TDBXCL::OpenDB(PGLOBAL g) } // end of OpenDB /***********************************************************************/ -/* Data Base read routine for XCV access method. */ +/* Data Base read routine for XCL access method. */ /***********************************************************************/ int TDBXCL::ReadDB(PGLOBAL g) { diff --git a/storage/connect/tabxcl.h b/storage/connect/tabxcl.h index 79b890c9f55..28fbf85d509 100644 --- a/storage/connect/tabxcl.h +++ b/storage/connect/tabxcl.h @@ -45,7 +45,7 @@ class XCLDEF : public PRXDEF { /* Logical table description */ }; // end of XCLDEF /***********************************************************************/ -/* This is the class declaration for the XCSV table. */ +/* This is the class declaration for the XCOL table. */ /***********************************************************************/ class TDBXCL : public TDBPRX { friend class XCLDEF; @@ -64,7 +64,6 @@ class TDBXCL : public TDBPRX { // 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); @@ -77,7 +76,7 @@ class TDBXCL : public TDBPRX { 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 + bool New; // TRUE for new line char Sep; // The Xcol separator }; // end of class TDBXCL From be268bed3d893ef053ff35a4900cc1c125bb5769 Mon Sep 17 00:00:00 2001 From: Olivier Bertrand Date: Thu, 9 May 2013 16:16:45 +0200 Subject: [PATCH 08/47] - Fix inverted test on am in MYSQLDEF::DefineAM modified: storage/connect/tabmysql.cpp --- storage/connect/tabmysql.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/storage/connect/tabmysql.cpp b/storage/connect/tabmysql.cpp index b3401530c1b..3ecfd6aa6c1 100644 --- a/storage/connect/tabmysql.cpp +++ b/storage/connect/tabmysql.cpp @@ -283,7 +283,7 @@ bool MYSQLDEF::DefineAM(PGLOBAL g, LPCSTR am, int poff) Desc = "MySQL Table"; - if (!stricmp(am, "MYPRX")) { + if (stricmp(am, "MYPRX")) { // Normal case of specific MYSQL table if (!url || !*url) { // Not using the connection URL From 99d95c8a2fec8037738a4c700a163b206f9ab4c8 Mon Sep 17 00:00:00 2001 From: Olivier Bertrand Date: Fri, 10 May 2013 20:22:21 +0200 Subject: [PATCH 09/47] - Added table type PIVOT modified: storage/connect/filamdbf.cpp storage/connect/ha_connect.cc storage/connect/ha_connect.h storage/connect/mycat.cc storage/connect/myconn.cpp storage/connect/odbconn.cpp storage/connect/plgcnx.h storage/connect/plgdbsem.h storage/connect/plgdbutl.cpp storage/connect/tabfmt.cpp storage/connect/tabpivot.cpp storage/connect/tabpivot.h storage/connect/tabutil.cpp storage/connect/tabwmi.cpp storage/connect/tabxcl.cpp storage/connect/value.cpp storage/connect/value.h --- storage/connect/filamdbf.cpp | 7 +- storage/connect/ha_connect.cc | 10 +- storage/connect/ha_connect.h | 2 + storage/connect/mycat.cc | 9 +- storage/connect/myconn.cpp | 10 +- storage/connect/odbconn.cpp | 28 +- storage/connect/plgcnx.h | 11 - storage/connect/plgdbsem.h | 3 +- storage/connect/plgdbutl.cpp | 3 +- storage/connect/tabfmt.cpp | 6 +- storage/connect/tabpivot.cpp | 596 ++++++++++++++++++++-------------- storage/connect/tabpivot.h | 107 +++--- storage/connect/tabutil.cpp | 9 +- storage/connect/tabwmi.cpp | 6 +- storage/connect/tabxcl.cpp | 1 - storage/connect/value.cpp | 49 +-- storage/connect/value.h | 5 +- 17 files changed, 444 insertions(+), 418 deletions(-) diff --git a/storage/connect/filamdbf.cpp b/storage/connect/filamdbf.cpp index 3575a6b422a..0a67195b200 100644 --- a/storage/connect/filamdbf.cpp +++ b/storage/connect/filamdbf.cpp @@ -178,15 +178,13 @@ static int dbfhead(PGLOBAL g, FILE *file, PSZ fn, DBFHEADER *buf) /****************************************************************************/ PQRYRES DBFColumns(PGLOBAL g, const char *fn, BOOL info) { - static int dbtype[] = {DB_CHAR, DB_SHORT, DB_CHAR, - DB_INT, DB_INT, DB_SHORT}; static int buftyp[] = {TYPE_STRING, TYPE_SHORT, TYPE_STRING, TYPE_INT, TYPE_INT, TYPE_SHORT}; static XFLD fldtyp[] = {FLD_NAME, FLD_TYPE, FLD_TYPENAME, FLD_PREC, FLD_LENGTH, FLD_SCALE}; static unsigned int length[] = {11, 6, 8, 10, 10, 6}; char buf[2], filename[_MAX_PATH]; - int ncol = sizeof(dbtype) / sizeof(int); + int ncol = sizeof(buftyp) / sizeof(int); int rc, type, len, field, fields; BOOL bad; DBFHEADER mainhead; @@ -228,8 +226,7 @@ PQRYRES DBFColumns(PGLOBAL g, const char *fn, BOOL info) fields = 0; qrp = PlgAllocResult(g, ncol, fields, IDS_COLUMNS + 3, - dbtype, buftyp, fldtyp, length, true, false); -//qrp->Info = info || (rc == RC_INFO); + buftyp, fldtyp, length, true, false); if (info) return qrp; diff --git a/storage/connect/ha_connect.cc b/storage/connect/ha_connect.cc index 2eefd1e20d2..298fb71b334 100644 --- a/storage/connect/ha_connect.cc +++ b/storage/connect/ha_connect.cc @@ -207,6 +207,8 @@ ha_create_table_option connect_table_option_list[]= HA_TOPTION_STRING("MODULE", module), HA_TOPTION_STRING("SUBTYPE", subtype), HA_TOPTION_STRING("CATFUNC", catfunc), + HA_TOPTION_STRING("SRCDEF", srcdef), + HA_TOPTION_STRING("COLIST", colist), HA_TOPTION_STRING("OPTION_LIST", oplist), HA_TOPTION_STRING("DATA_CHARSET", data_charset), HA_TOPTION_NUMBER("LRECL", lrecl, 0, 0, INT_MAX32, 1), @@ -590,7 +592,7 @@ static char *GetListOption(PGLOBAL g, const char *opname, } else { if (pn) { - n= pn - pk; + n= min(pn - pk, 15); memcpy(key, pk, n); key[n]= 0; } else @@ -655,6 +657,10 @@ char *ha_connect::GetStringOption(char *opname, char *sdef) opval= (char*)options->subtype; else if (!stricmp(opname, "Catfunc")) opval= (char*)options->catfunc; + else if (!stricmp(opname, "Srcdef")) + opval= (char*)options->srcdef; + else if (!stricmp(opname, "Colist")) + opval= (char*)options->colist; else if (!stricmp(opname, "Data_charset")) opval= (char*)options->data_charset; @@ -2667,7 +2673,6 @@ bool ha_connect::check_privileges(THD *thd, PTOS options) case TAB_JCT: case TAB_DMY: case TAB_NIY: - case TAB_PIVOT: my_printf_error(ER_UNKNOWN_ERROR, "Unsupported table type %s", MYF(0), options->type); return true; @@ -2706,6 +2711,7 @@ bool ha_connect::check_privileges(THD *thd, PTOS options) case TAB_XCL: case TAB_PRX: case TAB_OCCUR: + case TAB_PIVOT: return false; } diff --git a/storage/connect/ha_connect.h b/storage/connect/ha_connect.h index 53339d168d0..0d6354ca078 100644 --- a/storage/connect/ha_connect.h +++ b/storage/connect/ha_connect.h @@ -83,6 +83,8 @@ struct ha_table_option_struct { const char *module; const char *subtype; const char *catfunc; + const char *srcdef; + const char *colist; const char *oplist; const char *data_charset; ulonglong lrecl; diff --git a/storage/connect/mycat.cc b/storage/connect/mycat.cc index badcdcb9514..7b7f79d7b58 100644 --- a/storage/connect/mycat.cc +++ b/storage/connect/mycat.cc @@ -132,6 +132,9 @@ TABTYPE GetTypeID(const char *type) : (!stricmp(type, "OCCUR")) ? TAB_OCCUR : (!stricmp(type, "CATLG")) ? TAB_PRX // Legacy : (!stricmp(type, "PROXY")) ? TAB_PRX +#ifdef PIVOT_SUPPORT + : (!stricmp(type, "PIVOT")) ? TAB_PIVOT +#endif : (!stricmp(type, "OEM")) ? TAB_OEM : TAB_NIY; } // end of GetTypeID @@ -650,9 +653,9 @@ PRELDEF MYCAT::MakeTableDesc(PGLOBAL g, LPCSTR name, LPCSTR am) #if defined(MYSQL_SUPPORT) case TAB_MYSQL: tdp= new(g) MYSQLDEF; break; #endif // MYSQL_SUPPORT -//#if defined(PIVOT_SUPPORT) -// case TAB_PIVOT: tdp= new(g) PIVOTDEF; break; -//#endif // PIVOT_SUPPORT +#if defined(PIVOT_SUPPORT) + case TAB_PIVOT: tdp= new(g) PIVOTDEF; break; +#endif // PIVOT_SUPPORT default: sprintf(g->Message, MSG(BAD_TABLE_TYPE), am, name); } // endswitch diff --git a/storage/connect/myconn.cpp b/storage/connect/myconn.cpp index 53a2496b197..fab2af54aa7 100644 --- a/storage/connect/myconn.cpp +++ b/storage/connect/myconn.cpp @@ -74,10 +74,7 @@ PQRYRES MyColumns(PGLOBAL g, const char *host, const char *db, const char *table, const char *colpat, int port, bool key, bool info) { - static int dbtype[] = {DB_CHAR, DB_SHORT, DB_CHAR, DB_INT, - DB_CHAR, DB_SHORT, DB_SHORT, DB_SHORT, - DB_CHAR, DB_CHAR, DB_CHAR}; - static int buftyp[] = {TYPE_STRING, TYPE_SHORT, TYPE_STRING, TYPE_INT, + static int buftyp[] = {TYPE_STRING, TYPE_SHORT, TYPE_STRING, TYPE_INT, TYPE_STRING, TYPE_SHORT, TYPE_SHORT, TYPE_SHORT, TYPE_STRING, TYPE_STRING, TYPE_STRING}; static XFLD fldtyp[] = {FLD_NAME, FLD_TYPE, FLD_TYPENAME, FLD_PREC, @@ -85,7 +82,7 @@ PQRYRES MyColumns(PGLOBAL g, const char *host, const char *db, FLD_REM, FLD_NO, FLD_CHARSET}; static unsigned int length[] = {0, 4, 16, 4, 4, 4, 4, 4, 256, 32, 32}; char *fld, *fmt, cmd[128]; - int i, n, nf, ncol = sizeof(dbtype) / sizeof(int); + int i, n, nf, ncol = sizeof(buftyp) / sizeof(int); int len, type, prec, rc, k = 0; PQRYRES qrp; PCOLRES crp; @@ -134,7 +131,7 @@ PQRYRES MyColumns(PGLOBAL g, const char *host, const char *db, /* Allocate the structures used to refer to the result set. */ /**********************************************************************/ qrp = PlgAllocResult(g, ncol, n, IDS_COLUMNS + 3, - dbtype, buftyp, fldtyp, length, true, true); + buftyp, fldtyp, length, true, true); // Some columns must be renamed for (i = 0, crp = qrp->Colresp; crp; crp = crp->Next) @@ -665,7 +662,6 @@ PQRYRES MYSQLC::GetResult(PGLOBAL g, bool pdb) crp->Prec = fld->decimals; crp->Length = fld->max_length; crp->Clen = GetTypeSize(crp->Type, crp->Length); - crp->DBtype = GetDBType((int)crp->Type); if (!(crp->Kdata = AllocValBlock(g, NULL, crp->Type, m_Rows, crp->Clen, 0, FALSE, TRUE))) { diff --git a/storage/connect/odbconn.cpp b/storage/connect/odbconn.cpp index 6de2acef391..e32e666e1fe 100644 --- a/storage/connect/odbconn.cpp +++ b/storage/connect/odbconn.cpp @@ -230,11 +230,7 @@ void ResetNullValues(CATPARM *cap) PQRYRES ODBCColumns(PGLOBAL g, char *dsn, char *table, char *colpat, bool info) { - static int dbtype[] = {DB_CHAR, DB_CHAR, DB_CHAR, - DB_CHAR, DB_SHORT, DB_CHAR, - DB_INT, DB_INT, DB_SHORT, - DB_SHORT, DB_SHORT, DB_CHAR}; - static int buftyp[] = {TYPE_STRING, TYPE_STRING, TYPE_STRING, + static int buftyp[] = {TYPE_STRING, TYPE_STRING, TYPE_STRING, TYPE_STRING, TYPE_SHORT, TYPE_STRING, TYPE_INT, TYPE_INT, TYPE_SHORT, TYPE_SHORT, TYPE_SHORT, TYPE_STRING}; @@ -285,7 +281,7 @@ PQRYRES ODBCColumns(PGLOBAL g, char *dsn, char *table, /* Allocate the structures used to refer to the result set. */ /************************************************************************/ qrp = PlgAllocResult(g, ncol, maxres, IDS_COLUMNS, - dbtype, buftyp, fldtyp, length, true, true); + buftyp, fldtyp, length, true, true); if (info) // Info table return qrp; @@ -396,7 +392,6 @@ PQRYRES MyODBCCols(PGLOBAL g, char *dsn, char *tab, bool info) /*************************************************************************/ PQRYRES ODBCDataSources(PGLOBAL g, bool info) { - static int dbtype[] = {DB_CHAR, DB_CHAR}; static int buftyp[] = {TYPE_STRING, TYPE_STRING}; static XFLD fldtyp[] = {FLD_NAME, FLD_REM}; static unsigned int length[] = {0, 256}; @@ -425,7 +420,7 @@ PQRYRES ODBCDataSources(PGLOBAL g, bool info) /* Allocate the structures used to refer to the result set. */ /************************************************************************/ qrp = PlgAllocResult(g, ncol, maxres, IDS_DSRC, - dbtype, buftyp, fldtyp, length, true, true); + buftyp, fldtyp, length, true, true); /************************************************************************/ /* Now get the results into blocks. */ @@ -446,7 +441,6 @@ PQRYRES ODBCDataSources(PGLOBAL g, bool info) /*************************************************************************/ PQRYRES ODBCDrivers(PGLOBAL g, bool info) { - static int dbtype[] = {DB_CHAR, DB_CHAR}; static int buftyp[] = {TYPE_STRING, TYPE_STRING}; static XFLD fldtyp[] = {FLD_NAME, FLD_REM}; static unsigned int length[] = {128, 256}; @@ -471,7 +465,7 @@ PQRYRES ODBCDrivers(PGLOBAL g, bool info) /* Allocate the structures used to refer to the result set. */ /************************************************************************/ qrp = PlgAllocResult(g, ncol, maxres, IDS_DRIVER, - dbtype, buftyp, fldtyp, length, true, true); + buftyp, fldtyp, length, true, true); /************************************************************************/ /* Now get the results into blocks. */ @@ -492,8 +486,7 @@ PQRYRES ODBCDrivers(PGLOBAL g, bool info) /***********************************************************************/ PQRYRES ODBCTables(PGLOBAL g, char *dsn, char *tabpat, bool info) { - static int dbtype[] = {DB_CHAR, DB_CHAR, DB_CHAR, DB_CHAR, DB_CHAR}; - static int buftyp[] = {TYPE_STRING, TYPE_STRING, TYPE_STRING, + static int buftyp[] = {TYPE_STRING, TYPE_STRING, TYPE_STRING, TYPE_STRING, TYPE_STRING}; static XFLD fldtyp[] = {FLD_QUALIF, FLD_OWNER, FLD_NAME, FLD_TYPE, FLD_REM}; @@ -536,7 +529,7 @@ PQRYRES ODBCTables(PGLOBAL g, char *dsn, char *tabpat, bool info) /************************************************************************/ /* Allocate the structures used to refer to the result set. */ /************************************************************************/ - qrp = PlgAllocResult(g, ncol, maxres, IDS_TABLES, dbtype, buftyp, + qrp = PlgAllocResult(g, ncol, maxres, IDS_TABLES, buftyp, fldtyp, length, true, true); if (info) @@ -579,8 +572,6 @@ PQRYRES ODBCTables(PGLOBAL g, char *dsn, char *tabpat, bool info) /**************************************************************************/ PQRYRES ODBCPrimaryKeys(PGLOBAL g, ODBConn *op, char *dsn, char *table) { - static int dbtype[] = {DB_CHAR, DB_CHAR, DB_CHAR, - DB_CHAR, DB_SHORT, DB_CHAR}; static int buftyp[] = {TYPE_STRING, TYPE_STRING, TYPE_STRING, TYPE_STRING, TYPE_SHORT, TYPE_STRING}; static unsigned int length[] = {0, 0, 0, 0, 6, 128}; @@ -623,7 +614,7 @@ PQRYRES ODBCPrimaryKeys(PGLOBAL g, ODBConn *op, char *dsn, char *table) /* Allocate the structure used to refer to the result set. */ /************************************************************************/ qrp = PlgAllocResult(g, ncol, maxres, IDS_PKEY, - dbtype, buftyp, NULL, length, true, true); + buftyp, NULL, length, true, true); if (trace) htrc("Getting pkey results ncol=%d\n", qrp->Nbcol); @@ -662,9 +653,6 @@ PQRYRES ODBCPrimaryKeys(PGLOBAL g, ODBConn *op, char *dsn, char *table) PQRYRES ODBCStatistics(PGLOBAL g, ODBConn *op, char *dsn, char *pat, int un, int acc) { - static int dbtype[] = {DB_CHAR, DB_CHAR, DB_CHAR, DB_SHORT, DB_CHAR, - DB_CHAR, DB_SHORT, DB_SHORT, DB_CHAR, DB_CHAR, - DB_INT, DB_INT, DB_CHAR}; static int buftyp[] = {TYPE_STRING, TYPE_STRING, TYPE_STRING, TYPE_SHORT, TYPE_STRING, TYPE_STRING, TYPE_SHORT, TYPE_SHORT, TYPE_STRING, @@ -708,7 +696,7 @@ PQRYRES ODBCStatistics(PGLOBAL g, ODBConn *op, char *dsn, char *pat, /* Allocate the structure used to refer to the result set. */ /************************************************************************/ qrp = PlgAllocResult(g, ncol, maxres, IDS_STAT, - dbtype, buftyp, NULL, length, true, true); + buftyp, NULL, length, true, true); if (trace) htrc("Getting stat results ncol=%d\n", qrp->Nbcol); diff --git a/storage/connect/plgcnx.h b/storage/connect/plgcnx.h index 33b0ba64edc..7ce72b45268 100644 --- a/storage/connect/plgcnx.h +++ b/storage/connect/plgcnx.h @@ -49,17 +49,6 @@ enum RCODE {RC_OK = 0, /* No error return code */ RC_INFO = 4}; /* Success with info */ #endif // !RC_OK_DEFINED -/**************************************************************************/ -/* Data types. */ -/**************************************************************************/ -enum XDBTYPE {DB_ERROR = 0, /* Unknown or wrong type */ - DB_STRING = 1, /* Null terminated string */ - DB_CHAR = 2, /* Character array */ - DB_SHORT = 3, /* Used by some catalog functions */ - DB_INT = 4, /* Long integer array */ - DB_DOUBLE = 5, /* Double float array */ - DB_DATE = 6}; /* Datetime value array */ - /**************************************************************************/ /* Index of info values within the info int integer array. */ /**************************************************************************/ diff --git a/storage/connect/plgdbsem.h b/storage/connect/plgdbsem.h index a1eaf97bd10..5eb55c4a29b 100644 --- a/storage/connect/plgdbsem.h +++ b/storage/connect/plgdbsem.h @@ -513,7 +513,6 @@ typedef struct _colres { PVBLK Kdata; /* Column block of values */ char *Nulls; /* Column null value array */ int Type; /* Internal type */ - int DBtype; /* Data type */ int Datasize; /* Overall data size */ int Ncol; /* Column number */ int Clen; /* Data individual internal size */ @@ -545,7 +544,7 @@ int ExtractDate(char *, PDTP, int, int val[6]); /* Allocate the result structure that will contain result data. */ /**************************************************************************/ PQRYRES PlgAllocResult(PGLOBAL g, int ncol, int maxres, int ids, - int *dbtype, int *buftyp, XFLD *fldtyp, + int *buftyp, XFLD *fldtyp, unsigned int *length, bool blank, bool nonull); /***********************************************************************/ diff --git a/storage/connect/plgdbutl.cpp b/storage/connect/plgdbutl.cpp index 6d1e502945b..32ee105c19c 100644 --- a/storage/connect/plgdbutl.cpp +++ b/storage/connect/plgdbutl.cpp @@ -270,7 +270,7 @@ void ptrc(char const *fmt, ...) /* Allocate the result structure that will contain result data. */ /**************************************************************************/ PQRYRES PlgAllocResult(PGLOBAL g, int ncol, int maxres, int ids, - int *dbtype, int *buftyp, XFLD *fldtyp, + int *buftyp, XFLD *fldtyp, unsigned int *length, bool blank, bool nonull) { char cname[NAM_LEN+1]; @@ -304,7 +304,6 @@ PQRYRES PlgAllocResult(PGLOBAL g, int ncol, int maxres, int ids, crp->Length = length[i]; crp->Clen = GetTypeSize(crp->Type, length[i]); crp->Prec = 0; - crp->DBtype = dbtype[i]; if (ids > 0) { #if defined(XMSG) diff --git a/storage/connect/tabfmt.cpp b/storage/connect/tabfmt.cpp index 51631107f6e..aaa32a57f04 100644 --- a/storage/connect/tabfmt.cpp +++ b/storage/connect/tabfmt.cpp @@ -78,8 +78,6 @@ extern "C" int trace; PQRYRES CSVColumns(PGLOBAL g, const char *fn, char sep, char q, int hdr, int mxr, bool info) { - static int dbtype[] = {DB_CHAR, DB_SHORT, DB_CHAR, - DB_INT, DB_INT, DB_SHORT}; static int buftyp[] = {TYPE_STRING, TYPE_SHORT, TYPE_STRING, TYPE_INT, TYPE_INT, TYPE_SHORT}; static XFLD fldtyp[] = {FLD_NAME, FLD_TYPE, FLD_TYPENAME, @@ -87,7 +85,7 @@ PQRYRES CSVColumns(PGLOBAL g, const char *fn, char sep, char q, static unsigned int length[] = {6, 6, 8, 10, 10, 6}; char *p, *colname[MAXCOL], dechar, filename[_MAX_PATH], buf[4096]; int i, imax, hmax, n, nerr, phase, blank, digit, dec, type; - int ncol = sizeof(dbtype) / sizeof(int); + int ncol = sizeof(buftyp) / sizeof(int); int num_read = 0, num_max = 10000000; // Statistics int len[MAXCOL], typ[MAXCOL], prc[MAXCOL]; FILE *infile; @@ -341,7 +339,7 @@ PQRYRES CSVColumns(PGLOBAL g, const char *fn, char sep, char q, /* Allocate the structures used to refer to the result set. */ /*********************************************************************/ qrp = PlgAllocResult(g, ncol, imax, IDS_COLUMNS + 3, - dbtype, buftyp, fldtyp, length, true, false); + buftyp, fldtyp, length, true, false); qrp->Nblin = imax; if (info) diff --git a/storage/connect/tabpivot.cpp b/storage/connect/tabpivot.cpp index fccd8338d8a..429bb88e0fc 100644 --- a/storage/connect/tabpivot.cpp +++ b/storage/connect/tabpivot.cpp @@ -1,11 +1,11 @@ /************ TabPivot C++ Program Source Code File (.CPP) *************/ /* PROGRAM NAME: TABPIVOT */ /* ------------- */ -/* Version 1.3 */ +/* Version 1.4 */ /* */ /* COPYRIGHT: */ /* ---------- */ -/* (C) Copyright to the author Olivier BERTRAND 2005-2012 */ +/* (C) Copyright to the author Olivier BERTRAND 2005-2013 */ /* */ /* WHAT THIS PROGRAM DOES: */ /* ----------------------- */ @@ -41,10 +41,13 @@ #include "global.h" #include "plgdbsem.h" #include "xtable.h" -#include "xindex.h" +//#include "xindex.h" +#include "tabcol.h" #include "colblk.h" -#include "tabmysql.h" +//#include "tabmysql.h" +#include "myconn.h" #include "csort.h" +#include "tabutil.h" #include "tabpivot.h" #include "valblk.h" #include "ha_connect.h" @@ -52,111 +55,7 @@ extern "C" int trace; -/* --------------- Implementation of the PIVOT classes --------------- */ - -/***********************************************************************/ -/* DefineAM: define specific AM block values from PIVOT table. */ -/***********************************************************************/ -bool PIVOTDEF::DefineAM(PGLOBAL g, LPCSTR am, int poff) - { - char *p1, *p2; - PHC hc = ((MYCAT*)Cat)->GetHandler(); - - Host = Cat->GetStringCatInfo(g, Name, "Host", "localhost"); - User = Cat->GetStringCatInfo(g, Name, "User", "root"); - Pwd = Cat->GetStringCatInfo(g, Name, "Password", NULL); - DB = Cat->GetStringCatInfo(g, Name, "Database", (PSZ)hc->GetDBName(NULL)); - Tabsrc = Cat->GetStringCatInfo(g, Name, "SrcDef", NULL); - Tabname = Cat->GetStringCatInfo(g, Name, "Name", NULL); - Picol = Cat->GetStringCatInfo(g, Name, "PivotCol", NULL); - Fncol = Cat->GetStringCatInfo(g, Name, "FncCol", NULL); - - // If fncol is like avg(colname), separate Fncol and Function - if (Fncol && (p1 = strchr(Fncol, '(')) && (p2 = strchr(p1, ')')) && - (*Fncol != '"') && (!*(p2+1))) { - *p1++ = '\0'; *p2 = '\0'; - Function = Fncol; - Fncol = p1; - } else - Function = Cat->GetStringCatInfo(g, Name, "Function", "SUM"); - - GBdone = Cat->GetIntCatInfo(Name, "Groupby", 0) ? TRUE : FALSE; - Port = Cat->GetIntCatInfo(Name, "Port", 3306); - Desc = (*Tabname) ? Tabname : Tabsrc; - return FALSE; - } // end of DefineAM - -/***********************************************************************/ -/* GetTable: makes a new TDB of the proper type. */ -/***********************************************************************/ -PTDB PIVOTDEF::GetTable(PGLOBAL g, MODE m) - { - return new(g) TDBPIVOT(this); - } // end of GetTable - -/* ------------------------------------------------------------------- */ - -/***********************************************************************/ -/* Implementation of the TDBPIVOT class. */ -/***********************************************************************/ -TDBPIVOT::TDBPIVOT(PPIVOTDEF tdp) : TDBASE(tdp), CSORT(FALSE) - { - Tqrp = NULL; - Host = tdp->Host; - Database = tdp->DB; - User = tdp->User; - Pwd = tdp->Pwd; - Port = tdp->Port; - Qryp = NULL; - Tabname = tdp->Tabname; // Name of source table - Tabsrc = tdp->Tabsrc; // SQL description of source table - Picol = tdp->Picol; // Pivot column name - Fncol = tdp->Fncol; // Function column name - Function = tdp->Function; // Aggregate function name - Xcolp = NULL; // To the FNCCOL column -//Xresp = NULL; // To the pivot result column -//Rblkp = NULL; // The value block of the pivot column - Fcolp = NULL; // To the function column - GBdone = tdp->GBdone; - Mult = -1; // Estimated table size - N = 0; // The current table index - M = 0; // The occurence rank - FileStatus = 0; // Logical End-of-File - RowFlag = 0; // 0: Ok, 1: Same, 2: Skip - } // end of TDBPIVOT constructor - #if 0 -TDBPIVOT::TDBPIVOT(PTDBPIVOT tdbp) : TDBASE(tdbp), CSORT(FALSE) - { - Tdbp = tdbp->Tdbp; - Sqlp = tdbp->Sqlp; - Qryp = tdbp->Qryp; - Tabname = tdbp->Tabname; - Tabsrc = tdbp->Tabsrc; - Picol = tdbp->Picol; - Fncol = tdbp->Fncol; - Function = tdbp->Function; - Xcolp = tdbp->Xcolp; - Xresp = tdbp->Xresp; - Rblkp = tdbp->Rblkp; - Fcolp = tdbp->Fcolp; - Mult = tdbp->Mult; - N = tdbp->N; - M = tdbp->M; - FileStatus = tdbp->FileStatus; - RowFlag = tdbp->RowFlag; - } // end of TDBPIVOT copy constructor - -// Is this really useful ??? -PTDB TDBPIVOT::CopyOne(PTABS t) - { - PTDB tp = new(t->G) TDBPIVOT(this); - - tp->SetColumns(Columns); - return tp; - } // end of CopyOne -#endif // 0 - /***********************************************************************/ /* Prepare the source table Query. */ /***********************************************************************/ @@ -165,14 +64,17 @@ PQRYRES TDBPIVOT::GetSourceTable(PGLOBAL g) if (Qryp) return Qryp; // Already done - if (!Tabsrc && Tabname) { + if (Tabname) { char *def, *colist; size_t len = 0; PCOL colp; PDBUSER dup = (PDBUSER)g->Activityp->Aptr; + if (InitTable(g)) + return NULL; + // Evaluate the length of the column list - for (colp = Columns; colp; colp = colp->GetNext()) + for (colp = Tdbp->Columns; colp; colp = colp->GetNext()) len += (strlen(colp->GetName()) + 2); *(colist = (char*)PlugSubAlloc(g, NULL, len)) = 0; @@ -182,7 +84,7 @@ PQRYRES TDBPIVOT::GetSourceTable(PGLOBAL g) strcpy(def, "SELECT "); if (!Fncol) { - for (colp = Columns; colp; colp = colp->GetNext()) + for (colp = Tdbp->Columns; colp; colp = colp->GetNext()) if (!Picol || stricmp(Picol, colp->GetName())) Fncol = colp->GetName(); @@ -199,7 +101,7 @@ PQRYRES TDBPIVOT::GetSourceTable(PGLOBAL g) if (!Picol) { // Find default Picol as the last one not equal to Fncol - for (colp = Columns; colp; colp = colp->GetNext()) + for (colp = Tdbp->Columns; colp; colp = colp->GetNext()) if (!Fncol || stricmp(Fncol, colp->GetName())) Picol = colp->GetName(); @@ -357,7 +259,6 @@ int TDBPIVOT::MakePivotColumns(PGLOBAL g) return Mult; } // end of MakePivotColumns -#if 0 /***********************************************************************/ /* Update fields in the MySQL table structure */ /* Note: this does not work. Indeed the new rows are correctly made */ @@ -529,31 +430,257 @@ bool TDBPIVOT::UpdateTableFields(PGLOBAL g, int n) } // end of UpdateTableFields #endif // 0 +/* --------------- Implementation of the PIVOT classes --------------- */ + +/***********************************************************************/ +/* PIVOTDEF constructor. */ +/***********************************************************************/ + PIVOTDEF::PIVOTDEF(void) + { + Host = User = Pwd = DB = NULL; + Tabname = Tabsrc = Picol = Fncol = Function = NULL; + GBdone = Accept = false; + Port = 0; + } // end of PIVOTDEF constructor + +/***********************************************************************/ +/* DefineAM: define specific AM block values from PIVOT table. */ +/***********************************************************************/ +bool PIVOTDEF::DefineAM(PGLOBAL g, LPCSTR am, int poff) + { + char *p1, *p2; + PHC hc = ((MYCAT*)Cat)->GetHandler(); + + if (!PRXDEF::DefineAM(g, am, poff)) { + Tabname = (char*)Tablep->GetName(); + DB = (char*)Tablep->GetQualifier(); + } else { + DB = Cat->GetStringCatInfo(g, "Database", "*"); + Tabsrc = Cat->GetStringCatInfo(g, "SrcDef", NULL); + } // endif + + Host = Cat->GetStringCatInfo(g, "Host", "localhost"); + User = Cat->GetStringCatInfo(g, "User", "*"); + Pwd = Cat->GetStringCatInfo(g, "Password", NULL); + Picol = Cat->GetStringCatInfo(g, "PivotCol", NULL); + Fncol = Cat->GetStringCatInfo(g, "FncCol", NULL); + + // If fncol is like avg(colname), separate Fncol and Function + if (Fncol && (p1 = strchr(Fncol, '(')) && (p2 = strchr(p1, ')')) && + (*Fncol != '"') && (!*(p2+1))) { + *p1++ = '\0'; *p2 = '\0'; + Function = Fncol; + Fncol = p1; + } else + Function = Cat->GetStringCatInfo(g, "Function", "SUM"); + + GBdone = Cat->GetBoolCatInfo("Groupby", false); + Accept = Cat->GetBoolCatInfo("Accept", false); + Port = Cat->GetIntCatInfo("Port", 3306); + Desc = (Tabname) ? Tabname : Tabsrc; + return FALSE; + } // end of DefineAM + +/***********************************************************************/ +/* GetTable: makes a new TDB of the proper type. */ +/***********************************************************************/ +PTDB PIVOTDEF::GetTable(PGLOBAL g, MODE m) + { + return new(g) TDBPIVOT(this); + } // end of GetTable + +/* ------------------------------------------------------------------- */ + +/***********************************************************************/ +/* Implementation of the TDBPIVOT class. */ +/***********************************************************************/ +TDBPIVOT::TDBPIVOT(PPIVOTDEF tdp) : TDBPRX(tdp) + { + Host = tdp->Host; + Database = tdp->DB; + User = tdp->User; + Pwd = tdp->Pwd; + Port = tdp->Port; + Tabname = tdp->Tabname; // Name of source table + Tabsrc = tdp->Tabsrc; // SQL description of source table + Picol = tdp->Picol; // Pivot column name + Fncol = tdp->Fncol; // Function column name + Function = tdp->Function; // Aggregate function name + Xcolp = NULL; // To the FNCCOL column +//Xresp = NULL; // To the pivot result column +//Rblkp = NULL; // The value block of the pivot column + Fcolp = NULL; // To the function column + Dcolp = NULL; // To the dump column + GBdone = tdp->GBdone; + Accept = tdp->Accept; + Mult = -1; // Estimated table size + N = 0; // The current table index + M = 0; // The occurence rank + FileStatus = 0; // Logical End-of-File + RowFlag = 0; // 0: Ok, 1: Same, 2: Skip + } // end of TDBPIVOT constructor + +/***********************************************************************/ +/* Prepare the source table Query. */ +/***********************************************************************/ +bool TDBPIVOT::GetSourceTable(PGLOBAL g) + { + if (Tdbp) + return false; // Already done + + if (Tabname) { + PTABDEF defp; + PCOLDEF cdp; + + if (InitTable(g)) + return true; + else + defp = Tdbp->GetDef(); + + if (!Fncol) { + for (cdp = defp->GetCols(); cdp; cdp = cdp->GetNext()) + if (!Picol || stricmp(Picol, cdp->GetName())) + Fncol = cdp->GetName(); + + if (!Fncol) { + strcpy(g->Message, MSG(NO_DEF_FNCCOL)); + return true; + } // endif Fncol + + } // endif Fncol + + if (!Picol) { + // Find default Picol as the last one not equal to Fncol + for (cdp = defp->GetCols(); cdp; cdp = cdp->GetNext()) + if (!Fncol || stricmp(Fncol, cdp->GetName())) + Picol = cdp->GetName(); + + if (!Picol) { + strcpy(g->Message, MSG(NO_DEF_PIVOTCOL)); + return true; + } // endif Picol + + } // endif Picol + + if (!GBdone) { + char *colist; + + // Locate the suballocated colist (size is not known yet) + *(colist = (char*)PlugSubAlloc(g, NULL, 0)) = 0; + + // Make the column list + for (cdp = To_Def->GetCols(); cdp; cdp = cdp->GetNext()) + if (!cdp->GetOffset()) + strcat(strcat(colist, cdp->GetName()), ", "); + + // Add the Pivot column at the end of the list + strcat(colist, Picol); + + // Now we know how much was suballocated + PlugSubAlloc(g, NULL, strlen(colist)); + + // Locate the source string (size is not known yet) + Tabsrc = (char*)PlugSubAlloc(g, NULL, 0); + + // Start making the definition + strcat(strcat(strcpy(Tabsrc, "SELECT "), colist), ", "); + + // Make it suitable for Pivot by doing the group by + strcat(strcat(Tabsrc, Function), "("); + strcat(strcat(strcat(Tabsrc, Fncol), ") "), Fncol); + strcat(strcat(Tabsrc, " FROM "), Tabname); + strcat(strcat(Tabsrc, " GROUP BY "), colist); + + // Now we know how much was suballocated + PlugSubAlloc(g, NULL, strlen(Tabsrc)); + } // endif !GBdone + + } else if (!Tabsrc) { + strcpy(g->Message, MSG(SRC_TABLE_UNDEF)); + return true; + } // endif + + if (Tabsrc) { + MYSQLC myc; // MySQL connection class + PQRYRES qryp; + PCOLRES crp; + int w; + + // Open a MySQL connection for this table + if (myc.Open(g, Host, Database, User, Pwd, Port)) + return true; + + // Send the source command to MySQL + if (myc.ExecSQL(g, Tabsrc, &w) == RC_FX) { + myc.Close(); + return true; + } // endif Exec + + // We must have a storage query to get pivot column values + qryp = myc.GetResult(g); + myc.Close(); + Tdbp = new(g) TDBQRS(qryp); + + if (!Fncol) { + for (crp = qryp->Colresp; crp; crp = crp->Next) + if (!Picol || stricmp(Picol, crp->Name)) + Fncol = crp->Name; + + if (!Fncol) { + strcpy(g->Message, MSG(NO_DEF_FNCCOL)); + return true; + } // endif Fncol + + } // endif Fncol + + if (!Picol) { + // Find default Picol as the last one not equal to Fncol + for (crp = qryp->Colresp; crp; crp = crp->Next) + if (!Fncol || stricmp(Fncol, crp->Name)) + Picol = crp->Name; + + if (!Picol) { + strcpy(g->Message, MSG(NO_DEF_PIVOTCOL)); + return true; + } // endif Picol + + } // endif Picol + + } // endif Tabsrc + + // Now it is time to allocate the pivot and function columns + if (!(Fcolp = Tdbp->ColDB(g, Fncol, 0))) { + // Function column not found in table + sprintf(g->Message, MSG(COL_ISNOT_TABLE), Fncol, Tabname); + return true; + } else if (Fcolp->InitValue(g)) + return true; + + if (!(Xcolp = Tdbp->ColDB(g, Picol, 0))) { + // Pivot column not found in table + sprintf(g->Message, MSG(COL_ISNOT_TABLE), Picol, Tabname); + return true; + } else if (Xcolp->InitValue(g)) + return true; + + return false; + } // end of GetSourceTable + /***********************************************************************/ /* Allocate source column description block. */ /***********************************************************************/ PCOL TDBPIVOT::MakeCol(PGLOBAL g, PCOLDEF cdp, PCOL cprec, int n) { - PCOL colp = NULL; + PCOL colp; -//if (stricmp(cdp->GetName(), Picol) && stricmp(cdp->GetName(), Fncol)) { - colp = new(g) COLBLK(cdp, this, n); + if (cdp->GetOffset()) { + colp = new(g) FNCCOL(cdp, this, cprec, n); -// if (((PSRCCOL)colp)->Init(g, this)) -// return NULL; + if (cdp->GetOffset() > 1) + Dcolp = colp; -//} else { -// sprintf(g->Message, MSG(NO_MORE_COL), cdp->GetName()); -// return NULL; -//} // endif Name - - if (cprec) { - colp->SetNext(cprec->GetNext()); - cprec->SetNext(colp); - } else { - colp->SetNext(Columns); - Columns = colp; - } // endif cprec + } else + colp = new(g) SRCCOL(cdp, this, cprec, n); return colp; } // end of MakeCol @@ -598,13 +725,6 @@ bool TDBPIVOT::OpenDB(PGLOBAL g) return FALSE; } // endif use - /*********************************************************************/ - /* Do it here if not done yet (should not be the case). */ - /*********************************************************************/ -//if (MakePivotColumns(g) < 0) - if (!(Qryp = GetSourceTable(g))) - return TRUE; - if (Mode != MODE_READ) { /*******************************************************************/ /* Currently PIVOT tables cannot be modified. */ @@ -621,6 +741,30 @@ bool TDBPIVOT::OpenDB(PGLOBAL g) return TRUE; } // endif To_Key_Col + /*********************************************************************/ + /* Do it here if not done yet (should not be the case). */ + /*********************************************************************/ + if (GetSourceTable(g)) + return TRUE; + + /*********************************************************************/ + /* Check and initialize the subtable columns. */ + /*********************************************************************/ + for (PCOL cp = Columns; cp; cp = cp->GetNext()) + if (cp->GetAmType() == TYPE_AM_SRC) { + if (((PPRXCOL)cp)->Init(g)) + return TRUE; + + } else if (cp->GetAmType() == TYPE_AM_FNC) + if (((PFNCCOL)cp)->InitColumn(g)) + return TRUE; + + /*********************************************************************/ + /* Physically open the object table. */ + /*********************************************************************/ + if (Tdbp->OpenDB(g)) + return TRUE; + return FALSE; } // end of OpenDB @@ -632,7 +776,6 @@ int TDBPIVOT::ReadDB(PGLOBAL g) int rc = RC_OK; bool newrow = FALSE; PCOL colp; - PVAL vp1, vp2; if (FileStatus == 2) return RC_EF; @@ -652,7 +795,7 @@ int TDBPIVOT::ReadDB(PGLOBAL g) /*********************************************************************/ do { if (RowFlag != 1) { - if ((rc = Tqrp->ReadDB(g)) != RC_OK) { + if ((rc = Tdbp->ReadDB(g)) != RC_OK) { if (FileStatus && rc == RC_EF) { // A prepared row remains to be sent FileStatus = 2; @@ -662,14 +805,16 @@ int TDBPIVOT::ReadDB(PGLOBAL g) break; } // endif rc - for (colp = Tqrp->GetColumns(); colp; colp = colp->GetNext()) + for (colp = Tdbp->GetColumns(); colp; colp = colp->GetNext()) colp->ReadColumn(g); for (colp = Columns; colp; colp = colp->GetNext()) if (colp->GetAmType() == TYPE_AM_SRC) if (FileStatus) { - if (((PSRCCOL)colp)->CompareColumn()) + if (((PSRCCOL)colp)->CompareLast()) { newrow = (RowFlag) ? TRUE : FALSE; + break; + } // endif CompareLast } else ((PSRCCOL)colp)->SetColumn(); @@ -683,21 +828,21 @@ int TDBPIVOT::ReadDB(PGLOBAL g) } else RowFlag = 2; - vp1 = Xcolp->GetValue(); - // Look for the column having this header for (colp = Columns; colp; colp = colp->GetNext()) if (colp->GetAmType() == TYPE_AM_FNC) { - vp2 = ((PFNCCOL)colp)->Hval; - - if (!vp1->CompareValue(vp2)) + if (((PFNCCOL)colp)->CompareColumn()) break; } // endif AmType - if (!colp) { - strcpy(g->Message, MSG(NO_MATCH_COL)); - return RC_FX; + if (!colp && !(colp = Dcolp)) { + if (!Accept) { + strcpy(g->Message, MSG(NO_MATCH_COL)); + return RC_FX; + } else + continue; + } // endif colp // Set the value of the matching column from the fonction value @@ -734,6 +879,7 @@ void TDBPIVOT::CloseDB(PGLOBAL g) //Tdbp->CloseDB(g); } // end of CloseDB +#if 0 /***********************************************************************/ /* TDBPIVOT: Compare routine for sorting pivot column values. */ /***********************************************************************/ @@ -742,120 +888,81 @@ int TDBPIVOT::Qcompare(int *i1, int *i2) // TODO: the actual comparison between pivot column result values. return Rblkp->CompVal(*i1, *i2); } // end of Qcompare +#endif // 0 // ------------------------ FNCCOL functions ---------------------------- /***********************************************************************/ /* FNCCOL public constructor. */ /***********************************************************************/ -FNCCOL::FNCCOL(PCOL col1, PTDBPIVOT tdbp) - : COLBLK(col1, tdbp) +FNCCOL::FNCCOL(PCOLDEF cdp, PTDB tdbp, PCOL cprec, int i) + : COLBLK(cdp, tdbp, i) { + if (cprec) { + Next = cprec->GetNext(); + cprec->SetNext(this); + } else { + Next = tdbp->GetColumns(); + tdbp->SetColumns(this); + } // endif cprec + Value = NULL; // We'll get a new one later - Hval = NULL; // The unconverted header value + Hval = NULL; // The unconverted header value + Xcolp = NULL; } // end of FNCCOL constructor /***********************************************************************/ -/* FNCCOL initialization function. */ +/* FNCCOL initialization function. */ /***********************************************************************/ -bool FNCCOL::InitColumn(PGLOBAL g, PVAL valp) +bool FNCCOL::InitColumn(PGLOBAL g) { - char *p, buf[128]; - int len; - // Must have its own value block if (InitValue(g)) return TRUE; - // Convert header value to a null terminated character string - Hval = valp; - p = Hval->GetCharString(buf); - len = strlen(p) + 1; + // Make a value from the column name + Hval = AllocateValue(g, Name, TYPE_STRING); + Hval->SetPrec(1); // Case insensitive - if (len > (signed)sizeof(buf)) { - strcpy(g->Message, MSG(COLNAM_TOO_LONG)); - return TRUE; - } // endif buf - - // Set the name of the functional pivot column - Name = (PSZ)PlugSubAlloc(g, NULL, len); - strcpy(Name, p); + Xcolp = ((PTDBPIVOT)To_Tdb)->Xcolp; AddStatus(BUF_READ); // All is done here return FALSE; } // end of InitColumn +/***********************************************************************/ +/* CompareColumn: Compare column value with source column value. */ +/***********************************************************************/ +bool FNCCOL::CompareColumn(void) + { + // Compare the unconverted values + return Hval->IsEqual(Xcolp->GetValue(), false); + } // end of CompareColumn + // ------------------------ SRCCOL functions ---------------------------- -#if 0 /***********************************************************************/ /* SRCCOL public constructor. */ /***********************************************************************/ -SRCCOL::SRCCOL(PCOLDEF cdp, PTDBPIVOT tdbp, int n) - : COLBLK(cdp, tdbp, n) +SRCCOL::SRCCOL(PCOLDEF cdp, PTDB tdbp, PCOL cprec, int n) + : PRXCOL(cdp, tdbp, cprec, n) { // Set additional SRC access method information for column. - Colp = NULL; - Cnval = NULL; +//Cnval = NULL; } // end of SRCCOL constructor -#endif // 0 - -/***********************************************************************/ -/* SRCCOL public constructor. */ -/***********************************************************************/ -SRCCOL::SRCCOL(PCOL cp, PTDBPIVOT tdbp, int n) - : COLBLK(cp, tdbp) - { - Index = n; - - // Set additional SRC access method information for column. - Colp = (PQRSCOL)cp; - - // Don't share Value with the source column so we can compare - Cnval = Value = NULL; - } // end of SRCCOL constructor - -#if 0 -/***********************************************************************/ -/* SRCCOL constructor used for copying columns. */ -/* tdbp is the pointer to the new table descriptor. */ -/***********************************************************************/ -SRCCOL::SRCCOL(SRCCOL *col1, PTDB tdbp) : COLBLK(col1, tdbp) - { - Colp = col1->Colp; - } // end of SRCCOL copy constructor -#endif // 0 /***********************************************************************/ /* Initialize the column as pointing to the source column. */ /***********************************************************************/ -bool SRCCOL::Init(PGLOBAL g, PTDBPIVOT tdbp) +bool SRCCOL::Init(PGLOBAL g) { - // Currently we ignore the type of the create table column - bool conv = FALSE; + if (PRXCOL::Init(g)) + return true; -#if 0 - if (!Colp) { - // Column was defined in the Create Table statement - if (!(Colp = tdbp->ColDB(g, Name, 0))) - return TRUE; - - // We can have a conversion problem converting from numeric to - // character because GetCharValue does not exist for numeric types. - conv = (IsTypeChar(Buf_Type) && IsTypeNum(Colp->GetResultType())); - } else -#endif // 0 - conv = FALSE; - - if (InitValue(g)) - return TRUE; - -//if (conv) -// Cnval = AllocateValue(g, Colp->GetValue()); -//else - Cnval = Value; + // Will contain the last value +//Cnval = AllocateValue(g, Value, TYPE_VOID); AddStatus(BUF_READ); // All is done here - return FALSE; + return false; } // end of SRCCOL constructor /***********************************************************************/ @@ -863,25 +970,18 @@ bool SRCCOL::Init(PGLOBAL g, PTDBPIVOT tdbp) /***********************************************************************/ void SRCCOL::SetColumn(void) { -#if defined(_DEBUG) - Cnval->SetValue_pval(Colp->GetValue(), TRUE); -#else - Cnval->SetValue_pval(Colp->GetValue()); -#endif // _DEBUG - - if (Value != Cnval) - // Convert value - Value->SetValue_pval(Cnval); - +//Cnval->SetValue_pval(Value); + Value->SetValue_pval(To_Val); } // end of SetColumn /***********************************************************************/ /* SetColumn: Compare column value with source column value. */ /***********************************************************************/ -bool SRCCOL::CompareColumn(void) +bool SRCCOL::CompareLast(void) { // Compare the unconverted values - return Cnval->CompareValue(Colp->GetValue()); +//return !Cnval->IsEqual(Colp->GetValue(), true); + return !Value->IsEqual(To_Val, true); } // end of CompareColumn @@ -1019,18 +1119,8 @@ bool TDBQRS::OpenDB(PGLOBAL g) CurPos = -1; - if (Use == USE_OPEN) { - /*******************************************************************/ - /* Table already open, just replace it at its beginning. */ - /*******************************************************************/ - if (To_Kindex) - /*****************************************************************/ - /* Table is to be accessed through a sorted index table. */ - /*****************************************************************/ - To_Kindex->Reset(); - + if (Use == USE_OPEN) return FALSE; - } // endif use /*********************************************************************/ /* Open (retrieve data from) the query if not already open. */ @@ -1059,6 +1149,7 @@ int TDBQRS::ReadDB(PGLOBAL g) htrc("QRS ReadDB: R%d CurPos=%d key=%p link=%p Kindex=%p\n", GetTdb_No(), CurPos, To_Key_Col, To_Link, To_Kindex); +#if 0 if (To_Kindex) { /*******************************************************************/ /* Reading is by an index table. */ @@ -1086,6 +1177,7 @@ int TDBQRS::ReadDB(PGLOBAL g) htrc("Position is now %d\n", CurPos); } else +#endif // 0 /*******************************************************************/ /* !To_Kindex ---> sequential reading */ /*******************************************************************/ @@ -1117,10 +1209,10 @@ int TDBQRS::DeleteDB(PGLOBAL g, int irc) /***********************************************************************/ void TDBQRS::CloseDB(PGLOBAL g) { - if (To_Kindex) { - To_Kindex->Close(); - To_Kindex = NULL; - } // endif +//if (To_Kindex) { +// To_Kindex->Close(); +// To_Kindex = NULL; +// } // endif if (trace) htrc("Qryres CloseDB"); diff --git a/storage/connect/tabpivot.h b/storage/connect/tabpivot.h index fb480b9abbf..3aa5288b5d8 100644 --- a/storage/connect/tabpivot.h +++ b/storage/connect/tabpivot.h @@ -22,13 +22,12 @@ typedef class QRSCOL *PQRSCOL; /***********************************************************************/ /* PIVOT table. */ /***********************************************************************/ -//ass DllExport PIVOTDEF : public TABDEF {/* Logical table description */ -class PIVOTDEF : public TABDEF { /* Logical table description */ +//ass DllExport PIVOTDEF : public PRXDEF {/* Logical table description */ +class PIVOTDEF : public PRXDEF { /* Logical table description */ friend class TDBPIVOT; public: // Constructor - PIVOTDEF(void) {Pseudo = 3; - Tabname = Tabsrc = Picol = Fncol = Function = NULL;} + PIVOTDEF(void); // Implementation virtual const char *GetType(void) {return "PIVOT";} @@ -39,26 +38,27 @@ class PIVOTDEF : public TABDEF { /* Logical table description */ protected: // Members - char *Host; /* Host machine to use */ - char *User; /* User logon info */ - char *Pwd; /* Password logon info */ - char *DB; /* Database to be used by server */ - char *Tabname; /* Name of source table */ + char *Host; /* Host machine to use */ + char *User; /* User logon info */ + char *Pwd; /* Password logon info */ + char *DB; /* Database to be used by server */ + char *Tabname; /* Name of source table */ char *Tabsrc; /* The source table SQL description */ - char *Picol; /* The pivot column */ + char *Picol; /* The pivot column */ char *Fncol; /* The function column */ char *Function; /* The function applying to group by */ bool GBdone; /* True if tabname as group by format */ - int Port; /* MySQL port number */ + bool Accept; /* TRUE if no match is accepted */ + int Port; /* MySQL port number */ }; // end of PIVOTDEF /***********************************************************************/ /* This is the class declaration for the PIVOT table. */ /***********************************************************************/ //ass DllExport TDBPIVOT : public TDBASE, public CSORT { -class TDBPIVOT : public TDBASE, public CSORT { +class TDBPIVOT : public TDBPRX { friend class FNCCOL; - friend class SRCCOL; +//friend class SRCCOL; public: // Constructor TDBPIVOT(PPIVOTDEF tdp); @@ -85,39 +85,41 @@ class TDBPIVOT : public TDBASE, public CSORT { virtual void CloseDB(PGLOBAL g); // The sorting function - virtual int Qcompare(int *, int *); +//virtual int Qcompare(int *, int *); protected: - PQRYRES GetSourceTable(PGLOBAL g); - int MakePivotColumns(PGLOBAL g); - bool UpdateTableFields(PGLOBAL g, int n); + bool GetSourceTable(PGLOBAL g); +//int MakePivotColumns(PGLOBAL g); +//bool UpdateTableFields(PGLOBAL g, int n); // Members - MYSQLC Myc; // MySQL connection class - PTDBQRS Tqrp; // To the source table result - char *Host; // Host machine to use - char *User; // User logon info - char *Pwd; // Password logon info - char *Database; // Database to be used by server - PQRYRES Qryp; // Points to Query result block - char *Tabname; // Name of source table - char *Tabsrc; // SQL of source table - char *Picol; // Pivot column name - char *Fncol; // Function column name - char *Function; // The function applying to group by - PQRSCOL Fcolp; // To the function column in source - PQRSCOL Xcolp; // To the pivot column in source - PCOLRES Xresp; // To the pivot result column -//PCOLRES To_Sort; // Saved Qryp To_Sort pointer - PVBLK Rblkp; // The value block of the pivot column - bool GBdone; // True when subtable is "Group by" - int Mult; // Multiplication factor - int Ncol; // The number of generated columns - int N; // The current table index - int M; // The occurence rank - int Port; // MySQL port number - BYTE FileStatus; // 0: First 1: Rows 2: End-of-File - BYTE RowFlag; // 0: Ok, 1: Same, 2: Skip +//MYSQLC Myc; // MySQL connection class +//PTDBQRS Tqrp; // To the source table result + char *Host; // Host machine to use + char *User; // User logon info + char *Pwd; // Password logon info + char *Database; // Database to be used by server +//PQRYRES Qryp; // Points to Query result block + char *Tabname; // Name of source table + char *Tabsrc; // SQL of source table + char *Picol; // Pivot column name + char *Fncol; // Function column name + char *Function; // The function applying to group by + PCOL Fcolp; // To the function column in source + PCOL Xcolp; // To the pivot column in source + PCOL Dcolp; // To the dump column +//PCOLRES Xresp; // To the pivot result column +//PCOLRES To_Sort; // Saved Qryp To_Sort pointer +//PVBLK Rblkp; // The value block of the pivot column + bool GBdone; // True when subtable is "Group by" + bool Accept; // TRUE if no match is accepted + int Mult; // Multiplication factor + int Ncol; // The number of generated columns + int N; // The current table index + int M; // The occurence rank + int Port; // MySQL port number + BYTE FileStatus; // 0: First 1: Rows 2: End-of-File + BYTE RowFlag; // 0: Ok, 1: Same, 2: Skip }; // end of class TDBPIVOT /***********************************************************************/ @@ -127,30 +129,30 @@ class FNCCOL : public COLBLK { friend class TDBPIVOT; public: // Constructor - FNCCOL(PCOL colp, PTDBPIVOT tdbp); + FNCCOL(PCOLDEF cdp, PTDB tdbp, PCOL cprec, int i); // Implementation virtual int GetAmType(void) {return TYPE_AM_FNC;} // Methods virtual void Reset(void) {} - bool InitColumn(PGLOBAL g, PVAL valp); + bool InitColumn(PGLOBAL g); + bool CompareColumn(void); protected: // Member - PVAL Hval; // The original value used to generate the header + PVAL Hval; // The value containing the header + PCOL Xcolp; }; // end of class FNCCOL /***********************************************************************/ /* Class SRCCOL: for other source columns. */ /***********************************************************************/ -class SRCCOL : public COLBLK { +class SRCCOL : public PRXCOL { friend class TDBPIVOT; public: // Constructors -//SRCCOL(PCOLDEF cdp, PTDBPIVOT tdbp, int n); - SRCCOL(PCOL cp, PTDBPIVOT tdbp, int n); -//SRCCOL(SRCCOL *colp, PTDB tdbp); // Constructor used in copy process + SRCCOL(PCOLDEF cdp, PTDB tdbp, PCOL cprec, int n); // Implementation virtual int GetAmType(void) {return TYPE_AM_SRC;} @@ -158,16 +160,15 @@ class SRCCOL : public COLBLK { // Methods virtual void Reset(void) {} void SetColumn(void); - bool Init(PGLOBAL g, PTDBPIVOT tdbp); - bool CompareColumn(void); + bool Init(PGLOBAL g); + bool CompareLast(void); protected: // Default constructor not to be used SRCCOL(void) {} // Members - PQRSCOL Colp; - PVAL Cnval; +//PVAL Cnval; }; // end of class SRCCOL /***********************************************************************/ diff --git a/storage/connect/tabutil.cpp b/storage/connect/tabutil.cpp index 2bd92ff9607..2c14b711f86 100644 --- a/storage/connect/tabutil.cpp +++ b/storage/connect/tabutil.cpp @@ -121,10 +121,7 @@ TABLE_SHARE *GetTableShare(PGLOBAL g, THD *thd, const char *db, 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, + 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, @@ -132,7 +129,7 @@ PQRYRES TabColumns(PGLOBAL g, THD *thd, const char *db, 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 i, n, ncol = sizeof(buftyp) / sizeof(int); int len, type, prec; bool mysql; TABLE_SHARE *s; @@ -156,7 +153,7 @@ PQRYRES TabColumns(PGLOBAL g, THD *thd, const char *db, /* Allocate the structures used to refer to the result set. */ /**********************************************************************/ qrp = PlgAllocResult(g, ncol, n, IDS_COLUMNS + 3, - dbtype, buftyp, fldtyp, length, true, true); + buftyp, fldtyp, length, true, true); // Some columns must be renamed for (i = 0, crp = qrp->Colresp; crp; crp = crp->Next) diff --git a/storage/connect/tabwmi.cpp b/storage/connect/tabwmi.cpp index d89d61dc11c..dbd4330a2f9 100644 --- a/storage/connect/tabwmi.cpp +++ b/storage/connect/tabwmi.cpp @@ -135,14 +135,12 @@ PWMIUT InitWMI(PGLOBAL g, char *nsp, char *classname) /***********************************************************************/ PQRYRES WMIColumns(PGLOBAL g, char *nsp, char *cls, bool info) { - static int dbtype[] = {DB_CHAR, DB_SHORT, DB_CHAR, - DB_INT, DB_INT, DB_SHORT}; static int buftyp[] = {TYPE_STRING, TYPE_SHORT, TYPE_STRING, TYPE_INT, TYPE_INT, TYPE_SHORT}; static XFLD fldtyp[] = {FLD_NAME, FLD_TYPE, FLD_TYPENAME, FLD_PREC, FLD_LENGTH, FLD_SCALE}; static unsigned int len, length[] = {0, 6, 8, 10, 10, 6}; - int i = 0, n = 0, ncol = sizeof(dbtype) / sizeof(int); + int i = 0, n = 0, ncol = sizeof(buftyp) / sizeof(int); int lng, typ, prec; LONG low, upp; BSTR propname; @@ -213,7 +211,7 @@ PQRYRES WMIColumns(PGLOBAL g, char *nsp, char *cls, bool 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); + buftyp, fldtyp, length, true, true); if (info) return qrp; diff --git a/storage/connect/tabxcl.cpp b/storage/connect/tabxcl.cpp index d64a730beb0..96da0571271 100644 --- a/storage/connect/tabxcl.cpp +++ b/storage/connect/tabxcl.cpp @@ -66,7 +66,6 @@ extern "C" int trace; /***********************************************************************/ XCLDEF::XCLDEF(void) { - Pseudo = 3; Xcol = NULL; Sep = ','; Mult = 10; diff --git a/storage/connect/value.cpp b/storage/connect/value.cpp index 9053658b461..7a1146e6c32 100644 --- a/storage/connect/value.cpp +++ b/storage/connect/value.cpp @@ -154,46 +154,6 @@ int GetTypeSize(int type, int len) return len; } // end of GetTypeSize -/***********************************************************************/ -/* GetPLGType: returns the PlugDB type corresponding to a DB type. */ -/***********************************************************************/ -int GetPLGType(int type) - { - int tp; - - switch (type) { - case DB_CHAR: - case DB_STRING: tp = TYPE_STRING; break; - case DB_SHORT: tp = TYPE_SHORT; break; - case DB_INT: tp = TYPE_INT; break; - case DB_DOUBLE: tp = TYPE_FLOAT; break; - case DB_DATE: tp = TYPE_DATE; break; - default: tp = TYPE_ERROR; - } // endswitch type - - return tp; - } // end of GetPLGType - -/***********************************************************************/ -/* GetDBType: returns the DB type corresponding to a PlugDB type. */ -/***********************************************************************/ -int GetDBType(int type) - { - int tp; - - switch (type) { - case TYPE_STRING: tp = DB_CHAR; break; - case TYPE_SHORT: tp = DB_SHORT; break; - case TYPE_INT: tp = DB_INT; break; - case TYPE_BIGINT: - case TYPE_FLOAT: tp = DB_DOUBLE; break; - case TYPE_DATE: tp = DB_DATE; break; - default: tp = DB_ERROR; - } // endswitch type - - return tp; - } // end of GetPLGType - /***********************************************************************/ /* GetFormatType: returns the FORMAT character(s) according to type. */ /***********************************************************************/ @@ -1143,10 +1103,13 @@ bool TYPVAL::IsEqual(PVAL vp, bool chktype) return false; else if (Null || vp->IsNull()) return false; - else if (Ci || vp->IsCi()) - return !stricmp(Strp, vp->GetCharValue()); + + char buf[32]; + + if (Ci || vp->IsCi()) + return !stricmp(Strp, vp->GetCharString(buf)); else // (!Ci) - return !strcmp(Strp, vp->GetCharValue()); + return !strcmp(Strp, vp->GetCharString(buf)); } // end of IsEqual diff --git a/storage/connect/value.h b/storage/connect/value.h index 0f7b795c252..95d69dae92f 100644 --- a/storage/connect/value.h +++ b/storage/connect/value.h @@ -38,7 +38,6 @@ typedef struct _datpar *PDTP; // For DTVAL /***********************************************************************/ /* Utilities used to test types and to allocated values. */ /***********************************************************************/ -int GetPLGType(int); PVAL AllocateValue(PGLOBAL, void *, short); // Exported functions @@ -50,7 +49,6 @@ DllExport int TranslateSQLType(int stp, int prec, int& len); #endif DllExport char *GetFormatType(int); DllExport int GetFormatType(char); -DllExport int GetDBType(int); DllExport bool IsTypeChar(int type); DllExport bool IsTypeNum(int type); DllExport int ConvertType(int, int, CONV, bool match = false); @@ -82,12 +80,12 @@ class DllExport VALUE : public BLOCK { virtual longlong GetBigintValue(void) = 0; virtual double GetFloatValue(void) = 0; virtual void *GetTo_Val(void) = 0; + virtual void SetPrec(int prec) {Prec = prec;} bool IsNull(void) {return Null;} void SetNull(bool b) {Null = b;} void SetNullable(bool b) {Nullable = b;} int GetType(void) {return Type;} int GetClen(void) {return Clen;} - void SetPrec(int prec) {Prec = prec;} void SetGlobal(PGLOBAL g) {Global = g;} // Methods @@ -217,6 +215,7 @@ class DllExport TYPVAL: public VALUE { virtual longlong GetBigintValue(void) {return atoll(Strp);} virtual double GetFloatValue(void) {return atof(Strp);} virtual void *GetTo_Val(void) {return Strp;} + virtual void SetPrec(int prec) {Ci = prec != 0;} // Methods virtual bool SetValue_pval(PVAL valp, bool chktype); From 2cd63afe352ace53ca7069b71012121355ae565d Mon Sep 17 00:00:00 2001 From: Olivier Bertrand Date: Fri, 10 May 2013 23:05:16 +0200 Subject: [PATCH 10/47] - Add pivot table files and support modified: storage/connect/CMakeLists.txt --- storage/connect/CMakeLists.txt | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/storage/connect/CMakeLists.txt b/storage/connect/CMakeLists.txt index 41930c71aa4..4209ff40322 100644 --- a/storage/connect/CMakeLists.txt +++ b/storage/connect/CMakeLists.txt @@ -25,20 +25,20 @@ 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 +tabutil.cpp tabxcl.cpp taboccur.cpp tabpivot.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 -tabutil.h tabxcl.h taboccur.h) +tabutil.h tabxcl.h taboccur.h tabpivot.h) # # Definitions that are shared for all OSes # add_definitions( -DMARIADB -DFORCE_INIT_OF_VARS ) -add_definitions( -DHUGE_SUPPORT -DZIP_SUPPORT ) +add_definitions( -DHUGE_SUPPORT -DZIP_SUPPORT -DPIVOT_SUPPORT ) # From 5657660ab07a905a018cee5132618a12f7fcc851 Mon Sep 17 00:00:00 2001 From: Olivier Bertrand Date: Sat, 11 May 2013 13:21:15 +0200 Subject: [PATCH 11/47] - Added a test case for PIVOT tables added: storage/connect/mysql-test/connect/r/pivot.result storage/connect/mysql-test/connect/std_data/expenses.txt storage/connect/mysql-test/connect/t/pivot.test --- .../connect/mysql-test/connect/r/pivot.result | 230 ++++++++++++++++++ .../mysql-test/connect/std_data/expenses.txt | 24 ++ .../connect/mysql-test/connect/t/pivot.test | 144 +++++++++++ 3 files changed, 398 insertions(+) create mode 100644 storage/connect/mysql-test/connect/r/pivot.result create mode 100644 storage/connect/mysql-test/connect/std_data/expenses.txt create mode 100644 storage/connect/mysql-test/connect/t/pivot.test diff --git a/storage/connect/mysql-test/connect/r/pivot.result b/storage/connect/mysql-test/connect/r/pivot.result new file mode 100644 index 00000000000..4455d333e5a --- /dev/null +++ b/storage/connect/mysql-test/connect/r/pivot.result @@ -0,0 +1,230 @@ +# +# Testing the PIVOT table type +# +CREATE TABLE expenses ( +Who CHAR(10) NOT NULL, +Week INT(2) NOT NULL, +What CHAR(12) NOT NULL, +Amount DOUBLE(8,2)) +ENGINE=CONNECT TABLE_TYPE=FIX FILE_NAME='expenses.txt'; +SELECT * FROM expenses; +Who Week What Amount +Joe 3 Beer 18.00 +Beth 4 Food 17.00 +Janet 5 Beer 14.00 +Joe 3 Food 12.00 +Joe 4 Beer 19.00 +Janet 5 Car 12.00 +Joe 3 Food 19.00 +Beth 4 Beer 15.00 +Janet 5 Beer 19.00 +Joe 3 Car 20.00 +Joe 4 Beer 16.00 +Beth 5 Food 12.00 +Beth 3 Beer 16.00 +Joe 4 Food 17.00 +Joe 5 Beer 14.00 +Janet 3 Car 19.00 +Joe 4 Food 17.00 +Beth 5 Beer 20.00 +Janet 3 Food 18.00 +Joe 4 Beer 14.00 +Joe 5 Food 12.00 +Janet 3 Beer 18.00 +Janet 4 Car 17.00 +Janet 5 Food 12.00 +# +# Pivoting from What +# +CREATE TABLE pivex ( +Who CHAR(10) NOT NULL, +Week INT(2) NOT NULL, +Beer DOUBLE(8,2) FLAG=1, +Car DOUBLE(8,2) FLAG=1, +Food DOUBLE(8,2) FLAG=1) +ENGINE=CONNECT TABLE_TYPE=PIVOT TABNAME=expenses; +ALTER TABLE pivex OPTION_LIST='port=PORT'; +Warnings: +Warning 1105 The current version of CONNECT did not check what you changed in ALTER. Use at your own risk +SELECT * FROM pivex; +Who Week Beer Car Food +Beth 3 16.00 0.00 0.00 +Beth 4 15.00 0.00 17.00 +Beth 5 20.00 0.00 12.00 +Janet 3 18.00 19.00 18.00 +Janet 4 0.00 17.00 0.00 +Janet 5 33.00 12.00 12.00 +Joe 3 18.00 20.00 31.00 +Joe 4 49.00 0.00 34.00 +Joe 5 14.00 0.00 12.00 +# +# Restricting the columns in a Pivot Table +# +ALTER TABLE pivex DROP COLUMN week; +SELECT * FROM pivex; +Who Beer Car Food +Beth 51.00 0.00 29.00 +Janet 51.00 48.00 30.00 +Joe 81.00 20.00 77.00 +# +# Using a source definition +# +DROP TABLE pivex; +CREATE TABLE pivex ( +Who CHAR(10) NOT NULL, +Week INT(2) NOT NULL, +Beer DOUBLE(8,2) FLAG=1, +Car DOUBLE(8,2) FLAG=1, +Food DOUBLE(8,2) FLAG=1) +ENGINE=CONNECT TABLE_TYPE=PIVOT +SRCDEF='select who, week, what, sum(amount) from expenses where week in (4,5) group by who, week, what'; +ALTER TABLE pivex OPTION_LIST='port=PORT'; +Warnings: +Warning 1105 The current version of CONNECT did not check what you changed in ALTER. Use at your own risk +SELECT * FROM pivex; +Who Week Beer Car Food +Beth 4 15.00 0.00 17.00 +Beth 5 20.00 0.00 12.00 +Janet 4 0.00 17.00 0.00 +Janet 5 33.00 12.00 12.00 +Joe 4 49.00 0.00 34.00 +Joe 5 14.00 0.00 12.00 +# +# Pivoting from Week +# +DROP TABLE pivex; +CREATE TABLE pivex ( +Who CHAR(10) NOT NULL, +What CHAR(12) NOT NULL, +`3` DOUBLE(8,2) FLAG=1, +`4` DOUBLE(8,2) FLAG=1, +`5` DOUBLE(8,2) FLAG=1) +ENGINE=CONNECT TABLE_TYPE=PIVOT TABNAME=expenses; +ALTER TABLE pivex OPTION_LIST='PivotCol=Week,port=PORT'; +Warnings: +Warning 1105 The current version of CONNECT did not check what you changed in ALTER. Use at your own risk +SELECT * FROM pivex; +Who What 3 4 5 +Beth Beer 16.00 15.00 20.00 +Beth Food 0.00 17.00 12.00 +Janet Beer 18.00 0.00 33.00 +Janet Car 19.00 17.00 12.00 +Janet Food 18.00 0.00 12.00 +Joe Beer 18.00 49.00 14.00 +Joe Car 20.00 0.00 0.00 +Joe Food 31.00 34.00 12.00 +# +# Using scalar functions and expresssions +# +DROP TABLE pivex; +CREATE TABLE pivex ( +Who CHAR(10) NOT NULL, +What CHAR(12) NOT NULL, +First DOUBLE(8,2) FLAG=1, +Middle DOUBLE(8,2) FLAG=1, +Last DOUBLE(8,2) FLAG=1) +ENGINE=CONNECT TABLE_TYPE=PIVOT +SRCDEF='select who, what, case when week=3 then ''First'' when week=5 then ''Last'' else ''Middle'' end as wk, sum(amount) * 6.56 as amnt from expenses group by who, what, wk'; +ALTER TABLE pivex OPTION_LIST='PivotCol=wk,port=PORT'; +Warnings: +Warning 1105 The current version of CONNECT did not check what you changed in ALTER. Use at your own risk +SELECT * FROM pivex; +Who What First Middle Last +Beth Beer 104.96 98.40 131.20 +Beth Food 0.00 111.52 78.72 +Janet Beer 118.08 0.00 216.48 +Janet Car 124.64 111.52 78.72 +Janet Food 118.08 0.00 78.72 +Joe Beer 118.08 321.44 91.84 +Joe Car 131.20 0.00 0.00 +Joe Food 203.36 223.04 78.72 +DROP TABLE pivex; +DROP TABLE expenses; +# +# Make the PETS table +# +CREATE TABLE pets ( +Name VARCHAR(12) NOT NULL, +Race CHAR(6) NOT NULL, +Number INT NOT NULL) ENGINE=MYISAM; +INSERT INTO pets VALUES('John','dog',2); +INSERT INTO pets VALUES('Bill','cat',1); +INSERT INTO pets VALUES('Mary','dog',1); +INSERT INTO pets VALUES('Mary','cat',1); +INSERT INTO pets VALUES('Lisbeth','rabbit',2); +INSERT INTO pets VALUES('Kevin','cat',2); +INSERT INTO pets VALUES('Kevin','bird',6); +INSERT INTO pets VALUES('Donald','dog',1); +INSERT INTO pets VALUES('Donald','fish',3); +SELECT * FROM pets; +Name Race Number +John dog 2 +Bill cat 1 +Mary dog 1 +Mary cat 1 +Lisbeth rabbit 2 +Kevin cat 2 +Kevin bird 6 +Donald dog 1 +Donald fish 3 +# +# Pivot the PETS table +# +CREATE TABLE pivet ( +name VARCHAR(12) NOT NULL, +dog INT NOT NULL DEFAULT 0 FLAG=1, +cat INT NOT NULL DEFAULT 0 FLAG=1, +rabbit INT NOT NULL DEFAULT 0 FLAG=1, +bird INT NOT NULL DEFAULT 0 FLAG=1, +fish INT NOT NULL DEFAULT 0 FLAG=1) +ENGINE=CONNECT TABLE_TYPE=PIVOT TABNAME=pets OPTION_LIST='PivotCol=race,groupby=1'; +SELECT * FROM pivet; +name dog cat rabbit bird fish +John 2 0 0 0 0 +Bill 0 1 0 0 0 +Mary 1 1 0 0 0 +Lisbeth 0 0 2 0 0 +Kevin 0 2 0 6 0 +Donald 1 0 0 0 3 +DROP TABLE pivet; +# +# Testing the "data" column list +# +CREATE TABLE pivet ( +name VARCHAR(12) NOT NULL, +dog INT NOT NULL DEFAULT 0 FLAG=1, +cat INT NOT NULL DEFAULT 0 FLAG=1) +ENGINE=CONNECT TABLE_TYPE=PIVOT TABNAME=pets OPTION_LIST='PivotCol=race,groupby=1'; +SELECT * FROM pivet; +ERROR HY000: Got error 122 'Cannot find matching column' from CONNECT +ALTER TABLE pivet OPTION_LIST='PivotCol=race,groupby=1,accept=1'; +Warnings: +Warning 1105 The current version of CONNECT did not check what you changed in ALTER. Use at your own risk +SELECT * FROM pivet; +name dog cat +John 2 0 +Bill 0 1 +Mary 1 1 +Lisbeth 0 0 +Kevin 0 2 +Donald 1 0 +DROP TABLE pivet; +# +# Adding a "dump" column +# +CREATE TABLE pivet ( +name VARCHAR(12) NOT NULL, +dog INT NOT NULL DEFAULT 0 FLAG=1, +cat INT NOT NULL DEFAULT 0 FLAG=1, +other INT NOT NULL DEFAULT 0 FLAG=2) +ENGINE=CONNECT TABLE_TYPE=PIVOT TABNAME=pets OPTION_LIST='PivotCol=race,groupby=1'; +SELECT * FROM pivet; +name dog cat other +John 2 0 0 +Bill 0 1 0 +Mary 1 1 0 +Lisbeth 0 0 2 +Kevin 0 2 6 +Donald 1 0 3 +DROP TABLE pivet; +DROP TABLE pets; diff --git a/storage/connect/mysql-test/connect/std_data/expenses.txt b/storage/connect/mysql-test/connect/std_data/expenses.txt new file mode 100644 index 00000000000..66a94edbb9a --- /dev/null +++ b/storage/connect/mysql-test/connect/std_data/expenses.txt @@ -0,0 +1,24 @@ +Joe 3Beer 18.00 +Beth 4Food 17.00 +Janet 5Beer 14.00 +Joe 3Food 12.00 +Joe 4Beer 19.00 +Janet 5Car 12.00 +Joe 3Food 19.00 +Beth 4Beer 15.00 +Janet 5Beer 19.00 +Joe 3Car 20.00 +Joe 4Beer 16.00 +Beth 5Food 12.00 +Beth 3Beer 16.00 +Joe 4Food 17.00 +Joe 5Beer 14.00 +Janet 3Car 19.00 +Joe 4Food 17.00 +Beth 5Beer 20.00 +Janet 3Food 18.00 +Joe 4Beer 14.00 +Joe 5Food 12.00 +Janet 3Beer 18.00 +Janet 4Car 17.00 +Janet 5Food 12.00 diff --git a/storage/connect/mysql-test/connect/t/pivot.test b/storage/connect/mysql-test/connect/t/pivot.test new file mode 100644 index 00000000000..75a208e853b --- /dev/null +++ b/storage/connect/mysql-test/connect/t/pivot.test @@ -0,0 +1,144 @@ +let $MYSQLD_DATADIR= `select @@datadir`; +let $PORT= `select @@port`; +--copy_file $MTR_SUITE_DIR/std_data/expenses.txt $MYSQLD_DATADIR/test/expenses.txt + +--echo # +--echo # Testing the PIVOT table type +--echo # +CREATE TABLE expenses ( +Who CHAR(10) NOT NULL, +Week INT(2) NOT NULL, +What CHAR(12) NOT NULL, +Amount DOUBLE(8,2)) +ENGINE=CONNECT TABLE_TYPE=FIX FILE_NAME='expenses.txt'; +SELECT * FROM expenses; + +--echo # +--echo # Pivoting from What +--echo # +CREATE TABLE pivex ( +Who CHAR(10) NOT NULL, +Week INT(2) NOT NULL, +Beer DOUBLE(8,2) FLAG=1, +Car DOUBLE(8,2) FLAG=1, +Food DOUBLE(8,2) FLAG=1) +ENGINE=CONNECT TABLE_TYPE=PIVOT TABNAME=expenses; +--replace_result $PORT PORT +--eval ALTER TABLE pivex OPTION_LIST='port=$PORT' +SELECT * FROM pivex; + +--echo # +--echo # Restricting the columns in a Pivot Table +--echo # +ALTER TABLE pivex DROP COLUMN week; +SELECT * FROM pivex; + +--echo # +--echo # Using a source definition +--echo # +DROP TABLE pivex; +CREATE TABLE pivex ( +Who CHAR(10) NOT NULL, +Week INT(2) NOT NULL, +Beer DOUBLE(8,2) FLAG=1, +Car DOUBLE(8,2) FLAG=1, +Food DOUBLE(8,2) FLAG=1) +ENGINE=CONNECT TABLE_TYPE=PIVOT +SRCDEF='select who, week, what, sum(amount) from expenses where week in (4,5) group by who, week, what'; +--replace_result $PORT PORT +--eval ALTER TABLE pivex OPTION_LIST='port=$PORT' +SELECT * FROM pivex; + +--echo # +--echo # Pivoting from Week +--echo # +DROP TABLE pivex; +CREATE TABLE pivex ( +Who CHAR(10) NOT NULL, +What CHAR(12) NOT NULL, +`3` DOUBLE(8,2) FLAG=1, +`4` DOUBLE(8,2) FLAG=1, +`5` DOUBLE(8,2) FLAG=1) +ENGINE=CONNECT TABLE_TYPE=PIVOT TABNAME=expenses; +--replace_result $PORT PORT +--eval ALTER TABLE pivex OPTION_LIST='PivotCol=Week,port=$PORT' +SELECT * FROM pivex; + +--echo # +--echo # Using scalar functions and expresssions +--echo # +DROP TABLE pivex; +CREATE TABLE pivex ( +Who CHAR(10) NOT NULL, +What CHAR(12) NOT NULL, +First DOUBLE(8,2) FLAG=1, +Middle DOUBLE(8,2) FLAG=1, +Last DOUBLE(8,2) FLAG=1) +ENGINE=CONNECT TABLE_TYPE=PIVOT +SRCDEF='select who, what, case when week=3 then ''First'' when week=5 then ''Last'' else ''Middle'' end as wk, sum(amount) * 6.56 as amnt from expenses group by who, what, wk'; +--replace_result $PORT PORT +--eval ALTER TABLE pivex OPTION_LIST='PivotCol=wk,port=$PORT' +SELECT * FROM pivex; +DROP TABLE pivex; +DROP TABLE expenses; + +--echo # +--echo # Make the PETS table +--echo # +CREATE TABLE pets ( +Name VARCHAR(12) NOT NULL, +Race CHAR(6) NOT NULL, +Number INT NOT NULL) ENGINE=MYISAM; +INSERT INTO pets VALUES('John','dog',2); +INSERT INTO pets VALUES('Bill','cat',1); +INSERT INTO pets VALUES('Mary','dog',1); +INSERT INTO pets VALUES('Mary','cat',1); +INSERT INTO pets VALUES('Lisbeth','rabbit',2); +INSERT INTO pets VALUES('Kevin','cat',2); +INSERT INTO pets VALUES('Kevin','bird',6); +INSERT INTO pets VALUES('Donald','dog',1); +INSERT INTO pets VALUES('Donald','fish',3); +SELECT * FROM pets; + +--echo # +--echo # Pivot the PETS table +--echo # +CREATE TABLE pivet ( +name VARCHAR(12) NOT NULL, +dog INT NOT NULL DEFAULT 0 FLAG=1, +cat INT NOT NULL DEFAULT 0 FLAG=1, +rabbit INT NOT NULL DEFAULT 0 FLAG=1, +bird INT NOT NULL DEFAULT 0 FLAG=1, +fish INT NOT NULL DEFAULT 0 FLAG=1) +ENGINE=CONNECT TABLE_TYPE=PIVOT TABNAME=pets OPTION_LIST='PivotCol=race,groupby=1'; +SELECT * FROM pivet; +DROP TABLE pivet; + +--echo # +--echo # Testing the "data" column list +--echo # +CREATE TABLE pivet ( +name VARCHAR(12) NOT NULL, +dog INT NOT NULL DEFAULT 0 FLAG=1, +cat INT NOT NULL DEFAULT 0 FLAG=1) +ENGINE=CONNECT TABLE_TYPE=PIVOT TABNAME=pets OPTION_LIST='PivotCol=race,groupby=1'; +--error ER_GET_ERRMSG +SELECT * FROM pivet; +ALTER TABLE pivet OPTION_LIST='PivotCol=race,groupby=1,accept=1'; +SELECT * FROM pivet; +DROP TABLE pivet; + +--echo # +--echo # Adding a "dump" column +--echo # +CREATE TABLE pivet ( +name VARCHAR(12) NOT NULL, +dog INT NOT NULL DEFAULT 0 FLAG=1, +cat INT NOT NULL DEFAULT 0 FLAG=1, +other INT NOT NULL DEFAULT 0 FLAG=2) +ENGINE=CONNECT TABLE_TYPE=PIVOT TABNAME=pets OPTION_LIST='PivotCol=race,groupby=1'; +SELECT * FROM pivet; + +DROP TABLE pivet; +DROP TABLE pets; +--remove_file $MYSQLD_DATADIR/test/expenses.txt From 44cb1ce8a2d524c88cc8e2ea949cc933ba7a0832 Mon Sep 17 00:00:00 2001 From: Olivier Bertrand Date: Sat, 11 May 2013 17:00:36 +0200 Subject: [PATCH 12/47] - Fix tabpivot compile errors on Linux. - Fix Tabpivot not closing the source table. - Fix pivot.test error on Linux by specifying ENDING=2 for the expenses table. modified: storage/connect/mysql-test/connect/r/pivot.result storage/connect/mysql-test/connect/t/pivot.test storage/connect/tabpivot.cpp storage/connect/tabpivot.h --- storage/connect/mysql-test/connect/r/pivot.result | 2 +- storage/connect/mysql-test/connect/t/pivot.test | 2 +- storage/connect/tabpivot.cpp | 8 ++++---- storage/connect/tabpivot.h | 2 +- 4 files changed, 7 insertions(+), 7 deletions(-) diff --git a/storage/connect/mysql-test/connect/r/pivot.result b/storage/connect/mysql-test/connect/r/pivot.result index 4455d333e5a..4480788332b 100644 --- a/storage/connect/mysql-test/connect/r/pivot.result +++ b/storage/connect/mysql-test/connect/r/pivot.result @@ -6,7 +6,7 @@ Who CHAR(10) NOT NULL, Week INT(2) NOT NULL, What CHAR(12) NOT NULL, Amount DOUBLE(8,2)) -ENGINE=CONNECT TABLE_TYPE=FIX FILE_NAME='expenses.txt'; +ENGINE=CONNECT TABLE_TYPE=FIX FILE_NAME='expenses.txt' ENDING=2; SELECT * FROM expenses; Who Week What Amount Joe 3 Beer 18.00 diff --git a/storage/connect/mysql-test/connect/t/pivot.test b/storage/connect/mysql-test/connect/t/pivot.test index 75a208e853b..f06c92828f9 100644 --- a/storage/connect/mysql-test/connect/t/pivot.test +++ b/storage/connect/mysql-test/connect/t/pivot.test @@ -10,7 +10,7 @@ Who CHAR(10) NOT NULL, Week INT(2) NOT NULL, What CHAR(12) NOT NULL, Amount DOUBLE(8,2)) -ENGINE=CONNECT TABLE_TYPE=FIX FILE_NAME='expenses.txt'; +ENGINE=CONNECT TABLE_TYPE=FIX FILE_NAME='expenses.txt' ENDING=2; SELECT * FROM expenses; --echo # diff --git a/storage/connect/tabpivot.cpp b/storage/connect/tabpivot.cpp index 429bb88e0fc..efd9cf6a950 100644 --- a/storage/connect/tabpivot.cpp +++ b/storage/connect/tabpivot.cpp @@ -876,7 +876,7 @@ int TDBPIVOT::DeleteDB(PGLOBAL g, int irc) /***********************************************************************/ void TDBPIVOT::CloseDB(PGLOBAL g) { -//Tdbp->CloseDB(g); + Tdbp->CloseDB(g); } // end of CloseDB #if 0 @@ -1242,8 +1242,8 @@ QRSCOL::QRSCOL(PGLOBAL g, PCOLRES crp, PTDB tdbp, PCOL cprec, int i) Long = Crp->Clen; Buf_Type = crp->Type; strcpy(Format.Type, GetFormatType(Buf_Type)); - Format.Length = (SHORT)Long; - Format.Prec = (SHORT)Crp->Prec; + Format.Length = (short)Long; + Format.Prec = (short)Crp->Prec; if (trace) { htrc("Making new QRSCOL C%d %s at %p\n", Index, Name, this); @@ -1284,7 +1284,7 @@ void QRSCOL::ReadColumn(PGLOBAL g) /***********************************************************************/ /* Make file output of a Dos column descriptor block. */ /***********************************************************************/ -void QRSCOL::Print(PGLOBAL g, FILE *f, UINT n) +void QRSCOL::Print(PGLOBAL g, FILE *f, uint n) { COLBLK::Print(g, f, n); diff --git a/storage/connect/tabpivot.h b/storage/connect/tabpivot.h index 3aa5288b5d8..bed288dc560 100644 --- a/storage/connect/tabpivot.h +++ b/storage/connect/tabpivot.h @@ -231,7 +231,7 @@ class DllExport QRSCOL : public COLBLK { // Methods virtual void ReadColumn(PGLOBAL g); - virtual void Print(PGLOBAL g, FILE *, UINT); + virtual void Print(PGLOBAL g, FILE *, uint); protected: QRSCOL(void) {} // Default constructor not to be used From 8c9ce17359422c4cfe6c6c44e483d1b6ce9f8a56 Mon Sep 17 00:00:00 2001 From: Olivier Bertrand Date: Sun, 12 May 2013 18:14:03 +0200 Subject: [PATCH 13/47] - Code cleaning. modified: storage/connect/connect.cc storage/connect/tabutil.h - Fix closing invalid tdbp in External_lock. modified: storage/connect/ha_connect.cc - Fix closing null Tdbp modified: storage/connect/tabpivot.cpp* - Fix regression error in table type TBL no more accepting missing columns in sub-tables even when Accept was set to TRUE. modified: storage/connect/tabtbl.cpp --- storage/connect/connect.cc | 5 ---- storage/connect/ha_connect.cc | 6 +++-- .../connect/mysql-test/connect/r/pivot.result | 0 .../connect/mysql-test/connect/t/pivot.test | 0 storage/connect/tabpivot.cpp | 4 ++- storage/connect/tabpivot.h | 0 storage/connect/tabtbl.cpp | 27 +++++-------------- storage/connect/tabutil.h | 16 ----------- 8 files changed, 13 insertions(+), 45 deletions(-) mode change 100644 => 100755 storage/connect/mysql-test/connect/r/pivot.result mode change 100644 => 100755 storage/connect/mysql-test/connect/t/pivot.test mode change 100644 => 100755 storage/connect/tabpivot.cpp mode change 100644 => 100755 storage/connect/tabpivot.h diff --git a/storage/connect/connect.cc b/storage/connect/connect.cc index 54816f80e5c..6ae730f20b2 100644 --- a/storage/connect/connect.cc +++ b/storage/connect/connect.cc @@ -657,11 +657,6 @@ int CntIndexInit(PGLOBAL g, PTDB ptdb, int id) cdp= tdbp->Key(k)->GetCdp(); valp= AllocateValue(g, cdp->GetType(), cdp->GetLength()); tdbp->To_Link[k]= new(g) CONSTANT(valp); - -//if (kdp->Klen && tdbp->To_Link[k]->GetResultType() == TYPE_STRING) -// ((XCOLBLK*)tdbp->To_Link[k])->SetLength(kdp->Klen); - -//((PCOL)tdbp->To_Link[k])->InitValue(g); } // endfor k // Make the index on xdp diff --git a/storage/connect/ha_connect.cc b/storage/connect/ha_connect.cc index 298fb71b334..ca0f9f7e08a 100644 --- a/storage/connect/ha_connect.cc +++ b/storage/connect/ha_connect.cc @@ -3014,8 +3014,10 @@ int ha_connect::external_lock(THD *thd, int lock_type) // This can NOT be called without open called first, but // the table can have been closed since then } else if (!tdbp || xp->CheckQuery(valid_query_id) || xmod != newmode) { - if (tdbp) - CloseTable(g); + // If this is called by a later query, the table may have + // been already closed and the tdbp is not valid anymore. + if (tdbp && xp->last_query_id == valid_query_id) + rc= CloseTable(g); xmod= newmode; diff --git a/storage/connect/mysql-test/connect/r/pivot.result b/storage/connect/mysql-test/connect/r/pivot.result old mode 100644 new mode 100755 diff --git a/storage/connect/mysql-test/connect/t/pivot.test b/storage/connect/mysql-test/connect/t/pivot.test old mode 100644 new mode 100755 diff --git a/storage/connect/tabpivot.cpp b/storage/connect/tabpivot.cpp old mode 100644 new mode 100755 index efd9cf6a950..4ae1b3ceae6 --- a/storage/connect/tabpivot.cpp +++ b/storage/connect/tabpivot.cpp @@ -876,7 +876,9 @@ int TDBPIVOT::DeleteDB(PGLOBAL g, int irc) /***********************************************************************/ void TDBPIVOT::CloseDB(PGLOBAL g) { - Tdbp->CloseDB(g); + if (Tdbp) + Tdbp->CloseDB(g); + } // end of CloseDB #if 0 diff --git a/storage/connect/tabpivot.h b/storage/connect/tabpivot.h old mode 100644 new mode 100755 diff --git a/storage/connect/tabtbl.cpp b/storage/connect/tabtbl.cpp index 5a2089d04d6..7b10089ea36 100644 --- a/storage/connect/tabtbl.cpp +++ b/storage/connect/tabtbl.cpp @@ -214,8 +214,7 @@ PCOL TDBTBL::InsertSpecialColumn(PGLOBAL g, PCOL scp) /***********************************************************************/ bool TDBTBL::InitTableList(PGLOBAL g) { - char *colname; - int n, colpos; + int n; PTABLE tp, tabp; PTDB tdbp; PCOL colp; @@ -242,23 +241,9 @@ bool TDBTBL::InitTableList(PGLOBAL g) // Real initialization will be done later. for (PCOL cp = Columns; cp; cp = cp->GetNext()) if (!cp->IsSpecial()) { - colname = cp->GetName(); - colpos = ((PPRXCOL)cp)->Colnum; - - // We try first to get the column by name - if (!(colp = tdbp->ColDB(g, colname, 0)) && colpos) - // When unsuccessful, if a column number was specified - // try to get the column by its position in the table - colp = tdbp->ColDB(g, NULL, colpos); - - if (!colp) { - if (!Accept) { - sprintf(g->Message, MSG(NO_MATCHING_COL), - colname, tdbp->GetName()); - return TRUE; // Error return - } // endif !Accept - - } else // this is needed by some tables (which?) + if (((PPRXCOL)cp)->Init(g) && !Accept) + return TRUE; + else // this is needed by some tables (which?) colp->SetColUse(cp->GetColUse()); } // endif !special @@ -428,7 +413,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 (((PPRXCOL)cp)->Init(g)) + else if (((PPRXCOL)cp)->Init(g) && !Accept) return TRUE; if (trace) @@ -482,7 +467,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 (((PPRXCOL)cp)->Init(g)) + else if (((PPRXCOL)cp)->Init(g) && !Accept) return RC_FX; if (trace) diff --git a/storage/connect/tabutil.h b/storage/connect/tabutil.h index b99cf959bca..81e2a44464a 100644 --- a/storage/connect/tabutil.h +++ b/storage/connect/tabutil.h @@ -14,28 +14,12 @@ 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 -------------------------- */ /***********************************************************************/ From 5ac8c8bea660129dfb31faa9de5594c5d4342a4c Mon Sep 17 00:00:00 2001 From: Olivier Bertrand Date: Sun, 12 May 2013 18:37:53 +0200 Subject: [PATCH 14/47] - Changing mode from +x to -x modified: storage/connect/mysql-test/connect/r/pivot.result* storage/connect/mysql-test/connect/t/pivot.test* storage/connect/tabpivot.cpp* storage/connect/tabpivot.h* --- storage/connect/mysql-test/connect/r/pivot.result | 0 storage/connect/mysql-test/connect/t/pivot.test | 0 storage/connect/tabpivot.cpp | 0 storage/connect/tabpivot.h | 0 4 files changed, 0 insertions(+), 0 deletions(-) mode change 100755 => 100644 storage/connect/mysql-test/connect/r/pivot.result mode change 100755 => 100644 storage/connect/mysql-test/connect/t/pivot.test mode change 100755 => 100644 storage/connect/tabpivot.cpp mode change 100755 => 100644 storage/connect/tabpivot.h diff --git a/storage/connect/mysql-test/connect/r/pivot.result b/storage/connect/mysql-test/connect/r/pivot.result old mode 100755 new mode 100644 diff --git a/storage/connect/mysql-test/connect/t/pivot.test b/storage/connect/mysql-test/connect/t/pivot.test old mode 100755 new mode 100644 diff --git a/storage/connect/tabpivot.cpp b/storage/connect/tabpivot.cpp old mode 100755 new mode 100644 diff --git a/storage/connect/tabpivot.h b/storage/connect/tabpivot.h old mode 100755 new mode 100644 From 35f813143bbb4f3e06649678fc19a900667e6432 Mon Sep 17 00:00:00 2001 From: Olivier Bertrand Date: Mon, 13 May 2013 10:37:35 +0200 Subject: [PATCH 15/47] - Set tdbp to NULL when ignored modified: storage/connect/ha_connect.cc --- storage/connect/ha_connect.cc | 13 +++++++++---- 1 file changed, 9 insertions(+), 4 deletions(-) diff --git a/storage/connect/ha_connect.cc b/storage/connect/ha_connect.cc index ca0f9f7e08a..a4611c83ffe 100644 --- a/storage/connect/ha_connect.cc +++ b/storage/connect/ha_connect.cc @@ -3014,10 +3014,15 @@ int ha_connect::external_lock(THD *thd, int lock_type) // This can NOT be called without open called first, but // the table can have been closed since then } else if (!tdbp || xp->CheckQuery(valid_query_id) || xmod != newmode) { - // If this is called by a later query, the table may have - // been already closed and the tdbp is not valid anymore. - if (tdbp && xp->last_query_id == valid_query_id) - rc= CloseTable(g); + if (tdbp) { + // If this is called by a later query, the table may have + // been already closed and the tdbp is not valid anymore. + if (xp->last_query_id == valid_query_id) + rc= CloseTable(g); + else + tdbp= NULL; + + }// endif tdbp xmod= newmode; From 53e2023952d74e0b0dc76160c3a1ba5ee30f098c Mon Sep 17 00:00:00 2001 From: Alexander Barkov Date: Mon, 13 May 2013 13:35:56 +0400 Subject: [PATCH 16/47] Enabling --suite=connect by default modified: mysql-test/mysql-test-run.pl --- mysql-test/mysql-test-run.pl | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/mysql-test/mysql-test-run.pl b/mysql-test/mysql-test-run.pl index a6780b5038c..47a3ccfc6d8 100755 --- a/mysql-test/mysql-test-run.pl +++ b/mysql-test/mysql-test-run.pl @@ -377,7 +377,7 @@ sub main { # directly before it executes them, like "make test-force-pl" in RPM builds. mtr_report("Logging: $0 ", join(" ", @ARGV)); - $DEFAULT_SUITES.=",sequence,sql_discovery" if $source_dist; + $DEFAULT_SUITES.=",sequence,sql_discovery,connect" if $source_dist; command_line_setup(); From dee955bdee939506804fdc36bf33224e2b104926 Mon Sep 17 00:00:00 2001 From: Olivier Bertrand Date: Mon, 13 May 2013 11:37:34 +0200 Subject: [PATCH 17/47] - fix use of uninitialized variable (colp) modified: storage/connect/tabtbl.cpp storage/connect/tabutil.cpp --- storage/connect/tabtbl.cpp | 10 +++------- storage/connect/tabutil.cpp | 6 +++++- 2 files changed, 8 insertions(+), 8 deletions(-) diff --git a/storage/connect/tabtbl.cpp b/storage/connect/tabtbl.cpp index 7b10089ea36..7e89cccf583 100644 --- a/storage/connect/tabtbl.cpp +++ b/storage/connect/tabtbl.cpp @@ -239,14 +239,10 @@ bool TDBTBL::InitTableList(PGLOBAL g) // We must allocate subtable columns before GetMaxSize is called // because some (PLG, ODBC?) need to have their columns attached. // Real initialization will be done later. - for (PCOL cp = Columns; cp; cp = cp->GetNext()) - if (!cp->IsSpecial()) { - if (((PPRXCOL)cp)->Init(g) && !Accept) + for (colp = Columns; colp; colp = colp->GetNext()) + if (!colp->IsSpecial()) + if (((PPRXCOL)colp)->Init(g) && !Accept) return TRUE; - else // this is needed by some tables (which?) - colp->SetColUse(cp->GetColUse()); - - } // endif !special if (Tablist) Tablist->Link(tabp); diff --git a/storage/connect/tabutil.cpp b/storage/connect/tabutil.cpp index 2c14b711f86..c55b8d1fa5c 100644 --- a/storage/connect/tabutil.cpp +++ b/storage/connect/tabutil.cpp @@ -531,8 +531,12 @@ bool PRXCOL::Init(PGLOBAL g) Colp = tdbp->Tdbp->ColDB(g, NULL, Colnum); if (Colp) { - Colp->InitValue(g); // May not have been done elsewhere + // May not have been done elsewhere + Colp->InitValue(g); To_Val = Colp->GetValue(); + + // this may be needed by some tables (which?) + Colp->SetColUse(ColUse); } else { sprintf(g->Message, MSG(NO_MATCHING_COL), Name, tdbp->Tdbp->GetName()); return TRUE; From 24a7948343c712531236d4ec408178382433caa3 Mon Sep 17 00:00:00 2001 From: Olivier Bertrand Date: Mon, 13 May 2013 12:20:08 +0200 Subject: [PATCH 18/47] - Code cleaning. Eliminating unused code, functions, and variables. modified: storage/connect/catalog.h storage/connect/colblk.cpp storage/connect/colblk.h storage/connect/mycat.cc storage/connect/reldef.cpp storage/connect/tabcol.h storage/connect/tabsys.cpp storage/connect/tabsys.h storage/connect/xobject.h --- storage/connect/catalog.h | 10 ----- storage/connect/colblk.cpp | 13 ------- storage/connect/colblk.h | 1 - storage/connect/mycat.cc | 14 +------ storage/connect/reldef.cpp | 11 ++---- storage/connect/tabcol.h | 1 - storage/connect/tabsys.cpp | 79 ++++++++------------------------------ storage/connect/tabsys.h | 5 +-- storage/connect/xobject.h | 1 - 9 files changed, 21 insertions(+), 114 deletions(-) diff --git a/storage/connect/catalog.h b/storage/connect/catalog.h index 365169100d9..3a06aea7a30 100644 --- a/storage/connect/catalog.h +++ b/storage/connect/catalog.h @@ -62,14 +62,9 @@ class DllExport CATALOG { virtual ~CATALOG() { } // Make -Wdelete-non-virtual-dtor happy // Implementation - void *GetDescp(void) {return Descp;} -//PRELDEF GetTo_Desc(void) {return To_Desc;} -//PSZ GetDescFile(void) {return DescFile;} int GetCblen(void) {return Cblen;} bool GetDefHuge(void) {return DefHuge;} void SetDefHuge(bool b) {DefHuge = b;} -//bool GetSepIndex(void) {return SepIndex;} -//void SetSepIndex(bool b) {SepIndex = b;} char *GetCbuf(void) {return Cbuf;} char *GetDataPath(void) {return (char*)DataPath;} @@ -115,15 +110,10 @@ class DllExport CATALOG { virtual PRELDEF MakeTableDesc(PGLOBAL g, LPCSTR name, LPCSTR am) {return NULL;} // Members -//PRELDEF To_Desc; /* To chain of relation desc. */ - void *Descp; /* To DB description area */ -//AREADEF DescArea; /* Table desc. area size */ char *Cbuf; /* Buffer used for col section */ int Cblen; /* Length of suballoc. buffer */ CURTAB Ctb; /* Used to enumerate tables */ bool DefHuge; /* true: tables default to huge */ -//bool SepIndex; /* true: separate index files */ -//char DescFile[_MAX_PATH]; /* DB description filename */ LPCSTR DataPath; /* Is the Path of DB data dir */ }; // end of class CATALOG diff --git a/storage/connect/colblk.cpp b/storage/connect/colblk.cpp index cdbf6f4b42b..dfdc82e99a7 100644 --- a/storage/connect/colblk.cpp +++ b/storage/connect/colblk.cpp @@ -159,19 +159,6 @@ bool COLBLK::CheckSort(PTDB tdbp) return (tdbp == To_Tdb); } // end of CheckSort -/***********************************************************************/ -/* MarkCol: see PlugMarkCol for column references to mark. */ -/***********************************************************************/ -void COLBLK::MarkCol(ushort bits) - { - ColUse |= bits; - -#ifdef DEBTRACE - htrc(" column R%d.%s marked as %04X\n", - To_Tdb->GetTdb_No(), Name, ColUse); -#endif - } // end of MarkCol - /***********************************************************************/ /* InitValue: prepare a column block for read operation. */ /* Now we use Format.Length for the len parameter to avoid strings */ diff --git a/storage/connect/colblk.h b/storage/connect/colblk.h index cf6fb443308..5fbb118fc72 100644 --- a/storage/connect/colblk.h +++ b/storage/connect/colblk.h @@ -64,7 +64,6 @@ class DllExport COLBLK : public XOBJECT { virtual bool IsSpecial(void) {return false;} virtual int CheckSpcCol(PTDB tdbp, int n) {return 2;} virtual bool CheckSort(PTDB tdbp); - virtual void MarkCol(ushort bits); virtual bool Eval(PGLOBAL g); virtual bool SetBuffer(PGLOBAL g, PVAL value, bool ok, bool check); virtual void SetTo_Val(PVAL valp) {} diff --git a/storage/connect/mycat.cc b/storage/connect/mycat.cc index 7b7f79d7b58..35a66f0d1a2 100644 --- a/storage/connect/mycat.cc +++ b/storage/connect/mycat.cc @@ -256,15 +256,11 @@ uint GetFuncID(const char *func) /***********************************************************************/ CATALOG::CATALOG(void) { -//To_Desc= NULL; -//*DescFile= '\0'; #if defined(WIN32) DataPath= ".\\"; #else // !WIN32 DataPath= "./"; #endif // !WIN32 - Descp= NULL; -//memset(&DescArea, 0, sizeof(AREADEF)); memset(&Ctb, 0, sizeof(CURTAB)); Cbuf= NULL; Cblen= 0; @@ -279,17 +275,14 @@ CATALOG::CATALOG(void) MYCAT::MYCAT(PHC hc) : CATALOG() { Hc= hc; -//To_Desc= NULL; DefHuge= false; -//SepIndex= true; // Temporay until we can store offet and size } // end of MYCAT constructor /***********************************************************************/ -/* When using volatile storage, reset values pointing to Sarea. */ +/* Nothing to do for CONNECT. */ /***********************************************************************/ void MYCAT::Reset(void) { -//To_Desc= NULL; } // end of Reset /***********************************************************************/ @@ -597,10 +590,6 @@ PRELDEF MYCAT::GetTableDesc(PGLOBAL g, LPCSTR name, if (xtrace) printf("GetTableDesc: name=%s am=%s\n", name, SVP(type)); - // Firstly check whether this table descriptor is in memory -//if (To_Desc) -// return To_Desc; - // If not specified get the type of this table if (!type && !(type= Hc->GetStringOption("Type"))) type= (Hc->GetStringOption("Tabname")) ? "PROXY" : "DOS"; @@ -708,7 +697,6 @@ PTDB MYCAT::GetTable(PGLOBAL g, PTABLE tablep, MODE mode, LPCSTR type) /***********************************************************************/ void MYCAT::ClearDB(PGLOBAL g) { -//To_Desc= NULL; } // end of ClearDB /* ------------------------ End of MYCAT --------------------------- */ diff --git a/storage/connect/reldef.cpp b/storage/connect/reldef.cpp index 6d16dcde04a..8525fd09cbc 100644 --- a/storage/connect/reldef.cpp +++ b/storage/connect/reldef.cpp @@ -90,11 +90,9 @@ TABDEF::TABDEF(void) /***********************************************************************/ bool TABDEF::Define(PGLOBAL g, PCATLG cat, LPCSTR name, LPCSTR am) { -//char buf[8]; int poff = 0; - void *memp = cat->Descp; - Name = (PSZ)PlugSubAlloc(g, memp, strlen(name) + 1); + Name = (PSZ)PlugSubAlloc(g, NULL, strlen(name) + 1); strcpy(Name, name); Cat = cat; Catfunc = GetFuncID(Cat->GetStringCatInfo(g, "Catfunc", NULL)); @@ -127,7 +125,6 @@ PTABDEF OEMDEF::GetXdef(PGLOBAL g) PTABDEF xdefp; XGETDEF getdef = NULL; PCATLG cat = Cat; - void *memp = cat->Descp; #if defined(WIN32) // Is the DLL already loaded? @@ -189,7 +186,7 @@ PTABDEF OEMDEF::GetXdef(PGLOBAL g) sprintf(g->Message, MSG(DEF_ALLOC_ERROR), Subtype); // Get the table definition block - if (!(xdefp = getdef(g, memp))) + if (!(xdefp = getdef(g, NULL))) return NULL; // Have the external class do its complete definition @@ -223,15 +220,13 @@ bool OEMDEF::DeleteTableFile(PGLOBAL g) /***********************************************************************/ bool OEMDEF::DefineAM(PGLOBAL g, LPCSTR am, int poff) { - void *memp = Cat->Descp; - Module = Cat->GetStringCatInfo(g, "Module", ""); Subtype = Cat->GetStringCatInfo(g, "Subtype", Module); if (!*Module) Module = Subtype; - Desc = (char*)PlugSubAlloc(g, memp, strlen(Module) + Desc = (char*)PlugSubAlloc(g, NULL, strlen(Module) + strlen(Subtype) + 3); sprintf(Desc, "%s(%s)", Module, Subtype); return false; diff --git a/storage/connect/tabcol.h b/storage/connect/tabcol.h index 8c21fe6d1b2..4680e50f29e 100644 --- a/storage/connect/tabcol.h +++ b/storage/connect/tabcol.h @@ -86,7 +86,6 @@ class DllExport COLUMN: public XOBJECT { // Column Name/Qualifier block. virtual bool Eval(PGLOBAL) {assert(false); return true;} virtual int CheckSpcCol(PTDB, int) {assert(false); return 2;} virtual bool CheckSort(PTDB) {assert(false); return false;} - virtual void MarkCol(ushort) {assert(false);} private: // Members diff --git a/storage/connect/tabsys.cpp b/storage/connect/tabsys.cpp index 9f933e4e2b8..705bb79bcb4 100644 --- a/storage/connect/tabsys.cpp +++ b/storage/connect/tabsys.cpp @@ -65,7 +65,6 @@ INIDEF::INIDEF(void) Pseudo = 3; Fn = NULL; Xname = NULL; - Subtype = '?'; Layout = '?'; Ln = 0; } // end of INIDEF constructor @@ -75,63 +74,23 @@ INIDEF::INIDEF(void) /***********************************************************************/ bool INIDEF::DefineAM(PGLOBAL g, LPCSTR am, int poff) { - char buf[8], ds[2]; - void *memp = Cat->GetDescp(); - - if (!stricmp(am, "SYS")) - strcpy(ds, "T"); // SYS tables default to T(able) - else - strcpy(ds, "I"); // INI tables default to I(ni) + char buf[8]; Fn = Cat->GetStringCatInfo(g, "Filename", NULL); - Cat->GetCharCatInfo("Subtype", ds, buf, sizeof(buf)); - Subtype = toupper(*buf); Cat->GetCharCatInfo("Layout", "C", buf, sizeof(buf)); Layout = toupper(*buf); - switch (Subtype) { -#if 0 - case 'C': - case 'T': - // Restricted table - Xname = Cat->GetStringCatInfo(g, "Name", "?"); + if (Fn) { + char *p = (char*)PlugSubAlloc(g, NULL, _MAX_PATH); - if (!strcmp(Xname, "?")) - Xname = NULL; - - if (*Fn == '?') - Fn = Cat->GetStringCatInfo(g, "Database", "?"); - - if (*Fn != '?') { - char *p = (char*)PlugSubAlloc(g, memp, _MAX_PATH); - - if (!PlgSetXdbPath(g, Fn, NULL, p, _MAX_PATH, NULL, 0)) - Fn = p; - - } else - Fn = Cat->GetDescFile(); - - Ln = GetIniSize("Database", "Tabsize", "2K", Fn); - break; -#endif // 0 - case 'I': - if (*Fn != '?') { - char *p = (char*)PlugSubAlloc(g, memp, _MAX_PATH); - - PlugSetPath(p, Fn, GetPath()); - Fn = p; - } else { - strcpy(g->Message, MSG(MISSING_FNAME)); - return true; - } // endif Fn - - Ln = Cat->GetSizeCatInfo("Secsize", "8K"); - break; - default: - sprintf(g->Message, MSG(INV_SUBTYPE), buf); - return true; - } // endswitch Subtype + PlugSetPath(p, Fn, GetPath()); + Fn = p; + } else { + strcpy(g->Message, MSG(MISSING_FNAME)); + return true; + } // endif Fn + Ln = Cat->GetSizeCatInfo("Secsize", "8K"); Desc = Fn; return false; } // end of DefineAM @@ -143,17 +102,10 @@ PTDB INIDEF::GetTable(PGLOBAL g, MODE m) { PTDBASE tdbp; - switch (Subtype) { - case 'I': - if (Layout == 'C') - tdbp = new(g) TDBINI(this); - else - tdbp = new(g) TDBXIN(this); - - break; - default: - return NULL; - } // endswitch Subtype + if (Layout == 'C') + tdbp = new(g) TDBINI(this); + else + tdbp = new(g) TDBXIN(this); if (Multiple) tdbp = new(g) TDBMUL(tdbp); // No block optimization yet @@ -163,7 +115,6 @@ PTDB INIDEF::GetTable(PGLOBAL g, MODE m) /***********************************************************************/ /* DeleteTableFile: Delete INI table files using platform API. */ -/* SysTable and SysColumn tables are readonly and not erasable. */ /***********************************************************************/ bool INIDEF::DeleteTableFile(PGLOBAL g) { @@ -171,7 +122,7 @@ bool INIDEF::DeleteTableFile(PGLOBAL g) bool rc; // Delete the INI table file if not protected - if (Subtype == 'I' && !IsReadOnly()) { + if (!IsReadOnly()) { PlugSetPath(filename, Fn, GetPath()); #if defined(WIN32) rc = !DeleteFile(filename); diff --git a/storage/connect/tabsys.h b/storage/connect/tabsys.h index ac8ae05aee9..2780eb3ca98 100644 --- a/storage/connect/tabsys.h +++ b/storage/connect/tabsys.h @@ -38,7 +38,6 @@ class DllExport INIDEF : public TABDEF { /* INI table description */ // Members char *Fn; /* Path/Name of corresponding file */ char *Xname; /* The eventual table name */ - char Subtype; /* I: INI, T: Table, C: Column */ char Layout; /* R: Row, C: Column */ int Ln; /* Length of section list buffer */ }; // end of INIDEF @@ -83,8 +82,8 @@ class TDBINI : public TDBASE { // Members char *Ifile; // The INI file char *Seclist; // The section list - char *Section; // The current section - int Seclen; // Length of seclist buffer + char *Section; // The current section + int Seclen; // Length of seclist buffer int N; // The current section index }; // end of class TDBINI diff --git a/storage/connect/xobject.h b/storage/connect/xobject.h index c77fb703823..79325f155cf 100644 --- a/storage/connect/xobject.h +++ b/storage/connect/xobject.h @@ -71,7 +71,6 @@ class DllExport XOBJECT : public BLOCK { virtual bool VerifyColumn(PTBX txp) {return false;} virtual bool VerifyTdb(PTDB& tdbp) {return false;} virtual bool IsColInside(PCOL colp) {return false;} - virtual void MarkCol(ushort) {} protected: PVAL Value; // The current value of the object. From d22b1a0b35e794212c92e65f1d7f7d3e108cceef Mon Sep 17 00:00:00 2001 From: Alexander Barkov Date: Mon, 13 May 2013 14:59:59 +0400 Subject: [PATCH 19/47] Fixing a few compilation warnings ("no previous declaration for XXX") added: storage/connect/inihandl.h modified: storage/connect/CMakeLists.txt storage/connect/connect.h storage/connect/ha_connect.cc storage/connect/inihandl.c storage/connect/osutil.h storage/connect/tabsys.cpp storage/connect/user_connect.cc --- storage/connect/CMakeLists.txt | 2 +- storage/connect/connect.h | 1 + storage/connect/ha_connect.cc | 5 +-- storage/connect/inihandl.c | 12 +++++--- storage/connect/inihandl.h | 54 +++++++++++++++++++++++++++++++++ storage/connect/osutil.h | 46 ---------------------------- storage/connect/tabsys.cpp | 4 +-- storage/connect/user_connect.cc | 6 +--- 8 files changed, 68 insertions(+), 62 deletions(-) create mode 100644 storage/connect/inihandl.h diff --git a/storage/connect/CMakeLists.txt b/storage/connect/CMakeLists.txt index d3663c5eee3..81dd8c77b67 100644 --- a/storage/connect/CMakeLists.txt +++ b/storage/connect/CMakeLists.txt @@ -28,7 +28,7 @@ filamzip.cpp tabtbl.cpp myutil.cpp tabutil.cpp tabxcl.cpp taboccur.cpp tabpivot.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 +global.h ha_connect.h inihandl.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 diff --git a/storage/connect/connect.h b/storage/connect/connect.h index 3fd52d283c6..e81e54776c9 100644 --- a/storage/connect/connect.h +++ b/storage/connect/connect.h @@ -44,6 +44,7 @@ RCODE CntDeleteRow(PGLOBAL g, PTDB tdbp, bool all); bool CntInfo(PGLOBAL g, PTDB tdbp, PXF info); int CntIndexRange(PGLOBAL g, PTDB ptdb, const uchar* *key, uint *len, bool *incl, key_part_map *kmap); +PGLOBAL CntExit(PGLOBAL g); /***********************************************************************/ /* Definition of classes XCOLCRT, XIXDEF, XKPDEF, DOXDEF, TDBDOX */ diff --git a/storage/connect/ha_connect.cc b/storage/connect/ha_connect.cc index a4611c83ffe..214ad8ba049 100644 --- a/storage/connect/ha_connect.cc +++ b/storage/connect/ha_connect.cc @@ -137,6 +137,7 @@ #include "mycat.h" #include "myutil.h" #include "preparse.h" +#include "inihandl.h" #define PLGXINI "plgcnx.ini" /* Configuration settings file */ #define my_strupr(p) my_caseup_str(default_charset_info, (p)); @@ -3252,8 +3253,8 @@ static char *encode(PGLOBAL g, char *cnm) Return 0 if ok */ -bool add_field(String *sql, const char *field_name, const char *type, - int len, int dec, uint tm, const char *rem) +static bool add_field(String *sql, const char *field_name, const char *type, + int len, int dec, uint tm, const char *rem) { bool error= false; diff --git a/storage/connect/inihandl.c b/storage/connect/inihandl.c index 25629b04e60..60b72bd2604 100644 --- a/storage/connect/inihandl.c +++ b/storage/connect/inihandl.c @@ -29,9 +29,8 @@ //#include //#include #include "my_global.h" -//#include "osutil.h" #include "global.h" - +#include "inihandl.h" // The types and variables used locally //typedef int bool; @@ -672,7 +671,7 @@ static BOOL PROFILE_DeleteKey(PROFILESECTION* *section, * * Delete all keys from a profile tree. ***********************************************************************/ -void PROFILE_DeleteAllKeys(LPCSTR section_name) +static void PROFILE_DeleteAllKeys(LPCSTR section_name) { PROFILESECTION* *section= &CurProfile->section; @@ -1038,6 +1037,7 @@ static BOOL PROFILE_SetString(LPCSTR section_name, LPCSTR key_name, * Convenience function that turns a string 'xxx, yyy, zzz' into * the 'xxx\0 yyy, zzz' and returns a pointer to the 'yyy, zzz'. ***********************************************************************/ +#if 0 char *PROFILE_GetStringItem(char* start) { char *lpchX, *lpch; @@ -1065,6 +1065,7 @@ char *PROFILE_GetStringItem(char* start) return NULL; } // end of PROFILE_GetStringItem +#endif /********************************************************************** * if allow_section_name_copy is TRUE, allow the copying : @@ -1132,7 +1133,7 @@ static int PROFILE_GetPrivateProfileString(LPCSTR section, LPCSTR entry, * GetPrivateProfileStringA (KERNEL32.@) ***********************************************************************/ int GetPrivateProfileString(LPCSTR section, LPCSTR entry, LPCSTR def_val, - LPSTR buffer, uint len, LPCSTR filename) + LPSTR buffer, DWORD len, LPCSTR filename) { return PROFILE_GetPrivateProfileString(section, entry, def_val, buffer, len, filename, TRUE); @@ -1308,7 +1309,8 @@ BOOL WritePrivateProfileSection(LPCSTR section, * Note that when the buffer is big enough then the return value may be any * value between 1 and len-1 (or len in Win95), including len-2. */ -DWORD GetPrivateProfileSectionNames(LPSTR buffer, DWORD size, LPCSTR filename) +static DWORD +GetPrivateProfileSectionNames(LPSTR buffer, DWORD size, LPCSTR filename) { DWORD ret = 0; diff --git a/storage/connect/inihandl.h b/storage/connect/inihandl.h new file mode 100644 index 00000000000..7f6fcb1f582 --- /dev/null +++ b/storage/connect/inihandl.h @@ -0,0 +1,54 @@ +#ifndef __INIHANDL_H__ +#define __INIHANDL_H__ + +#if defined(UNIX) || defined(UNIV_LINUX) + +#ifdef __cplusplus +extern "C" { +#endif + +void PROFILE_Close(LPCSTR filename); + +int GetPrivateProfileString( + LPCTSTR lpAppName, // section name + LPCTSTR lpKeyName, // key name + LPCTSTR lpDefault, // default string + LPTSTR lpReturnedString, // destination buffer + DWORD nSize, // size of destination buffer + LPCTSTR lpFileName // initialization file name + ); + +uint GetPrivateProfileInt( + LPCTSTR lpAppName, // section name + LPCTSTR lpKeyName, // key name + INT nDefault, // return value if key name not found + LPCTSTR lpFileName // initialization file name + ); + +BOOL WritePrivateProfileString( + LPCTSTR lpAppName, // section name + LPCTSTR lpKeyName, // key name + LPCTSTR lpString, // string to add + LPCTSTR lpFileName // initialization file + ); + +int GetPrivateProfileSection( + LPCTSTR lpAppName, // section name + LPTSTR lpReturnedString, // return buffer + DWORD nSize, // size of return buffer + LPCTSTR lpFileName // initialization file name + ); + +BOOL WritePrivateProfileSection( + LPCTSTR lpAppName, // section name + LPCTSTR lpString, // data + LPCTSTR lpFileName // file name + ); + +#ifdef __cplusplus +} +#endif + +#endif /* defined(UNIX) */ + +#endif /* __INIHANDL_H__ */ diff --git a/storage/connect/osutil.h b/storage/connect/osutil.h index 440373dd7a1..148a22321f4 100644 --- a/storage/connect/osutil.h +++ b/storage/connect/osutil.h @@ -32,44 +32,6 @@ char *_fullpath(char *absPath, const char *relPath, size_t maxLength); BOOL MessageBeep(uint); unsigned long _filelength(int fd); -void PROFILE_Close(LPCSTR filename); - -int GetPrivateProfileString( - LPCTSTR lpAppName, // section name - LPCTSTR lpKeyName, // key name - LPCTSTR lpDefault, // default string - LPTSTR lpReturnedString, // destination buffer - int nSize, // size of destination buffer - LPCTSTR lpFileName // initialization file name - ); - -uint GetPrivateProfileInt( - LPCTSTR lpAppName, // section name - LPCTSTR lpKeyName, // key name - INT nDefault, // return value if key name not found - LPCTSTR lpFileName // initialization file name - ); - -BOOL WritePrivateProfileString( - LPCTSTR lpAppName, // section name - LPCTSTR lpKeyName, // key name - LPCTSTR lpString, // string to add - LPCTSTR lpFileName // initialization file - ); - -int GetPrivateProfileSection( - LPCTSTR lpAppName, // section name - LPTSTR lpReturnedString, // return buffer - int nSize, // size of return buffer - LPCTSTR lpFileName // initialization file name - ); - -BOOL WritePrivateProfileSection( - LPCTSTR lpAppName, // section name - LPCTSTR lpString, // data - LPCTSTR lpFileName // file name - ); - PSZ strupr(PSZ s); PSZ strlwr(PSZ s); @@ -90,12 +52,4 @@ typedef __int64 FILEPOS; #define XSTR(x) ((x)?(x):"") -#ifdef __cplusplus -extern "C" { -#endif - -#ifdef __cplusplus -} -#endif - #endif /* __OSUTIL_H__ */ diff --git a/storage/connect/tabsys.cpp b/storage/connect/tabsys.cpp index 705bb79bcb4..6434e011882 100644 --- a/storage/connect/tabsys.cpp +++ b/storage/connect/tabsys.cpp @@ -41,9 +41,7 @@ #include "tabdos.h" #include "tabsys.h" #include "tabmul.h" -#if defined(UNIX) -#include "osutil.h" -#endif // UNIX +#include "inihandl.h" #define CSZ 36 // Column section name length #define CDZ 256 // Column definition length diff --git a/storage/connect/user_connect.cc b/storage/connect/user_connect.cc index 3fd3ac43e32..d85f11d1950 100644 --- a/storage/connect/user_connect.cc +++ b/storage/connect/user_connect.cc @@ -43,6 +43,7 @@ #include "osutil.h" #include "global.h" #include "plgdbsem.h" +#include "connect.h" #include "user_connect.h" #include "mycat.h" @@ -54,11 +55,6 @@ extern int xtrace; /****************************************************************************/ PCONNECT user_connect::to_users= NULL; -/****************************************************************************/ -/* CONNECT functions called externally. */ -/****************************************************************************/ -PGLOBAL CntExit(PGLOBAL g); - /* -------------------------- class user_connect -------------------------- */ /****************************************************************************/ From 35a879d06dbd58f4ae8203419915d7de67e821a9 Mon Sep 17 00:00:00 2001 From: Alexander Barkov Date: Mon, 13 May 2013 15:23:24 +0400 Subject: [PATCH 20/47] Fixing a few "no previous declaration" warnings modified: storage/connect/ha_connect.cc storage/connect/odbconn.cpp storage/connect/plgdbutl.cpp storage/connect/plugutil.c storage/connect/value.cpp --- storage/connect/ha_connect.cc | 2 +- storage/connect/odbconn.cpp | 3 ++- storage/connect/plgdbutl.cpp | 4 +++- storage/connect/plugutil.c | 3 ++- storage/connect/value.cpp | 2 +- 5 files changed, 9 insertions(+), 5 deletions(-) diff --git a/storage/connect/ha_connect.cc b/storage/connect/ha_connect.cc index 214ad8ba049..4d6889f7f8b 100644 --- a/storage/connect/ha_connect.cc +++ b/storage/connect/ha_connect.cc @@ -3829,7 +3829,7 @@ int ha_connect::create(const char *name, TABLE *table_arg, my_message(ER_UNKNOWN_ERROR, g->Message, MYF(0)); return HA_ERR_INTERNAL_ERROR; } // endif tab - + default: /* do nothing */; } // endswitch ttp if (type == TAB_XML) { diff --git a/storage/connect/odbconn.cpp b/storage/connect/odbconn.cpp index e32e666e1fe..881e554163e 100644 --- a/storage/connect/odbconn.cpp +++ b/storage/connect/odbconn.cpp @@ -36,6 +36,7 @@ //#include "kindex.h" #include "xtable.h" #include "tabodbc.h" +#include "odbccat.h" #include "plgcnx.h" // For DB types #include "resource.h" #include "valblk.h" @@ -203,7 +204,7 @@ CATPARM *AllocCatInfo(PGLOBAL g, CATINFO fid, char *tab, PQRYRES qrp) /***********************************************************************/ /* Check for nulls and reset them to Null (?) values. */ /***********************************************************************/ -void ResetNullValues(CATPARM *cap) +static void ResetNullValues(CATPARM *cap) { int i, n, ncol; PCOLRES crp; diff --git a/storage/connect/plgdbutl.cpp b/storage/connect/plgdbutl.cpp index 32ee105c19c..d0f3896bc4f 100644 --- a/storage/connect/plgdbutl.cpp +++ b/storage/connect/plgdbutl.cpp @@ -519,6 +519,7 @@ bool PlgSetXdbPath(PGLOBAL g, PSZ dbname, PSZ dbpath, /* Extract from a path name the required component. */ /* This function assumes there is enough space in the buffer. */ /***********************************************************************/ +#if 0 char *ExtractFromPath(PGLOBAL g, char *pBuff, char *FileName, OPVAL op) { char *drive = NULL, *direc = NULL, *fname = NULL, *ftype = NULL; @@ -539,13 +540,14 @@ char *ExtractFromPath(PGLOBAL g, char *pBuff, char *FileName, OPVAL op) _splitpath(FileName, drive, direc, fname, ftype); return pBuff; } // end of PlgExtractFromPath +#endif /***********************************************************************/ /* Check the occurence and matching of a pattern against a string. */ /* Because this function is only used for catalog name checking, */ /* it must be case insensitive. */ /***********************************************************************/ -bool PlugCheckPattern(PGLOBAL g, LPCSTR string, LPCSTR pat) +static bool PlugCheckPattern(PGLOBAL g, LPCSTR string, LPCSTR pat) { if (pat && strlen(pat)) { // This leaves 512 bytes (MAX_STR / 2) for each components diff --git a/storage/connect/plugutil.c b/storage/connect/plugutil.c index 693ae96cf52..2c7eaa893b6 100644 --- a/storage/connect/plugutil.c +++ b/storage/connect/plugutil.c @@ -491,9 +491,10 @@ void *MakePtr(void *memp, OFFSET offset) /***********************************************************************/ /* This routine makes an offset from a pointer new format. */ /***********************************************************************/ +#if 0 OFFSET MakeOff(void *memp, void *ptr) { return ((!ptr) ? 0 : (OFFSET)((char *)ptr - (char *)memp)); } /* end of MakeOff */ - +#endif /*--------------------- End of PLUGUTIL program -----------------------*/ diff --git a/storage/connect/value.cpp b/storage/connect/value.cpp index 7a1146e6c32..6152fdc238f 100644 --- a/storage/connect/value.cpp +++ b/storage/connect/value.cpp @@ -93,7 +93,7 @@ PSZ strlwr(PSZ s); /* met when returning from TestValue for a given operator. */ /* Bit one is EQ, bit 2 is LT, and bit 3 is GT. */ /***********************************************************************/ -BYTE OpBmp(PGLOBAL g, OPVAL opc) +static BYTE OpBmp(PGLOBAL g, OPVAL opc) { BYTE bt; From 33d1689fcf252d29a24cf05ca88c6711d682fb2e Mon Sep 17 00:00:00 2001 From: Alexander Barkov Date: Mon, 13 May 2013 15:57:49 +0400 Subject: [PATCH 21/47] Fixing compiler warnings ("no previous declaration for ...") added: storage/connect/rcmsg.h modified: storage/connect/CMakeLists.txt storage/connect/odbconn.cpp storage/connect/plgdbutl.cpp storage/connect/plugutil.c storage/connect/rcmsg.c storage/connect/tabodbc.cpp --- storage/connect/CMakeLists.txt | 5 +---- storage/connect/odbconn.cpp | 4 +--- storage/connect/plgdbutl.cpp | 2 +- storage/connect/plugutil.c | 2 +- storage/connect/rcmsg.c | 1 + storage/connect/rcmsg.h | 15 +++++++++++++++ storage/connect/tabodbc.cpp | 1 - 7 files changed, 20 insertions(+), 10 deletions(-) create mode 100644 storage/connect/rcmsg.h diff --git a/storage/connect/CMakeLists.txt b/storage/connect/CMakeLists.txt index 81dd8c77b67..6cae17c4dd9 100644 --- a/storage/connect/CMakeLists.txt +++ b/storage/connect/CMakeLists.txt @@ -18,7 +18,7 @@ SET(CONNECT_PLUGIN_DYNAMIC "connect") SET(CONNECT_SOURCES ha_connect.cc connect.cc user_connect.cc mycat.cc -fmdlex.c osutil.c plugutil.c rcmsg.c +fmdlex.c osutil.c plugutil.c rcmsg.c rcmsg.h csort.cpp maputil.cpp plgdbutl.cpp colblk.cpp reldef.cpp tabcol.cpp table.cpp filamap.cpp filamdbf.cpp filamfix.cpp filamtxt.cpp filamvct.cpp @@ -48,7 +48,6 @@ IF(UNIX) # Bar: -Wfatal-errors removed (does not present in gcc on solaris10) if(WITH_WARNINGS) add_definitions(-Wall -Wextra -Wmissing-declarations) - add_definitions(-Wno-non-virtual-dtor) message(STATUS "CONNECT: GCC: All warnings enabled") else() add_definitions(-Wall -Wmissing-declarations) @@ -64,13 +63,11 @@ IF(UNIX) # add_definitions(-Wno-int-to-pointer-cast) # Bar: -Wno-narrowing commented (does not present in gcc on solaris10) # add_definitions(-Wno-narrowing) - add_definitions(-Wno-non-virtual-dtor) # This switch is for pure C only: # add_definitions(-Wno-implicit-function-declaration) # These switches are for C++ only # add_definitions(-Wno-reorder) -# add_definitions(-Wno-delete-non-virtual-dtor) message(STATUS "CONNECT: GCC: Some warnings disabled") endif(WITH_WARNINGS) diff --git a/storage/connect/odbconn.cpp b/storage/connect/odbconn.cpp index 881e554163e..14b5f582962 100644 --- a/storage/connect/odbconn.cpp +++ b/storage/connect/odbconn.cpp @@ -48,9 +48,7 @@ /***********************************************************************/ #pragma comment(lib, "odbc32.lib") extern "C" HINSTANCE s_hModule; // Saved module handle -#else // !WIN32 -extern "C" int GetRcString(int id, char *buf, int bufsize); -#endif // !WIN32 +#endif // WIN32 /***********************************************************************/ /* Some macro's (should be defined elsewhere to be more accessible) */ diff --git a/storage/connect/plgdbutl.cpp b/storage/connect/plgdbutl.cpp index d0f3896bc4f..598075ac52a 100644 --- a/storage/connect/plgdbutl.cpp +++ b/storage/connect/plgdbutl.cpp @@ -67,6 +67,7 @@ #include "xtable.h" // header of TBX, TDB and TDBASE classes #include "tabcol.h" // header of XTAB and COLUMN classes #include "valblk.h" +#include "rcmsg.h" /***********************************************************************/ /* Macro or external routine definition */ @@ -129,7 +130,6 @@ void CloseXMLFile(PGLOBAL, PFBLOCK, bool); void CloseXML2File(PGLOBAL, PFBLOCK, bool); #endif // LIBXML2_SUPPORT -extern "C" int GetRcString(int id, char *buf, int bufsize); /***********************************************************************/ /* Routines for file IO with error reporting to g->Message */ diff --git a/storage/connect/plugutil.c b/storage/connect/plugutil.c index 2c7eaa893b6..12810d74284 100644 --- a/storage/connect/plugutil.c +++ b/storage/connect/plugutil.c @@ -107,7 +107,7 @@ ACTIVITY defActivity = { /* Describes activity and language */ #endif // XMSG || NEWMSG #if defined(UNIX) || defined(UNIV_LINUX) -int GetRcString(int id, char *buf, int bufsize); +#include "rcmsg.h" #endif // UNIX /**************************************************************************/ diff --git a/storage/connect/rcmsg.c b/storage/connect/rcmsg.c index e1a71cde9c6..0c63fd55242 100644 --- a/storage/connect/rcmsg.c +++ b/storage/connect/rcmsg.c @@ -14,6 +14,7 @@ /***********************************************************************/ #include #include "resource.h" +#include "rcmsg.h" char *GetMsgid(int id) { diff --git a/storage/connect/rcmsg.h b/storage/connect/rcmsg.h new file mode 100644 index 00000000000..b22e77f5175 --- /dev/null +++ b/storage/connect/rcmsg.h @@ -0,0 +1,15 @@ +#ifndef __RCMSG_H__ +#define __RCMSG_H__ + +#ifdef __cplusplus +extern "C" { +#endif + +char *GetMsgid(int id); +int GetRcString(int id, char *buf, int bufsize); + +#ifdef __cplusplus +} +#endif + +#endif /* __RCMSG_H__ */ diff --git a/storage/connect/tabodbc.cpp b/storage/connect/tabodbc.cpp index 5bbc9effa92..909fcda4abf 100644 --- a/storage/connect/tabodbc.cpp +++ b/storage/connect/tabodbc.cpp @@ -75,7 +75,6 @@ #include "sql_string.h" -extern "C" char *GetMsgid(int id); extern "C" int trace; /***********************************************************************/ From 54f32928315f7f1863dd43589d1a67cbf05b254a Mon Sep 17 00:00:00 2001 From: Alexander Barkov Date: Mon, 13 May 2013 16:48:03 +0400 Subject: [PATCH 22/47] Fixing warnings (mostly "no previous declaration") modified: storage/connect/ha_connect.cc storage/connect/maputil.h storage/connect/odbconn.cpp storage/connect/osutil.c storage/connect/osutil.h storage/connect/tabmysql.cpp storage/connect/tabutil.cpp storage/connect/tabutil.h --- storage/connect/ha_connect.cc | 2 -- storage/connect/maputil.h | 1 - storage/connect/odbconn.cpp | 2 +- storage/connect/osutil.c | 4 ++++ storage/connect/osutil.h | 10 ++++++++++ storage/connect/tabmysql.cpp | 4 +--- storage/connect/tabutil.cpp | 2 +- storage/connect/tabutil.h | 2 ++ 8 files changed, 19 insertions(+), 8 deletions(-) diff --git a/storage/connect/ha_connect.cc b/storage/connect/ha_connect.cc index 4d6889f7f8b..4466b19dd6d 100644 --- a/storage/connect/ha_connect.cc +++ b/storage/connect/ha_connect.cc @@ -3311,7 +3311,6 @@ static int connect_assisted_discovery(handlerton *hton, THD* thd, bool ok= false, dbf= false; TABTYPE ttp= TAB_UNDEF; MEM_ROOT *mem= thd->mem_root; - CHARSET_INFO *cs; PQRYRES qrp; PCOLRES crp; PGLOBAL g= GetPlug(thd, NULL); @@ -3567,7 +3566,6 @@ static int connect_assisted_discovery(handlerton *hton, THD* thd, rem= NULL; typ= len= dec= 0; tm= NOT_NULL_FLAG; - cs= NULL; for (crp= qrp->Colresp; crp; crp= crp->Next) switch (crp->Fld) { diff --git a/storage/connect/maputil.h b/storage/connect/maputil.h index 8ab41487a63..b5e54affcea 100644 --- a/storage/connect/maputil.h +++ b/storage/connect/maputil.h @@ -13,7 +13,6 @@ typedef struct { HANDLE CreateFileMap(PGLOBAL, LPCSTR, MEMMAP *, MODE, bool); bool CloseMemMap(void *memory, size_t dwSize); -my_bool CloseFileHandle(HANDLE h); #ifdef __cplusplus } diff --git a/storage/connect/odbconn.cpp b/storage/connect/odbconn.cpp index 14b5f582962..b39f1c9ba5b 100644 --- a/storage/connect/odbconn.cpp +++ b/storage/connect/odbconn.cpp @@ -175,7 +175,7 @@ int TranslateSQLType(int stp, int prec, int& len) /***********************************************************************/ /* Allocate the structure used to refer to the result set. */ /***********************************************************************/ -CATPARM *AllocCatInfo(PGLOBAL g, CATINFO fid, char *tab, PQRYRES qrp) +static CATPARM *AllocCatInfo(PGLOBAL g, CATINFO fid, char *tab, PQRYRES qrp) { size_t i, m, n; CATPARM *cap; diff --git a/storage/connect/osutil.c b/storage/connect/osutil.c index 45c834a4cfc..1b7332357e6 100644 --- a/storage/connect/osutil.c +++ b/storage/connect/osutil.c @@ -142,10 +142,12 @@ my_bool CloseFileHandle(HANDLE h) return (close(h)) ? TRUE : FALSE; } /* end of CloseFileHandle */ +#if 0 void Sleep(DWORD time) { //FIXME: TODO } /* end of Sleep */ +#endif int GetLastError() { @@ -213,6 +215,7 @@ int _isatty(int fileNo) return isatty(fileNo); } /* end of _isatty */ +#if 0 /* This function is ridiculous and should be revisited */ DWORD FormatMessage(DWORD dwFlags, LPCVOID lpSource, DWORD dwMessageId, DWORD dwLanguageId, LPSTR lpBuffer, DWORD nSize, ...) @@ -227,5 +230,6 @@ DWORD FormatMessage(DWORD dwFlags, LPCVOID lpSource, DWORD dwMessageId, strncpy(lpBuffer, buff, nSize); return min(n, nSize); } /* end of FormatMessage */ +#endif #endif // UNIX diff --git a/storage/connect/osutil.h b/storage/connect/osutil.h index 148a22321f4..63a3e18084c 100644 --- a/storage/connect/osutil.h +++ b/storage/connect/osutil.h @@ -52,4 +52,14 @@ typedef __int64 FILEPOS; #define XSTR(x) ((x)?(x):"") + +#ifdef __cplusplus +extern "C" { +#endif +my_bool CloseFileHandle(HANDLE h); +#ifdef __cplusplus +} +#endif + + #endif /* __OSUTIL_H__ */ diff --git a/storage/connect/tabmysql.cpp b/storage/connect/tabmysql.cpp index 3ecfd6aa6c1..b99823a8c4f 100644 --- a/storage/connect/tabmysql.cpp +++ b/storage/connect/tabmysql.cpp @@ -57,6 +57,7 @@ #include "reldef.h" #include "tabmysql.h" #include "valblk.h" +#include "tabutil.h" #if defined(_CONSOLE) void PrintResult(PGLOBAL, PSEM, PQRYRES); @@ -65,9 +66,6 @@ void PrintResult(PGLOBAL, PSEM, PQRYRES); extern "C" int trace; extern MYSQL_PLUGIN_IMPORT uint mysqld_port; -// This function is located in tabutil.cpp -void Remove_tshp(PCATLG cat); - /* -------------- Implementation of the MYSQLDEF class --------------- */ /***********************************************************************/ diff --git a/storage/connect/tabutil.cpp b/storage/connect/tabutil.cpp index c55b8d1fa5c..487555b52a8 100644 --- a/storage/connect/tabutil.cpp +++ b/storage/connect/tabutil.cpp @@ -396,7 +396,7 @@ int TDBPRX::GetMaxSize(PGLOBAL g) { if (MaxSize < 0) { if (InitTable(g)) - return NULL; + return 0; MaxSize = Tdbp->GetMaxSize(g); } // endif MaxSize diff --git a/storage/connect/tabutil.h b/storage/connect/tabutil.h index 81e2a44464a..76e1d1153b9 100644 --- a/storage/connect/tabutil.h +++ b/storage/connect/tabutil.h @@ -20,6 +20,8 @@ TABLE_SHARE *GetTableShare(PGLOBAL g, THD *thd, const char *db, PQRYRES TabColumns(PGLOBAL g, THD *thd, const char *db, const char *name, bool info); +void Remove_tshp(PCATLG cat); + /* -------------------------- PROXY classes -------------------------- */ /***********************************************************************/ From c035bde34c3a5a63451b51031d508a425ce9a3ae Mon Sep 17 00:00:00 2001 From: Olivier Bertrand Date: Sun, 19 May 2013 19:25:06 +0200 Subject: [PATCH 23/47] - Allowing views and queries as parameters for PROXY base tables NOTE: Checking for looping references cannot be done when using views as parameters. This should not be allowed on production servers and should be dependant on a system variable and/or on speciel grant. modified: storage/connect/CMakeLists.txt storage/connect/connect.cc storage/connect/ha_connect.cc storage/connect/myconn.cpp storage/connect/myconn.h storage/connect/mysql-test/connect/r/fmt.result storage/connect/mysql-test/connect/r/pivot.result storage/connect/mysql-test/connect/t/fmt.test storage/connect/mysql-test/connect/t/pivot.test storage/connect/plgdbsem.h storage/connect/plugutil.c storage/connect/tabcol.cpp storage/connect/tabcol.h storage/connect/tabfmt.cpp storage/connect/tabmysql.cpp storage/connect/tabmysql.h storage/connect/taboccur.cpp storage/connect/taboccur.h storage/connect/tabpivot.cpp storage/connect/tabpivot.h storage/connect/tabtbl.cpp storage/connect/tabutil.cpp storage/connect/tabutil.h storage/connect/xtable.h --- storage/connect/CMakeLists.txt | 2 +- storage/connect/connect.cc | 20 +- storage/connect/ha_connect.cc | 80 +- storage/connect/myconn.cpp | 38 +- storage/connect/myconn.h | 7 +- .../connect/mysql-test/connect/r/fmt.result | 4 +- .../connect/mysql-test/connect/r/pivot.result | 6 +- storage/connect/mysql-test/connect/t/fmt.test | 170 +-- .../connect/mysql-test/connect/t/pivot.test | 289 ++--- storage/connect/plgdbsem.h | 4 +- storage/connect/plugutil.c | 5 +- storage/connect/tabcol.cpp | 20 +- storage/connect/tabcol.h | 16 +- storage/connect/tabfmt.cpp | 22 +- storage/connect/tabmysql.cpp | 185 ++- storage/connect/tabmysql.h | 14 +- storage/connect/taboccur.cpp | 172 ++- storage/connect/taboccur.h | 23 +- storage/connect/tabpivot.cpp | 1017 +++-------------- storage/connect/tabpivot.h | 101 +- storage/connect/tabtbl.cpp | 4 +- storage/connect/tabutil.cpp | 95 +- storage/connect/tabutil.h | 3 +- storage/connect/xtable.h | 1 + 24 files changed, 907 insertions(+), 1391 deletions(-) diff --git a/storage/connect/CMakeLists.txt b/storage/connect/CMakeLists.txt index d3663c5eee3..86dddcdb892 100644 --- a/storage/connect/CMakeLists.txt +++ b/storage/connect/CMakeLists.txt @@ -178,7 +178,7 @@ OPTION(CONNECT_WITH_MYSQL IF(CONNECT_WITH_MYSQL) SET(CONNECT_SOURCES ${CONNECT_SOURCES} - myconn.cpp myconn.h tabmysql.cpp tabxml.h) + myconn.cpp myconn.h tabmysql.cpp tabmysql.h) add_definitions(-DMYSQL_SUPPORT) IF(NOT UNIX) # diff --git a/storage/connect/connect.cc b/storage/connect/connect.cc index 6ae730f20b2..7d9456c3259 100644 --- a/storage/connect/connect.cc +++ b/storage/connect/connect.cc @@ -71,10 +71,7 @@ int rename_file_ext(const char *from, const char *to,const char *ext); PGLOBAL CntExit(PGLOBAL g) { if (g) { - PDBUSER dup= PlgGetUser(g); - CntEndDB(g); - free(dup); if (g->Activityp) delete g->Activityp; @@ -94,13 +91,10 @@ void CntEndDB(PGLOBAL g) PDBUSER dbuserp= PlgGetUser(g); if (dbuserp) { - if (dbuserp->Catalog) { + if (dbuserp->Catalog) delete dbuserp->Catalog; - dbuserp->Catalog= NULL; - } // endif Catalog - *dbuserp->Name= '\0'; -// *dbuserp->Work= '\0'; + free(dbuserp); } // endif dbuserp } // end of CntEndDB @@ -258,10 +252,12 @@ bool CntOpenTable(PGLOBAL g, PTDB tdbp, MODE mode, char *c1, char *c2, return true; } // endif tdbp - if (!c1) - // Allocate all column blocks for that table - tdbp->ColDB(g, NULL, 0); - else for (p= c1; *p; p+= n) { + if (!c1) { + if (mode == MODE_INSERT) + // Allocate all column blocks for that table + tdbp->ColDB(g, NULL, 0); + + } else for (p= c1; *p; p+= n) { // Allocate only used column blocks if (xtrace) printf("Allocating column %s\n", p); diff --git a/storage/connect/ha_connect.cc b/storage/connect/ha_connect.cc index a4611c83ffe..9bc0d2a9942 100644 --- a/storage/connect/ha_connect.cc +++ b/storage/connect/ha_connect.cc @@ -696,7 +696,9 @@ bool ha_connect::GetBooleanOption(char *opname, bool bdef) char *pv; PTOS options= GetTableOptionStruct(table); - if (!options) + if (!stricmp(opname, "View")) + opval= (tshp) ? tshp->is_view : table->s->is_view; + else if (!options) ; else if (!stricmp(opname, "Mapped")) opval= options->mapped; @@ -838,7 +840,7 @@ void *ha_connect::GetColumnOption(void *field, PCOLINFO pcf) } else fldp= (tshp) ? tshp->field : table->field; - if (!(fp= *fldp)) + if (!fldp || !(fp= *fldp)) return NULL; // Get the CONNECT field options structure @@ -1843,11 +1845,13 @@ int ha_connect::open(const char *name, int mode, uint test_if_locked) // Try to get the user if possible xp= GetUser(ha_thd(), xp); - PGLOBAL g= xp->g; + PGLOBAL g= (xp) ? xp->g : NULL; // Try to set the database environment if (g) rc= (CntCheckDB(g, this, name)) ? (-2) : 0; + else + rc= HA_ERR_INTERNAL_ERROR; DBUG_RETURN(rc); } // end of open @@ -2809,6 +2813,10 @@ int ha_connect::external_lock(THD *thd, int lock_type) bool oldsep= ((PCHK)g->Xchk)->oldsep; bool newsep= ((PCHK)g->Xchk)->newsep; PTDBDOS tdp= (PTDBDOS)(tdbp ? tdbp : GetTDB(g)); + + if (!tdp) + DBUG_RETURN(HA_ERR_INTERNAL_ERROR); + PDOSDEF ddp= (PDOSDEF)tdp->GetDef(); PIXDEF xp, xp1, xp2, drp=NULL, adp= NULL; PIXDEF oldpix= ((PCHK)g->Xchk)->oldpix; @@ -3300,7 +3308,7 @@ static int connect_assisted_discovery(handlerton *hton, THD* thd, { char spc= ',', qch= 0; const char *fncn= "?"; - const char *user, *fn, *db, *host, *pwd, *prt, *sep, *tbl; // *csn; + const char *user, *fn, *db, *host, *pwd, *prt, *sep, *tbl, *src; char *tab, *dsn; #if defined(WIN32) char *nsp= NULL, *cls= NULL; @@ -3324,16 +3332,17 @@ static int connect_assisted_discovery(handlerton *hton, THD* thd, sql.copy(STRING_WITH_LEN("CREATE TABLE whatever ("), system_charset_info); - user= host= pwd= prt= tbl= dsn= NULL; + user= host= pwd= prt= tbl= src= dsn= NULL; // Get the useful create options - ttp= GetTypeID(topt->type); - fn= topt->filename; - tab= (char*)topt->tabname; - db= topt->dbname; + ttp= GetTypeID(topt->type); + fn= topt->filename; + tab= (char*)topt->tabname; + src= topt->srcdef; + db= topt->dbname; fncn= topt->catfunc; fnc= GetFuncID(fncn); - sep= topt->separator; + sep= topt->separator; spc= (!sep || !strcmp(sep, "\\t")) ? '\t' : *sep; qch= topt->qchar ? *topt->qchar : topt->quoted >= 0 ? '"' : 0; hdr= (int)topt->header; @@ -3352,25 +3361,20 @@ static int connect_assisted_discovery(handlerton *hton, THD* thd, cls= GetListOption(g,"class", topt->oplist); #endif // WIN32 mxr= atoi(GetListOption(g,"maxerr", topt->oplist, "0")); - } // endif option_list + } else { + host= "localhost"; + user= "root"; + } // endif option_list if (!db) db= thd->db; // Default value // Check table type if (ttp == TAB_UNDEF) { - 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 - + topt->type= (src) ? "MYSQL" : (tab) ? "PROXY" : "DOS"; + ttp= GetTypeID(topt->type); + sprintf(g->Message, "No table_type. Was set to %s", topt->type); + push_warning(thd, MYSQL_ERROR::WARN_LEVEL_WARN, 0, g->Message); } else if (ttp == TAB_NIY) { sprintf(g->Message, "Unsupported table type %s", topt->type); my_message(ER_UNKNOWN_ERROR, g->Message, MYF(0)); @@ -3494,7 +3498,9 @@ static int connect_assisted_discovery(handlerton *hton, THD* thd, else return HA_ERR_INTERNAL_ERROR; // Should never happen - switch (ttp) { + if (src && fnc == FNC_NO) + qrp= SrcColumns(g, host, db, user, pwd, src, port); + else switch (ttp) { case TAB_DBF: qrp= DBFColumns(g, fn, fnc == FNC_COL); break; @@ -3523,7 +3529,7 @@ static int connect_assisted_discovery(handlerton *hton, THD* thd, #if defined(MYSQL_SUPPORT) case TAB_MYSQL: qrp= MyColumns(g, host, db, user, pwd, tab, - NULL, port, false, fnc == FNC_COL); + NULL, port, fnc == FNC_COL); break; #endif // MYSQL_SUPPORT case TAB_CSV: @@ -3549,7 +3555,7 @@ static int connect_assisted_discovery(handlerton *hton, THD* thd, return HA_ERR_INTERNAL_ERROR; } // endif qrp - if (fnc != FNC_NO) { + if (fnc != FNC_NO || src) { // Catalog table for (crp=qrp->Colresp; !b && crp; crp= crp->Next) { cnm= encode(g, crp->Name); @@ -3821,13 +3827,23 @@ int ha_connect::create(const char *name, TABLE *table_arg, case TAB_PRX: case TAB_XCL: case TAB_OCCUR: - if (!stricmp(options->tabname, create_info->alias) && - (!options->dbname || !stricmp(options->dbname, thd->db))) { - sprintf(g->Message, "A %s table cannot refer to itself", - options->type); + if (options->srcdef) { + strcpy(g->Message, "Cannot check looping reference"); + push_warning(thd, MYSQL_ERROR::WARN_LEVEL_WARN, 0, g->Message); + } else if (options->tabname) { + if (!stricmp(options->tabname, create_info->alias) && + (!options->dbname || !stricmp(options->dbname, thd->db))) { + sprintf(g->Message, "A %s table cannot refer to itself", + options->type); + my_message(ER_UNKNOWN_ERROR, g->Message, MYF(0)); + DBUG_RETURN(HA_ERR_INTERNAL_ERROR); + } // endif tab + + } else { + strcpy(g->Message, "Missing object table name or definition"); my_message(ER_UNKNOWN_ERROR, g->Message, MYF(0)); - return HA_ERR_INTERNAL_ERROR; - } // endif tab + DBUG_RETURN(HA_ERR_INTERNAL_ERROR); + } // endif tabname } // endswitch ttp diff --git a/storage/connect/myconn.cpp b/storage/connect/myconn.cpp index fab2af54aa7..5320171beeb 100644 --- a/storage/connect/myconn.cpp +++ b/storage/connect/myconn.cpp @@ -66,13 +66,13 @@ extern MYSQL_PLUGIN_IMPORT uint mysqld_port; /************************************************************************/ /* MyColumns: constructs the result blocks containing all columns */ -/* of a MySQL table that will be retrieved by GetData commands. */ -/* key = TRUE when called from Create Table to get key informations. */ +/* of a MySQL table or view. */ +/* info = TRUE to get catalog column informations. */ /************************************************************************/ PQRYRES MyColumns(PGLOBAL g, const char *host, const char *db, const char *user, const char *pwd, const char *table, const char *colpat, - int port, bool key, bool info) + int port, bool info) { static int buftyp[] = {TYPE_STRING, TYPE_SHORT, TYPE_STRING, TYPE_INT, TYPE_STRING, TYPE_SHORT, TYPE_SHORT, TYPE_SHORT, @@ -124,9 +124,6 @@ PQRYRES MyColumns(PGLOBAL g, const char *host, const char *db, length[0] = 128; } // endif info -//if (!key) // We are not called from Create table -// ncol--; // No date format column yet - /**********************************************************************/ /* Allocate the structures used to refer to the result set. */ /**********************************************************************/ @@ -219,6 +216,7 @@ PQRYRES MyColumns(PGLOBAL g, const char *host, const char *db, crp->Kdata->SetValue(fld, i); } // endfor i +#if 0 if (k > 1) { // Multicolumn primary key PVBLK vbp = qrp->Colresp->Next->Next->Next->Next->Kdata; @@ -228,6 +226,7 @@ PQRYRES MyColumns(PGLOBAL g, const char *host, const char *db, vbp->SetValue(k, i); } // endif k +#endif // 0 /**********************************************************************/ /* Close MySQL connection. */ @@ -240,6 +239,33 @@ PQRYRES MyColumns(PGLOBAL g, const char *host, const char *db, return qrp; } // end of MyColumns +/************************************************************************/ +/* SrcColumns: constructs the result blocks containing all columns */ +/* resulting from an SQL source definition query execution. */ +/************************************************************************/ +PQRYRES SrcColumns(PGLOBAL g, const char *host, const char *db, + const char *user, const char *pwd, + const char *srcdef, int port) + { + int w; + MYSQLC myc; + PQRYRES qrp = NULL; + + if (!port) + port = mysqld_port; + + // Open a MySQL connection for this table + if (myc.Open(g, host, db, user, pwd, port)) + return NULL; + + // Send the source command to MySQL + if (myc.ExecSQL(g, srcdef, &w) == RC_OK) + qrp = myc.GetResult(g); + + myc.Close(); + return qrp; + } // end of SrcColumns + /* -------------------------- Class MYSQLC --------------------------- */ /***********************************************************************/ diff --git a/storage/connect/myconn.h b/storage/connect/myconn.h index 72ce58e70aa..8148630b812 100644 --- a/storage/connect/myconn.h +++ b/storage/connect/myconn.h @@ -38,7 +38,11 @@ typedef class MYSQLC *PMYC; PQRYRES MyColumns(PGLOBAL g, const char *host, const char *db, const char *user, const char *pwd, const char *table, const char *colpat, - int port, bool key, bool info); + int port, bool info); + +PQRYRES SrcColumns(PGLOBAL g, const char *host, const char *db, + const char *user, const char *pwd, + const char *srcdef, int port); /* -------------------------- MYCONN class --------------------------- */ @@ -47,6 +51,7 @@ PQRYRES MyColumns(PGLOBAL g, const char *host, const char *db, /***********************************************************************/ class DllItem MYSQLC { friend class TDBMYSQL; + friend class MYSQLCOL; // Construction public: MYSQLC(void); diff --git a/storage/connect/mysql-test/connect/r/fmt.result b/storage/connect/mysql-test/connect/r/fmt.result index dc3b42b2231..0be10f69bfd 100644 --- a/storage/connect/mysql-test/connect/r/fmt.result +++ b/storage/connect/mysql-test/connect/r/fmt.result @@ -18,7 +18,7 @@ CREATE TABLE t1 id INT NOT NULL field_format=' %n%d%n' ) ENGINE=CONNECT TABLE_TYPE=FMT FILE_NAME='t1.txt'; INSERT INTO t1 VALUES (10),(20); -ERROR HY000: Got error 122 'Writing FMT files is not implemented yet' from CONNECT +ERROR HY000: Got error 174 'Writing FMT files is not implemented yet' from CONNECT DROP TABLE t1; # # Testing manual examples @@ -59,7 +59,7 @@ ID NAME DEPNO SALARY 56 POIROT-DELMOTTE 0 18009.00 345 67 19000.25 UPDATE t1 SET SALARY=1234; -ERROR HY000: Got error 122 'Writing FMT files is not implemented yet' from CONNECT +ERROR HY000: Got error 174 'Writing FMT files is not implemented yet' from CONNECT DELETE FROM t1 WHERE ID=56; SELECT * FROM t1; ID NAME DEPNO SALARY diff --git a/storage/connect/mysql-test/connect/r/pivot.result b/storage/connect/mysql-test/connect/r/pivot.result index 4480788332b..1b790662c4b 100644 --- a/storage/connect/mysql-test/connect/r/pivot.result +++ b/storage/connect/mysql-test/connect/r/pivot.result @@ -77,8 +77,8 @@ Beer DOUBLE(8,2) FLAG=1, Car DOUBLE(8,2) FLAG=1, Food DOUBLE(8,2) FLAG=1) ENGINE=CONNECT TABLE_TYPE=PIVOT -SRCDEF='select who, week, what, sum(amount) from expenses where week in (4,5) group by who, week, what'; -ALTER TABLE pivex OPTION_LIST='port=PORT'; +SRCDEF='select who, week, what, sum(amount) as amount from expenses where week in (4,5) group by who, week, what'; +ALTER TABLE pivex OPTION_LIST='PivotCol=what,FncCol=amount,port=PORT'; Warnings: Warning 1105 The current version of CONNECT did not check what you changed in ALTER. Use at your own risk SELECT * FROM pivex; @@ -125,7 +125,7 @@ Middle DOUBLE(8,2) FLAG=1, Last DOUBLE(8,2) FLAG=1) ENGINE=CONNECT TABLE_TYPE=PIVOT SRCDEF='select who, what, case when week=3 then ''First'' when week=5 then ''Last'' else ''Middle'' end as wk, sum(amount) * 6.56 as amnt from expenses group by who, what, wk'; -ALTER TABLE pivex OPTION_LIST='PivotCol=wk,port=PORT'; +ALTER TABLE pivex OPTION_LIST='PivotCol=wk,FncCol=amnt,port=PORT'; Warnings: Warning 1105 The current version of CONNECT did not check what you changed in ALTER. Use at your own risk SELECT * FROM pivex; diff --git a/storage/connect/mysql-test/connect/t/fmt.test b/storage/connect/mysql-test/connect/t/fmt.test index de7f8c06c1b..662bc70c8b1 100644 --- a/storage/connect/mysql-test/connect/t/fmt.test +++ b/storage/connect/mysql-test/connect/t/fmt.test @@ -1,85 +1,85 @@ -let $MYSQLD_DATADIR= `select @@datadir`; ---copy_file $MTR_SUITE_DIR/std_data/funny.txt $MYSQLD_DATADIR/test/funny.txt ---copy_file $MTR_SUITE_DIR/std_data/funny2.txt $MYSQLD_DATADIR/test/funny2.txt - ---echo # ---echo # Testing errors ---echo # -CREATE TABLE t1 -( - ID INT NOT NULL field_format=' %n%d%n' -) Engine=CONNECT table_type=FMT file_name='nonexistent.txt'; ---replace_regex /on .*test.nonexistent.txt/on DATADIR\/test\/nonexistent.txt/ -# TODO: check why this is needed for Windows ---replace_result Open(rt) Open(rb) -SELECT * FROM t1; -DROP TABLE t1; - - ---echo # ---echo # Testing update on FMT tables ---echo # -CREATE TABLE t1 -( - id INT NOT NULL field_format=' %n%d%n' -) ENGINE=CONNECT TABLE_TYPE=FMT FILE_NAME='t1.txt'; ---error ER_GET_ERRMSG -INSERT INTO t1 VALUES (10),(20); -# TODO: -#--error ER_GET_ERRMSG -#UPDATE t1 SET id=20; -#TRUNCATE TABLE t1; -#DELETE FROM t1 WHERE id=10; -#SELECT * FROM t1; -DROP TABLE t1; ---remove_file $MYSQLD_DATADIR/test/t1.txt - - ---echo # ---echo # Testing manual examples ---echo # -CREATE TABLE t1 -( - ID Integer(5) not null field_format=' %n%d%n', - NAME Char(16) not null field_format=" , '%n%[^']%n'", - DEPNO Integer(4) not null field_format=' , #%n%d%n', - SALARY Double(12,2) not null field_format=' ; %n%f%n' -) Engine=CONNECT table_type=FMT file_name='funny.txt'; -SELECT * FROM t1; -DROP TABLE t1; - -# -# TODO: shoudn't a warning instead of error be returned on bad format? -# -CREATE TABLE t1 -( - ID Integer(5) not null field_format=' %n%d%n', - NAME Char(16) not null field_format=" , '%n%[^']%n'", - DEPNO Integer(4) not null field_format=' , #%n%d%n', - SALARY Double(12,2) not null field_format=' ; %n%f%n' -) Engine=CONNECT table_type=FMT file_name='funny2.txt'; ---error ER_GET_ERRMSG -SELECT * FROM t1; -DROP TABLE t1; - -CREATE TABLE t1 -( - ID Integer(5) not null field_format=' %n%d%n', - NAME Char(16) not null field_format=' , ''%n%[^'']%m', - DEPNO Integer(4) not null field_format=''' , #%n%d%m', - SALARY Double(12,2) not null field_format=' ; %n%f%n' -) Engine=CONNECT table_type=FMT file_name='funny2.txt'; -SELECT * FROM t1; ---error ER_GET_ERRMSG -UPDATE t1 SET SALARY=1234; -# TODO: this query crashes -# UPDATE t1 SET SALARY=1234 WHERE ID=56; -DELETE FROM t1 WHERE ID=56; -SELECT * FROM t1; -DROP TABLE t1; - -# -# Clean up -# ---remove_file $MYSQLD_DATADIR/test/funny.txt ---remove_file $MYSQLD_DATADIR/test/funny2.txt +let $MYSQLD_DATADIR= `select @@datadir`; +--copy_file $MTR_SUITE_DIR/std_data/funny.txt $MYSQLD_DATADIR/test/funny.txt +--copy_file $MTR_SUITE_DIR/std_data/funny2.txt $MYSQLD_DATADIR/test/funny2.txt + +--echo # +--echo # Testing errors +--echo # +CREATE TABLE t1 +( + ID INT NOT NULL field_format=' %n%d%n' +) Engine=CONNECT table_type=FMT file_name='nonexistent.txt'; +--replace_regex /on .*test.nonexistent.txt/on DATADIR\/test\/nonexistent.txt/ +# TODO: check why this is needed for Windows +--replace_result Open(rt) Open(rb) +SELECT * FROM t1; +DROP TABLE t1; + + +--echo # +--echo # Testing update on FMT tables +--echo # +CREATE TABLE t1 +( + id INT NOT NULL field_format=' %n%d%n' +) ENGINE=CONNECT TABLE_TYPE=FMT FILE_NAME='t1.txt'; +--error ER_GET_ERRMSG +INSERT INTO t1 VALUES (10),(20); +# TODO: +#--error ER_GET_ERRMSG +#UPDATE t1 SET id=20; +#TRUNCATE TABLE t1; +#DELETE FROM t1 WHERE id=10; +#SELECT * FROM t1; +DROP TABLE t1; +#--remove_file $MYSQLD_DATADIR/test/t1.txt + + +--echo # +--echo # Testing manual examples +--echo # +CREATE TABLE t1 +( + ID Integer(5) not null field_format=' %n%d%n', + NAME Char(16) not null field_format=" , '%n%[^']%n'", + DEPNO Integer(4) not null field_format=' , #%n%d%n', + SALARY Double(12,2) not null field_format=' ; %n%f%n' +) Engine=CONNECT table_type=FMT file_name='funny.txt'; +SELECT * FROM t1; +DROP TABLE t1; + +# +# TODO: shoudn't a warning instead of error be returned on bad format? +# +CREATE TABLE t1 +( + ID Integer(5) not null field_format=' %n%d%n', + NAME Char(16) not null field_format=" , '%n%[^']%n'", + DEPNO Integer(4) not null field_format=' , #%n%d%n', + SALARY Double(12,2) not null field_format=' ; %n%f%n' +) Engine=CONNECT table_type=FMT file_name='funny2.txt'; +--error ER_GET_ERRMSG +SELECT * FROM t1; +DROP TABLE t1; + +CREATE TABLE t1 +( + ID Integer(5) not null field_format=' %n%d%n', + NAME Char(16) not null field_format=' , ''%n%[^'']%m', + DEPNO Integer(4) not null field_format=''' , #%n%d%m', + SALARY Double(12,2) not null field_format=' ; %n%f%n' +) Engine=CONNECT table_type=FMT file_name='funny2.txt'; +SELECT * FROM t1; +--error ER_GET_ERRMSG +UPDATE t1 SET SALARY=1234; +# TODO: this query crashes +# UPDATE t1 SET SALARY=1234 WHERE ID=56; +DELETE FROM t1 WHERE ID=56; +SELECT * FROM t1; +DROP TABLE t1; + +# +# Clean up +# +--remove_file $MYSQLD_DATADIR/test/funny.txt +--remove_file $MYSQLD_DATADIR/test/funny2.txt diff --git a/storage/connect/mysql-test/connect/t/pivot.test b/storage/connect/mysql-test/connect/t/pivot.test index f06c92828f9..87601a26d28 100644 --- a/storage/connect/mysql-test/connect/t/pivot.test +++ b/storage/connect/mysql-test/connect/t/pivot.test @@ -1,144 +1,145 @@ -let $MYSQLD_DATADIR= `select @@datadir`; -let $PORT= `select @@port`; ---copy_file $MTR_SUITE_DIR/std_data/expenses.txt $MYSQLD_DATADIR/test/expenses.txt - ---echo # ---echo # Testing the PIVOT table type ---echo # -CREATE TABLE expenses ( -Who CHAR(10) NOT NULL, -Week INT(2) NOT NULL, -What CHAR(12) NOT NULL, -Amount DOUBLE(8,2)) -ENGINE=CONNECT TABLE_TYPE=FIX FILE_NAME='expenses.txt' ENDING=2; -SELECT * FROM expenses; - ---echo # ---echo # Pivoting from What ---echo # -CREATE TABLE pivex ( -Who CHAR(10) NOT NULL, -Week INT(2) NOT NULL, -Beer DOUBLE(8,2) FLAG=1, -Car DOUBLE(8,2) FLAG=1, -Food DOUBLE(8,2) FLAG=1) -ENGINE=CONNECT TABLE_TYPE=PIVOT TABNAME=expenses; ---replace_result $PORT PORT ---eval ALTER TABLE pivex OPTION_LIST='port=$PORT' -SELECT * FROM pivex; - ---echo # ---echo # Restricting the columns in a Pivot Table ---echo # -ALTER TABLE pivex DROP COLUMN week; -SELECT * FROM pivex; - ---echo # ---echo # Using a source definition ---echo # -DROP TABLE pivex; -CREATE TABLE pivex ( -Who CHAR(10) NOT NULL, -Week INT(2) NOT NULL, -Beer DOUBLE(8,2) FLAG=1, -Car DOUBLE(8,2) FLAG=1, -Food DOUBLE(8,2) FLAG=1) -ENGINE=CONNECT TABLE_TYPE=PIVOT -SRCDEF='select who, week, what, sum(amount) from expenses where week in (4,5) group by who, week, what'; ---replace_result $PORT PORT ---eval ALTER TABLE pivex OPTION_LIST='port=$PORT' -SELECT * FROM pivex; - ---echo # ---echo # Pivoting from Week ---echo # -DROP TABLE pivex; -CREATE TABLE pivex ( -Who CHAR(10) NOT NULL, -What CHAR(12) NOT NULL, -`3` DOUBLE(8,2) FLAG=1, -`4` DOUBLE(8,2) FLAG=1, -`5` DOUBLE(8,2) FLAG=1) -ENGINE=CONNECT TABLE_TYPE=PIVOT TABNAME=expenses; ---replace_result $PORT PORT ---eval ALTER TABLE pivex OPTION_LIST='PivotCol=Week,port=$PORT' -SELECT * FROM pivex; - ---echo # ---echo # Using scalar functions and expresssions ---echo # -DROP TABLE pivex; -CREATE TABLE pivex ( -Who CHAR(10) NOT NULL, -What CHAR(12) NOT NULL, -First DOUBLE(8,2) FLAG=1, -Middle DOUBLE(8,2) FLAG=1, -Last DOUBLE(8,2) FLAG=1) -ENGINE=CONNECT TABLE_TYPE=PIVOT -SRCDEF='select who, what, case when week=3 then ''First'' when week=5 then ''Last'' else ''Middle'' end as wk, sum(amount) * 6.56 as amnt from expenses group by who, what, wk'; ---replace_result $PORT PORT ---eval ALTER TABLE pivex OPTION_LIST='PivotCol=wk,port=$PORT' -SELECT * FROM pivex; -DROP TABLE pivex; -DROP TABLE expenses; - ---echo # ---echo # Make the PETS table ---echo # -CREATE TABLE pets ( -Name VARCHAR(12) NOT NULL, -Race CHAR(6) NOT NULL, -Number INT NOT NULL) ENGINE=MYISAM; -INSERT INTO pets VALUES('John','dog',2); -INSERT INTO pets VALUES('Bill','cat',1); -INSERT INTO pets VALUES('Mary','dog',1); -INSERT INTO pets VALUES('Mary','cat',1); -INSERT INTO pets VALUES('Lisbeth','rabbit',2); -INSERT INTO pets VALUES('Kevin','cat',2); -INSERT INTO pets VALUES('Kevin','bird',6); -INSERT INTO pets VALUES('Donald','dog',1); -INSERT INTO pets VALUES('Donald','fish',3); -SELECT * FROM pets; - ---echo # ---echo # Pivot the PETS table ---echo # -CREATE TABLE pivet ( -name VARCHAR(12) NOT NULL, -dog INT NOT NULL DEFAULT 0 FLAG=1, -cat INT NOT NULL DEFAULT 0 FLAG=1, -rabbit INT NOT NULL DEFAULT 0 FLAG=1, -bird INT NOT NULL DEFAULT 0 FLAG=1, -fish INT NOT NULL DEFAULT 0 FLAG=1) -ENGINE=CONNECT TABLE_TYPE=PIVOT TABNAME=pets OPTION_LIST='PivotCol=race,groupby=1'; -SELECT * FROM pivet; -DROP TABLE pivet; - ---echo # ---echo # Testing the "data" column list ---echo # -CREATE TABLE pivet ( -name VARCHAR(12) NOT NULL, -dog INT NOT NULL DEFAULT 0 FLAG=1, -cat INT NOT NULL DEFAULT 0 FLAG=1) -ENGINE=CONNECT TABLE_TYPE=PIVOT TABNAME=pets OPTION_LIST='PivotCol=race,groupby=1'; ---error ER_GET_ERRMSG -SELECT * FROM pivet; -ALTER TABLE pivet OPTION_LIST='PivotCol=race,groupby=1,accept=1'; -SELECT * FROM pivet; -DROP TABLE pivet; - ---echo # ---echo # Adding a "dump" column ---echo # -CREATE TABLE pivet ( -name VARCHAR(12) NOT NULL, -dog INT NOT NULL DEFAULT 0 FLAG=1, -cat INT NOT NULL DEFAULT 0 FLAG=1, -other INT NOT NULL DEFAULT 0 FLAG=2) -ENGINE=CONNECT TABLE_TYPE=PIVOT TABNAME=pets OPTION_LIST='PivotCol=race,groupby=1'; -SELECT * FROM pivet; - -DROP TABLE pivet; -DROP TABLE pets; ---remove_file $MYSQLD_DATADIR/test/expenses.txt +let $MYSQLD_DATADIR= `select @@datadir`; +let $PORT= `select @@port`; +--copy_file $MTR_SUITE_DIR/std_data/expenses.txt $MYSQLD_DATADIR/test/expenses.txt +--copy_file $MTR_SUITE_DIR/std_data/connect.ini $MYSQLD_DATADIR/test/connect.ini + +--echo # +--echo # Testing the PIVOT table type +--echo # +CREATE TABLE expenses ( +Who CHAR(10) NOT NULL, +Week INT(2) NOT NULL, +What CHAR(12) NOT NULL, +Amount DOUBLE(8,2)) +ENGINE=CONNECT TABLE_TYPE=FIX FILE_NAME='expenses.txt' ENDING=2; +SELECT * FROM expenses; + +--echo # +--echo # Pivoting from What +--echo # +CREATE TABLE pivex ( +Who CHAR(10) NOT NULL, +Week INT(2) NOT NULL, +Beer DOUBLE(8,2) FLAG=1, +Car DOUBLE(8,2) FLAG=1, +Food DOUBLE(8,2) FLAG=1) +ENGINE=CONNECT TABLE_TYPE=PIVOT TABNAME=expenses; +--replace_result $PORT PORT +--eval ALTER TABLE pivex OPTION_LIST='port=$PORT' +SELECT * FROM pivex; + +--echo # +--echo # Restricting the columns in a Pivot Table +--echo # +ALTER TABLE pivex DROP COLUMN week; +SELECT * FROM pivex; + +--echo # +--echo # Using a source definition +--echo # +DROP TABLE pivex; +CREATE TABLE pivex ( +Who CHAR(10) NOT NULL, +Week INT(2) NOT NULL, +Beer DOUBLE(8,2) FLAG=1, +Car DOUBLE(8,2) FLAG=1, +Food DOUBLE(8,2) FLAG=1) +ENGINE=CONNECT TABLE_TYPE=PIVOT +SRCDEF='select who, week, what, sum(amount) as amount from expenses where week in (4,5) group by who, week, what'; +--replace_result $PORT PORT +--eval ALTER TABLE pivex OPTION_LIST='PivotCol=what,FncCol=amount,port=$PORT' +SELECT * FROM pivex; + +--echo # +--echo # Pivoting from Week +--echo # +DROP TABLE pivex; +CREATE TABLE pivex ( +Who CHAR(10) NOT NULL, +What CHAR(12) NOT NULL, +`3` DOUBLE(8,2) FLAG=1, +`4` DOUBLE(8,2) FLAG=1, +`5` DOUBLE(8,2) FLAG=1) +ENGINE=CONNECT TABLE_TYPE=PIVOT TABNAME=expenses; +--replace_result $PORT PORT +--eval ALTER TABLE pivex OPTION_LIST='PivotCol=Week,port=$PORT' +SELECT * FROM pivex; + +--echo # +--echo # Using scalar functions and expresssions +--echo # +DROP TABLE pivex; +CREATE TABLE pivex ( +Who CHAR(10) NOT NULL, +What CHAR(12) NOT NULL, +First DOUBLE(8,2) FLAG=1, +Middle DOUBLE(8,2) FLAG=1, +Last DOUBLE(8,2) FLAG=1) +ENGINE=CONNECT TABLE_TYPE=PIVOT +SRCDEF='select who, what, case when week=3 then ''First'' when week=5 then ''Last'' else ''Middle'' end as wk, sum(amount) * 6.56 as amnt from expenses group by who, what, wk'; +--replace_result $PORT PORT +--eval ALTER TABLE pivex OPTION_LIST='PivotCol=wk,FncCol=amnt,port=$PORT' +SELECT * FROM pivex; +DROP TABLE pivex; +DROP TABLE expenses; + +--echo # +--echo # Make the PETS table +--echo # +CREATE TABLE pets ( +Name VARCHAR(12) NOT NULL, +Race CHAR(6) NOT NULL, +Number INT NOT NULL) ENGINE=MYISAM; +INSERT INTO pets VALUES('John','dog',2); +INSERT INTO pets VALUES('Bill','cat',1); +INSERT INTO pets VALUES('Mary','dog',1); +INSERT INTO pets VALUES('Mary','cat',1); +INSERT INTO pets VALUES('Lisbeth','rabbit',2); +INSERT INTO pets VALUES('Kevin','cat',2); +INSERT INTO pets VALUES('Kevin','bird',6); +INSERT INTO pets VALUES('Donald','dog',1); +INSERT INTO pets VALUES('Donald','fish',3); +SELECT * FROM pets; + +--echo # +--echo # Pivot the PETS table +--echo # +CREATE TABLE pivet ( +name VARCHAR(12) NOT NULL, +dog INT NOT NULL DEFAULT 0 FLAG=1, +cat INT NOT NULL DEFAULT 0 FLAG=1, +rabbit INT NOT NULL DEFAULT 0 FLAG=1, +bird INT NOT NULL DEFAULT 0 FLAG=1, +fish INT NOT NULL DEFAULT 0 FLAG=1) +ENGINE=CONNECT TABLE_TYPE=PIVOT TABNAME=pets OPTION_LIST='PivotCol=race,groupby=1'; +SELECT * FROM pivet; +DROP TABLE pivet; + +--echo # +--echo # Testing the "data" column list +--echo # +CREATE TABLE pivet ( +name VARCHAR(12) NOT NULL, +dog INT NOT NULL DEFAULT 0 FLAG=1, +cat INT NOT NULL DEFAULT 0 FLAG=1) +ENGINE=CONNECT TABLE_TYPE=PIVOT TABNAME=pets OPTION_LIST='PivotCol=race,groupby=1'; +--error ER_GET_ERRMSG +SELECT * FROM pivet; +ALTER TABLE pivet OPTION_LIST='PivotCol=race,groupby=1,accept=1'; +SELECT * FROM pivet; +DROP TABLE pivet; + +--echo # +--echo # Adding a "dump" column +--echo # +CREATE TABLE pivet ( +name VARCHAR(12) NOT NULL, +dog INT NOT NULL DEFAULT 0 FLAG=1, +cat INT NOT NULL DEFAULT 0 FLAG=1, +other INT NOT NULL DEFAULT 0 FLAG=2) +ENGINE=CONNECT TABLE_TYPE=PIVOT TABNAME=pets OPTION_LIST='PivotCol=race,groupby=1'; +SELECT * FROM pivet; + +DROP TABLE pivet; +DROP TABLE pets; +--remove_file $MYSQLD_DATADIR/test/expenses.txt diff --git a/storage/connect/plgdbsem.h b/storage/connect/plgdbsem.h index 5eb55c4a29b..6884c1c4176 100644 --- a/storage/connect/plgdbsem.h +++ b/storage/connect/plgdbsem.h @@ -24,8 +24,8 @@ #define DOS_BUFF_LEN 100 /* Number of lines in binary file buffer */ #undef DOMAIN /* For Unix version */ -enum BLKTYP {TYPE_TABLE = 50, /* Table Name/Correl Block */ - TYPE_COLUMN = 51, /* Column Name/Correl Block */ +enum BLKTYP {TYPE_TABLE = 50, /* Table Name/Srcdef/... Block */ + TYPE_COLUMN = 51, /* Column Name/Qualifier Block */ // TYPE_OPVAL = 52, /* Operator value (OPVAL) */ TYPE_TDB = 53, /* Table Description Block */ TYPE_COLBLK = 54, /* Column Description Block */ diff --git a/storage/connect/plugutil.c b/storage/connect/plugutil.c index 693ae96cf52..426401a0c47 100644 --- a/storage/connect/plugutil.c +++ b/storage/connect/plugutil.c @@ -147,6 +147,7 @@ PGLOBAL PlugInit(LPCSTR Language, uint worksize) if (!(g = malloc(sizeof(GLOBAL)))) { fprintf(stderr, MSG(GLOBAL_ERROR), (int)sizeof(GLOBAL)); + return NULL; } else { g->Sarea_Size = worksize; g->Trace = 0; @@ -180,7 +181,9 @@ int PlugExit(PGLOBAL g) if (!g) return rc; - free(g->Sarea); + if (g->Sarea) + free(g->Sarea); + free(g); return rc; } /* end of PlugExit */ diff --git a/storage/connect/tabcol.cpp b/storage/connect/tabcol.cpp index f0e010291c3..9af52043f0c 100644 --- a/storage/connect/tabcol.cpp +++ b/storage/connect/tabcol.cpp @@ -1,7 +1,7 @@ /************* TabCol C++ Functions Source Code File (.CPP) ************/ -/* Name: TABCOL.CPP Version 2.6 */ +/* Name: TABCOL.CPP Version 2.7 */ /* */ -/* (C) Copyright to the author Olivier BERTRAND 1998-2012 */ +/* (C) Copyright to the author Olivier BERTRAND 1998-2013 */ /* */ /* This file contains the PlugDB++ XTAB, COLUMN and XORDER methods. */ /***********************************************************************/ @@ -23,18 +23,18 @@ #include "tabcol.h" /***********************************************************************/ -/* XTAB public constructor (in which Correl defaults to Name). */ +/* XTAB public constructor. */ /***********************************************************************/ -XTAB::XTAB(LPCSTR name, LPCSTR correl) : Name(name) +XTAB::XTAB(LPCSTR name, LPCSTR srcdef) : Name(name) { Next = NULL; To_Tdb = NULL; - Correl = (correl) ? correl : name; + Srcdef = srcdef; Creator = NULL; Qualifier = NULL; #ifdef DEBTRACE - htrc(" making new TABLE %s %s\n", Name, Correl); + htrc(" making new TABLE %s %s\n", Name, Srcdef); #endif } // end of XTAB constructor @@ -45,12 +45,12 @@ XTAB::XTAB(PTABLE tp) : Name(tp->Name) { Next = NULL; To_Tdb = NULL; - Correl = tp->Correl; + Srcdef = tp->Srcdef; Creator = tp->Creator; Qualifier = tp->Qualifier; #ifdef DEBTRACE - htrc(" making copy TABLE %s %s\n", Name, Correl); + htrc(" making copy TABLE %s %s\n", Name, Srcdef); #endif } // end of XTAB constructor @@ -83,7 +83,7 @@ void XTAB::Print(PGLOBAL g, FILE *f, uint n) for (PTABLE tp = this; tp; tp = tp->Next) { fprintf(f, "%sTABLE: %s.%s %s\n", - m, SVP(tp->Creator), tp->Name, SVP(tp->Correl)); + m, SVP(tp->Creator), tp->Name, SVP(tp->Srcdef)); PlugPutOut(g, f, TYPE_TDB, tp->To_Tdb, n + 2); } /* endfor tp */ @@ -101,7 +101,7 @@ void XTAB::Print(PGLOBAL g, char *ps, uint z) for (PTABLE tp = this; tp && n > 0; tp = tp->Next) { i = sprintf(buf, "TABLE: %s.%s %s To_Tdb=%p ", - SVP(tp->Creator), tp->Name, SVP(tp->Correl), tp->To_Tdb); + SVP(tp->Creator), tp->Name, SVP(tp->Srcdef), tp->To_Tdb); strncat(ps, buf, n); n -= i; } // endif tp diff --git a/storage/connect/tabcol.h b/storage/connect/tabcol.h index 4680e50f29e..20e23b80225 100644 --- a/storage/connect/tabcol.h +++ b/storage/connect/tabcol.h @@ -1,7 +1,7 @@ /*************** TabCol H Declares Source Code File (.H) ***************/ -/* Name: TABCOL.H Version 2.7 */ +/* Name: TABCOL.H Version 2.8 */ /* */ -/* (C) Copyright to the author Olivier BERTRAND 1998-2012 */ +/* (C) Copyright to the author Olivier BERTRAND 1998-2013 */ /* */ /* This file contains the XTAB, COLUMN and XORDER class definitions. */ /***********************************************************************/ @@ -15,23 +15,23 @@ /***********************************************************************/ /* Definition of class XTAB with all its method functions. */ /***********************************************************************/ -class DllExport XTAB: public BLOCK { // Table Name-Owner-Correl block. +class DllExport XTAB: public BLOCK { // Table Name-Owner-Srcdef block. friend class TDBPRX; public: // Constructors - XTAB(LPCSTR name, LPCSTR correl = NULL); + XTAB(LPCSTR name, LPCSTR srcdef = NULL); XTAB(PTABLE tp); // Implementation PTABLE GetNext(void) {return Next;} PTDB GetTo_Tdb(void) {return To_Tdb;} LPCSTR GetName(void) {return Name;} - LPCSTR GetCorrel(void) {return Correl;} + LPCSTR GetSrc(void) {return Srcdef;} LPCSTR GetCreator(void) {return Creator;} LPCSTR GetQualifier(void) {return Qualifier;} void SetTo_Tdb(PTDB tdbp) {To_Tdb = tdbp;} void SetName(LPCSTR name) {Name = name;} - void SetCorrel(LPCSTR correl) {Correl = correl;} + void SetSrc(LPCSTR srcdef) {Srcdef = srcdef;} void SetCreator(LPCSTR crname) {Creator = crname;} void SetQualifier(LPCSTR qname) {Qualifier = qname;} @@ -44,8 +44,8 @@ class DllExport XTAB: public BLOCK { // Table Name-Owner-Correl block. // Members PTABLE Next; // Points to next table in chain PTDB To_Tdb; // Points to Table description Block - LPCSTR Name; // Table name (can be changed by LNA and PLG) - LPCSTR Correl; // Correlation name + LPCSTR Name; // Table name + LPCSTR Srcdef; // Table Source definition LPCSTR Creator; // Creator name LPCSTR Qualifier; // Qualifier name }; // end of class XTAB diff --git a/storage/connect/tabfmt.cpp b/storage/connect/tabfmt.cpp index aaa32a57f04..860a1304a14 100644 --- a/storage/connect/tabfmt.cpp +++ b/storage/connect/tabfmt.cpp @@ -1088,7 +1088,12 @@ bool TDBFMT::OpenDB(PGLOBAL g) { Linenum = 0; - if (Use != USE_OPEN && (Columns || Mode == MODE_UPDATE)) { + if (Mode == MODE_INSERT || Mode == MODE_UPDATE) { + sprintf(g->Message, MSG(FMT_WRITE_NIY), "FMT"); + return true; // NIY + } // endif Mode + + if (Use != USE_OPEN && Columns) { // Make the formats used to read records PSZ pfm; int i, n; @@ -1096,17 +1101,12 @@ bool TDBFMT::OpenDB(PGLOBAL g) PCOLDEF cdp; PDOSDEF tdp = (PDOSDEF)To_Def; -// if (Mode != MODE_UPDATE) { - for (colp = (PCSVCOL)Columns; colp; colp = (PCSVCOL)colp->Next) - if (!colp->IsSpecial()) // Not a pseudo column - Fields = max(Fields, (int)colp->Fldnum); + for (colp = (PCSVCOL)Columns; colp; colp = (PCSVCOL)colp->Next) + if (!colp->IsSpecial()) // Not a pseudo column + Fields = max(Fields, (int)colp->Fldnum); - if (Columns) - Fields++; // Fldnum was 0 based - -// } else -// for (cdp = tdp->GetCols(); cdp; cdp = cdp->GetNext()) -// Fields++; + if (Columns) + Fields++; // Fldnum was 0 based To_Fld = PlugSubAlloc(g, NULL, Lrecl + 1); FldFormat = (PSZ*)PlugSubAlloc(g, NULL, sizeof(PSZ) * Fields); diff --git a/storage/connect/tabmysql.cpp b/storage/connect/tabmysql.cpp index 3ecfd6aa6c1..c9bb47792f5 100644 --- a/storage/connect/tabmysql.cpp +++ b/storage/connect/tabmysql.cpp @@ -79,9 +79,11 @@ MYSQLDEF::MYSQLDEF(void) Hostname = NULL; Database = NULL; Tabname = NULL; + Srcdef = NULL; Username = NULL; Password = NULL; Portnumber = 0; + Isview = FALSE; Bind = FALSE; Delayed = FALSE; } // end of MYSQLDEF constructor @@ -302,8 +304,8 @@ bool MYSQLDEF::DefineAM(PGLOBAL g, LPCSTR am, int poff) } else { // MYSQL access from a PROXY table, not using URL Database = Cat->GetStringCatInfo(g, "Database", "*"); - Tabname = Cat->GetStringCatInfo(g, "Name", Name); // Deprecated - Tabname = Cat->GetStringCatInfo(g, "Tabname", Tabname); + Tabname = Name; + Isview = Cat->GetBoolCatInfo("View", FALSE); // We must get connection parms from the calling table Remove_tshp(Cat); @@ -313,6 +315,9 @@ bool MYSQLDEF::DefineAM(PGLOBAL g, LPCSTR am, int poff) Portnumber = Cat->GetIntCatInfo("Port", mysqld_port); } // endif am + if ((Srcdef = Cat->GetStringCatInfo(g, "Srcdef", NULL))) + Isview = TRUE; + return FALSE; } // end of DefineAM @@ -339,18 +344,22 @@ TDBMYSQL::TDBMYSQL(PMYDEF tdp) : TDBASE(tdp) Host = tdp->GetHostname(); Database = tdp->GetDatabase(); Tabname = tdp->GetTabname(); + Srcdef = tdp->GetSrcdef(); User = tdp->GetUsername(); Pwd = tdp->GetPassword(); Port = tdp->GetPortnumber(); + Isview = tdp->Isview; Prep = tdp->Bind; Delayed = tdp->Delayed; } else { Host = NULL; Database = NULL; Tabname = NULL; + Srcdef = NULL; User = NULL; Pwd = NULL; Port = 0; + Isview = FALSE; Prep = FALSE; Delayed = FALSE; } // endif tdp @@ -370,9 +379,11 @@ TDBMYSQL::TDBMYSQL(PGLOBAL g, PTDBMY tdbp) : TDBASE(tdbp) Host = tdbp->Host; Database = tdbp->Database; Tabname = tdbp->Tabname; + Srcdef = tdbp->Srcdef; User = tdbp->User; Pwd = tdbp->Pwd; Port = tdbp->Port; + Isview = tdbp->Isview; Prep = tdbp->Prep; Delayed = tdbp->Delayed; Bind = NULL; @@ -418,55 +429,54 @@ PCOL TDBMYSQL::MakeCol(PGLOBAL g, PCOLDEF cdp, PCOL cprec, int n) /***********************************************************************/ bool TDBMYSQL::MakeSelect(PGLOBAL g) { - char *colist; char *tk = "`"; - int len = 0, ncol = 0, rank = 0; + int rank = 0; bool b = FALSE; PCOL colp; - PDBUSER dup = PlgGetUser(g); +//PDBUSER dup = PlgGetUser(g); if (Query) return FALSE; // already done - for (colp = Columns; colp; colp = colp->GetNext()) - ncol++; + if (Srcdef) { + Query = Srcdef; + return false; + } // endif Srcdef - if (ncol) { - colist = (char*)PlugSubAlloc(g, NULL, (NAM_LEN + 4) * ncol); - *colist = '\0'; + //Find the address of the suballocated query + Query = (char*)PlugSubAlloc(g, NULL, 0); + strcpy(Query, "SELECT "); + if (Columns) { for (colp = Columns; colp; colp = colp->GetNext()) if (colp->IsSpecial()) { strcpy(g->Message, MSG(NO_SPEC_COL)); return TRUE; } else { if (b) - strcat(colist, ", "); + strcat(Query, ", "); else b = TRUE; - strcat(strcat(strcat(colist, tk), colp->GetName()), tk); + strcat(strcat(strcat(Query, tk), colp->GetName()), tk); ((PMYCOL)colp)->Rank = rank++; } // endif colp } else { - // ncol == 0 can occur for queries such as Query count(*) from... - // for which we will count the rows from Query '*' from... + // ncol == 0 can occur for views or queries such as + // Query count(*) from... for which we will count the rows from + // Query '*' from... // (the use of a char constant minimize the result storage) - colist = (char*)PlugSubAlloc(g, NULL, 2); - strcpy(colist, "'*'"); + strcat(Query, (Isview) ? "*" : "'*'"); } // endif ncol - // Below 32 is space to contain extra stuff - len += (strlen(colist) + strlen(Tabname) + 32); - len += (To_Filter ? strlen(To_Filter) + 7 : 0); - Query = (char*)PlugSubAlloc(g, NULL, len); - strcat(strcpy(Query, "SELECT "), colist); strcat(strcat(strcat(strcat(Query, " FROM "), tk), Tabname), tk); if (To_Filter) strcat(strcat(Query, " WHERE "), To_Filter); + // Now we know how much to suballocate + PlugSubAlloc(g, NULL, strlen(Query) + 1); return FALSE; } // end of MakeSelect @@ -751,7 +761,7 @@ bool TDBMYSQL::OpenDB(PGLOBAL g) /* Table already open, just replace it at its beginning. */ /*******************************************************************/ Myc.Rewind(); - return FALSE; + return false; } // endif use /*********************************************************************/ @@ -763,7 +773,7 @@ bool TDBMYSQL::OpenDB(PGLOBAL g) /*********************************************************************/ if (!Myc.Connected()) { if (Myc.Open(g, Host, Database, User, Pwd, Port)) - return TRUE; + return true; } // endif Connected @@ -774,7 +784,24 @@ bool TDBMYSQL::OpenDB(PGLOBAL g) if (!MakeSelect(g)) m_Rc = Myc.ExecSQL(g, Query); +#if 0 + if (!Myc.m_Res || !Myc.m_Fields) { + sprintf(g->Message, "%s result", (Myc.m_Res) ? "Void" : "No"); + Myc.Close(); + return true; + } // endif m_Res +#endif // 0 + + if (Srcdef) + if (SetColumnRanks(g)) + return true; + } else if (Mode == MODE_INSERT) { + if (Srcdef) { + strcpy(g->Message, "No insert into anonym views"); + return true; + } // endif Srcdef + if (!MakeInsert(g)) { #if defined(MYSQL_PREPARED_STATEMENTS) int n = (Prep) ? Myc.PrepareSQL(g, Query) : Nparm; @@ -826,6 +853,55 @@ bool TDBMYSQL::OpenDB(PGLOBAL g) return FALSE; } // end of OpenDB +/***********************************************************************/ +/* Set the rank of columns in the result set. */ +/***********************************************************************/ +bool TDBMYSQL::SetColumnRanks(PGLOBAL g) + { + for (PCOL colp = Columns; colp; colp = colp->GetNext()) + if (((PMYCOL)colp)->FindRank(g)) + return TRUE; + + return FALSE; + } // end of SetColumnRanks + +/***********************************************************************/ +/* Called by Parent table to make the columns of a View. */ +/***********************************************************************/ +PCOL TDBMYSQL::MakeFieldColumn(PGLOBAL g, char *name) + { + int n; + MYSQL_FIELD *fld; + PCOL cp, colp = NULL; + + for (n = 0; n < Myc.m_Fields; n++) { + fld = &Myc.m_Res->fields[n]; + + if (!stricmp(name, fld->name)) { + colp = new(g) MYSQLCOL(fld, this, n); + + if (colp->InitValue(g)) + return NULL; + + if (!Columns) + Columns = colp; + else for (cp = Columns; cp; cp = cp->GetNext()) + if (!cp->GetNext()) { + cp->SetNext(colp); + break; + } // endif Next + + break; + } // endif name + + } // endfor n + + if (!colp) + sprintf(g->Message, "Column %s is not in view", name); + + return colp; + } // end of MakeFieldColumn + /***********************************************************************/ /* Data Base read routine for MYSQL access method. */ /***********************************************************************/ @@ -939,7 +1015,7 @@ MYSQLCOL::MYSQLCOL(PCOLDEF cdp, PTDB tdbp, PCOL cprec, int i, PSZ am) tdbp->SetColumns(this); } // endif cprec - // Set additional Dos access method information for column. + // Set additional MySQL access method information for column. Long = cdp->GetLong(); Bind = NULL; To_Val = NULL; @@ -951,6 +1027,33 @@ MYSQLCOL::MYSQLCOL(PCOLDEF cdp, PTDB tdbp, PCOL cprec, int i, PSZ am) } // end of MYSQLCOL constructor +/***********************************************************************/ +/* MYSQLCOL public constructor. */ +/***********************************************************************/ +MYSQLCOL::MYSQLCOL(MYSQL_FIELD *fld, PTDB tdbp, int i, PSZ am) + : COLBLK(NULL, tdbp, i) + { + Name = fld->name; + Opt = 0; + Long = fld->length; + Buf_Type = MYSQLtoPLG(fld->type); + strcpy(Format.Type, GetFormatType(Buf_Type)); + Format.Length = Long; + Format.Prec = fld->decimals; + ColUse = U_P; + Nullable = !IS_NOT_NULL(fld->flags); + + // Set additional MySQL access method information for column. + Bind = NULL; + To_Val = NULL; + Slen = 0; + Rank = i; + + if (trace) + htrc(" making new %sCOL C%d %s at %p\n", am, Index, Name, this); + + } // end of MYSQLCOL constructor + /***********************************************************************/ /* MYSQLCOL constructor used for copying columns. */ /* tdbp is the pointer to the new table descriptor. */ @@ -964,6 +1067,24 @@ MYSQLCOL::MYSQLCOL(MYSQLCOL *col1, PTDB tdbp) : COLBLK(col1, tdbp) Rank = col1->Rank; } // end of MYSQLCOL copy constructor +/***********************************************************************/ +/* FindRank: Find the rank of this column in the result set. */ +/***********************************************************************/ +bool MYSQLCOL::FindRank(PGLOBAL g) +{ + int n; + MYSQLC myc = ((PTDBMY)To_Tdb)->Myc; + + for (n = 0; n < myc.m_Fields; n++) + if (!stricmp(Name, myc.m_Res->fields[n].name)) { + Rank = n; + return false; + } // endif Name + + sprintf(g->Message, "Column %s not in result set", Name); + return true; +} // end of FindRank + /***********************************************************************/ /* SetBuffer: prepare a column block for write operation. */ /***********************************************************************/ @@ -1049,11 +1170,6 @@ void MYSQLCOL::ReadColumn(PGLOBAL g) int rc; PTDBMY tdbp = (PTDBMY)To_Tdb; - if (trace) - htrc("MySQL ReadColumn: name=%s\n", Name); - - assert (Rank >= 0); - /*********************************************************************/ /* If physical fetching of the line was deferred, do it now. */ /*********************************************************************/ @@ -1066,14 +1182,17 @@ void MYSQLCOL::ReadColumn(PGLOBAL g) } else tdbp->Fetched = TRUE; - if ((buf = ((PTDBMY)To_Tdb)->Myc.GetCharField(Rank))) + if ((buf = ((PTDBMY)To_Tdb)->Myc.GetCharField(Rank))) { + if (trace) + htrc("MySQL ReadColumn: name=%s buf=%s\n", Name, buf); + Value->SetValue_char(buf, Long); - else { + } else { if (Nullable) Value->SetNull(true); Value->Reset(); // Null value - } // endelse + } // endif buf } // end of ReadColumn @@ -1121,5 +1240,5 @@ TDBMCL::TDBMCL(PMYDEF tdp) : TDBCAT(tdp) /***********************************************************************/ PQRYRES TDBMCL::GetResult(PGLOBAL g) { - return MyColumns(g, Host, Db, User, Pwd, Tab, NULL, Port, false, false); + return MyColumns(g, Host, Db, User, Pwd, Tab, NULL, Port, false); } // end of GetResult diff --git a/storage/connect/tabmysql.h b/storage/connect/tabmysql.h index 56d21550df6..5d8f32e9f21 100644 --- a/storage/connect/tabmysql.h +++ b/storage/connect/tabmysql.h @@ -30,6 +30,7 @@ class MYSQLDEF : public TABDEF {/* Logical table description */ inline PSZ GetHostname(void) {return Hostname;}; inline PSZ GetDatabase(void) {return Database;}; inline PSZ GetTabname(void) {return Tabname;} + inline PSZ GetSrcdef(void) {return Srcdef;} inline PSZ GetUsername(void) {return Username;}; inline PSZ GetPassword(void) {return Password;}; inline int GetPortnumber(void) {return Portnumber;} @@ -44,9 +45,11 @@ class MYSQLDEF : public TABDEF {/* Logical table description */ PSZ Hostname; /* Host machine to use */ PSZ Database; /* Database to be used by server */ PSZ Tabname; /* External table name */ + PSZ Srcdef; /* The source table SQL definition */ PSZ Username; /* User logon name */ PSZ Password; /* Password logon info */ int Portnumber; /* MySQL port number (0 = default) */ + bool Isview; /* TRUE if this table is a MySQL view */ bool Bind; /* Use prepared statement on insert */ bool Delayed; /* Delayed insert */ }; // end of MYSQLDEF @@ -72,6 +75,7 @@ class TDBMYSQL : public TDBASE { virtual int GetProgMax(PGLOBAL g); virtual void ResetDB(void) {N = 0;} virtual int RowNumber(PGLOBAL g, bool b = FALSE); + virtual bool IsView(void) {return Isview;} void SetDatabase(LPCSTR db) {Database = (char*)db;} // Database routines @@ -83,6 +87,10 @@ class TDBMYSQL : public TDBASE { virtual int DeleteDB(PGLOBAL g, int irc); virtual void CloseDB(PGLOBAL g); + // Specific routines + bool SetColumnRanks(PGLOBAL g); + PCOL MakeFieldColumn(PGLOBAL g, char *name); + protected: // Internal functions bool MakeSelect(PGLOBAL g); @@ -99,9 +107,11 @@ class TDBMYSQL : public TDBASE { char *Pwd; // Password logon info char *Database; // Database to be used by server char *Tabname; // External table name + char *Srcdef; // The source table SQL definition char *Query; // Points to SQL query - char *Qbuf; // Used for not prepared insert + char *Qbuf; // Used for not prepared insert bool Fetched; // True when fetch was done + bool Isview; // True if this table is a MySQL view bool Prep; // Use prepared statement on insert bool Delayed; // Use delayed insert int m_Rc; // Return code from command @@ -119,6 +129,7 @@ class MYSQLCOL : public COLBLK { public: // Constructors MYSQLCOL(PCOLDEF cdp, PTDB tdbp, PCOL cprec, int i, PSZ am = "MYSQL"); + MYSQLCOL(MYSQL_FIELD *fld, PTDB tdbp, int i, PSZ am = "MYSQL"); MYSQLCOL(MYSQLCOL *colp, PTDB tdbp); // Constructor used in copy process // Implementation @@ -129,6 +140,7 @@ class MYSQLCOL : public COLBLK { virtual bool SetBuffer(PGLOBAL g, PVAL value, bool ok, bool check); virtual void ReadColumn(PGLOBAL g); virtual void WriteColumn(PGLOBAL g); + bool FindRank(PGLOBAL g); protected: // Default constructor not to be used diff --git a/storage/connect/taboccur.cpp b/storage/connect/taboccur.cpp index 2f721c6a7cf..6c33aefbb68 100644 --- a/storage/connect/taboccur.cpp +++ b/storage/connect/taboccur.cpp @@ -85,19 +85,43 @@ PTDB OCCURDEF::GetTable(PGLOBAL g, MODE m) /***********************************************************************/ TDBOCCUR::TDBOCCUR(POCCURDEF tdp) : TDBPRX(tdp) { -//Tdbp = NULL; // Source table +//Tdbp = NULL; // Source table (in TDBPRX) 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 + 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 = PrepareColist(); // 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 +/***********************************************************************/ +/* Prepare and count columns in the column list. */ +/***********************************************************************/ +int TDBOCCUR::PrepareColist(void) + { + char *p, *pn; + int n = 0; + + // Count the number of columns and change separator into null char + for (pn = Colist; ; pn += (strlen(pn) + 1)) + // Separator can be ; if colist was specified in the option_list + if ((p = strchr(pn, ',')) || (p = strchr(pn, ';'))) { + *p++ = '\0'; + n++; + } else { + if (*pn) + n++; + + break; + } // endif p + + return n; + } // end of PrepareColist + /***********************************************************************/ /* Allocate OCCUR/SRC column description block. */ /***********************************************************************/ @@ -111,14 +135,8 @@ PCOL TDBOCCUR::MakeCol(PGLOBAL g, PCOLDEF cdp, PCOL cprec, int 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 + } else + return new(g) PRXCOL(cdp, this, cprec, n); if (cprec) { colp->SetNext(cprec->GetNext()); @@ -136,75 +154,100 @@ PCOL TDBOCCUR::MakeCol(PGLOBAL g, PCOLDEF cdp, PCOL cprec, int n) /***********************************************************************/ bool TDBOCCUR::InitTable(PGLOBAL g) { - if (!Tdbp) { + if (!Tdbp) // Get the table description block of this table - if (!(Tdbp = (PTDBASE)GetSubTable(g, ((POCCURDEF)To_Def)->Tablep))) + if (!(Tdbp = GetSubTable(g, ((POCCURDEF)To_Def)->Tablep, TRUE))) return TRUE; - if (MakeColumnList(g) < 0) + if (!Tdbp->IsView()) + if (MakeColumnList(g)) return TRUE; - } // endif Tdbp - return FALSE; } // end of InitTable /***********************************************************************/ /* Allocate OCCUR column description block. */ /***********************************************************************/ -int TDBOCCUR::MakeColumnList(PGLOBAL g) +bool TDBOCCUR::MakeColumnList(PGLOBAL g) { - if (Mult < 0) { - char *p, *pn; - int i; - int n = 0; + char *pn; + int i; + PCOL colp; - // Count the number of columns and change separator into null char - for (pn = Colist; ; pn += (strlen(pn) + 1)) - if ((p = strchr(pn, ',')) || (p = strchr(pn, ';'))) { - *p++ = '\0'; - n++; - } else { - if (*pn) - n++; + for (colp = Columns; colp; colp = colp->GetNext()) + if (colp->GetAmType() == TYPE_AM_PRX) + if (((PPRXCOL)colp)->Init(g)) + return true; - break; - } // endif p + Col = (PCOL*)PlugSubAlloc(g, NULL, Mult * sizeof(PCOL)); - Col = (PCOL*)PlugSubAlloc(g, NULL, n * sizeof(PCOL)); + for (i = 0, pn = Colist; i < Mult; 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 true; + } // endif Col - 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 true; + } // endif InitValue - if (Col[i]->InitValue(g)) { - strcpy(g->Message, "OCCUR InitValue failed"); - return -1; - } // endif InitValue + } // endfor i - } // endfor i - - // OCCUR column name defaults to the name of the list first column - if (!Xcolumn) - Xcolumn = Colist; - - Mult = n; - } // endif Mult - - return Mult; + return false; } // end of MakeColumnList +/***********************************************************************/ +/* Allocate OCCUR column description block for a view. */ +/***********************************************************************/ +bool TDBOCCUR::ViewColumnList(PGLOBAL g) + { + char *pn; + int i; + PCOL colp, cp; + PTDBMY tdbp; + + if (!Tdbp->IsView()) + return false; + + if (Tdbp->GetAmType() != TYPE_AM_MYSQL) { + strcpy(g->Message, "View is not MySQL"); + return true; + } else + tdbp = (PTDBMY)Tdbp; + + for (cp = Columns; cp; cp = cp->GetNext()) + if (cp->GetAmType() == TYPE_AM_PRX) { + if ((colp = tdbp->MakeFieldColumn(g, cp->GetName()))) { + ((PPRXCOL)cp)->Colp = colp; + ((PPRXCOL)cp)->To_Val = colp->GetValue(); + } else + return true; + + } // endif Type + + Col = (PCOL*)PlugSubAlloc(g, NULL, Mult * sizeof(PCOL)); + + for (i = 0, pn = Colist; i < Mult; i++, pn += (strlen(pn) + 1)) + if (!(Col[i] = tdbp->MakeFieldColumn(g, pn))) { + // Column not found in table + sprintf(g->Message, MSG(COL_ISNOT_TABLE), pn, Tabname); + return true; + } // endif Col + + return false; + } // end of ViewColumnList + /***********************************************************************/ /* OCCUR GetMaxSize: returns the maximum number of rows in the table. */ /***********************************************************************/ int TDBOCCUR::GetMaxSize(PGLOBAL g) { if (MaxSize < 0) { - if (InitTable(g)) - return NULL; + if (!(Tdbp = GetSubTable(g, ((POCCURDEF)To_Def)->Tablep, TRUE))) + return 0; MaxSize = Mult * Tdbp->GetMaxSize(g); } // endif MaxSize @@ -252,7 +295,7 @@ bool TDBOCCUR::OpenDB(PGLOBAL g) /* Do it here if not done yet. */ /*********************************************************************/ if (InitTable(g)) - return NULL; + return TRUE; if (Xcolp) // Lock this column so it is evaluated by its table only @@ -269,7 +312,10 @@ bool TDBOCCUR::OpenDB(PGLOBAL g) /*********************************************************************/ /* Do open the source table. */ /*********************************************************************/ - return Tdbp->OpenDB(g); + if (Tdbp->OpenDB(g)) + return TRUE; + + return ViewColumnList(g); } // end of OpenDB /***********************************************************************/ diff --git a/storage/connect/taboccur.h b/storage/connect/taboccur.h index 076202be477..b7d51e05b7d 100644 --- a/storage/connect/taboccur.h +++ b/storage/connect/taboccur.h @@ -52,21 +52,22 @@ class TDBOCCUR : public TDBPRX { TDBOCCUR(POCCURDEF tdp); // Implementation - virtual AMT GetAmType(void) {return TYPE_AM_OCCUR;} - void SetTdbp(PTDBASE tdbp) {Tdbp = tdbp;} + virtual AMT GetAmType(void) {return TYPE_AM_OCCUR;} + void SetTdbp(PTDBASE tdbp) {Tdbp = tdbp;} // Methods - virtual void ResetDB(void) {N = 0; Tdbp->ResetDB();} - virtual int RowNumber(PGLOBAL g, bool b = FALSE); - PTDB GetSourceTable(PGLOBAL g); - int MakeColumnList(PGLOBAL g); + virtual void ResetDB(void) {N = 0; Tdbp->ResetDB();} + virtual int RowNumber(PGLOBAL g, bool b = FALSE); + int PrepareColist(void); + bool MakeColumnList(PGLOBAL g); + bool ViewColumnList(PGLOBAL g); // 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 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 diff --git a/storage/connect/tabpivot.cpp b/storage/connect/tabpivot.cpp index 4ae1b3ceae6..1a73f353970 100644 --- a/storage/connect/tabpivot.cpp +++ b/storage/connect/tabpivot.cpp @@ -1,7 +1,7 @@ /************ TabPivot C++ Program Source Code File (.CPP) *************/ /* PROGRAM NAME: TABPIVOT */ /* ------------- */ -/* Version 1.4 */ +/* Version 1.5 */ /* */ /* COPYRIGHT: */ /* ---------- */ @@ -41,11 +41,9 @@ #include "global.h" #include "plgdbsem.h" #include "xtable.h" -//#include "xindex.h" #include "tabcol.h" #include "colblk.h" -//#include "tabmysql.h" -#include "myconn.h" +#include "tabmysql.h" #include "csort.h" #include "tabutil.h" #include "tabpivot.h" @@ -55,381 +53,6 @@ extern "C" int trace; -#if 0 -/***********************************************************************/ -/* Prepare the source table Query. */ -/***********************************************************************/ -PQRYRES TDBPIVOT::GetSourceTable(PGLOBAL g) - { - if (Qryp) - return Qryp; // Already done - - if (Tabname) { - char *def, *colist; - size_t len = 0; - PCOL colp; - PDBUSER dup = (PDBUSER)g->Activityp->Aptr; - - if (InitTable(g)) - return NULL; - - // Evaluate the length of the column list - for (colp = Tdbp->Columns; colp; colp = colp->GetNext()) - len += (strlen(colp->GetName()) + 2); - - *(colist = (char*)PlugSubAlloc(g, NULL, len)) = 0; - - // Locate the suballocated string (size is not known yet) - def = (char*)PlugSubAlloc(g, NULL, 0); - strcpy(def, "SELECT "); - - if (!Fncol) { - for (colp = Tdbp->Columns; colp; colp = colp->GetNext()) - if (!Picol || stricmp(Picol, colp->GetName())) - Fncol = colp->GetName(); - - if (!Fncol) { - strcpy(g->Message, MSG(NO_DEF_FNCCOL)); - return NULL; - } // endif Fncol - - } else if (!(ColDB(g, Fncol, 0))) { - // Function column not found in table - sprintf(g->Message, MSG(COL_ISNOT_TABLE), Fncol, Tabname); - return NULL; - } // endif Fcolp - - if (!Picol) { - // Find default Picol as the last one not equal to Fncol - for (colp = Tdbp->Columns; colp; colp = colp->GetNext()) - if (!Fncol || stricmp(Fncol, colp->GetName())) - Picol = colp->GetName(); - - if (!Picol) { - strcpy(g->Message, MSG(NO_DEF_PIVOTCOL)); - return NULL; - } // endif Picol - - } else if (!(ColDB(g, Picol, 0))) { - // Pivot column not found in table - sprintf(g->Message, MSG(COL_ISNOT_TABLE), Picol, Tabname); - return NULL; - } // endif Xcolp - - // Make the other column list - for (colp = Columns; colp; colp = colp->GetNext()) - if (stricmp(Picol, colp->GetName()) && - stricmp(Fncol, colp->GetName())) - strcat(strcat(colist, colp->GetName()), ", "); - - // Add the Pivot column at the end of the list - strcat(strcat(def, strcat(colist, Picol)), ", "); - - // Continue making the definition - if (!GBdone) { - // Make it suitable for Pivot by doing the group by - strcat(strcat(def, Function), "("); - strcat(strcat(strcat(def, Fncol), ") "), Fncol); - strcat(strcat(def, " FROM "), Tabname); - strcat(strcat(def, " GROUP BY "), colist); - } else // Gbdone - strcat(strcat(strcat(def, Fncol), " FROM "), Tabname); - - // Now we know how much was suballocated - Tabsrc = (char*)PlugSubAlloc(g, NULL, strlen(def)); - } else { - strcpy(g->Message, MSG(SRC_TABLE_UNDEF)); - return NULL; - } // endif Tabsrc - - int w; - - // Open a MySQL connection for this table - if (Myc.Open(g, Host, Database, User, Pwd, Port)) - return NULL; - - // Send the source command to MySQL - if (Myc.ExecSQL(g, Tabsrc, &w) == RC_FX) { - Myc.Close(); - return NULL; - } // endif Exec - - // We must have a storage query to get pivot column values - Qryp = Myc.GetResult(g); - Myc.Close(); - Tqrp = new(g) TDBQRS(Qryp); - Tqrp->OpenDB(g); - - if (MakePivotColumns(g) < 0) - return NULL; - - return Qryp; - } // end of GetSourceTable - -/***********************************************************************/ -/* Allocate PIVOT columns description block. */ -/***********************************************************************/ -int TDBPIVOT::MakePivotColumns(PGLOBAL g) - { - if (Mult < 0) { - int ndif, n = 0, nblin = Qryp->Nblin; - PVAL valp; - PCOL cp; - PSRCCOL colp; - PFNCCOL cfnp; - - // Allocate all the source columns - Tqrp->ColDB(g, NULL, 0); - Columns = NULL; // Discard dummy columns blocks - - for (cp = Tqrp->GetColumns(); cp; cp = cp->GetNext()) { - if (cp->InitValue(g)) - return -1; - - if (!stricmp(cp->GetName(), Picol)) { - Xcolp = (PQRSCOL)cp; - Xresp = Xcolp->GetCrp(); - Rblkp = Xresp->Kdata; - } else if (!stricmp(cp->GetName(), Fncol)) { - Fcolp = (PQRSCOL)cp; - } else - if ((colp = new(g) SRCCOL(cp, this, ++n))->Init(g, this)) - return -1; - - } // endfor cp - - if (!Xcolp) { - sprintf(g->Message, MSG(COL_ISNOT_TABLE), - Picol, Tabname ? Tabname : "TabSrc"); - return -1; - } else if (!Fcolp) { - sprintf(g->Message, MSG(COL_ISNOT_TABLE), - Fncol, Tabname ? Tabname : "TabSrc"); - return -1; - } // endif Fcolp - - // Before calling sort, initialize all - Index.Size = nblin * sizeof(int); - Index.Sub = TRUE; // Should be small enough - - if (!PlgDBalloc(g, NULL, Index)) - return -1; - - Offset.Size = (nblin + 1) * sizeof(int); - Offset.Sub = TRUE; // Should be small enough - - if (!PlgDBalloc(g, NULL, Offset)) - return -2; - - ndif = Qsort(g, nblin); - - if (ndif < 0) { // error - return -3; - } else - Ncol = ndif; - - // Now make the functional columns - for (int i = 0; i < Ncol; i++) { - // Allocate the Value used to retieve column names - if (!(valp = AllocateValue(g, Xcolp->GetResultType(), - Xcolp->GetLengthEx(), Xcolp->GetPrecision(), - Xcolp->GetDomain(), Xcolp->GetTo_Tdb()->GetCat()))) - return -4; - - // Get the value that will be the generated column name - valp->SetValue_pvblk(Rblkp, Pex[Pof[i]]); - - // Copy the functional column with new Name and new Value - cfnp = (PFNCCOL)new(g) FNCCOL(Fcolp, this); - - // Initialize the generated column - if (cfnp->InitColumn(g, valp)) - return -5; - - } // endfor i - - // Fields must be updated for ha_connect -// if (UpdateTableFields(g, n + Ncol)) -// return -6; - - // This should be refined later - Mult = nblin; - } // endif Mult - - return Mult; - } // end of MakePivotColumns - -/***********************************************************************/ -/* Update fields in the MySQL table structure */ -/* Note: this does not work. Indeed the new rows are correctly made */ -/* but the final result still specify the unmodified table and the */ -/* returned table only contains the original column values. */ -/* In addition, a new query on the table, when it is into the cache, */ -/* specifies all the new columns and fails because they do not belong */ -/* to the original table. */ -/***********************************************************************/ -bool TDBPIVOT::UpdateTableFields(PGLOBAL g, int n) - { - uchar *trec, *srec, *tptr, *sptr; - int i = 0, k = 0; - uint len; - uint32 nmp, lwm; - size_t buffsize; - PCOL colp; - PHC hc = ((MYCAT*)((PIVOTDEF*)To_Def)->Cat)->GetHandler(); - TABLE *table = hc->GetTable(); - st_mem_root *tmr = &table->mem_root; - st_mem_root *smr = &table->s->mem_root; - Field* *field; - Field *fp, *tfncp, *sfncp; - Field* *ntf; - Field* *nsf; -//my_bitmap_map *org_bitmap; - const MY_BITMAP *map; - - // When sorting read_set selects all columns, so we use def_read_set - map= (const MY_BITMAP *)&table->def_read_set; - - // Find the function field - for (field= table->field; *field; field++) { - fp= *field; - - if (bitmap_is_set(map, fp->field_index)) - if (!stricmp(fp->field_name, Fncol)) { - tfncp = fp; - break; - } // endif Name - - } // endfor field - - for (field= table->s->field; *field; field++) { - fp= *field; - - if (bitmap_is_set(map, fp->field_index)) - if (!stricmp(fp->field_name, Fncol)) { - sfncp = fp; - break; - } // endif Name - - } // endfor field - - // Calculate the new buffer size - len = tfncp->max_data_length(); - buffsize = table->s->rec_buff_length + len * Ncol; - - // Allocate the new record space - if (!(tptr = trec = (uchar*)alloc_root(tmr, 2 * buffsize))) - return TRUE; - - if (!(sptr = srec = (uchar*)alloc_root(smr, 2 * buffsize))) - return TRUE; - - - // Allocate the array of all new table field pointers - if (!(ntf = (Field**)alloc_root(tmr, (uint)((n+1) * sizeof(Field*))))) - return TRUE; - - // Allocate the array of all new table share field pointers - if (!(nsf = (Field**)alloc_root(smr, (uint)((n+1) * sizeof(Field*))))) - return TRUE; - - // First fields are the the ones of the source columns - for (colp = Columns; colp; colp = colp->GetNext()) - if (colp->GetAmType() == TYPE_AM_SRC) { - for (field= table->field; *field; field++) { - fp= *field; - - if (bitmap_is_set(map, fp->field_index)) - if (!stricmp(colp->GetName(), fp->field_name)) { - ntf[i] = fp; - fp->field_index = i++; - fp->ptr = tptr; - tptr += fp->max_data_length(); - break; - } // endif Name - - } // endfor field - - for (field= table->s->field; *field; field++) { - fp= *field; - - if (bitmap_is_set(map, fp->field_index)) - if (!stricmp(colp->GetName(), fp->field_name)) { - nsf[k] = fp; - fp->field_index = k++; - fp->ptr = srec; - srec += fp->max_data_length(); - break; - } // endif Name - - } // endfor field - - } // endif AmType - - // Now add the pivot generated columns - for (colp = Columns; colp; colp = colp->GetNext()) - if (colp->GetAmType() == TYPE_AM_FNC) { - if ((fp = (Field*)memdup_root(tmr, (char*)tfncp, tfncp->size_of()))) { - ntf[i] = fp; - fp->ptr = tptr; - fp->field_name = colp->GetName(); - fp->field_index = i++; - fp->vcol_info = NULL; - fp->stored_in_db = TRUE; - tptr += len; - } else - return TRUE; - - if ((fp = (Field*)memdup_root(smr, (char*)sfncp, sfncp->size_of()))) { - nsf[i] = fp; - fp->ptr = sptr; - fp->field_name = colp->GetName(); - fp->field_index = k++; - fp->vcol_info = NULL; - fp->stored_in_db = TRUE; - sptr += len; - } else - return TRUE; - - } // endif AM_FNC - - // Mark end of the list - ntf[i] = NULL; - nsf[k] = NULL; - - // Update the table fields - nmp = (uint32)((1<field = ntf; - table->used_fields = i; - table->record[0] = trec; - table->record[1] = trec + buffsize; - *table->def_read_set.bitmap = nmp; - *table->def_read_set.last_word_ptr = nmp; - table->def_read_set.last_word_mask = lwm; - table->def_read_set.n_bits = i; - *table->read_set->bitmap = nmp; - *table->read_set->last_word_ptr = nmp; - table->read_set->last_word_mask = lwm; - table->read_set->n_bits = i; - table->write_set->n_bits = i; - *table->vcol_set->bitmap = 0; - table->vcol_set->n_bits = i; - - // and the share fields - table->s->field = nsf; - table->s->reclength = sptr - srec; - table->s->stored_rec_length = sptr - srec; - table->s->fields = k; - table->s->stored_fields = k; - table->s->rec_buff_length = buffsize; -//table->s->varchar_fields = ???; -//table->s->db_record_offset = ???; -//table->s->null_field_first = ???; - return FALSE; - } // end of UpdateTableFields -#endif // 0 - /* --------------- Implementation of the PIVOT classes --------------- */ /***********************************************************************/ @@ -451,13 +74,12 @@ bool PIVOTDEF::DefineAM(PGLOBAL g, LPCSTR am, int poff) char *p1, *p2; PHC hc = ((MYCAT*)Cat)->GetHandler(); - if (!PRXDEF::DefineAM(g, am, poff)) { - Tabname = (char*)Tablep->GetName(); - DB = (char*)Tablep->GetQualifier(); - } else { - DB = Cat->GetStringCatInfo(g, "Database", "*"); - Tabsrc = Cat->GetStringCatInfo(g, "SrcDef", NULL); - } // endif + if (PRXDEF::DefineAM(g, am, poff)) + return TRUE; + + Tabname = (char*)Tablep->GetName(); + DB = (char*)Tablep->GetQualifier(); + Tabsrc = (char*)Tablep->GetSrc(); Host = Cat->GetStringCatInfo(g, "Host", "localhost"); User = Cat->GetStringCatInfo(g, "User", "*"); @@ -477,7 +99,7 @@ bool PIVOTDEF::DefineAM(PGLOBAL g, LPCSTR am, int poff) GBdone = Cat->GetBoolCatInfo("Groupby", false); Accept = Cat->GetBoolCatInfo("Accept", false); Port = Cat->GetIntCatInfo("Port", 3306); - Desc = (Tabname) ? Tabname : Tabsrc; + Desc = (Tabsrc) ? Tabsrc : Tabname; return FALSE; } // end of DefineAM @@ -520,6 +142,25 @@ TDBPIVOT::TDBPIVOT(PPIVOTDEF tdp) : TDBPRX(tdp) RowFlag = 0; // 0: Ok, 1: Same, 2: Skip } // end of TDBPIVOT constructor +/***********************************************************************/ +/* Allocate source column description block. */ +/***********************************************************************/ +PCOL TDBPIVOT::MakeCol(PGLOBAL g, PCOLDEF cdp, PCOL cprec, int n) + { + PCOL colp; + + if (cdp->GetOffset()) { + colp = new(g) FNCCOL(cdp, this, cprec, n); + + if (cdp->GetOffset() > 1) + Dcolp = colp; + + } else + colp = new(g) SRCCOL(cdp, this, cprec, n); + + return colp; + } // end of MakeCol + /***********************************************************************/ /* Prepare the source table Query. */ /***********************************************************************/ @@ -528,72 +169,74 @@ bool TDBPIVOT::GetSourceTable(PGLOBAL g) if (Tdbp) return false; // Already done - if (Tabname) { - PTABDEF defp; - PCOLDEF cdp; - - if (InitTable(g)) + if (!Tabsrc && Tabname) { + // Get the table description block of this table + if (!(Tdbp = GetSubTable(g, ((PPIVOTDEF)To_Def)->Tablep, true))) return true; - else - defp = Tdbp->GetDef(); - if (!Fncol) { - for (cdp = defp->GetCols(); cdp; cdp = cdp->GetNext()) - if (!Picol || stricmp(Picol, cdp->GetName())) - Fncol = cdp->GetName(); + if (!Tdbp->IsView()) { + PCOLDEF cdp; + PTABDEF defp = Tdbp->GetDef(); if (!Fncol) { - strcpy(g->Message, MSG(NO_DEF_FNCCOL)); - return true; + for (cdp = defp->GetCols(); cdp; cdp = cdp->GetNext()) + if (!Picol || stricmp(Picol, cdp->GetName())) + Fncol = cdp->GetName(); + + if (!Fncol) { + strcpy(g->Message, MSG(NO_DEF_FNCCOL)); + return true; + } // endif Fncol + } // endif Fncol - - } // endif Fncol - - if (!Picol) { - // Find default Picol as the last one not equal to Fncol - for (cdp = defp->GetCols(); cdp; cdp = cdp->GetNext()) - if (!Fncol || stricmp(Fncol, cdp->GetName())) - Picol = cdp->GetName(); - + if (!Picol) { - strcpy(g->Message, MSG(NO_DEF_PIVOTCOL)); - return true; + // Find default Picol as the last one not equal to Fncol + for (cdp = defp->GetCols(); cdp; cdp = cdp->GetNext()) + if (!Fncol || stricmp(Fncol, cdp->GetName())) + Picol = cdp->GetName(); + + if (!Picol) { + strcpy(g->Message, MSG(NO_DEF_PIVOTCOL)); + return true; + } // endif Picol + } // endif Picol + + if (!GBdone) { + char *colist; + + // Locate the suballocated colist (size is not known yet) + *(colist = (char*)PlugSubAlloc(g, NULL, 0)) = 0; + + // Make the column list + for (cdp = To_Def->GetCols(); cdp; cdp = cdp->GetNext()) + if (!cdp->GetOffset()) + strcat(strcat(colist, cdp->GetName()), ", "); + + // Add the Pivot column at the end of the list + strcat(colist, Picol); + + // Now we know how much was suballocated + PlugSubAlloc(g, NULL, strlen(colist)); + + // Locate the source string (size is not known yet) + Tabsrc = (char*)PlugSubAlloc(g, NULL, 0); + + // Start making the definition + strcat(strcat(strcpy(Tabsrc, "SELECT "), colist), ", "); + + // Make it suitable for Pivot by doing the group by + strcat(strcat(Tabsrc, Function), "("); + strcat(strcat(strcat(Tabsrc, Fncol), ") "), Fncol); + strcat(strcat(Tabsrc, " FROM "), Tabname); + strcat(strcat(Tabsrc, " GROUP BY "), colist); + + // Now we know how much was suballocated + PlugSubAlloc(g, NULL, strlen(Tabsrc)); + } // endif !GBdone - } // endif Picol - - if (!GBdone) { - char *colist; - - // Locate the suballocated colist (size is not known yet) - *(colist = (char*)PlugSubAlloc(g, NULL, 0)) = 0; - - // Make the column list - for (cdp = To_Def->GetCols(); cdp; cdp = cdp->GetNext()) - if (!cdp->GetOffset()) - strcat(strcat(colist, cdp->GetName()), ", "); - - // Add the Pivot column at the end of the list - strcat(colist, Picol); - - // Now we know how much was suballocated - PlugSubAlloc(g, NULL, strlen(colist)); - - // Locate the source string (size is not known yet) - Tabsrc = (char*)PlugSubAlloc(g, NULL, 0); - - // Start making the definition - strcat(strcat(strcpy(Tabsrc, "SELECT "), colist), ", "); - - // Make it suitable for Pivot by doing the group by - strcat(strcat(Tabsrc, Function), "("); - strcat(strcat(strcat(Tabsrc, Fncol), ") "), Fncol); - strcat(strcat(Tabsrc, " FROM "), Tabname); - strcat(strcat(Tabsrc, " GROUP BY "), colist); - - // Now we know how much was suballocated - PlugSubAlloc(g, NULL, strlen(Tabsrc)); - } // endif !GBdone + } // endif IsView } else if (!Tabsrc) { strcpy(g->Message, MSG(SRC_TABLE_UNDEF)); @@ -601,26 +244,76 @@ bool TDBPIVOT::GetSourceTable(PGLOBAL g) } // endif if (Tabsrc) { - MYSQLC myc; // MySQL connection class - PQRYRES qryp; - PCOLRES crp; - int w; + // Get the new table description block of this source table + PTABLE tablep = new(g) XTAB("whatever", Tabsrc); - // Open a MySQL connection for this table - if (myc.Open(g, Host, Database, User, Pwd, Port)) + tablep->SetQualifier(Database); + + if (!(Tdbp = GetSubTable(g, tablep, true))) return true; - // Send the source command to MySQL - if (myc.ExecSQL(g, Tabsrc, &w) == RC_FX) { - myc.Close(); + } // endif Tabsrc + + return false; + } // end of GetSourceTable + +/***********************************************************************/ +/* Make the required pivot columns. */ +/***********************************************************************/ +bool TDBPIVOT::MakePivotColumns(PGLOBAL g) + { + if (!Tdbp->IsView()) { + // Now it is time to allocate the pivot and function columns + if (!(Fcolp = Tdbp->ColDB(g, Fncol, 0))) { + // Function column not found in table + sprintf(g->Message, MSG(COL_ISNOT_TABLE), Fncol, Tabname); + return true; + } else if (Fcolp->InitValue(g)) return true; - } // endif Exec - // We must have a storage query to get pivot column values - qryp = myc.GetResult(g); - myc.Close(); - Tdbp = new(g) TDBQRS(qryp); + if (!(Xcolp = Tdbp->ColDB(g, Picol, 0))) { + // Pivot column not found in table + sprintf(g->Message, MSG(COL_ISNOT_TABLE), Picol, Tabname); + return true; + } else if (Xcolp->InitValue(g)) + return true; + // Check and initialize the subtable columns + for (PCOL cp = Columns; cp; cp = cp->GetNext()) + if (cp->GetAmType() == TYPE_AM_SRC) { + if (((PSRCCOL)cp)->Init(g)) + return TRUE; + + } else if (cp->GetAmType() == TYPE_AM_FNC) + if (((PFNCCOL)cp)->InitColumn(g)) + return TRUE; + + } // endif isview + + return false; + } // end of MakePivotColumns + +/***********************************************************************/ +/* Make the required pivot columns for an object view. */ +/***********************************************************************/ +bool TDBPIVOT::MakeViewColumns(PGLOBAL g) + { + if (Tdbp->IsView()) { + // Tdbp is a view ColDB cannot be used + PCOL colp, cp; + PTDBMY tdbp; + + if (Tdbp->GetAmType() != TYPE_AM_MYSQL) { + strcpy(g->Message, "View is not MySQL"); + return true; + } else + tdbp = (PTDBMY)Tdbp; + + if (!Fncol || !Picol) { + strcpy(g->Message, "Missing Function or Pivot column"); + return true; + } // endif +#if 0 if (!Fncol) { for (crp = qryp->Colresp; crp; crp = crp->Next) if (!Picol || stricmp(Picol, crp->Name)) @@ -645,45 +338,33 @@ bool TDBPIVOT::GetSourceTable(PGLOBAL g) } // endif Picol } // endif Picol +#endif // 0 - } // endif Tabsrc + // Now it is time to allocate the pivot and function columns + if (!(Fcolp = tdbp->MakeFieldColumn(g, Fncol))) + return true; - // Now it is time to allocate the pivot and function columns - if (!(Fcolp = Tdbp->ColDB(g, Fncol, 0))) { - // Function column not found in table - sprintf(g->Message, MSG(COL_ISNOT_TABLE), Fncol, Tabname); - return true; - } else if (Fcolp->InitValue(g)) - return true; + if (!(Xcolp = tdbp->MakeFieldColumn(g, Picol))) + return true; - if (!(Xcolp = Tdbp->ColDB(g, Picol, 0))) { - // Pivot column not found in table - sprintf(g->Message, MSG(COL_ISNOT_TABLE), Picol, Tabname); - return true; - } else if (Xcolp->InitValue(g)) - return true; + // Check and initialize the subtable columns + for (cp = Columns; cp; cp = cp->GetNext()) + if (cp->GetAmType() == TYPE_AM_SRC) { + if ((colp = tdbp->MakeFieldColumn(g, cp->GetName()))) { + ((PSRCCOL)cp)->Colp = colp; + ((PSRCCOL)cp)->To_Val = colp->GetValue(); + cp->AddStatus(BUF_READ); // All is done here + } else + return true; + + } else if (cp->GetAmType() == TYPE_AM_FNC) + if (((PFNCCOL)cp)->InitColumn(g)) + return TRUE; + + } // endif isview return false; - } // end of GetSourceTable - -/***********************************************************************/ -/* Allocate source column description block. */ -/***********************************************************************/ -PCOL TDBPIVOT::MakeCol(PGLOBAL g, PCOLDEF cdp, PCOL cprec, int n) - { - PCOL colp; - - if (cdp->GetOffset()) { - colp = new(g) FNCCOL(cdp, this, cprec, n); - - if (cdp->GetOffset() > 1) - Dcolp = colp; - - } else - colp = new(g) SRCCOL(cdp, this, cprec, n); - - return colp; - } // end of MakeCol + } // end of MakeViewColumns /***********************************************************************/ /* PIVOT GetMaxSize: returns the maximum number of rows in the table. */ @@ -696,7 +377,7 @@ int TDBPIVOT::GetMaxSize(PGLOBAL g) return MaxSize; #endif // 0 - return 0; + return 10; } // end of GetMaxSize /***********************************************************************/ @@ -713,8 +394,6 @@ int TDBPIVOT::RowNumber(PGLOBAL g, bool b) /***********************************************************************/ bool TDBPIVOT::OpenDB(PGLOBAL g) { -//PDBUSER dup = (PDBUSER)g->Activityp->Aptr; - if (Use == USE_OPEN) { /*******************************************************************/ /* Table already open, just replace it at its beginning. */ @@ -746,18 +425,10 @@ bool TDBPIVOT::OpenDB(PGLOBAL g) /*********************************************************************/ if (GetSourceTable(g)) return TRUE; - - /*********************************************************************/ - /* Check and initialize the subtable columns. */ - /*********************************************************************/ - for (PCOL cp = Columns; cp; cp = cp->GetNext()) - if (cp->GetAmType() == TYPE_AM_SRC) { - if (((PPRXCOL)cp)->Init(g)) - return TRUE; - - } else if (cp->GetAmType() == TYPE_AM_FNC) - if (((PFNCCOL)cp)->InitColumn(g)) - return TRUE; + + // For tables, columns must be allocated before opening + if (MakePivotColumns(g)) + return TRUE; /*********************************************************************/ /* Physically open the object table. */ @@ -765,7 +436,10 @@ bool TDBPIVOT::OpenDB(PGLOBAL g) if (Tdbp->OpenDB(g)) return TRUE; - return FALSE; + /*********************************************************************/ + /* Make all required pivot columns for object views. */ + /*********************************************************************/ + return MakeViewColumns(g); } // end of OpenDB /***********************************************************************/ @@ -881,17 +555,6 @@ void TDBPIVOT::CloseDB(PGLOBAL g) } // end of CloseDB -#if 0 -/***********************************************************************/ -/* TDBPIVOT: Compare routine for sorting pivot column values. */ -/***********************************************************************/ -int TDBPIVOT::Qcompare(int *i1, int *i2) - { - // TODO: the actual comparison between pivot column result values. - return Rblkp->CompVal(*i1, *i2); - } // end of Qcompare -#endif // 0 - // ------------------------ FNCCOL functions ---------------------------- /***********************************************************************/ @@ -948,8 +611,6 @@ bool FNCCOL::CompareColumn(void) SRCCOL::SRCCOL(PCOLDEF cdp, PTDB tdbp, PCOL cprec, int n) : PRXCOL(cdp, tdbp, cprec, n) { - // Set additional SRC access method information for column. -//Cnval = NULL; } // end of SRCCOL constructor /***********************************************************************/ @@ -960,9 +621,6 @@ bool SRCCOL::Init(PGLOBAL g) if (PRXCOL::Init(g)) return true; - // Will contain the last value -//Cnval = AllocateValue(g, Value, TYPE_VOID); - AddStatus(BUF_READ); // All is done here return false; } // end of SRCCOL constructor @@ -972,7 +630,6 @@ bool SRCCOL::Init(PGLOBAL g) /***********************************************************************/ void SRCCOL::SetColumn(void) { -//Cnval->SetValue_pval(Value); Value->SetValue_pval(To_Val); } // end of SetColumn @@ -982,315 +639,7 @@ void SRCCOL::SetColumn(void) bool SRCCOL::CompareLast(void) { // Compare the unconverted values -//return !Cnval->IsEqual(Colp->GetValue(), true); return !Value->IsEqual(To_Val, true); } // end of CompareColumn - -/* ------------------------------------------------------------------- */ - -/***********************************************************************/ -/* Implementation of the TDBQRS class. */ -/***********************************************************************/ -TDBQRS::TDBQRS(PTDBQRS tdbp) : TDBASE(tdbp) - { - Qrp = tdbp->Qrp; - CurPos = tdbp->CurPos; - } // end of TDBQRS copy constructor - -// Method -PTDB TDBQRS::CopyOne(PTABS t) - { - PTDB tp; - PQRSCOL cp1, cp2; - PGLOBAL g = t->G; // Is this really useful ??? - - tp = new(g) TDBQRS(this); - - for (cp1 = (PQRSCOL)Columns; cp1; cp1 = (PQRSCOL)cp1->GetNext()) { - cp2 = new(g) QRSCOL(cp1, tp); // Make a copy - NewPointer(t, cp1, cp2); - } // endfor cp1 - - return tp; - } // end of CopyOne - -#if 0 // The TDBASE functions return NULL when To_Def is NULL -/***********************************************************************/ -/* Return the pointer on the DB catalog this table belongs to. */ -/***********************************************************************/ -PCATLG TDBQRS::GetCat(void) - { - // To_Def is null for QRYRES tables - return NULL; - } // end of GetCat - -/***********************************************************************/ -/* Return the datapath of the DB this table belongs to. */ -/***********************************************************************/ -PSZ TDBQRS::GetPath(void) - { - // To_Def is null for QRYRES tables - return NULL; - } // end of GetPath -#endif // 0 - -/***********************************************************************/ -/* Initialize QRS column description block construction. */ -/* name is used to call columns by name. */ -/* num is used by LNA to construct columns by index number. */ -/* Note: name=Null and num=0 for constructing all columns (select *) */ -/***********************************************************************/ -PCOL TDBQRS::ColDB(PGLOBAL g, PSZ name, int num) - { - int i; - PCOLRES crp; - PCOL cp, colp = NULL, cprec = NULL; - - if (trace) - htrc("QRS ColDB: colname=%s tabname=%s num=%d\n", - SVP(name), Name, num); - - for (crp = Qrp->Colresp, i = 1; crp; crp = crp->Next, i++) - if ((!name && !num) || - (name && !stricmp(crp->Name, name)) || num == i) { - // Check for existence of desired column - // Also find where to insert the new block - for (cp = Columns; cp; cp = cp->GetNext()) - if (cp->GetIndex() < i) - cprec = cp; - else if (cp->GetIndex() == i) - break; - - if (trace) { - if (cp) - htrc("cp(%d).Name=%s cp=%p\n", i, cp->GetName(), cp); - else - htrc("cp(%d) cp=%p\n", i, cp); - } // endif trace - - // Now take care of Column Description Block - if (cp) - colp = cp; - else - colp = new(g) QRSCOL(g, crp, this, cprec, i); - - if (name || num) - break; - else - cprec = colp; - - } // endif Name - - return (colp); - } // end of ColDB - -/***********************************************************************/ -/* QRS GetMaxSize: returns maximum table size in number of lines. */ -/***********************************************************************/ -int TDBQRS::GetMaxSize(PGLOBAL g) - { - MaxSize = Qrp->Maxsize; - return MaxSize; - } // end of GetMaxSize - -/***********************************************************************/ -/* RowNumber: returns the current row ordinal number. */ -/***********************************************************************/ -int TDBQRS::RowNumber(PGLOBAL g, BOOL b) - { - return (CurPos + 1); - } // end of RowNumber - -/***********************************************************************/ -/* QRS Access Method opening routine. */ -/* New method now that this routine is called recursively (last table */ -/* first in reverse order): index blocks are immediately linked to */ -/* join block of next table if it exists or else are discarted. */ -/***********************************************************************/ -bool TDBQRS::OpenDB(PGLOBAL g) - { - if (trace) - htrc("QRS OpenDB: tdbp=%p tdb=R%d use=%d key=%p mode=%d\n", - this, Tdb_No, Use, To_Key_Col, Mode); - - if (Mode != MODE_READ) { - sprintf(g->Message, MSG(BAD_QUERY_OPEN), Mode); - return TRUE; - } // endif Mode - - CurPos = -1; - - if (Use == USE_OPEN) - return FALSE; - - /*********************************************************************/ - /* Open (retrieve data from) the query if not already open. */ - /*********************************************************************/ - Use = USE_OPEN; // Do it now in case we are recursively called - - return FALSE; - } // end of OpenDB - -/***********************************************************************/ -/* GetRecpos: returns current position of next sequential read. */ -/***********************************************************************/ -int TDBQRS::GetRecpos(void) - { - return (CurPos); - } // end of GetRecpos - -/***********************************************************************/ -/* ReadDB: Data Base read routine for QRS access method. */ -/***********************************************************************/ -int TDBQRS::ReadDB(PGLOBAL g) - { - int rc = RC_OK; - - if (trace) - htrc("QRS ReadDB: R%d CurPos=%d key=%p link=%p Kindex=%p\n", - GetTdb_No(), CurPos, To_Key_Col, To_Link, To_Kindex); - -#if 0 - if (To_Kindex) { - /*******************************************************************/ - /* Reading is by an index table. */ - /*******************************************************************/ - int recpos = To_Kindex->Fetch(g); - - switch (recpos) { - case -1: // End of file reached - rc = RC_EF; - break; - case -2: // No match for join - rc = RC_NF; - break; - case -3: // Same record as last non null one - rc = RC_OK; - break; - default: - /***************************************************************/ - /* Set the file position according to record to read. */ - /***************************************************************/ - CurPos = recpos; - } // endswitch recpos - - if (trace) - htrc("Position is now %d\n", CurPos); - - } else -#endif // 0 - /*******************************************************************/ - /* !To_Kindex ---> sequential reading */ - /*******************************************************************/ - rc = (++CurPos < Qrp->Nblin) ? RC_OK : RC_EF; - - return rc; - } // end of ReadDB - -/***********************************************************************/ -/* Dummy WriteDB: just send back an error return. */ -/***********************************************************************/ -int TDBQRS::WriteDB(PGLOBAL g) - { - strcpy(g->Message, MSG(QRY_READ_ONLY)); - return RC_FX; - } // end of WriteDB - -/***********************************************************************/ -/* Dummy DeleteDB routine, just returns an error code. */ -/***********************************************************************/ -int TDBQRS::DeleteDB(PGLOBAL g, int irc) - { - strcpy(g->Message, MSG(NO_QRY_DELETE)); - return RC_FX; - } // end of DeleteDB - -/***********************************************************************/ -/* Data Base close routine for QRS access method. */ -/***********************************************************************/ -void TDBQRS::CloseDB(PGLOBAL g) - { -//if (To_Kindex) { -// To_Kindex->Close(); -// To_Kindex = NULL; -// } // endif - - if (trace) - htrc("Qryres CloseDB"); - -//Qryp->Sqlp->CloseDB(); - } // end of CloseDB - -// ------------------------ QRSCOL functions ---------------------------- - -/***********************************************************************/ -/* QRSCOL public constructor. */ -/***********************************************************************/ -QRSCOL::QRSCOL(PGLOBAL g, PCOLRES crp, PTDB tdbp, PCOL cprec, int i) - : COLBLK(NULL, tdbp, i) - { - if (cprec) { - Next = cprec->GetNext(); - cprec->SetNext(this); - } else { - Next = tdbp->GetColumns(); - tdbp->SetColumns(this); - } // endif cprec - - // Set additional QRS access method information for column. - Crp = crp; - Name = Crp->Name; - Long = Crp->Clen; - Buf_Type = crp->Type; - strcpy(Format.Type, GetFormatType(Buf_Type)); - Format.Length = (short)Long; - Format.Prec = (short)Crp->Prec; - - if (trace) { - htrc("Making new QRSCOL C%d %s at %p\n", Index, Name, this); - htrc(" BufType=%d Long=%d length=%d clen=%d\n", - Buf_Type, Long, Format.Length, Crp->Clen); - } // endif trace - - } // end of QRSCOL constructor - -/***********************************************************************/ -/* QRSCOL constructor used for copying columns. */ -/* tdbp is the pointer to the new table descriptor. */ -/***********************************************************************/ -QRSCOL::QRSCOL(QRSCOL *col1, PTDB tdbp) : COLBLK(col1, tdbp) - { - Crp = col1->Crp; - } // end of QRSCOL copy constructor - -/***********************************************************************/ -/* ReadColumn: what this routine does is to extract the RESCOL block */ -/* current value and convert it to the column buffer type. */ -/***********************************************************************/ -void QRSCOL::ReadColumn(PGLOBAL g) - { - PTDBQRS tdbp = (PTDBQRS)To_Tdb; - - if (trace) - htrc("QRS RC: col %s R%d type=%d CurPos=%d Len=%d\n", - Name, tdbp->GetTdb_No(), Buf_Type, tdbp->CurPos, Crp->Clen); - - if (Crp->Kdata) - Value->SetValue_pvblk(Crp->Kdata, tdbp->CurPos); - else - Value->Reset(); - - } // end of ReadColumn - -/***********************************************************************/ -/* Make file output of a Dos column descriptor block. */ -/***********************************************************************/ -void QRSCOL::Print(PGLOBAL g, FILE *f, uint n) - { - COLBLK::Print(g, f, n); - - fprintf(f, " Crp=%p\n", Crp); - } // end of Print - /* --------------------- End of TabPivot/TabQrs ---------------------- */ diff --git a/storage/connect/tabpivot.h b/storage/connect/tabpivot.h index bed288dc560..e869d1cae6c 100644 --- a/storage/connect/tabpivot.h +++ b/storage/connect/tabpivot.h @@ -1,15 +1,14 @@ /************** TabPivot H Declares Source Code File (.H) **************/ -/* Name: TABPIVOT.H Version 1.3 */ +/* Name: TABPIVOT.H Version 1.4 */ /* */ -/* (C) Copyright to the author Olivier BERTRAND 2005-2012 */ +/* (C) Copyright to the author Olivier BERTRAND 2005-2013 */ /* */ /* This file contains the PIVOT classes declares. */ /***********************************************************************/ +typedef class PIVOTDEF *PPIVOTDEF; typedef class TDBPIVOT *PTDBPIVOT; typedef class FNCCOL *PFNCCOL; typedef class SRCCOL *PSRCCOL; -typedef class TDBQRS *PTDBQRS; -typedef class QRSCOL *PQRSCOL; /* -------------------------- PIVOT classes -------------------------- */ @@ -22,7 +21,6 @@ typedef class QRSCOL *PQRSCOL; /***********************************************************************/ /* PIVOT table. */ /***********************************************************************/ -//ass DllExport PIVOTDEF : public PRXDEF {/* Logical table description */ class PIVOTDEF : public PRXDEF { /* Logical table description */ friend class TDBPIVOT; public: @@ -55,22 +53,16 @@ class PIVOTDEF : public PRXDEF { /* Logical table description */ /***********************************************************************/ /* This is the class declaration for the PIVOT table. */ /***********************************************************************/ -//ass DllExport TDBPIVOT : public TDBASE, public CSORT { class TDBPIVOT : public TDBPRX { friend class FNCCOL; -//friend class SRCCOL; public: // Constructor TDBPIVOT(PPIVOTDEF tdp); -//TDBPIVOT(PTDBPIVOT tdbp); // Implementation virtual AMT GetAmType(void) {return TYPE_AM_PIVOT;} -//virtual PTDB Duplicate(PGLOBAL g) {return (PTDB)new(g) TDBPIVOT(this);} -// void SetTdbp(PTDB tdbp) {Tdbp = tdbp;} // Methods -//virtual PTDB CopyOne(PTABS t); virtual int GetRecpos(void) {return N;} virtual void ResetDB(void) {N = 0;} virtual int RowNumber(PGLOBAL g, bool b = FALSE); @@ -84,22 +76,17 @@ class TDBPIVOT : public TDBPRX { virtual int DeleteDB(PGLOBAL g, int irc); virtual void CloseDB(PGLOBAL g); - // The sorting function -//virtual int Qcompare(int *, int *); - protected: - bool GetSourceTable(PGLOBAL g); -//int MakePivotColumns(PGLOBAL g); -//bool UpdateTableFields(PGLOBAL g, int n); + // Internal routines + bool GetSourceTable(PGLOBAL g); + bool MakePivotColumns(PGLOBAL g); + bool MakeViewColumns(PGLOBAL g); // Members -//MYSQLC Myc; // MySQL connection class -//PTDBQRS Tqrp; // To the source table result char *Host; // Host machine to use char *User; // User logon info char *Pwd; // Password logon info char *Database; // Database to be used by server -//PQRYRES Qryp; // Points to Query result block char *Tabname; // Name of source table char *Tabsrc; // SQL of source table char *Picol; // Pivot column name @@ -108,9 +95,6 @@ class TDBPIVOT : public TDBPRX { PCOL Fcolp; // To the function column in source PCOL Xcolp; // To the pivot column in source PCOL Dcolp; // To the dump column -//PCOLRES Xresp; // To the pivot result column -//PCOLRES To_Sort; // Saved Qryp To_Sort pointer -//PVBLK Rblkp; // The value block of the pivot column bool GBdone; // True when subtable is "Group by" bool Accept; // TRUE if no match is accepted int Mult; // Multiplication factor @@ -168,75 +152,4 @@ class SRCCOL : public PRXCOL { SRCCOL(void) {} // Members -//PVAL Cnval; }; // end of class SRCCOL - -/***********************************************************************/ -/* TDBQRS: This is the Access Method class declaration for the Query */ -/* Result stored in memory in the current work area (volatil). */ -/***********************************************************************/ -class DllExport TDBQRS : public TDBASE { - friend class QRSCOL; - public: - // Constructor - TDBQRS(PQRYRES qrp) : TDBASE() {Qrp = qrp; CurPos = 0;} - TDBQRS(PTDBQRS tdbp); - - // Implementation - virtual AMT GetAmType(void) {return TYPE_AM_QRS;} - virtual PTDB Duplicate(PGLOBAL g) - {return (PTDB)new(g) TDBQRS(this);} - PQRYRES GetQrp(void) {return Qrp;} - - // Methods - virtual PTDB CopyOne(PTABS t); - virtual int RowNumber(PGLOBAL g, BOOL b = FALSE); - virtual int GetRecpos(void); -//virtual PCATLG GetCat(void); -//virtual PSZ GetPath(void); - virtual int GetBadLines(void) {return Qrp->BadLines;} - - // Database routines - virtual PCOL ColDB(PGLOBAL g, PSZ name, int num); - 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); - - private: - TDBQRS(void) : TDBASE() {} // Standard constructor not to be used - - protected: - // Members - PQRYRES Qrp; // Points to Query Result block - int CurPos; // Current line position - }; // end of class TDBQRS - -/***********************************************************************/ -/* Class QRSCOL: QRS access method column descriptor. */ -/***********************************************************************/ -class DllExport QRSCOL : public COLBLK { - friend class TDBQRS; - public: - // Constructors - QRSCOL(PGLOBAL g, PCOLRES crp, PTDB tdbp, PCOL cprec, int i); - QRSCOL(QRSCOL *colp, PTDB tdbp); // Constructor used in copy process - - // Implementation - virtual int GetAmType(void) {return TYPE_AM_QRS;} - PCOLRES GetCrp(void) {return Crp;} - void *GetQrsData(void) {return Crp->Kdata;} - - // Methods - virtual void ReadColumn(PGLOBAL g); - virtual void Print(PGLOBAL g, FILE *, uint); - - protected: - QRSCOL(void) {} // Default constructor not to be used - - // Members - PCOLRES Crp; - }; // end of class QRSCOL - diff --git a/storage/connect/tabtbl.cpp b/storage/connect/tabtbl.cpp index 7e89cccf583..43fbb27a715 100644 --- a/storage/connect/tabtbl.cpp +++ b/storage/connect/tabtbl.cpp @@ -216,7 +216,7 @@ bool TDBTBL::InitTableList(PGLOBAL g) { int n; PTABLE tp, tabp; - PTDB tdbp; + PTDBASE tdbp; PCOL colp; PTBLDEF tdp = (PTBLDEF)To_Def; @@ -252,7 +252,7 @@ bool TDBTBL::InitTableList(PGLOBAL g) n++; } // endif filp - } // endfor tblp + } // endfor tp //NumTables = n; To_Filter = NULL; // To avoid doing it several times diff --git a/storage/connect/tabutil.cpp b/storage/connect/tabutil.cpp index c55b8d1fa5c..8698d4697b7 100644 --- a/storage/connect/tabutil.cpp +++ b/storage/connect/tabutil.cpp @@ -90,20 +90,21 @@ TABLE_SHARE *GetTableShare(PGLOBAL g, THD *thd, const char *db, // 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 (!open_table_def(thd, s, GTS_TABLE | GTS_VIEW)) { + if (!s->is_view) { + if (stricmp(plugin_name(s->db_plugin)->str, "connect")) { #if defined(MYSQL_SUPPORT) - mysql = true; + mysql = true; #else // !MYSQL_SUPPORT - sprintf(g->Message, "%s.%s is not a CONNECT table", db, name); - return NULL; + sprintf(g->Message, "%s.%s is not a CONNECT table", db, name); + return NULL; #endif // MYSQL_SUPPORT - } else - mysql = false; + } else + mysql = false; + + } else { + mysql = true; + } // endif is_view } else { sprintf(g->Message, "Error %d opening share\n", s->error); @@ -139,9 +140,12 @@ PQRYRES TabColumns(PGLOBAL g, THD *thd, const char *db, PCOLRES crp; if (!info) { - if (!(s = GetTableShare(g, thd, db, name, mysql))) + if (!(s = GetTableShare(g, thd, db, name, mysql))) { return NULL; - else + } else if (s->is_view) { + strcpy(g->Message, "Cannot retreive Proxy columns from a view"); + return NULL; + } else n = s->fieldnames.count; } else { @@ -257,23 +261,27 @@ PRXDEF::PRXDEF(void) /***********************************************************************/ bool PRXDEF::DefineAM(PGLOBAL g, LPCSTR am, int poff) { - char *pn, *db, *tab; + char *pn, *db, *tab, *def = NULL; db = Cat->GetStringCatInfo(g, "Dbname", "*"); + def = Cat->GetStringCatInfo(g, "Srcdef", NULL); if (!(tab = Cat->GetStringCatInfo(g, "Tabname", NULL))) { - strcpy(g->Message, "Missing object table name"); - return TRUE; - } // endif tab + if (!def) { + strcpy(g->Message, "Missing object table definition"); + return TRUE; + } else + tab = "Noname"; - // Analyze the table name, it may have the format: [dbname.]tabname - if ((pn = strchr(tab, '.'))) { - *pn++ = 0; - db = tab; - tab = pn; - } // endif pn + } else + // 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 = new(g) XTAB(tab, def); Tablep->SetQualifier(db); return FALSE; } // end of DefineAM @@ -303,12 +311,13 @@ TDBPRX::TDBPRX(PPRXDEF tdp) : TDBASE(tdp) /***********************************************************************/ /* Get the PTDB of the sub-table. */ /***********************************************************************/ -PTDB TDBPRX::GetSubTable(PGLOBAL g, PTABLE tabp) +PTDBASE TDBPRX::GetSubTable(PGLOBAL g, PTABLE tabp, bool b) { char *db, *name; - bool mysql; + bool mysql = true; PTDB tdbp = NULL; - TABLE_SHARE *s; + TABLE_SHARE *s = NULL; + Field* *fp; PCATLG cat = To_Def->GetCat(); PHC hc = ((MYCAT*)cat)->GetHandler(); LPCSTR cdb, curdb = hc->GetDBName(NULL); @@ -328,10 +337,20 @@ PTDB TDBPRX::GetSubTable(PGLOBAL g, PTABLE tabp) } // endfor tp - if (!(s = GetTableShare(g, thd, db, name, mysql))) - return NULL; + if (!tabp->GetSrc()) { + if (!(s = GetTableShare(g, thd, db, name, mysql))) + return NULL; - hc->tshp = s; + if (s->is_view && !b) + s->field = hc->get_table()->s->field; + + hc->tshp = s; + } else if (b) { + // Don't use caller's columns + fp = hc->get_table()->field; + hc->get_table()->field = NULL; + hc->get_table()->s->option_struct->srcdef = tabp->GetSrc(); + } // endif srcdef if (mysql) { #if defined(MYSQL_SUPPORT) @@ -355,15 +374,23 @@ PTDB TDBPRX::GetSubTable(PGLOBAL g, PTABLE tabp) tdbp = cat->GetTable(g, tabp); } // endif mysql - hc->tshp = NULL; + if (s) { + if (s->is_view && !b) + s->field = NULL; + + hc->tshp = NULL; + } else if (b) + hc->get_table()->field = fp; if (trace && tdbp) htrc("Subtable %s in %s\n", name, SVP(((PTDBASE)tdbp)->GetDef()->GetDB())); err: - free_table_share(s); - return tdbp; + if (s) + free_table_share(s); + + return (PTDBASE)tdbp; } // end of GetSubTable /***********************************************************************/ @@ -373,7 +400,7 @@ bool TDBPRX::InitTable(PGLOBAL g) { if (!Tdbp) { // Get the table description block of this table - if (!(Tdbp = (PTDBASE)GetSubTable(g, ((PPRXDEF)To_Def)->Tablep))) + if (!(Tdbp = GetSubTable(g, ((PPRXDEF)To_Def)->Tablep))) return TRUE; } // endif Tdbp diff --git a/storage/connect/tabutil.h b/storage/connect/tabutil.h index 81e2a44464a..a6b08bce3d4 100644 --- a/storage/connect/tabutil.h +++ b/storage/connect/tabutil.h @@ -78,7 +78,7 @@ class DllExport TDBPRX : public TDBASE { 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); + PTDBASE GetSubTable(PGLOBAL g, PTABLE tabp, bool b = false); void RemoveNext(PTABLE tp); protected: @@ -93,6 +93,7 @@ class DllExport TDBPRX : public TDBASE { class DllExport PRXCOL : public COLBLK { friend class TDBPRX; friend class TDBTBL; + friend class TDBOCCUR; public: // Constructors PRXCOL(PCOLDEF cdp, PTDB tdbp, PCOL cprec, int i, PSZ am = "PRX"); diff --git a/storage/connect/xtable.h b/storage/connect/xtable.h index 8475c46d52d..7ef2d26136c 100644 --- a/storage/connect/xtable.h +++ b/storage/connect/xtable.h @@ -173,6 +173,7 @@ class DllExport TDBASE : public TDB { virtual int GetRecpos(void) = 0; virtual bool SetRecpos(PGLOBAL g, int recpos); virtual bool IsReadOnly(void) {return Read_Only;} + virtual bool IsView(void) {return FALSE;} virtual CHARSET_INFO *data_charset() { /* From aacd6f55af5f84298d3d7be26673d1e063092dc1 Mon Sep 17 00:00:00 2001 From: Olivier Bertrand Date: Sun, 19 May 2013 20:16:04 +0200 Subject: [PATCH 24/47] - Removing unused copy file modified: storage/connect/mysql-test/connect/t/pivot.test --- storage/connect/mysql-test/connect/t/pivot.test | 1 - 1 file changed, 1 deletion(-) diff --git a/storage/connect/mysql-test/connect/t/pivot.test b/storage/connect/mysql-test/connect/t/pivot.test index 87601a26d28..e66d927bad5 100644 --- a/storage/connect/mysql-test/connect/t/pivot.test +++ b/storage/connect/mysql-test/connect/t/pivot.test @@ -1,7 +1,6 @@ let $MYSQLD_DATADIR= `select @@datadir`; let $PORT= `select @@port`; --copy_file $MTR_SUITE_DIR/std_data/expenses.txt $MYSQLD_DATADIR/test/expenses.txt ---copy_file $MTR_SUITE_DIR/std_data/connect.ini $MYSQLD_DATADIR/test/connect.ini --echo # --echo # Testing the PIVOT table type From 38a5bb2c1b0f7c1daa121a603c345dbc83d10f5b Mon Sep 17 00:00:00 2001 From: Olivier Bertrand Date: Mon, 20 May 2013 13:12:34 +0200 Subject: [PATCH 25/47] - Save and restore srcdef when getting a sub-table (could stay in cache) modified: storage/connect/tabutil.cpp - Change order of tests when looking for valid tdbp. In rare cases an invalid tdbp was still existing causing a crash of the server. modified: storage/connect/ha_connect.cc --- storage/connect/ha_connect.cc | 5 +++-- storage/connect/tabutil.cpp | 9 ++++++++- 2 files changed, 11 insertions(+), 3 deletions(-) diff --git a/storage/connect/ha_connect.cc b/storage/connect/ha_connect.cc index 9020220f5d0..f41b584a377 100644 --- a/storage/connect/ha_connect.cc +++ b/storage/connect/ha_connect.cc @@ -1094,8 +1094,9 @@ PTDB ha_connect::GetTDB(PGLOBAL g) table_name= GetTableName(); - if (tdbp && !stricmp(tdbp->GetName(), table_name) - && tdbp->GetMode() == xmod && !xp->CheckQuery(valid_query_id)) { + if (!xp->CheckQuery(valid_query_id && tdbp + && !stricmp(tdbp->GetName(), table_name) + && tdbp->GetMode() == xmod)) { tp= tdbp; tp->SetMode(xmod); } else if ((tp= CntGetTDB(g, table_name, xmod, this))) diff --git a/storage/connect/tabutil.cpp b/storage/connect/tabutil.cpp index 93c0a8a83ea..5c4b428b09a 100644 --- a/storage/connect/tabutil.cpp +++ b/storage/connect/tabutil.cpp @@ -313,6 +313,7 @@ TDBPRX::TDBPRX(PPRXDEF tdp) : TDBASE(tdp) /***********************************************************************/ PTDBASE TDBPRX::GetSubTable(PGLOBAL g, PTABLE tabp, bool b) { + const char *sp; char *db, *name; bool mysql = true; PTDB tdbp = NULL; @@ -349,6 +350,9 @@ PTDBASE TDBPRX::GetSubTable(PGLOBAL g, PTABLE tabp, bool b) // Don't use caller's columns fp = hc->get_table()->field; hc->get_table()->field = NULL; + + // Make caller use the source definition + sp = hc->get_table()->s->option_struct->srcdef; hc->get_table()->s->option_struct->srcdef = tabp->GetSrc(); } // endif srcdef @@ -379,8 +383,11 @@ PTDBASE TDBPRX::GetSubTable(PGLOBAL g, PTABLE tabp, bool b) s->field = NULL; hc->tshp = NULL; - } else if (b) + } else if (b) { + // Restore s structure that can be in cache hc->get_table()->field = fp; + hc->get_table()->s->option_struct->srcdef = sp; + } // endif s if (trace && tdbp) htrc("Subtable %s in %s\n", From ca024d1c21649dec1caab2d4027b56f3fa01407e Mon Sep 17 00:00:00 2001 From: Olivier Bertrand Date: Mon, 20 May 2013 18:17:09 +0200 Subject: [PATCH 26/47] - Correct misplaced parenthesis in last change modified: storage/connect/ha_connect.cc - Tdbp must be assigned before calling PRX column init modified: storage/connect/tabtbl.cpp --- storage/connect/ha_connect.cc | 4 ++-- storage/connect/tabtbl.cpp | 3 +-- 2 files changed, 3 insertions(+), 4 deletions(-) diff --git a/storage/connect/ha_connect.cc b/storage/connect/ha_connect.cc index f41b584a377..7baffbb0684 100644 --- a/storage/connect/ha_connect.cc +++ b/storage/connect/ha_connect.cc @@ -1094,9 +1094,9 @@ PTDB ha_connect::GetTDB(PGLOBAL g) table_name= GetTableName(); - if (!xp->CheckQuery(valid_query_id && tdbp + if (!xp->CheckQuery(valid_query_id) && tdbp && !stricmp(tdbp->GetName(), table_name) - && tdbp->GetMode() == xmod)) { + && tdbp->GetMode() == xmod) { tp= tdbp; tp->SetMode(xmod); } else if ((tp= CntGetTDB(g, table_name, xmod, this))) diff --git a/storage/connect/tabtbl.cpp b/storage/connect/tabtbl.cpp index 43fbb27a715..9207ad636cf 100644 --- a/storage/connect/tabtbl.cpp +++ b/storage/connect/tabtbl.cpp @@ -216,7 +216,6 @@ bool TDBTBL::InitTableList(PGLOBAL g) { int n; PTABLE tp, tabp; - PTDBASE tdbp; PCOL colp; PTBLDEF tdp = (PTBLDEF)To_Def; @@ -227,7 +226,7 @@ bool TDBTBL::InitTableList(PGLOBAL g) tabp = new(g) XTAB(tp); // Get the table description block of this table - if (!(tdbp = GetSubTable(g, tabp))) { + if (!(Tdbp = GetSubTable(g, tabp))) { if (++Nbf > Maxerr) return TRUE; // Error return else From 41bda068a5affa1f8b483784df532c5a3ee8dcfd Mon Sep 17 00:00:00 2001 From: Alexander Barkov Date: Tue, 21 May 2013 18:29:10 +0400 Subject: [PATCH 27/47] "mtr --suite=connect --embedded" tests did not work for two reasons: 1. The Connect engine code assumed that mysql_home_directory is always "./", which is not the fact in case of embedded server. Fixing the routines creating file names to add the mysql_home_directory prefix. 2. FILE privilege is not checked in embedded server. Moving FILE related tests into separate files. Skipping the FILE related tests when running with --embedded. added: storage/connect/mysql-test/connect/r/grant.result storage/connect/mysql-test/connect/r/ini_grant.result storage/connect/mysql-test/connect/r/mysql_grant.result storage/connect/mysql-test/connect/r/xml_grant.result storage/connect/mysql-test/connect/t/grant.test storage/connect/mysql-test/connect/t/ini_grant.test storage/connect/mysql-test/connect/t/mysql_grant.test storage/connect/mysql-test/connect/t/xml_grant.test modified: storage/connect/global.h storage/connect/ha_connect.cc storage/connect/mycat.cc storage/connect/mysql-test/connect/r/bin.result storage/connect/mysql-test/connect/r/csv.result storage/connect/mysql-test/connect/r/dbf.result storage/connect/mysql-test/connect/r/dir.result storage/connect/mysql-test/connect/r/fix.result storage/connect/mysql-test/connect/r/ini.result storage/connect/mysql-test/connect/r/mysql.result storage/connect/mysql-test/connect/r/vec.result storage/connect/mysql-test/connect/r/xml.result storage/connect/mysql-test/connect/t/bin.test storage/connect/mysql-test/connect/t/csv.test storage/connect/mysql-test/connect/t/dbf.test storage/connect/mysql-test/connect/t/dir.test storage/connect/mysql-test/connect/t/fix.test storage/connect/mysql-test/connect/t/ini.test storage/connect/mysql-test/connect/t/mysql.test storage/connect/mysql-test/connect/t/vec.test storage/connect/mysql-test/connect/t/xml.test storage/connect/plgdbsem.h storage/connect/plugutil.c --- storage/connect/global.h | 3 +- storage/connect/ha_connect.cc | 80 ++- storage/connect/mycat.cc | 7 + .../connect/mysql-test/connect/r/bin.result | 94 --- .../connect/mysql-test/connect/r/csv.result | 94 --- .../connect/mysql-test/connect/r/dbf.result | 94 --- .../connect/mysql-test/connect/r/dir.result | 69 --- .../connect/mysql-test/connect/r/fix.result | 94 --- .../connect/mysql-test/connect/r/grant.result | 539 ++++++++++++++++++ .../connect/mysql-test/connect/r/ini.result | 79 --- .../mysql-test/connect/r/ini_grant.result | 79 +++ .../connect/mysql-test/connect/r/mysql.result | 63 -- .../mysql-test/connect/r/mysql_grant.result | 63 ++ .../connect/mysql-test/connect/r/vec.result | 94 --- .../connect/mysql-test/connect/r/xml.result | 104 +--- .../mysql-test/connect/r/xml_grant.result | 96 ++++ storage/connect/mysql-test/connect/t/bin.test | 4 - storage/connect/mysql-test/connect/t/csv.test | 4 - storage/connect/mysql-test/connect/t/dbf.test | 4 - storage/connect/mysql-test/connect/t/dir.test | 70 --- storage/connect/mysql-test/connect/t/fix.test | 4 - .../connect/mysql-test/connect/t/grant.test | 95 +++ storage/connect/mysql-test/connect/t/ini.test | 75 --- .../mysql-test/connect/t/ini_grant.test | 79 +++ .../connect/mysql-test/connect/t/mysql.test | 60 -- .../mysql-test/connect/t/mysql_grant.test | 78 +++ storage/connect/mysql-test/connect/t/vec.test | 4 - storage/connect/mysql-test/connect/t/xml.test | 17 +- .../mysql-test/connect/t/xml_grant.test | 23 + storage/connect/plgdbsem.h | 1 + storage/connect/plugutil.c | 30 +- 31 files changed, 1175 insertions(+), 1025 deletions(-) create mode 100644 storage/connect/mysql-test/connect/r/grant.result create mode 100644 storage/connect/mysql-test/connect/r/ini_grant.result create mode 100644 storage/connect/mysql-test/connect/r/mysql_grant.result create mode 100644 storage/connect/mysql-test/connect/r/xml_grant.result create mode 100644 storage/connect/mysql-test/connect/t/grant.test create mode 100644 storage/connect/mysql-test/connect/t/ini_grant.test create mode 100644 storage/connect/mysql-test/connect/t/mysql_grant.test create mode 100644 storage/connect/mysql-test/connect/t/xml_grant.test diff --git a/storage/connect/global.h b/storage/connect/global.h index ae50e5ac160..303078f5a18 100644 --- a/storage/connect/global.h +++ b/storage/connect/global.h @@ -239,7 +239,8 @@ DllExport short GetLineLength(PGLOBAL); // Console line length DllExport PGLOBAL PlugInit(LPCSTR, uint); // Plug global initialization DllExport int PlugExit(PGLOBAL); // Plug global termination DllExport LPSTR PlugRemoveType(LPSTR, LPCSTR); -DllExport LPCSTR PlugSetPath(LPSTR, LPCSTR, LPCSTR); +DllExport LPCSTR PlugSetPath(LPSTR to, LPCSTR prefix, LPCSTR name, LPCSTR dir); +DllExport BOOL PlugIsAbsolutePath(LPCSTR path); DllExport void *PlugAllocMem(PGLOBAL, uint); DllExport BOOL PlugSubSet(PGLOBAL, void *, uint); DllExport void *PlugSubAlloc(PGLOBAL, void *, size_t); diff --git a/storage/connect/ha_connect.cc b/storage/connect/ha_connect.cc index 7baffbb0684..3db86b8e607 100644 --- a/storage/connect/ha_connect.cc +++ b/storage/connect/ha_connect.cc @@ -289,6 +289,13 @@ static void init_connect_psi_keys() {} #endif +DllExport LPCSTR PlugSetPath(LPSTR to, LPCSTR name, LPCSTR dir) +{ + const char *res= PlugSetPath(to, mysql_data_home, name, dir); + return res; +} + + /** @brief If frm_error() is called then we will use this to determine @@ -3097,6 +3104,63 @@ THR_LOCK_DATA **ha_connect::store_lock(THD *thd, } +/** + Searches for a pointer to the last occurrence of the + character c in the string src. + Returns true on failure, false on success. +*/ +static bool +strnrchr(LEX_CSTRING *ls, const char *src, size_t length, int c) +{ + const char *srcend, *s; + for (s= srcend= src + length; s > src; s--) + { + if (s[-1] == c) + { + ls->str= s; + ls->length= srcend - s; + return false; + } + } + return true; +} + + +/** + Split filename into database and table name. +*/ +static bool +filename_to_dbname_and_tablename(const char *filename, + char *database, size_t database_size, + char *table, size_t table_size) +{ +#if defined(WIN32) + char slash= '\\'; +#else // !WIN32 + char slash= '/'; +#endif // !WIN32 + LEX_CSTRING d, t; + size_t length= strlen(filename); + + /* Find filename - the rightmost directory part */ + if (strnrchr(&t, filename, length, slash) || t.length + 1 > table_size) + return true; + memcpy(table, t.str, t.length); + table[t.length]= '\0'; + if (!(length-= t.length)) + return true; + + length--; /* Skip slash */ + + /* Find database name - the second rightmost directory part */ + if (strnrchr(&d, filename, length, slash) || d.length + 1 > database_size) + return true; + memcpy(database, d.str, d.length); + database[d.length]= '\0'; + return false; +} + + /** @brief Used to delete or rename a table. By the time delete_table() has been @@ -3123,22 +3187,20 @@ int ha_connect::delete_or_rename_table(const char *name, const char *to) DBUG_ENTER("ha_connect::delete_or_rename_table"); /* We have to retrieve the information about this table options. */ ha_table_option_struct *pos; -#if defined(WIN32) - const char *fmt= ".\\%[^\\]\\%s"; -#else // !WIN32 - const char *fmt= "./%[^/]/%s"; -#endif // !WIN32 char key[MAX_DBKEY_LENGTH], db[128], tabname[128]; int rc; uint key_length; TABLE_SHARE *share; THD *thd= current_thd; - if (to) - if (sscanf(to, fmt, db, tabname) != 2 || *tabname == '#') - goto fin; + if (to && (filename_to_dbname_and_tablename(to, db, sizeof(db), + tabname, sizeof(tabname)) || + *tabname == '#')) + goto fin; - if (sscanf(name, fmt, db, tabname) != 2 || *tabname == '#') + if (filename_to_dbname_and_tablename(name, db, sizeof(db), + tabname, sizeof(tabname)) || + *tabname == '#') goto fin; key_length= create_table_def_key(key, db, tabname); diff --git a/storage/connect/mycat.cc b/storage/connect/mycat.cc index 35a66f0d1a2..b5767b02180 100644 --- a/storage/connect/mycat.cc +++ b/storage/connect/mycat.cc @@ -293,6 +293,13 @@ void MYCAT::SetPath(PGLOBAL g, LPCSTR *datapath, const char *path) if (path) { size_t len= strlen(path) + (*path != '.' ? 4 : 1); char *buf= (char*)PlugSubAlloc(g, NULL, len); + + if (PlugIsAbsolutePath(path)) + { + strcpy(buf, path); + *datapath= buf; + return; + } if (*path != '.') { #if defined(WIN32) diff --git a/storage/connect/mysql-test/connect/r/bin.result b/storage/connect/mysql-test/connect/r/bin.result index d476aef6293..c64b270b538 100644 --- a/storage/connect/mysql-test/connect/r/bin.result +++ b/storage/connect/mysql-test/connect/r/bin.result @@ -1,98 +1,4 @@ # -# Beginning of grant.inc -# -GRANT ALL PRIVILEGES ON *.* TO user@localhost; -REVOKE FILE ON *.* FROM user@localhost; -SELECT user(); -user() -user@localhost -CREATE TABLE t1 (a INT NOT NULL) ENGINE=CONNECT TABLE_TYPE=BIN; -Warnings: -Warning 1105 No file name. Table will use t1.bin -INSERT INTO t1 VALUES (10); -SELECT * FROM t1; -a -10 -UPDATE t1 SET a=20; -SELECT * FROM t1; -a -20 -DELETE FROM t1; -SELECT * FROM t1; -a -INSERT INTO t1 VALUES(10); -TRUNCATE TABLE t1; -SELECT * FROM t1; -a -CREATE VIEW v1 AS SELECT * FROM t1; -SELECT * FROM v1; -a -DROP VIEW v1; -DROP TABLE t1; -CREATE TABLE t1 (a INT NOT NULL) ENGINE=CONNECT TABLE_TYPE=BIN FILE_NAME='t1.EXT'; -ERROR 28000: Access denied for user 'user'@'localhost' (using password: NO) -SELECT user(); -user() -root@localhost -CREATE TABLE t1 (a INT NOT NULL) ENGINE=CONNECT TABLE_TYPE=BIN FILE_NAME='t1.EXT'; -INSERT INTO t1 VALUES (10); -SELECT user(); -user() -user@localhost -INSERT INTO t1 VALUES (10); -ERROR 28000: Access denied for user 'user'@'localhost' (using password: NO) -SELECT * FROM t1; -ERROR 28000: Access denied for user 'user'@'localhost' (using password: NO) -UPDATE t1 SET a=20; -ERROR 28000: Access denied for user 'user'@'localhost' (using password: NO) -DELETE FROM t1; -ERROR 28000: Access denied for user 'user'@'localhost' (using password: NO) -TRUNCATE TABLE t1; -ERROR 28000: Access denied for user 'user'@'localhost' (using password: NO) -ALTER TABLE t1 READONLY=1; -ERROR 28000: Access denied for user 'user'@'localhost' (using password: NO) -ALTER TABLE t1 FILE_NAME='t2.EXT'; -ERROR 28000: Access denied for user 'user'@'localhost' (using password: NO) -DROP TABLE t1; -ERROR 28000: Access denied for user 'user'@'localhost' (using password: NO) -CREATE VIEW v1 AS SELECT * FROM t1; -ERROR 28000: Access denied for user 'user'@'localhost' (using password: NO) -# Testing a VIEW created with FILE privileges but accessed with no FILE -SELECT user(); -user() -root@localhost -CREATE VIEW v1 AS SELECT * FROM t1; -SELECT user(); -user() -user@localhost -SELECT * FROM v1; -ERROR 28000: Access denied for user 'user'@'localhost' (using password: NO) -INSERT INTO v1 VALUES (2); -ERROR 28000: Access denied for user 'user'@'localhost' (using password: NO) -UPDATE v1 SET a=123; -ERROR 28000: Access denied for user 'user'@'localhost' (using password: NO) -DELETE FROM v1; -ERROR 28000: Access denied for user 'user'@'localhost' (using password: NO) -SELECT user(); -user() -root@localhost -DROP VIEW v1; -DROP TABLE t1; -CREATE TABLE t1 (a INT NOT NULL) ENGINE=CONNECT TABLE_TYPE=BIN; -Warnings: -Warning 1105 No file name. Table will use t1.bin -INSERT INTO t1 VALUES (10); -SELECT user(); -user() -user@localhost -ALTER TABLE t1 FILE_NAME='t1.EXT'; -ERROR 28000: Access denied for user 'user'@'localhost' (using password: NO) -DROP TABLE t1; -DROP USER user@localhost; -# -# End of grant.inc -# -# # Testing errors # CREATE TABLE t1 diff --git a/storage/connect/mysql-test/connect/r/csv.result b/storage/connect/mysql-test/connect/r/csv.result index 34734e164c0..b2498326edb 100644 --- a/storage/connect/mysql-test/connect/r/csv.result +++ b/storage/connect/mysql-test/connect/r/csv.result @@ -1,97 +1,3 @@ -# -# Beginning of grant.inc -# -GRANT ALL PRIVILEGES ON *.* TO user@localhost; -REVOKE FILE ON *.* FROM user@localhost; -SELECT user(); -user() -user@localhost -CREATE TABLE t1 (a INT NOT NULL) ENGINE=CONNECT TABLE_TYPE=CSV; -Warnings: -Warning 1105 No file name. Table will use t1.csv -INSERT INTO t1 VALUES (10); -SELECT * FROM t1; -a -10 -UPDATE t1 SET a=20; -SELECT * FROM t1; -a -20 -DELETE FROM t1; -SELECT * FROM t1; -a -INSERT INTO t1 VALUES(10); -TRUNCATE TABLE t1; -SELECT * FROM t1; -a -CREATE VIEW v1 AS SELECT * FROM t1; -SELECT * FROM v1; -a -DROP VIEW v1; -DROP TABLE t1; -CREATE TABLE t1 (a INT NOT NULL) ENGINE=CONNECT TABLE_TYPE=CSV FILE_NAME='t1.EXT'; -ERROR 28000: Access denied for user 'user'@'localhost' (using password: NO) -SELECT user(); -user() -root@localhost -CREATE TABLE t1 (a INT NOT NULL) ENGINE=CONNECT TABLE_TYPE=CSV FILE_NAME='t1.EXT'; -INSERT INTO t1 VALUES (10); -SELECT user(); -user() -user@localhost -INSERT INTO t1 VALUES (10); -ERROR 28000: Access denied for user 'user'@'localhost' (using password: NO) -SELECT * FROM t1; -ERROR 28000: Access denied for user 'user'@'localhost' (using password: NO) -UPDATE t1 SET a=20; -ERROR 28000: Access denied for user 'user'@'localhost' (using password: NO) -DELETE FROM t1; -ERROR 28000: Access denied for user 'user'@'localhost' (using password: NO) -TRUNCATE TABLE t1; -ERROR 28000: Access denied for user 'user'@'localhost' (using password: NO) -ALTER TABLE t1 READONLY=1; -ERROR 28000: Access denied for user 'user'@'localhost' (using password: NO) -ALTER TABLE t1 FILE_NAME='t2.EXT'; -ERROR 28000: Access denied for user 'user'@'localhost' (using password: NO) -DROP TABLE t1; -ERROR 28000: Access denied for user 'user'@'localhost' (using password: NO) -CREATE VIEW v1 AS SELECT * FROM t1; -ERROR 28000: Access denied for user 'user'@'localhost' (using password: NO) -# Testing a VIEW created with FILE privileges but accessed with no FILE -SELECT user(); -user() -root@localhost -CREATE VIEW v1 AS SELECT * FROM t1; -SELECT user(); -user() -user@localhost -SELECT * FROM v1; -ERROR 28000: Access denied for user 'user'@'localhost' (using password: NO) -INSERT INTO v1 VALUES (2); -ERROR 28000: Access denied for user 'user'@'localhost' (using password: NO) -UPDATE v1 SET a=123; -ERROR 28000: Access denied for user 'user'@'localhost' (using password: NO) -DELETE FROM v1; -ERROR 28000: Access denied for user 'user'@'localhost' (using password: NO) -SELECT user(); -user() -root@localhost -DROP VIEW v1; -DROP TABLE t1; -CREATE TABLE t1 (a INT NOT NULL) ENGINE=CONNECT TABLE_TYPE=CSV; -Warnings: -Warning 1105 No file name. Table will use t1.csv -INSERT INTO t1 VALUES (10); -SELECT user(); -user() -user@localhost -ALTER TABLE t1 FILE_NAME='t1.EXT'; -ERROR 28000: Access denied for user 'user'@'localhost' (using password: NO) -DROP TABLE t1; -DROP USER user@localhost; -# -# End of grant.inc -# SET NAMES utf8; # # Testing errors diff --git a/storage/connect/mysql-test/connect/r/dbf.result b/storage/connect/mysql-test/connect/r/dbf.result index 27abbb84dc6..2e84c5b3090 100644 --- a/storage/connect/mysql-test/connect/r/dbf.result +++ b/storage/connect/mysql-test/connect/r/dbf.result @@ -1,98 +1,4 @@ # -# Beginning of grant.inc -# -GRANT ALL PRIVILEGES ON *.* TO user@localhost; -REVOKE FILE ON *.* FROM user@localhost; -SELECT user(); -user() -user@localhost -CREATE TABLE t1 (a INT NOT NULL) ENGINE=CONNECT TABLE_TYPE=DBF; -Warnings: -Warning 1105 No file name. Table will use t1.dbf -INSERT INTO t1 VALUES (10); -SELECT * FROM t1; -a -10 -UPDATE t1 SET a=20; -SELECT * FROM t1; -a -20 -DELETE FROM t1; -SELECT * FROM t1; -a -INSERT INTO t1 VALUES(10); -TRUNCATE TABLE t1; -SELECT * FROM t1; -a -CREATE VIEW v1 AS SELECT * FROM t1; -SELECT * FROM v1; -a -DROP VIEW v1; -DROP TABLE t1; -CREATE TABLE t1 (a INT NOT NULL) ENGINE=CONNECT TABLE_TYPE=DBF FILE_NAME='t1.EXT'; -ERROR 28000: Access denied for user 'user'@'localhost' (using password: NO) -SELECT user(); -user() -root@localhost -CREATE TABLE t1 (a INT NOT NULL) ENGINE=CONNECT TABLE_TYPE=DBF FILE_NAME='t1.EXT'; -INSERT INTO t1 VALUES (10); -SELECT user(); -user() -user@localhost -INSERT INTO t1 VALUES (10); -ERROR 28000: Access denied for user 'user'@'localhost' (using password: NO) -SELECT * FROM t1; -ERROR 28000: Access denied for user 'user'@'localhost' (using password: NO) -UPDATE t1 SET a=20; -ERROR 28000: Access denied for user 'user'@'localhost' (using password: NO) -DELETE FROM t1; -ERROR 28000: Access denied for user 'user'@'localhost' (using password: NO) -TRUNCATE TABLE t1; -ERROR 28000: Access denied for user 'user'@'localhost' (using password: NO) -ALTER TABLE t1 READONLY=1; -ERROR 28000: Access denied for user 'user'@'localhost' (using password: NO) -ALTER TABLE t1 FILE_NAME='t2.EXT'; -ERROR 28000: Access denied for user 'user'@'localhost' (using password: NO) -DROP TABLE t1; -ERROR 28000: Access denied for user 'user'@'localhost' (using password: NO) -CREATE VIEW v1 AS SELECT * FROM t1; -ERROR 28000: Access denied for user 'user'@'localhost' (using password: NO) -# Testing a VIEW created with FILE privileges but accessed with no FILE -SELECT user(); -user() -root@localhost -CREATE VIEW v1 AS SELECT * FROM t1; -SELECT user(); -user() -user@localhost -SELECT * FROM v1; -ERROR 28000: Access denied for user 'user'@'localhost' (using password: NO) -INSERT INTO v1 VALUES (2); -ERROR 28000: Access denied for user 'user'@'localhost' (using password: NO) -UPDATE v1 SET a=123; -ERROR 28000: Access denied for user 'user'@'localhost' (using password: NO) -DELETE FROM v1; -ERROR 28000: Access denied for user 'user'@'localhost' (using password: NO) -SELECT user(); -user() -root@localhost -DROP VIEW v1; -DROP TABLE t1; -CREATE TABLE t1 (a INT NOT NULL) ENGINE=CONNECT TABLE_TYPE=DBF; -Warnings: -Warning 1105 No file name. Table will use t1.dbf -INSERT INTO t1 VALUES (10); -SELECT user(); -user() -user@localhost -ALTER TABLE t1 FILE_NAME='t1.EXT'; -ERROR 28000: Access denied for user 'user'@'localhost' (using password: NO) -DROP TABLE t1; -DROP USER user@localhost; -# -# End of grant.inc -# -# # Testing errors # CREATE TABLE t1 (a INT NOT NULL) ENGINE=CONNECT TABLE_TYPE=DBF FILE_NAME='t1.dbf'; diff --git a/storage/connect/mysql-test/connect/r/dir.result b/storage/connect/mysql-test/connect/r/dir.result index 7beae815580..f4feb5fa960 100644 --- a/storage/connect/mysql-test/connect/r/dir.result +++ b/storage/connect/mysql-test/connect/r/dir.result @@ -1,72 +1,3 @@ -# -# Testing FILE privilege -# -GRANT ALL PRIVILEGES ON *.* TO user@localhost; -REVOKE FILE ON *.* FROM user@localhost; -SELECT user(); -user() -user@localhost -CREATE TABLE t1 ( -path VARCHAR(256) NOT NULL flag=1, -fname VARCHAR(256) NOT NULL, -ftype CHAR(4) NOT NULL, -size DOUBLE(12,0) NOT NULL flag=5 -) ENGINE=CONNECT TABLE_TYPE=DIR FILE_NAME='*.*'; -ERROR 28000: Access denied for user 'user'@'localhost' (using password: NO) -SELECT user(); -user() -root@localhost -CREATE TABLE t1 ( -path VARCHAR(256) NOT NULL flag=1, -fname VARCHAR(256) NOT NULL, -ftype CHAR(4) NOT NULL, -size DOUBLE(12,0) NOT NULL flag=5 -) ENGINE=CONNECT TABLE_TYPE=DIR FILE_NAME='*.*'; -SELECT fname, ftype, size FROM t1 WHERE size>0; -fname ftype size -t1 .frm 1081 -SELECT user(); -user() -user@localhost -SELECT * FROM t1; -ERROR 28000: Access denied for user 'user'@'localhost' (using password: NO) -INSERT INTO t1 VALUES (); -ERROR 28000: Access denied for user 'user'@'localhost' (using password: NO) -DELETE FROM t1 WHERE path='xxx'; -ERROR 28000: Access denied for user 'user'@'localhost' (using password: NO) -UPDATE t1 SET path='yyy' WHERE path='xxx'; -ERROR 28000: Access denied for user 'user'@'localhost' (using password: NO) -TRUNCATE TABLE t1; -ERROR 28000: Access denied for user 'user'@'localhost' (using password: NO) -ALTER TABLE t1 READONLY=1; -ERROR 28000: Access denied for user 'user'@'localhost' (using password: NO) -CREATE VIEW v1 AS SELECT * FROM t1; -ERROR 28000: Access denied for user 'user'@'localhost' (using password: NO) -# Testing a VIEW created with FILE privileges but accessed with no FILE -SELECT user(); -user() -root@localhost -CREATE VIEW v1 AS SELECT * FROM t1; -SELECT user(); -user() -user@localhost -SELECT * FROM v1; -ERROR 28000: Access denied for user 'user'@'localhost' (using password: NO) -INSERT INTO v1 VALUES (1,1,1,1); -ERROR 28000: Access denied for user 'user'@'localhost' (using password: NO) -UPDATE v1 SET path=123; -ERROR 28000: Access denied for user 'user'@'localhost' (using password: NO) -DELETE FROM v1; -ERROR 28000: Access denied for user 'user'@'localhost' (using password: NO) -SELECT user(); -user() -root@localhost -DROP VIEW v1; -DROP TABLE t1; -DROP USER user@localhost; -# -# Testing FILE privileges done -# CREATE TABLE t1 ( path VARCHAR(256) NOT NULL flag=1, fname VARCHAR(256) NOT NULL, diff --git a/storage/connect/mysql-test/connect/r/fix.result b/storage/connect/mysql-test/connect/r/fix.result index e9eb31d9bc8..c8f51abe961 100644 --- a/storage/connect/mysql-test/connect/r/fix.result +++ b/storage/connect/mysql-test/connect/r/fix.result @@ -1,98 +1,4 @@ # -# Beginning of grant.inc -# -GRANT ALL PRIVILEGES ON *.* TO user@localhost; -REVOKE FILE ON *.* FROM user@localhost; -SELECT user(); -user() -user@localhost -CREATE TABLE t1 (a INT NOT NULL) ENGINE=CONNECT TABLE_TYPE=FIX; -Warnings: -Warning 1105 No file name. Table will use t1.fix -INSERT INTO t1 VALUES (10); -SELECT * FROM t1; -a -10 -UPDATE t1 SET a=20; -SELECT * FROM t1; -a -20 -DELETE FROM t1; -SELECT * FROM t1; -a -INSERT INTO t1 VALUES(10); -TRUNCATE TABLE t1; -SELECT * FROM t1; -a -CREATE VIEW v1 AS SELECT * FROM t1; -SELECT * FROM v1; -a -DROP VIEW v1; -DROP TABLE t1; -CREATE TABLE t1 (a INT NOT NULL) ENGINE=CONNECT TABLE_TYPE=FIX FILE_NAME='t1.EXT'; -ERROR 28000: Access denied for user 'user'@'localhost' (using password: NO) -SELECT user(); -user() -root@localhost -CREATE TABLE t1 (a INT NOT NULL) ENGINE=CONNECT TABLE_TYPE=FIX FILE_NAME='t1.EXT'; -INSERT INTO t1 VALUES (10); -SELECT user(); -user() -user@localhost -INSERT INTO t1 VALUES (10); -ERROR 28000: Access denied for user 'user'@'localhost' (using password: NO) -SELECT * FROM t1; -ERROR 28000: Access denied for user 'user'@'localhost' (using password: NO) -UPDATE t1 SET a=20; -ERROR 28000: Access denied for user 'user'@'localhost' (using password: NO) -DELETE FROM t1; -ERROR 28000: Access denied for user 'user'@'localhost' (using password: NO) -TRUNCATE TABLE t1; -ERROR 28000: Access denied for user 'user'@'localhost' (using password: NO) -ALTER TABLE t1 READONLY=1; -ERROR 28000: Access denied for user 'user'@'localhost' (using password: NO) -ALTER TABLE t1 FILE_NAME='t2.EXT'; -ERROR 28000: Access denied for user 'user'@'localhost' (using password: NO) -DROP TABLE t1; -ERROR 28000: Access denied for user 'user'@'localhost' (using password: NO) -CREATE VIEW v1 AS SELECT * FROM t1; -ERROR 28000: Access denied for user 'user'@'localhost' (using password: NO) -# Testing a VIEW created with FILE privileges but accessed with no FILE -SELECT user(); -user() -root@localhost -CREATE VIEW v1 AS SELECT * FROM t1; -SELECT user(); -user() -user@localhost -SELECT * FROM v1; -ERROR 28000: Access denied for user 'user'@'localhost' (using password: NO) -INSERT INTO v1 VALUES (2); -ERROR 28000: Access denied for user 'user'@'localhost' (using password: NO) -UPDATE v1 SET a=123; -ERROR 28000: Access denied for user 'user'@'localhost' (using password: NO) -DELETE FROM v1; -ERROR 28000: Access denied for user 'user'@'localhost' (using password: NO) -SELECT user(); -user() -root@localhost -DROP VIEW v1; -DROP TABLE t1; -CREATE TABLE t1 (a INT NOT NULL) ENGINE=CONNECT TABLE_TYPE=FIX; -Warnings: -Warning 1105 No file name. Table will use t1.fix -INSERT INTO t1 VALUES (10); -SELECT user(); -user() -user@localhost -ALTER TABLE t1 FILE_NAME='t1.EXT'; -ERROR 28000: Access denied for user 'user'@'localhost' (using password: NO) -DROP TABLE t1; -DROP USER user@localhost; -# -# End of grant.inc -# -# # Testing errors # CREATE TABLE t1 diff --git a/storage/connect/mysql-test/connect/r/grant.result b/storage/connect/mysql-test/connect/r/grant.result new file mode 100644 index 00000000000..ba5728703a5 --- /dev/null +++ b/storage/connect/mysql-test/connect/r/grant.result @@ -0,0 +1,539 @@ +# +# Testing FILE privilege +# +GRANT ALL PRIVILEGES ON *.* TO user@localhost; +REVOKE FILE ON *.* FROM user@localhost; +SELECT user(); +user() +user@localhost +CREATE TABLE t1 ( +path VARCHAR(256) NOT NULL flag=1, +fname VARCHAR(256) NOT NULL, +ftype CHAR(4) NOT NULL, +size DOUBLE(12,0) NOT NULL flag=5 +) ENGINE=CONNECT TABLE_TYPE=DIR FILE_NAME='*.*'; +ERROR 28000: Access denied for user 'user'@'localhost' (using password: NO) +SELECT user(); +user() +root@localhost +CREATE TABLE t1 ( +path VARCHAR(256) NOT NULL flag=1, +fname VARCHAR(256) NOT NULL, +ftype CHAR(4) NOT NULL, +size DOUBLE(12,0) NOT NULL flag=5 +) ENGINE=CONNECT TABLE_TYPE=DIR FILE_NAME='*.*'; +SELECT fname, ftype, size FROM t1 WHERE size>0; +fname ftype size +t1 .frm 1081 +SELECT user(); +user() +user@localhost +SELECT * FROM t1; +ERROR 28000: Access denied for user 'user'@'localhost' (using password: NO) +INSERT INTO t1 VALUES (); +ERROR 28000: Access denied for user 'user'@'localhost' (using password: NO) +DELETE FROM t1 WHERE path='xxx'; +ERROR 28000: Access denied for user 'user'@'localhost' (using password: NO) +UPDATE t1 SET path='yyy' WHERE path='xxx'; +ERROR 28000: Access denied for user 'user'@'localhost' (using password: NO) +TRUNCATE TABLE t1; +ERROR 28000: Access denied for user 'user'@'localhost' (using password: NO) +ALTER TABLE t1 READONLY=1; +ERROR 28000: Access denied for user 'user'@'localhost' (using password: NO) +CREATE VIEW v1 AS SELECT * FROM t1; +ERROR 28000: Access denied for user 'user'@'localhost' (using password: NO) +# Testing a VIEW created with FILE privileges but accessed with no FILE +SELECT user(); +user() +root@localhost +CREATE VIEW v1 AS SELECT * FROM t1; +SELECT user(); +user() +user@localhost +SELECT * FROM v1; +ERROR 28000: Access denied for user 'user'@'localhost' (using password: NO) +INSERT INTO v1 VALUES (1,1,1,1); +ERROR 28000: Access denied for user 'user'@'localhost' (using password: NO) +UPDATE v1 SET path=123; +ERROR 28000: Access denied for user 'user'@'localhost' (using password: NO) +DELETE FROM v1; +ERROR 28000: Access denied for user 'user'@'localhost' (using password: NO) +SELECT user(); +user() +root@localhost +DROP VIEW v1; +DROP TABLE t1; +DROP USER user@localhost; +# +# Testing FILE privileges done +# +# +# Beginning of grant.inc +# +GRANT ALL PRIVILEGES ON *.* TO user@localhost; +REVOKE FILE ON *.* FROM user@localhost; +SELECT user(); +user() +user@localhost +CREATE TABLE t1 (a INT NOT NULL) ENGINE=CONNECT TABLE_TYPE=BIN; +Warnings: +Warning 1105 No file name. Table will use t1.bin +INSERT INTO t1 VALUES (10); +SELECT * FROM t1; +a +10 +UPDATE t1 SET a=20; +SELECT * FROM t1; +a +20 +DELETE FROM t1; +SELECT * FROM t1; +a +INSERT INTO t1 VALUES(10); +TRUNCATE TABLE t1; +SELECT * FROM t1; +a +CREATE VIEW v1 AS SELECT * FROM t1; +SELECT * FROM v1; +a +DROP VIEW v1; +DROP TABLE t1; +CREATE TABLE t1 (a INT NOT NULL) ENGINE=CONNECT TABLE_TYPE=BIN FILE_NAME='t1.EXT'; +ERROR 28000: Access denied for user 'user'@'localhost' (using password: NO) +SELECT user(); +user() +root@localhost +CREATE TABLE t1 (a INT NOT NULL) ENGINE=CONNECT TABLE_TYPE=BIN FILE_NAME='t1.EXT'; +INSERT INTO t1 VALUES (10); +SELECT user(); +user() +user@localhost +INSERT INTO t1 VALUES (10); +ERROR 28000: Access denied for user 'user'@'localhost' (using password: NO) +SELECT * FROM t1; +ERROR 28000: Access denied for user 'user'@'localhost' (using password: NO) +UPDATE t1 SET a=20; +ERROR 28000: Access denied for user 'user'@'localhost' (using password: NO) +DELETE FROM t1; +ERROR 28000: Access denied for user 'user'@'localhost' (using password: NO) +TRUNCATE TABLE t1; +ERROR 28000: Access denied for user 'user'@'localhost' (using password: NO) +ALTER TABLE t1 READONLY=1; +ERROR 28000: Access denied for user 'user'@'localhost' (using password: NO) +ALTER TABLE t1 FILE_NAME='t2.EXT'; +ERROR 28000: Access denied for user 'user'@'localhost' (using password: NO) +DROP TABLE t1; +ERROR 28000: Access denied for user 'user'@'localhost' (using password: NO) +CREATE VIEW v1 AS SELECT * FROM t1; +ERROR 28000: Access denied for user 'user'@'localhost' (using password: NO) +# Testing a VIEW created with FILE privileges but accessed with no FILE +SELECT user(); +user() +root@localhost +CREATE VIEW v1 AS SELECT * FROM t1; +SELECT user(); +user() +user@localhost +SELECT * FROM v1; +ERROR 28000: Access denied for user 'user'@'localhost' (using password: NO) +INSERT INTO v1 VALUES (2); +ERROR 28000: Access denied for user 'user'@'localhost' (using password: NO) +UPDATE v1 SET a=123; +ERROR 28000: Access denied for user 'user'@'localhost' (using password: NO) +DELETE FROM v1; +ERROR 28000: Access denied for user 'user'@'localhost' (using password: NO) +SELECT user(); +user() +root@localhost +DROP VIEW v1; +DROP TABLE t1; +CREATE TABLE t1 (a INT NOT NULL) ENGINE=CONNECT TABLE_TYPE=BIN; +Warnings: +Warning 1105 No file name. Table will use t1.bin +INSERT INTO t1 VALUES (10); +SELECT user(); +user() +user@localhost +ALTER TABLE t1 FILE_NAME='t1.EXT'; +ERROR 28000: Access denied for user 'user'@'localhost' (using password: NO) +DROP TABLE t1; +DROP USER user@localhost; +# +# End of grant.inc +# +# +# Beginning of grant.inc +# +GRANT ALL PRIVILEGES ON *.* TO user@localhost; +REVOKE FILE ON *.* FROM user@localhost; +SELECT user(); +user() +user@localhost +CREATE TABLE t1 (a INT NOT NULL) ENGINE=CONNECT TABLE_TYPE=CSV; +Warnings: +Warning 1105 No file name. Table will use t1.csv +INSERT INTO t1 VALUES (10); +SELECT * FROM t1; +a +10 +UPDATE t1 SET a=20; +SELECT * FROM t1; +a +20 +DELETE FROM t1; +SELECT * FROM t1; +a +INSERT INTO t1 VALUES(10); +TRUNCATE TABLE t1; +SELECT * FROM t1; +a +CREATE VIEW v1 AS SELECT * FROM t1; +SELECT * FROM v1; +a +DROP VIEW v1; +DROP TABLE t1; +CREATE TABLE t1 (a INT NOT NULL) ENGINE=CONNECT TABLE_TYPE=CSV FILE_NAME='t1.EXT'; +ERROR 28000: Access denied for user 'user'@'localhost' (using password: NO) +SELECT user(); +user() +root@localhost +CREATE TABLE t1 (a INT NOT NULL) ENGINE=CONNECT TABLE_TYPE=CSV FILE_NAME='t1.EXT'; +INSERT INTO t1 VALUES (10); +SELECT user(); +user() +user@localhost +INSERT INTO t1 VALUES (10); +ERROR 28000: Access denied for user 'user'@'localhost' (using password: NO) +SELECT * FROM t1; +ERROR 28000: Access denied for user 'user'@'localhost' (using password: NO) +UPDATE t1 SET a=20; +ERROR 28000: Access denied for user 'user'@'localhost' (using password: NO) +DELETE FROM t1; +ERROR 28000: Access denied for user 'user'@'localhost' (using password: NO) +TRUNCATE TABLE t1; +ERROR 28000: Access denied for user 'user'@'localhost' (using password: NO) +ALTER TABLE t1 READONLY=1; +ERROR 28000: Access denied for user 'user'@'localhost' (using password: NO) +ALTER TABLE t1 FILE_NAME='t2.EXT'; +ERROR 28000: Access denied for user 'user'@'localhost' (using password: NO) +DROP TABLE t1; +ERROR 28000: Access denied for user 'user'@'localhost' (using password: NO) +CREATE VIEW v1 AS SELECT * FROM t1; +ERROR 28000: Access denied for user 'user'@'localhost' (using password: NO) +# Testing a VIEW created with FILE privileges but accessed with no FILE +SELECT user(); +user() +root@localhost +CREATE VIEW v1 AS SELECT * FROM t1; +SELECT user(); +user() +user@localhost +SELECT * FROM v1; +ERROR 28000: Access denied for user 'user'@'localhost' (using password: NO) +INSERT INTO v1 VALUES (2); +ERROR 28000: Access denied for user 'user'@'localhost' (using password: NO) +UPDATE v1 SET a=123; +ERROR 28000: Access denied for user 'user'@'localhost' (using password: NO) +DELETE FROM v1; +ERROR 28000: Access denied for user 'user'@'localhost' (using password: NO) +SELECT user(); +user() +root@localhost +DROP VIEW v1; +DROP TABLE t1; +CREATE TABLE t1 (a INT NOT NULL) ENGINE=CONNECT TABLE_TYPE=CSV; +Warnings: +Warning 1105 No file name. Table will use t1.csv +INSERT INTO t1 VALUES (10); +SELECT user(); +user() +user@localhost +ALTER TABLE t1 FILE_NAME='t1.EXT'; +ERROR 28000: Access denied for user 'user'@'localhost' (using password: NO) +DROP TABLE t1; +DROP USER user@localhost; +# +# End of grant.inc +# +# +# Beginning of grant.inc +# +GRANT ALL PRIVILEGES ON *.* TO user@localhost; +REVOKE FILE ON *.* FROM user@localhost; +SELECT user(); +user() +user@localhost +CREATE TABLE t1 (a INT NOT NULL) ENGINE=CONNECT TABLE_TYPE=DBF; +Warnings: +Warning 1105 No file name. Table will use t1.dbf +INSERT INTO t1 VALUES (10); +SELECT * FROM t1; +a +10 +UPDATE t1 SET a=20; +SELECT * FROM t1; +a +20 +DELETE FROM t1; +SELECT * FROM t1; +a +INSERT INTO t1 VALUES(10); +TRUNCATE TABLE t1; +SELECT * FROM t1; +a +CREATE VIEW v1 AS SELECT * FROM t1; +SELECT * FROM v1; +a +DROP VIEW v1; +DROP TABLE t1; +CREATE TABLE t1 (a INT NOT NULL) ENGINE=CONNECT TABLE_TYPE=DBF FILE_NAME='t1.EXT'; +ERROR 28000: Access denied for user 'user'@'localhost' (using password: NO) +SELECT user(); +user() +root@localhost +CREATE TABLE t1 (a INT NOT NULL) ENGINE=CONNECT TABLE_TYPE=DBF FILE_NAME='t1.EXT'; +INSERT INTO t1 VALUES (10); +SELECT user(); +user() +user@localhost +INSERT INTO t1 VALUES (10); +ERROR 28000: Access denied for user 'user'@'localhost' (using password: NO) +SELECT * FROM t1; +ERROR 28000: Access denied for user 'user'@'localhost' (using password: NO) +UPDATE t1 SET a=20; +ERROR 28000: Access denied for user 'user'@'localhost' (using password: NO) +DELETE FROM t1; +ERROR 28000: Access denied for user 'user'@'localhost' (using password: NO) +TRUNCATE TABLE t1; +ERROR 28000: Access denied for user 'user'@'localhost' (using password: NO) +ALTER TABLE t1 READONLY=1; +ERROR 28000: Access denied for user 'user'@'localhost' (using password: NO) +ALTER TABLE t1 FILE_NAME='t2.EXT'; +ERROR 28000: Access denied for user 'user'@'localhost' (using password: NO) +DROP TABLE t1; +ERROR 28000: Access denied for user 'user'@'localhost' (using password: NO) +CREATE VIEW v1 AS SELECT * FROM t1; +ERROR 28000: Access denied for user 'user'@'localhost' (using password: NO) +# Testing a VIEW created with FILE privileges but accessed with no FILE +SELECT user(); +user() +root@localhost +CREATE VIEW v1 AS SELECT * FROM t1; +SELECT user(); +user() +user@localhost +SELECT * FROM v1; +ERROR 28000: Access denied for user 'user'@'localhost' (using password: NO) +INSERT INTO v1 VALUES (2); +ERROR 28000: Access denied for user 'user'@'localhost' (using password: NO) +UPDATE v1 SET a=123; +ERROR 28000: Access denied for user 'user'@'localhost' (using password: NO) +DELETE FROM v1; +ERROR 28000: Access denied for user 'user'@'localhost' (using password: NO) +SELECT user(); +user() +root@localhost +DROP VIEW v1; +DROP TABLE t1; +CREATE TABLE t1 (a INT NOT NULL) ENGINE=CONNECT TABLE_TYPE=DBF; +Warnings: +Warning 1105 No file name. Table will use t1.dbf +INSERT INTO t1 VALUES (10); +SELECT user(); +user() +user@localhost +ALTER TABLE t1 FILE_NAME='t1.EXT'; +ERROR 28000: Access denied for user 'user'@'localhost' (using password: NO) +DROP TABLE t1; +DROP USER user@localhost; +# +# End of grant.inc +# +# +# Beginning of grant.inc +# +GRANT ALL PRIVILEGES ON *.* TO user@localhost; +REVOKE FILE ON *.* FROM user@localhost; +SELECT user(); +user() +user@localhost +CREATE TABLE t1 (a INT NOT NULL) ENGINE=CONNECT TABLE_TYPE=FIX; +Warnings: +Warning 1105 No file name. Table will use t1.fix +INSERT INTO t1 VALUES (10); +SELECT * FROM t1; +a +10 +UPDATE t1 SET a=20; +SELECT * FROM t1; +a +20 +DELETE FROM t1; +SELECT * FROM t1; +a +INSERT INTO t1 VALUES(10); +TRUNCATE TABLE t1; +SELECT * FROM t1; +a +CREATE VIEW v1 AS SELECT * FROM t1; +SELECT * FROM v1; +a +DROP VIEW v1; +DROP TABLE t1; +CREATE TABLE t1 (a INT NOT NULL) ENGINE=CONNECT TABLE_TYPE=FIX FILE_NAME='t1.EXT'; +ERROR 28000: Access denied for user 'user'@'localhost' (using password: NO) +SELECT user(); +user() +root@localhost +CREATE TABLE t1 (a INT NOT NULL) ENGINE=CONNECT TABLE_TYPE=FIX FILE_NAME='t1.EXT'; +INSERT INTO t1 VALUES (10); +SELECT user(); +user() +user@localhost +INSERT INTO t1 VALUES (10); +ERROR 28000: Access denied for user 'user'@'localhost' (using password: NO) +SELECT * FROM t1; +ERROR 28000: Access denied for user 'user'@'localhost' (using password: NO) +UPDATE t1 SET a=20; +ERROR 28000: Access denied for user 'user'@'localhost' (using password: NO) +DELETE FROM t1; +ERROR 28000: Access denied for user 'user'@'localhost' (using password: NO) +TRUNCATE TABLE t1; +ERROR 28000: Access denied for user 'user'@'localhost' (using password: NO) +ALTER TABLE t1 READONLY=1; +ERROR 28000: Access denied for user 'user'@'localhost' (using password: NO) +ALTER TABLE t1 FILE_NAME='t2.EXT'; +ERROR 28000: Access denied for user 'user'@'localhost' (using password: NO) +DROP TABLE t1; +ERROR 28000: Access denied for user 'user'@'localhost' (using password: NO) +CREATE VIEW v1 AS SELECT * FROM t1; +ERROR 28000: Access denied for user 'user'@'localhost' (using password: NO) +# Testing a VIEW created with FILE privileges but accessed with no FILE +SELECT user(); +user() +root@localhost +CREATE VIEW v1 AS SELECT * FROM t1; +SELECT user(); +user() +user@localhost +SELECT * FROM v1; +ERROR 28000: Access denied for user 'user'@'localhost' (using password: NO) +INSERT INTO v1 VALUES (2); +ERROR 28000: Access denied for user 'user'@'localhost' (using password: NO) +UPDATE v1 SET a=123; +ERROR 28000: Access denied for user 'user'@'localhost' (using password: NO) +DELETE FROM v1; +ERROR 28000: Access denied for user 'user'@'localhost' (using password: NO) +SELECT user(); +user() +root@localhost +DROP VIEW v1; +DROP TABLE t1; +CREATE TABLE t1 (a INT NOT NULL) ENGINE=CONNECT TABLE_TYPE=FIX; +Warnings: +Warning 1105 No file name. Table will use t1.fix +INSERT INTO t1 VALUES (10); +SELECT user(); +user() +user@localhost +ALTER TABLE t1 FILE_NAME='t1.EXT'; +ERROR 28000: Access denied for user 'user'@'localhost' (using password: NO) +DROP TABLE t1; +DROP USER user@localhost; +# +# End of grant.inc +# +# +# Beginning of grant.inc +# +GRANT ALL PRIVILEGES ON *.* TO user@localhost; +REVOKE FILE ON *.* FROM user@localhost; +SELECT user(); +user() +user@localhost +CREATE TABLE t1 (a INT NOT NULL) ENGINE=CONNECT TABLE_TYPE=VEC MAX_ROWS=100; +Warnings: +Warning 1105 No file name. Table will use t1.vec +INSERT INTO t1 VALUES (10); +SELECT * FROM t1; +a +10 +UPDATE t1 SET a=20; +SELECT * FROM t1; +a +20 +DELETE FROM t1; +SELECT * FROM t1; +a +INSERT INTO t1 VALUES(10); +TRUNCATE TABLE t1; +SELECT * FROM t1; +a +CREATE VIEW v1 AS SELECT * FROM t1; +SELECT * FROM v1; +a +DROP VIEW v1; +DROP TABLE t1; +CREATE TABLE t1 (a INT NOT NULL) ENGINE=CONNECT TABLE_TYPE=VEC MAX_ROWS=100 FILE_NAME='t1.EXT'; +ERROR 28000: Access denied for user 'user'@'localhost' (using password: NO) +SELECT user(); +user() +root@localhost +CREATE TABLE t1 (a INT NOT NULL) ENGINE=CONNECT TABLE_TYPE=VEC MAX_ROWS=100 FILE_NAME='t1.EXT'; +INSERT INTO t1 VALUES (10); +SELECT user(); +user() +user@localhost +INSERT INTO t1 VALUES (10); +ERROR 28000: Access denied for user 'user'@'localhost' (using password: NO) +SELECT * FROM t1; +ERROR 28000: Access denied for user 'user'@'localhost' (using password: NO) +UPDATE t1 SET a=20; +ERROR 28000: Access denied for user 'user'@'localhost' (using password: NO) +DELETE FROM t1; +ERROR 28000: Access denied for user 'user'@'localhost' (using password: NO) +TRUNCATE TABLE t1; +ERROR 28000: Access denied for user 'user'@'localhost' (using password: NO) +ALTER TABLE t1 READONLY=1; +ERROR 28000: Access denied for user 'user'@'localhost' (using password: NO) +ALTER TABLE t1 FILE_NAME='t2.EXT'; +ERROR 28000: Access denied for user 'user'@'localhost' (using password: NO) +DROP TABLE t1; +ERROR 28000: Access denied for user 'user'@'localhost' (using password: NO) +CREATE VIEW v1 AS SELECT * FROM t1; +ERROR 28000: Access denied for user 'user'@'localhost' (using password: NO) +# Testing a VIEW created with FILE privileges but accessed with no FILE +SELECT user(); +user() +root@localhost +CREATE VIEW v1 AS SELECT * FROM t1; +SELECT user(); +user() +user@localhost +SELECT * FROM v1; +ERROR 28000: Access denied for user 'user'@'localhost' (using password: NO) +INSERT INTO v1 VALUES (2); +ERROR 28000: Access denied for user 'user'@'localhost' (using password: NO) +UPDATE v1 SET a=123; +ERROR 28000: Access denied for user 'user'@'localhost' (using password: NO) +DELETE FROM v1; +ERROR 28000: Access denied for user 'user'@'localhost' (using password: NO) +SELECT user(); +user() +root@localhost +DROP VIEW v1; +DROP TABLE t1; +CREATE TABLE t1 (a INT NOT NULL) ENGINE=CONNECT TABLE_TYPE=VEC MAX_ROWS=100; +Warnings: +Warning 1105 No file name. Table will use t1.vec +INSERT INTO t1 VALUES (10); +SELECT user(); +user() +user@localhost +ALTER TABLE t1 FILE_NAME='t1.EXT'; +ERROR 28000: Access denied for user 'user'@'localhost' (using password: NO) +DROP TABLE t1; +DROP USER user@localhost; +# +# End of grant.inc +# diff --git a/storage/connect/mysql-test/connect/r/ini.result b/storage/connect/mysql-test/connect/r/ini.result index da846d466ba..83ba98fbd84 100644 --- a/storage/connect/mysql-test/connect/r/ini.result +++ b/storage/connect/mysql-test/connect/r/ini.result @@ -1,83 +1,4 @@ # -# Checking FILE privileges -# -GRANT ALL PRIVILEGES ON *.* TO user@localhost; -REVOKE FILE ON *.* FROM user@localhost; -SELECT user(); -user() -user@localhost -CREATE TABLE t1 (sec CHAR(10) NOT NULL FLAG=1, val CHAR(10) NOT NULL) ENGINE=CONNECT TABLE_TYPE=INI; -Warnings: -Warning 1105 No file name. Table will use t1.ini -INSERT INTO t1 VALUES ('sec1','val1'); -SELECT * FROM t1; -sec val -sec1 val1 -UPDATE t1 SET val='val11'; -SELECT * FROM t1; -sec val -sec1 val11 -DELETE FROM t1; -SELECT * FROM t1; -sec val -INSERT INTO t1 VALUES('sec2','val2'); -TRUNCATE TABLE t1; -SELECT * FROM t1; -sec val -CREATE VIEW v1 AS SELECT * FROM t1; -SELECT * FROM v1; -sec val -DROP VIEW v1; -DROP TABLE t1; -CREATE TABLE t1 (sec CHAR(10) NOT NULL FLAG=1, val CHAR(10) NOT NULL) ENGINE=CONNECT TABLE_TYPE=INI FILE_NAME='t1.EXT'; -ERROR 28000: Access denied for user 'user'@'localhost' (using password: NO) -SELECT user(); -user() -root@localhost -CREATE TABLE t1 (sec CHAR(10) NOT NULL FLAG=1, val CHAR(10) NOT NULL) ENGINE=CONNECT TABLE_TYPE=INI FILE_NAME='t1.EXT'; -INSERT INTO t1 VALUES ('sec1','val1'); -SELECT user(); -user() -user@localhost -INSERT INTO t1 VALUES ('sec2','val2'); -ERROR 28000: Access denied for user 'user'@'localhost' (using password: NO) -SELECT * FROM t1; -ERROR 28000: Access denied for user 'user'@'localhost' (using password: NO) -UPDATE t1 SET val='val11'; -ERROR 28000: Access denied for user 'user'@'localhost' (using password: NO) -DELETE FROM t1; -ERROR 28000: Access denied for user 'user'@'localhost' (using password: NO) -TRUNCATE TABLE t1; -ERROR 28000: Access denied for user 'user'@'localhost' (using password: NO) -ALTER TABLE t1 READONLY=1; -ERROR 28000: Access denied for user 'user'@'localhost' (using password: NO) -DROP TABLE t1; -ERROR 28000: Access denied for user 'user'@'localhost' (using password: NO) -CREATE VIEW v1 AS SELECT * FROM t1; -ERROR 28000: Access denied for user 'user'@'localhost' (using password: NO) -# Testing a VIEW created with FILE privileges but accessed with no FILE -SELECT user(); -user() -root@localhost -CREATE VIEW v1 AS SELECT * FROM t1; -SELECT user(); -user() -user@localhost -SELECT * FROM v1; -ERROR 28000: Access denied for user 'user'@'localhost' (using password: NO) -INSERT INTO v1 VALUES ('sec3','val3'); -ERROR 28000: Access denied for user 'user'@'localhost' (using password: NO) -UPDATE v1 SET val='val11'; -ERROR 28000: Access denied for user 'user'@'localhost' (using password: NO) -DELETE FROM v1; -ERROR 28000: Access denied for user 'user'@'localhost' (using password: NO) -DROP VIEW v1; -DROP TABLE t1; -DROP USER user@localhost; -# -# Checking FILE privileges: done -# -# # Testing errors # CREATE TABLE t1 diff --git a/storage/connect/mysql-test/connect/r/ini_grant.result b/storage/connect/mysql-test/connect/r/ini_grant.result new file mode 100644 index 00000000000..c3acf7c8dfc --- /dev/null +++ b/storage/connect/mysql-test/connect/r/ini_grant.result @@ -0,0 +1,79 @@ +# +# Checking FILE privileges +# +GRANT ALL PRIVILEGES ON *.* TO user@localhost; +REVOKE FILE ON *.* FROM user@localhost; +SELECT user(); +user() +user@localhost +CREATE TABLE t1 (sec CHAR(10) NOT NULL FLAG=1, val CHAR(10) NOT NULL) ENGINE=CONNECT TABLE_TYPE=INI; +Warnings: +Warning 1105 No file name. Table will use t1.ini +INSERT INTO t1 VALUES ('sec1','val1'); +SELECT * FROM t1; +sec val +sec1 val1 +UPDATE t1 SET val='val11'; +SELECT * FROM t1; +sec val +sec1 val11 +DELETE FROM t1; +SELECT * FROM t1; +sec val +INSERT INTO t1 VALUES('sec2','val2'); +TRUNCATE TABLE t1; +SELECT * FROM t1; +sec val +CREATE VIEW v1 AS SELECT * FROM t1; +SELECT * FROM v1; +sec val +DROP VIEW v1; +DROP TABLE t1; +CREATE TABLE t1 (sec CHAR(10) NOT NULL FLAG=1, val CHAR(10) NOT NULL) ENGINE=CONNECT TABLE_TYPE=INI FILE_NAME='t1.EXT'; +ERROR 28000: Access denied for user 'user'@'localhost' (using password: NO) +SELECT user(); +user() +root@localhost +CREATE TABLE t1 (sec CHAR(10) NOT NULL FLAG=1, val CHAR(10) NOT NULL) ENGINE=CONNECT TABLE_TYPE=INI FILE_NAME='t1.EXT'; +INSERT INTO t1 VALUES ('sec1','val1'); +SELECT user(); +user() +user@localhost +INSERT INTO t1 VALUES ('sec2','val2'); +ERROR 28000: Access denied for user 'user'@'localhost' (using password: NO) +SELECT * FROM t1; +ERROR 28000: Access denied for user 'user'@'localhost' (using password: NO) +UPDATE t1 SET val='val11'; +ERROR 28000: Access denied for user 'user'@'localhost' (using password: NO) +DELETE FROM t1; +ERROR 28000: Access denied for user 'user'@'localhost' (using password: NO) +TRUNCATE TABLE t1; +ERROR 28000: Access denied for user 'user'@'localhost' (using password: NO) +ALTER TABLE t1 READONLY=1; +ERROR 28000: Access denied for user 'user'@'localhost' (using password: NO) +DROP TABLE t1; +ERROR 28000: Access denied for user 'user'@'localhost' (using password: NO) +CREATE VIEW v1 AS SELECT * FROM t1; +ERROR 28000: Access denied for user 'user'@'localhost' (using password: NO) +# Testing a VIEW created with FILE privileges but accessed with no FILE +SELECT user(); +user() +root@localhost +CREATE VIEW v1 AS SELECT * FROM t1; +SELECT user(); +user() +user@localhost +SELECT * FROM v1; +ERROR 28000: Access denied for user 'user'@'localhost' (using password: NO) +INSERT INTO v1 VALUES ('sec3','val3'); +ERROR 28000: Access denied for user 'user'@'localhost' (using password: NO) +UPDATE v1 SET val='val11'; +ERROR 28000: Access denied for user 'user'@'localhost' (using password: NO) +DELETE FROM v1; +ERROR 28000: Access denied for user 'user'@'localhost' (using password: NO) +DROP VIEW v1; +DROP TABLE t1; +DROP USER user@localhost; +# +# Checking FILE privileges: done +# diff --git a/storage/connect/mysql-test/connect/r/mysql.result b/storage/connect/mysql-test/connect/r/mysql.result index a538c57c5ce..8d5507e121a 100644 --- a/storage/connect/mysql-test/connect/r/mysql.result +++ b/storage/connect/mysql-test/connect/r/mysql.result @@ -1,66 +1,3 @@ -# -# Testing FILE privilege -# -GRANT ALL PRIVILEGES ON *.* TO user@localhost; -REVOKE FILE ON *.* FROM user@localhost; -SELECT user(); -user() -user@localhost -CREATE TABLE t1 (a INT NOT NULL) ENGINE=CONNECT TABLE_TYPE=MySQL OPTION_LIST='host=localhost,user=root1,port=PORT'; -ERROR 28000: Access denied for user 'user'@'localhost' (using password: NO) -SELECT user(); -user() -root@localhost -CREATE TABLE t1remote (a INT NOT NULL); -INSERT INTO t1remote VALUES (10),(20),(30); -CREATE TABLE t1 (a INT NOT NULL) ENGINE=CONNECT TABLE_TYPE=MySQL TABNAME=t1remote OPTION_LIST='host=localhost,user=root,port=PORT'; -SELECT * FROM t1; -a -10 -20 -30 -SELECT user(); -user() -user@localhost -SELECT * FROM t1; -ERROR 28000: Access denied for user 'user'@'localhost' (using password: NO) -INSERT INTO t1 VALUES ('xxx'); -ERROR 28000: Access denied for user 'user'@'localhost' (using password: NO) -DELETE FROM t1 WHERE a='xxx'; -ERROR 28000: Access denied for user 'user'@'localhost' (using password: NO) -UPDATE t1 SET a='yyy' WHERE a='xxx'; -ERROR 28000: Access denied for user 'user'@'localhost' (using password: NO) -TRUNCATE TABLE t1; -ERROR 28000: Access denied for user 'user'@'localhost' (using password: NO) -ALTER TABLE t1 READONLY=1; -ERROR 28000: Access denied for user 'user'@'localhost' (using password: NO) -CREATE VIEW v1 AS SELECT * FROM t1; -ERROR 28000: Access denied for user 'user'@'localhost' (using password: NO) -# Testing a VIEW created with FILE privileges but accessed with no FILE -SELECT user(); -user() -root@localhost -CREATE VIEW v1 AS SELECT * FROM t1; -SELECT user(); -user() -user@localhost -SELECT * FROM v1; -ERROR 28000: Access denied for user 'user'@'localhost' (using password: NO) -INSERT INTO v1 VALUES (2); -ERROR 28000: Access denied for user 'user'@'localhost' (using password: NO) -UPDATE v1 SET a=123; -ERROR 28000: Access denied for user 'user'@'localhost' (using password: NO) -DELETE FROM v1; -ERROR 28000: Access denied for user 'user'@'localhost' (using password: NO) -SELECT user(); -user() -root@localhost -DROP VIEW v1; -DROP TABLE t1, t1remote; -DROP USER user@localhost; -# -# Testing FILE privileges done -# CREATE TABLE t1 (a int, b char(10)); INSERT INTO t1 VALUES (NULL,NULL),(0,'test00'),(1,'test01'),(2,'test02'),(3,'test03'); SELECT * FROM t1; diff --git a/storage/connect/mysql-test/connect/r/mysql_grant.result b/storage/connect/mysql-test/connect/r/mysql_grant.result new file mode 100644 index 00000000000..f8d0ee6ad6f --- /dev/null +++ b/storage/connect/mysql-test/connect/r/mysql_grant.result @@ -0,0 +1,63 @@ +# +# Testing FILE privilege +# +GRANT ALL PRIVILEGES ON *.* TO user@localhost; +REVOKE FILE ON *.* FROM user@localhost; +SELECT user(); +user() +user@localhost +CREATE TABLE t1 (a INT NOT NULL) ENGINE=CONNECT TABLE_TYPE=MySQL OPTION_LIST='host=localhost,user=root1,port=PORT'; +ERROR 28000: Access denied for user 'user'@'localhost' (using password: NO) +SELECT user(); +user() +root@localhost +CREATE TABLE t1remote (a INT NOT NULL); +INSERT INTO t1remote VALUES (10),(20),(30); +CREATE TABLE t1 (a INT NOT NULL) ENGINE=CONNECT TABLE_TYPE=MySQL TABNAME=t1remote OPTION_LIST='host=localhost,user=root,port=PORT'; +SELECT * FROM t1; +a +10 +20 +30 +SELECT user(); +user() +user@localhost +SELECT * FROM t1; +ERROR 28000: Access denied for user 'user'@'localhost' (using password: NO) +INSERT INTO t1 VALUES ('xxx'); +ERROR 28000: Access denied for user 'user'@'localhost' (using password: NO) +DELETE FROM t1 WHERE a='xxx'; +ERROR 28000: Access denied for user 'user'@'localhost' (using password: NO) +UPDATE t1 SET a='yyy' WHERE a='xxx'; +ERROR 28000: Access denied for user 'user'@'localhost' (using password: NO) +TRUNCATE TABLE t1; +ERROR 28000: Access denied for user 'user'@'localhost' (using password: NO) +ALTER TABLE t1 READONLY=1; +ERROR 28000: Access denied for user 'user'@'localhost' (using password: NO) +CREATE VIEW v1 AS SELECT * FROM t1; +ERROR 28000: Access denied for user 'user'@'localhost' (using password: NO) +# Testing a VIEW created with FILE privileges but accessed with no FILE +SELECT user(); +user() +root@localhost +CREATE VIEW v1 AS SELECT * FROM t1; +SELECT user(); +user() +user@localhost +SELECT * FROM v1; +ERROR 28000: Access denied for user 'user'@'localhost' (using password: NO) +INSERT INTO v1 VALUES (2); +ERROR 28000: Access denied for user 'user'@'localhost' (using password: NO) +UPDATE v1 SET a=123; +ERROR 28000: Access denied for user 'user'@'localhost' (using password: NO) +DELETE FROM v1; +ERROR 28000: Access denied for user 'user'@'localhost' (using password: NO) +SELECT user(); +user() +root@localhost +DROP VIEW v1; +DROP TABLE t1, t1remote; +DROP USER user@localhost; +# +# Testing FILE privileges done +# diff --git a/storage/connect/mysql-test/connect/r/vec.result b/storage/connect/mysql-test/connect/r/vec.result index 9461966aef7..65513dc07db 100644 --- a/storage/connect/mysql-test/connect/r/vec.result +++ b/storage/connect/mysql-test/connect/r/vec.result @@ -1,97 +1,3 @@ -# -# Beginning of grant.inc -# -GRANT ALL PRIVILEGES ON *.* TO user@localhost; -REVOKE FILE ON *.* FROM user@localhost; -SELECT user(); -user() -user@localhost -CREATE TABLE t1 (a INT NOT NULL) ENGINE=CONNECT TABLE_TYPE=VEC MAX_ROWS=100; -Warnings: -Warning 1105 No file name. Table will use t1.vec -INSERT INTO t1 VALUES (10); -SELECT * FROM t1; -a -10 -UPDATE t1 SET a=20; -SELECT * FROM t1; -a -20 -DELETE FROM t1; -SELECT * FROM t1; -a -INSERT INTO t1 VALUES(10); -TRUNCATE TABLE t1; -SELECT * FROM t1; -a -CREATE VIEW v1 AS SELECT * FROM t1; -SELECT * FROM v1; -a -DROP VIEW v1; -DROP TABLE t1; -CREATE TABLE t1 (a INT NOT NULL) ENGINE=CONNECT TABLE_TYPE=VEC MAX_ROWS=100 FILE_NAME='t1.EXT'; -ERROR 28000: Access denied for user 'user'@'localhost' (using password: NO) -SELECT user(); -user() -root@localhost -CREATE TABLE t1 (a INT NOT NULL) ENGINE=CONNECT TABLE_TYPE=VEC MAX_ROWS=100 FILE_NAME='t1.EXT'; -INSERT INTO t1 VALUES (10); -SELECT user(); -user() -user@localhost -INSERT INTO t1 VALUES (10); -ERROR 28000: Access denied for user 'user'@'localhost' (using password: NO) -SELECT * FROM t1; -ERROR 28000: Access denied for user 'user'@'localhost' (using password: NO) -UPDATE t1 SET a=20; -ERROR 28000: Access denied for user 'user'@'localhost' (using password: NO) -DELETE FROM t1; -ERROR 28000: Access denied for user 'user'@'localhost' (using password: NO) -TRUNCATE TABLE t1; -ERROR 28000: Access denied for user 'user'@'localhost' (using password: NO) -ALTER TABLE t1 READONLY=1; -ERROR 28000: Access denied for user 'user'@'localhost' (using password: NO) -ALTER TABLE t1 FILE_NAME='t2.EXT'; -ERROR 28000: Access denied for user 'user'@'localhost' (using password: NO) -DROP TABLE t1; -ERROR 28000: Access denied for user 'user'@'localhost' (using password: NO) -CREATE VIEW v1 AS SELECT * FROM t1; -ERROR 28000: Access denied for user 'user'@'localhost' (using password: NO) -# Testing a VIEW created with FILE privileges but accessed with no FILE -SELECT user(); -user() -root@localhost -CREATE VIEW v1 AS SELECT * FROM t1; -SELECT user(); -user() -user@localhost -SELECT * FROM v1; -ERROR 28000: Access denied for user 'user'@'localhost' (using password: NO) -INSERT INTO v1 VALUES (2); -ERROR 28000: Access denied for user 'user'@'localhost' (using password: NO) -UPDATE v1 SET a=123; -ERROR 28000: Access denied for user 'user'@'localhost' (using password: NO) -DELETE FROM v1; -ERROR 28000: Access denied for user 'user'@'localhost' (using password: NO) -SELECT user(); -user() -root@localhost -DROP VIEW v1; -DROP TABLE t1; -CREATE TABLE t1 (a INT NOT NULL) ENGINE=CONNECT TABLE_TYPE=VEC MAX_ROWS=100; -Warnings: -Warning 1105 No file name. Table will use t1.vec -INSERT INTO t1 VALUES (10); -SELECT user(); -user() -user@localhost -ALTER TABLE t1 FILE_NAME='t1.EXT'; -ERROR 28000: Access denied for user 'user'@'localhost' (using password: NO) -DROP TABLE t1; -DROP USER user@localhost; -# -# End of grant.inc -# CREATE TABLE dir1 ( spath VARCHAR(256) NOT NULL flag=1, fname VARCHAR(256) NOT NULL, diff --git a/storage/connect/mysql-test/connect/r/xml.result b/storage/connect/mysql-test/connect/r/xml.result index 554039dc3f1..44fab646dcf 100644 --- a/storage/connect/mysql-test/connect/r/xml.result +++ b/storage/connect/mysql-test/connect/r/xml.result @@ -1,99 +1,5 @@ Warnings: Warning 1105 No file name. Table will use t1.xml -# -# Beginning of grant.inc -# -GRANT ALL PRIVILEGES ON *.* TO user@localhost; -REVOKE FILE ON *.* FROM user@localhost; -SELECT user(); -user() -user@localhost -CREATE TABLE t1 (a INT NOT NULL) ENGINE=CONNECT TABLE_TYPE=XML OPTION_LIST='xmlsup=libxml2,rownode=row'; -Warnings: -Warning 1105 No file name. Table will use t1.xml -INSERT INTO t1 VALUES (10); -SELECT * FROM t1; -a -10 -UPDATE t1 SET a=20; -SELECT * FROM t1; -a -20 -DELETE FROM t1; -SELECT * FROM t1; -a -INSERT INTO t1 VALUES(10); -TRUNCATE TABLE t1; -SELECT * FROM t1; -a -CREATE VIEW v1 AS SELECT * FROM t1; -SELECT * FROM v1; -a -DROP VIEW v1; -DROP TABLE t1; -CREATE TABLE t1 (a INT NOT NULL) ENGINE=CONNECT TABLE_TYPE=XML OPTION_LIST='xmlsup=libxml2,rownode=row' FILE_NAME='t1.EXT'; -ERROR 28000: Access denied for user 'user'@'localhost' (using password: NO) -SELECT user(); -user() -root@localhost -CREATE TABLE t1 (a INT NOT NULL) ENGINE=CONNECT TABLE_TYPE=XML OPTION_LIST='xmlsup=libxml2,rownode=row' FILE_NAME='t1.EXT'; -INSERT INTO t1 VALUES (10); -SELECT user(); -user() -user@localhost -INSERT INTO t1 VALUES (10); -ERROR 28000: Access denied for user 'user'@'localhost' (using password: NO) -SELECT * FROM t1; -ERROR 28000: Access denied for user 'user'@'localhost' (using password: NO) -UPDATE t1 SET a=20; -ERROR 28000: Access denied for user 'user'@'localhost' (using password: NO) -DELETE FROM t1; -ERROR 28000: Access denied for user 'user'@'localhost' (using password: NO) -TRUNCATE TABLE t1; -ERROR 28000: Access denied for user 'user'@'localhost' (using password: NO) -ALTER TABLE t1 READONLY=1; -ERROR 28000: Access denied for user 'user'@'localhost' (using password: NO) -ALTER TABLE t1 FILE_NAME='t2.EXT'; -ERROR 28000: Access denied for user 'user'@'localhost' (using password: NO) -DROP TABLE t1; -ERROR 28000: Access denied for user 'user'@'localhost' (using password: NO) -CREATE VIEW v1 AS SELECT * FROM t1; -ERROR 28000: Access denied for user 'user'@'localhost' (using password: NO) -# Testing a VIEW created with FILE privileges but accessed with no FILE -SELECT user(); -user() -root@localhost -CREATE VIEW v1 AS SELECT * FROM t1; -SELECT user(); -user() -user@localhost -SELECT * FROM v1; -ERROR 28000: Access denied for user 'user'@'localhost' (using password: NO) -INSERT INTO v1 VALUES (2); -ERROR 28000: Access denied for user 'user'@'localhost' (using password: NO) -UPDATE v1 SET a=123; -ERROR 28000: Access denied for user 'user'@'localhost' (using password: NO) -DELETE FROM v1; -ERROR 28000: Access denied for user 'user'@'localhost' (using password: NO) -SELECT user(); -user() -root@localhost -DROP VIEW v1; -DROP TABLE t1; -CREATE TABLE t1 (a INT NOT NULL) ENGINE=CONNECT TABLE_TYPE=XML OPTION_LIST='xmlsup=libxml2,rownode=row'; -Warnings: -Warning 1105 No file name. Table will use t1.xml -INSERT INTO t1 VALUES (10); -SELECT user(); -user() -user@localhost -ALTER TABLE t1 FILE_NAME='t1.EXT'; -ERROR 28000: Access denied for user 'user'@'localhost' (using password: NO) -DROP TABLE t1; -DROP USER user@localhost; -# -# End of grant.inc -# SET NAMES utf8; # # Testing tag values @@ -253,8 +159,8 @@ TITLE XML, Langage et Applications TRANSLATOR NULL PUBLISHER Eyrolles Paris DATEPUB 1998 -SELECT LOAD_FILE('test/xsample2.xml'); -LOAD_FILE('test/xsample2.xml') +SELECT LOAD_FILE('MYSQLD_DATADIR/test/xsample2.xml') AS xml; +xml @@ -467,7 +373,7 @@ SELECT node, hex(node) FROM t1; node ÀÁÂÃ hex(node) C0C1C2C3 DROP TABLE t1; -SET @a=LOAD_FILE('test/t1.xml'); +SET @a=LOAD_FILE('MYSQLD_DATADIR/test/t1.xml'); SELECT LEFT(@a,38); LEFT(@a,38) SELECT HEX(EXTRACTVALUE(@a,'/t1/line/node')); @@ -481,7 +387,7 @@ SELECT node, hex(node) FROM t1; node ÀÁÂÃ hex(node) C0C1C2C3 DROP TABLE t1; -SET @a=LOAD_FILE('test/t1.xml'); +SET @a=LOAD_FILE('MYSQLD_DATADIR/test/t1.xml'); SELECT LEFT(@a,43); LEFT(@a,43) SELECT HEX(EXTRACTVALUE(@a,'/t1/line/node')); @@ -504,7 +410,7 @@ hex(node) D090D091D092D093 node &<>"' hex(node) 263C3E2227 DROP TABLE t1; -SET @a=LOAD_FILE('test/t1.xml'); +SET @a=LOAD_FILE('MYSQLD_DATADIR/test/t1.xml'); SELECT CAST(@a AS CHAR CHARACTER SET latin1); CAST(@a AS CHAR CHARACTER SET latin1) diff --git a/storage/connect/mysql-test/connect/r/xml_grant.result b/storage/connect/mysql-test/connect/r/xml_grant.result new file mode 100644 index 00000000000..ea38e57af86 --- /dev/null +++ b/storage/connect/mysql-test/connect/r/xml_grant.result @@ -0,0 +1,96 @@ +Warnings: +Warning 1105 No file name. Table will use t1.xml +# +# Beginning of grant.inc +# +GRANT ALL PRIVILEGES ON *.* TO user@localhost; +REVOKE FILE ON *.* FROM user@localhost; +SELECT user(); +user() +user@localhost +CREATE TABLE t1 (a INT NOT NULL) ENGINE=CONNECT TABLE_TYPE=XML OPTION_LIST='xmlsup=libxml2,rownode=row'; +Warnings: +Warning 1105 No file name. Table will use t1.xml +INSERT INTO t1 VALUES (10); +SELECT * FROM t1; +a +10 +UPDATE t1 SET a=20; +SELECT * FROM t1; +a +20 +DELETE FROM t1; +SELECT * FROM t1; +a +INSERT INTO t1 VALUES(10); +TRUNCATE TABLE t1; +SELECT * FROM t1; +a +CREATE VIEW v1 AS SELECT * FROM t1; +SELECT * FROM v1; +a +DROP VIEW v1; +DROP TABLE t1; +CREATE TABLE t1 (a INT NOT NULL) ENGINE=CONNECT TABLE_TYPE=XML OPTION_LIST='xmlsup=libxml2,rownode=row' FILE_NAME='t1.EXT'; +ERROR 28000: Access denied for user 'user'@'localhost' (using password: NO) +SELECT user(); +user() +root@localhost +CREATE TABLE t1 (a INT NOT NULL) ENGINE=CONNECT TABLE_TYPE=XML OPTION_LIST='xmlsup=libxml2,rownode=row' FILE_NAME='t1.EXT'; +INSERT INTO t1 VALUES (10); +SELECT user(); +user() +user@localhost +INSERT INTO t1 VALUES (10); +ERROR 28000: Access denied for user 'user'@'localhost' (using password: NO) +SELECT * FROM t1; +ERROR 28000: Access denied for user 'user'@'localhost' (using password: NO) +UPDATE t1 SET a=20; +ERROR 28000: Access denied for user 'user'@'localhost' (using password: NO) +DELETE FROM t1; +ERROR 28000: Access denied for user 'user'@'localhost' (using password: NO) +TRUNCATE TABLE t1; +ERROR 28000: Access denied for user 'user'@'localhost' (using password: NO) +ALTER TABLE t1 READONLY=1; +ERROR 28000: Access denied for user 'user'@'localhost' (using password: NO) +ALTER TABLE t1 FILE_NAME='t2.EXT'; +ERROR 28000: Access denied for user 'user'@'localhost' (using password: NO) +DROP TABLE t1; +ERROR 28000: Access denied for user 'user'@'localhost' (using password: NO) +CREATE VIEW v1 AS SELECT * FROM t1; +ERROR 28000: Access denied for user 'user'@'localhost' (using password: NO) +# Testing a VIEW created with FILE privileges but accessed with no FILE +SELECT user(); +user() +root@localhost +CREATE VIEW v1 AS SELECT * FROM t1; +SELECT user(); +user() +user@localhost +SELECT * FROM v1; +ERROR 28000: Access denied for user 'user'@'localhost' (using password: NO) +INSERT INTO v1 VALUES (2); +ERROR 28000: Access denied for user 'user'@'localhost' (using password: NO) +UPDATE v1 SET a=123; +ERROR 28000: Access denied for user 'user'@'localhost' (using password: NO) +DELETE FROM v1; +ERROR 28000: Access denied for user 'user'@'localhost' (using password: NO) +SELECT user(); +user() +root@localhost +DROP VIEW v1; +DROP TABLE t1; +CREATE TABLE t1 (a INT NOT NULL) ENGINE=CONNECT TABLE_TYPE=XML OPTION_LIST='xmlsup=libxml2,rownode=row'; +Warnings: +Warning 1105 No file name. Table will use t1.xml +INSERT INTO t1 VALUES (10); +SELECT user(); +user() +user@localhost +ALTER TABLE t1 FILE_NAME='t1.EXT'; +ERROR 28000: Access denied for user 'user'@'localhost' (using password: NO) +DROP TABLE t1; +DROP USER user@localhost; +# +# End of grant.inc +# diff --git a/storage/connect/mysql-test/connect/t/bin.test b/storage/connect/mysql-test/connect/t/bin.test index 0266fd3e357..a9dab32987e 100644 --- a/storage/connect/mysql-test/connect/t/bin.test +++ b/storage/connect/mysql-test/connect/t/bin.test @@ -1,9 +1,5 @@ let $MYSQLD_DATADIR= `select @@datadir`; -let $TABLE_OPTIONS=TABLE_TYPE=BIN; -let $FILE_EXT=BIN; ---source grant.inc - --copy_file $MTR_SUITE_DIR/std_data/Testbal.dat $MYSQLD_DATADIR/test/Testbal.dat --echo # diff --git a/storage/connect/mysql-test/connect/t/csv.test b/storage/connect/mysql-test/connect/t/csv.test index 6578ba83a9a..685ac434df7 100644 --- a/storage/connect/mysql-test/connect/t/csv.test +++ b/storage/connect/mysql-test/connect/t/csv.test @@ -1,9 +1,5 @@ let $MYSQLD_DATADIR= `select @@datadir`; -let $TABLE_OPTIONS=TABLE_TYPE=CSV; -let $FILE_EXT=CSV; ---source grant.inc - --copy_file $MTR_SUITE_DIR/std_data/people.csv $MYSQLD_DATADIR/test/people.csv SET NAMES utf8; diff --git a/storage/connect/mysql-test/connect/t/dbf.test b/storage/connect/mysql-test/connect/t/dbf.test index fb0bc21f52d..b9a1b6e2183 100644 --- a/storage/connect/mysql-test/connect/t/dbf.test +++ b/storage/connect/mysql-test/connect/t/dbf.test @@ -1,9 +1,5 @@ let $MYSQLD_DATADIR= `select @@datadir`; -let $TABLE_OPTIONS=TABLE_TYPE=DBF; -let $FILE_EXT=DBF; ---source grant.inc - --echo # --echo # Testing errors --echo # diff --git a/storage/connect/mysql-test/connect/t/dir.test b/storage/connect/mysql-test/connect/t/dir.test index 073cdaa380b..fb69813d9f0 100644 --- a/storage/connect/mysql-test/connect/t/dir.test +++ b/storage/connect/mysql-test/connect/t/dir.test @@ -1,76 +1,6 @@ let $MYSQLD_DATADIR= `select @@datadir`; ---echo # ---echo # Testing FILE privilege ---echo # -GRANT ALL PRIVILEGES ON *.* TO user@localhost; -REVOKE FILE ON *.* FROM user@localhost; ---connect(user,localhost,user,,) ---connection user -SELECT user(); ---error ER_ACCESS_DENIED_ERROR -CREATE TABLE t1 ( - path VARCHAR(256) NOT NULL flag=1, - fname VARCHAR(256) NOT NULL, - ftype CHAR(4) NOT NULL, - size DOUBLE(12,0) NOT NULL flag=5 -) ENGINE=CONNECT TABLE_TYPE=DIR FILE_NAME='*.*'; ---connection default -SELECT user(); -CREATE TABLE t1 ( - path VARCHAR(256) NOT NULL flag=1, - fname VARCHAR(256) NOT NULL, - ftype CHAR(4) NOT NULL, - size DOUBLE(12,0) NOT NULL flag=5 -) ENGINE=CONNECT TABLE_TYPE=DIR FILE_NAME='*.*'; -# "size>0" to skip directory names on Windows ---replace_result $MYSQLD_DATADIR DATADIR/ -SELECT fname, ftype, size FROM t1 WHERE size>0; - ---connection user -SELECT user(); ---error ER_ACCESS_DENIED_ERROR -SELECT * FROM t1; ---error ER_ACCESS_DENIED_ERROR -INSERT INTO t1 VALUES (); ---error ER_ACCESS_DENIED_ERROR -DELETE FROM t1 WHERE path='xxx'; ---error ER_ACCESS_DENIED_ERROR -UPDATE t1 SET path='yyy' WHERE path='xxx'; ---error ER_ACCESS_DENIED_ERROR -TRUNCATE TABLE t1; ---error ER_ACCESS_DENIED_ERROR -ALTER TABLE t1 READONLY=1; ---error ER_ACCESS_DENIED_ERROR -CREATE VIEW v1 AS SELECT * FROM t1; - ---echo # Testing a VIEW created with FILE privileges but accessed with no FILE ---connection default -SELECT user(); -CREATE VIEW v1 AS SELECT * FROM t1; ---connection user -SELECT user(); ---error ER_ACCESS_DENIED_ERROR -SELECT * FROM v1; ---error ER_ACCESS_DENIED_ERROR -INSERT INTO v1 VALUES (1,1,1,1); ---error ER_ACCESS_DENIED_ERROR -UPDATE v1 SET path=123; ---error ER_ACCESS_DENIED_ERROR -DELETE FROM v1; - ---disconnect user ---connection default -SELECT user(); -DROP VIEW v1; -DROP TABLE t1; -DROP USER user@localhost; ---echo # ---echo # Testing FILE privileges done ---echo # - - CREATE TABLE t1 ( path VARCHAR(256) NOT NULL flag=1, fname VARCHAR(256) NOT NULL, diff --git a/storage/connect/mysql-test/connect/t/fix.test b/storage/connect/mysql-test/connect/t/fix.test index d2dfeb21352..c3cec55a217 100644 --- a/storage/connect/mysql-test/connect/t/fix.test +++ b/storage/connect/mysql-test/connect/t/fix.test @@ -1,9 +1,5 @@ let $MYSQLD_DATADIR= `select @@datadir`; -let $TABLE_OPTIONS=TABLE_TYPE=FIX; -let $FILE_EXT=FIX; ---source grant.inc - --copy_file $MTR_SUITE_DIR/std_data/dept.dat $MYSQLD_DATADIR/test/dept.dat --copy_file $MTR_SUITE_DIR/std_data/boys.txt $MYSQLD_DATADIR/test/boys.txt --copy_file $MTR_SUITE_DIR/std_data/boyswin.txt $MYSQLD_DATADIR/test/boyswin.txt diff --git a/storage/connect/mysql-test/connect/t/grant.test b/storage/connect/mysql-test/connect/t/grant.test new file mode 100644 index 00000000000..909bb4117a1 --- /dev/null +++ b/storage/connect/mysql-test/connect/t/grant.test @@ -0,0 +1,95 @@ +-- source include/not_embedded.inc + +let $MYSQLD_DATADIR= `select @@datadir`; + +--echo # +--echo # Testing FILE privilege +--echo # +GRANT ALL PRIVILEGES ON *.* TO user@localhost; +REVOKE FILE ON *.* FROM user@localhost; +--connect(user,localhost,user,,) +--connection user +SELECT user(); +--error ER_ACCESS_DENIED_ERROR +CREATE TABLE t1 ( + path VARCHAR(256) NOT NULL flag=1, + fname VARCHAR(256) NOT NULL, + ftype CHAR(4) NOT NULL, + size DOUBLE(12,0) NOT NULL flag=5 +) ENGINE=CONNECT TABLE_TYPE=DIR FILE_NAME='*.*'; +--connection default +SELECT user(); +CREATE TABLE t1 ( + path VARCHAR(256) NOT NULL flag=1, + fname VARCHAR(256) NOT NULL, + ftype CHAR(4) NOT NULL, + size DOUBLE(12,0) NOT NULL flag=5 +) ENGINE=CONNECT TABLE_TYPE=DIR FILE_NAME='*.*'; +# "size>0" to skip directory names on Windows +--replace_result $MYSQLD_DATADIR DATADIR/ +SELECT fname, ftype, size FROM t1 WHERE size>0; + +--connection user +SELECT user(); +--error ER_ACCESS_DENIED_ERROR +SELECT * FROM t1; +--error ER_ACCESS_DENIED_ERROR +INSERT INTO t1 VALUES (); +--error ER_ACCESS_DENIED_ERROR +DELETE FROM t1 WHERE path='xxx'; +--error ER_ACCESS_DENIED_ERROR +UPDATE t1 SET path='yyy' WHERE path='xxx'; +--error ER_ACCESS_DENIED_ERROR +TRUNCATE TABLE t1; +--error ER_ACCESS_DENIED_ERROR +ALTER TABLE t1 READONLY=1; +--error ER_ACCESS_DENIED_ERROR +CREATE VIEW v1 AS SELECT * FROM t1; + +--echo # Testing a VIEW created with FILE privileges but accessed with no FILE +--connection default +SELECT user(); +CREATE VIEW v1 AS SELECT * FROM t1; +--connection user +SELECT user(); +--error ER_ACCESS_DENIED_ERROR +SELECT * FROM v1; +--error ER_ACCESS_DENIED_ERROR +INSERT INTO v1 VALUES (1,1,1,1); +--error ER_ACCESS_DENIED_ERROR +UPDATE v1 SET path=123; +--error ER_ACCESS_DENIED_ERROR +DELETE FROM v1; + +--disconnect user +--connection default +SELECT user(); +DROP VIEW v1; +DROP TABLE t1; +DROP USER user@localhost; +--echo # +--echo # Testing FILE privileges done +--echo # + + +let $TABLE_OPTIONS=TABLE_TYPE=BIN; +let $FILE_EXT=BIN; +--source grant.inc + +let $TABLE_OPTIONS=TABLE_TYPE=CSV; +let $FILE_EXT=CSV; +--source grant.inc + +let $TABLE_OPTIONS=TABLE_TYPE=DBF; +let $FILE_EXT=DBF; +--source grant.inc + +let $TABLE_OPTIONS=TABLE_TYPE=FIX; +let $FILE_EXT=FIX; +--source grant.inc + +let $TABLE_OPTIONS=TABLE_TYPE=VEC MAX_ROWS=100; +let $FILE_EXT=VEC; +--source grant.inc + + diff --git a/storage/connect/mysql-test/connect/t/ini.test b/storage/connect/mysql-test/connect/t/ini.test index e862f3cd672..0d23142ac9e 100644 --- a/storage/connect/mysql-test/connect/t/ini.test +++ b/storage/connect/mysql-test/connect/t/ini.test @@ -1,80 +1,5 @@ let $MYSQLD_DATADIR= `select @@datadir`; ---echo # ---echo # Checking FILE privileges ---echo # -GRANT ALL PRIVILEGES ON *.* TO user@localhost; -REVOKE FILE ON *.* FROM user@localhost; ---connect(user,localhost,user,,) ---connection user -SELECT user(); -CREATE TABLE t1 (sec CHAR(10) NOT NULL FLAG=1, val CHAR(10) NOT NULL) ENGINE=CONNECT TABLE_TYPE=INI; -INSERT INTO t1 VALUES ('sec1','val1'); -SELECT * FROM t1; -UPDATE t1 SET val='val11'; -SELECT * FROM t1; -DELETE FROM t1; -SELECT * FROM t1; -INSERT INTO t1 VALUES('sec2','val2'); -TRUNCATE TABLE t1; -SELECT * FROM t1; -CREATE VIEW v1 AS SELECT * FROM t1; -SELECT * FROM v1; -DROP VIEW v1; -DROP TABLE t1; -# Making sure DROP erased the data file ---error 1 ---remove_file $MYSQLD_DATADIR/test/t1.ini ---error ER_ACCESS_DENIED_ERROR -CREATE TABLE t1 (sec CHAR(10) NOT NULL FLAG=1, val CHAR(10) NOT NULL) ENGINE=CONNECT TABLE_TYPE=INI FILE_NAME='t1.EXT'; ---connection default -SELECT user(); -CREATE TABLE t1 (sec CHAR(10) NOT NULL FLAG=1, val CHAR(10) NOT NULL) ENGINE=CONNECT TABLE_TYPE=INI FILE_NAME='t1.EXT'; -INSERT INTO t1 VALUES ('sec1','val1'); ---connection user -SELECT user(); ---error ER_ACCESS_DENIED_ERROR -INSERT INTO t1 VALUES ('sec2','val2'); ---error ER_ACCESS_DENIED_ERROR -SELECT * FROM t1; ---error ER_ACCESS_DENIED_ERROR -UPDATE t1 SET val='val11'; ---error ER_ACCESS_DENIED_ERROR -DELETE FROM t1; ---error ER_ACCESS_DENIED_ERROR -TRUNCATE TABLE t1; ---error ER_ACCESS_DENIED_ERROR -ALTER TABLE t1 READONLY=1; ---error ER_ACCESS_DENIED_ERROR -DROP TABLE t1; ---error ER_ACCESS_DENIED_ERROR -CREATE VIEW v1 AS SELECT * FROM t1; ---echo # Testing a VIEW created with FILE privileges but accessed with no FILE ---connection default -SELECT user(); -CREATE VIEW v1 AS SELECT * FROM t1; ---connection user -SELECT user(); ---error ER_ACCESS_DENIED_ERROR -SELECT * FROM v1; ---error ER_ACCESS_DENIED_ERROR -INSERT INTO v1 VALUES ('sec3','val3'); ---error ER_ACCESS_DENIED_ERROR -UPDATE v1 SET val='val11'; ---error ER_ACCESS_DENIED_ERROR -DELETE FROM v1; ---disconnect user ---connection default -DROP VIEW v1; -DROP TABLE t1; ---remove_file $MYSQLD_DATADIR/test/t1.EXT -DROP USER user@localhost; - ---echo # ---echo # Checking FILE privileges: done ---echo # - - --copy_file $MTR_SUITE_DIR/std_data/contact.ini $MYSQLD_DATADIR/test/contact.ini --echo # diff --git a/storage/connect/mysql-test/connect/t/ini_grant.test b/storage/connect/mysql-test/connect/t/ini_grant.test new file mode 100644 index 00000000000..30678645692 --- /dev/null +++ b/storage/connect/mysql-test/connect/t/ini_grant.test @@ -0,0 +1,79 @@ +-- source include/not_embedded.inc + +let $MYSQLD_DATADIR= `select @@datadir`; + +--echo # +--echo # Checking FILE privileges +--echo # +GRANT ALL PRIVILEGES ON *.* TO user@localhost; +REVOKE FILE ON *.* FROM user@localhost; +--connect(user,localhost,user,,) +--connection user +SELECT user(); +CREATE TABLE t1 (sec CHAR(10) NOT NULL FLAG=1, val CHAR(10) NOT NULL) ENGINE=CONNECT TABLE_TYPE=INI; +INSERT INTO t1 VALUES ('sec1','val1'); +SELECT * FROM t1; +UPDATE t1 SET val='val11'; +SELECT * FROM t1; +DELETE FROM t1; +SELECT * FROM t1; +INSERT INTO t1 VALUES('sec2','val2'); +TRUNCATE TABLE t1; +SELECT * FROM t1; +CREATE VIEW v1 AS SELECT * FROM t1; +SELECT * FROM v1; +DROP VIEW v1; +DROP TABLE t1; +# Making sure DROP erased the data file +--error 1 +--remove_file $MYSQLD_DATADIR/test/t1.ini +--error ER_ACCESS_DENIED_ERROR +CREATE TABLE t1 (sec CHAR(10) NOT NULL FLAG=1, val CHAR(10) NOT NULL) ENGINE=CONNECT TABLE_TYPE=INI FILE_NAME='t1.EXT'; +--connection default +SELECT user(); +CREATE TABLE t1 (sec CHAR(10) NOT NULL FLAG=1, val CHAR(10) NOT NULL) ENGINE=CONNECT TABLE_TYPE=INI FILE_NAME='t1.EXT'; +INSERT INTO t1 VALUES ('sec1','val1'); +--connection user +SELECT user(); +--error ER_ACCESS_DENIED_ERROR +INSERT INTO t1 VALUES ('sec2','val2'); +--error ER_ACCESS_DENIED_ERROR +SELECT * FROM t1; +--error ER_ACCESS_DENIED_ERROR +UPDATE t1 SET val='val11'; +--error ER_ACCESS_DENIED_ERROR +DELETE FROM t1; +--error ER_ACCESS_DENIED_ERROR +TRUNCATE TABLE t1; +--error ER_ACCESS_DENIED_ERROR +ALTER TABLE t1 READONLY=1; +--error ER_ACCESS_DENIED_ERROR +DROP TABLE t1; +--error ER_ACCESS_DENIED_ERROR +CREATE VIEW v1 AS SELECT * FROM t1; +--echo # Testing a VIEW created with FILE privileges but accessed with no FILE +--connection default +SELECT user(); +CREATE VIEW v1 AS SELECT * FROM t1; +--connection user +SELECT user(); +--error ER_ACCESS_DENIED_ERROR +SELECT * FROM v1; +--error ER_ACCESS_DENIED_ERROR +INSERT INTO v1 VALUES ('sec3','val3'); +--error ER_ACCESS_DENIED_ERROR +UPDATE v1 SET val='val11'; +--error ER_ACCESS_DENIED_ERROR +DELETE FROM v1; +--disconnect user +--connection default +DROP VIEW v1; +DROP TABLE t1; +--remove_file $MYSQLD_DATADIR/test/t1.EXT +DROP USER user@localhost; + +--echo # +--echo # Checking FILE privileges: done +--echo # + + diff --git a/storage/connect/mysql-test/connect/t/mysql.test b/storage/connect/mysql-test/connect/t/mysql.test index 45d26cdf9eb..7c90acdd149 100644 --- a/storage/connect/mysql-test/connect/t/mysql.test +++ b/storage/connect/mysql-test/connect/t/mysql.test @@ -14,66 +14,6 @@ if (!`SELECT count(*) FROM INFORMATION_SCHEMA.TABLES DROP TABLE t1; --enable_query_log ---echo # ---echo # Testing FILE privilege ---echo # -GRANT ALL PRIVILEGES ON *.* TO user@localhost; -REVOKE FILE ON *.* FROM user@localhost; ---connect(user,localhost,user,,) ---connection user -SELECT user(); ---replace_result $PORT PORT ---error ER_ACCESS_DENIED_ERROR ---eval CREATE TABLE t1 (a INT NOT NULL) ENGINE=CONNECT TABLE_TYPE=MySQL OPTION_LIST='host=localhost,user=root1,port=$PORT' ---connection default -SELECT user(); -CREATE TABLE t1remote (a INT NOT NULL); -INSERT INTO t1remote VALUES (10),(20),(30); ---replace_result $PORT PORT ---eval CREATE TABLE t1 (a INT NOT NULL) ENGINE=CONNECT TABLE_TYPE=MySQL TABNAME=t1remote OPTION_LIST='host=localhost,user=root,port=$PORT' -SELECT * FROM t1; ---connection user -SELECT user(); ---error ER_ACCESS_DENIED_ERROR -SELECT * FROM t1; ---error ER_ACCESS_DENIED_ERROR -INSERT INTO t1 VALUES ('xxx'); ---error ER_ACCESS_DENIED_ERROR -DELETE FROM t1 WHERE a='xxx'; ---error ER_ACCESS_DENIED_ERROR -UPDATE t1 SET a='yyy' WHERE a='xxx'; ---error ER_ACCESS_DENIED_ERROR -TRUNCATE TABLE t1; ---error ER_ACCESS_DENIED_ERROR -ALTER TABLE t1 READONLY=1; ---error ER_ACCESS_DENIED_ERROR -CREATE VIEW v1 AS SELECT * FROM t1; - ---echo # Testing a VIEW created with FILE privileges but accessed with no FILE ---connection default -SELECT user(); -CREATE VIEW v1 AS SELECT * FROM t1; ---connection user -SELECT user(); ---error ER_ACCESS_DENIED_ERROR -SELECT * FROM v1; ---error ER_ACCESS_DENIED_ERROR -INSERT INTO v1 VALUES (2); ---error ER_ACCESS_DENIED_ERROR -UPDATE v1 SET a=123; ---error ER_ACCESS_DENIED_ERROR -DELETE FROM v1; - ---disconnect user ---connection default -SELECT user(); -DROP VIEW v1; -DROP TABLE t1, t1remote; -DROP USER user@localhost; ---echo # ---echo # Testing FILE privileges done ---echo # - # TODO: remote VARCHAR is displayed as CHAR CREATE TABLE t1 (a int, b char(10)); diff --git a/storage/connect/mysql-test/connect/t/mysql_grant.test b/storage/connect/mysql-test/connect/t/mysql_grant.test new file mode 100644 index 00000000000..e825e70a84b --- /dev/null +++ b/storage/connect/mysql-test/connect/t/mysql_grant.test @@ -0,0 +1,78 @@ +-- source include/not_embedded.inc + +let $PORT= `select @@port`; + +--disable_query_log +--replace_result $PORT PORT +--error 0,ER_UNKNOWN_ERROR +--eval CREATE TABLE t1 (a INT) ENGINE=CONNECT TABLE_TYPE=MYSQL TABNAME='t1' OPTION_LIST='host=localhost,user=root,port=$PORT' +if (!`SELECT count(*) FROM INFORMATION_SCHEMA.TABLES + WHERE TABLE_SCHEMA='test' AND TABLE_NAME='t1' + AND ENGINE='CONNECT' + AND CREATE_OPTIONS LIKE '%`table_type`=MySQL%'`) +{ + Skip Need MySQL support; +} +DROP TABLE t1; +--enable_query_log + +--echo # +--echo # Testing FILE privilege +--echo # +GRANT ALL PRIVILEGES ON *.* TO user@localhost; +REVOKE FILE ON *.* FROM user@localhost; +--connect(user,localhost,user,,) +--connection user +SELECT user(); +--replace_result $PORT PORT +--error ER_ACCESS_DENIED_ERROR +--eval CREATE TABLE t1 (a INT NOT NULL) ENGINE=CONNECT TABLE_TYPE=MySQL OPTION_LIST='host=localhost,user=root1,port=$PORT' +--connection default +SELECT user(); +CREATE TABLE t1remote (a INT NOT NULL); +INSERT INTO t1remote VALUES (10),(20),(30); +--replace_result $PORT PORT +--eval CREATE TABLE t1 (a INT NOT NULL) ENGINE=CONNECT TABLE_TYPE=MySQL TABNAME=t1remote OPTION_LIST='host=localhost,user=root,port=$PORT' +SELECT * FROM t1; +--connection user +SELECT user(); +--error ER_ACCESS_DENIED_ERROR +SELECT * FROM t1; +--error ER_ACCESS_DENIED_ERROR +INSERT INTO t1 VALUES ('xxx'); +--error ER_ACCESS_DENIED_ERROR +DELETE FROM t1 WHERE a='xxx'; +--error ER_ACCESS_DENIED_ERROR +UPDATE t1 SET a='yyy' WHERE a='xxx'; +--error ER_ACCESS_DENIED_ERROR +TRUNCATE TABLE t1; +--error ER_ACCESS_DENIED_ERROR +ALTER TABLE t1 READONLY=1; +--error ER_ACCESS_DENIED_ERROR +CREATE VIEW v1 AS SELECT * FROM t1; + +--echo # Testing a VIEW created with FILE privileges but accessed with no FILE +--connection default +SELECT user(); +CREATE VIEW v1 AS SELECT * FROM t1; +--connection user +SELECT user(); +--error ER_ACCESS_DENIED_ERROR +SELECT * FROM v1; +--error ER_ACCESS_DENIED_ERROR +INSERT INTO v1 VALUES (2); +--error ER_ACCESS_DENIED_ERROR +UPDATE v1 SET a=123; +--error ER_ACCESS_DENIED_ERROR +DELETE FROM v1; + +--disconnect user +--connection default +SELECT user(); +DROP VIEW v1; +DROP TABLE t1, t1remote; +DROP USER user@localhost; +--echo # +--echo # Testing FILE privileges done +--echo # + diff --git a/storage/connect/mysql-test/connect/t/vec.test b/storage/connect/mysql-test/connect/t/vec.test index 79ed4eabd86..ee504e9925a 100644 --- a/storage/connect/mysql-test/connect/t/vec.test +++ b/storage/connect/mysql-test/connect/t/vec.test @@ -1,9 +1,5 @@ let $MYSQLD_DATADIR= `select @@datadir`; -let $TABLE_OPTIONS=TABLE_TYPE=VEC MAX_ROWS=100; -let $FILE_EXT=VEC; ---source grant.inc - CREATE TABLE dir1 ( spath VARCHAR(256) NOT NULL flag=1, fname VARCHAR(256) NOT NULL, diff --git a/storage/connect/mysql-test/connect/t/xml.test b/storage/connect/mysql-test/connect/t/xml.test index 96e7e1a3a97..3914bed307d 100644 --- a/storage/connect/mysql-test/connect/t/xml.test +++ b/storage/connect/mysql-test/connect/t/xml.test @@ -16,11 +16,6 @@ DROP TABLE t1; let $MYSQLD_DATADIR= `select @@datadir`; -let $TABLE_OPTIONS=TABLE_TYPE=XML OPTION_LIST='xmlsup=libxml2,rownode=row'; -let $FILE_EXT=XML; ---source grant.inc - - SET NAMES utf8; --vertical_results @@ -132,7 +127,8 @@ INSERT INTO t1 (ISBN, LANG, SUBJECT, AUTHOR, TITLE, PUBLISHEr, DATEPUB) VALUES('9782212090529','fr','général','Alain Michard', 'XML, Langage et Applications','Eyrolles Paris',1998); SELECT * FROM t1; -SELECT LOAD_FILE('test/xsample2.xml'); +--replace_result $MYSQLD_DATADIR MYSQLD_DATADIR +--eval SELECT LOAD_FILE('$MYSQLD_DATADIR/test/xsample2.xml') AS xml DROP TABLE t1; --remove_file $MYSQLD_DATADIR/test/xsample2.xml @@ -289,7 +285,8 @@ INSERT INTO t1 VALUES (_latin1 0xC0C1C2C3); SELECT node, hex(node) FROM t1; DROP TABLE t1; --chmod 0777 $MYSQLD_DATADIR/test/t1.xml -SET @a=LOAD_FILE('test/t1.xml'); +--replace_result $MYSQLD_DATADIR MYSQLD_DATADIR +--eval SET @a=LOAD_FILE('$MYSQLD_DATADIR/test/t1.xml') SELECT LEFT(@a,38); SELECT HEX(EXTRACTVALUE(@a,'/t1/line/node')); --remove_file $MYSQLD_DATADIR/test/t1.xml @@ -302,7 +299,8 @@ INSERT INTO t1 VALUES (_latin1 0xC0C1C2C3); SELECT node, hex(node) FROM t1; DROP TABLE t1; --chmod 0777 $MYSQLD_DATADIR/test/t1.xml -SET @a=LOAD_FILE('test/t1.xml'); +--replace_result $MYSQLD_DATADIR MYSQLD_DATADIR +--eval SET @a=LOAD_FILE('$MYSQLD_DATADIR/test/t1.xml') SELECT LEFT(@a,43); SELECT HEX(EXTRACTVALUE(@a,'/t1/line/node')); --remove_file $MYSQLD_DATADIR/test/t1.xml @@ -321,7 +319,8 @@ INSERT INTO t1 VALUES ('&<>"\''); SELECT node, hex(node) FROM t1; DROP TABLE t1; --chmod 0777 $MYSQLD_DATADIR/test/t1.xml -SET @a=LOAD_FILE('test/t1.xml'); +--replace_result $MYSQLD_DATADIR MYSQLD_DATADIR +--eval SET @a=LOAD_FILE('$MYSQLD_DATADIR/test/t1.xml') SELECT CAST(@a AS CHAR CHARACTER SET latin1); --remove_file $MYSQLD_DATADIR/test/t1.xml diff --git a/storage/connect/mysql-test/connect/t/xml_grant.test b/storage/connect/mysql-test/connect/t/xml_grant.test new file mode 100644 index 00000000000..f8401efaa64 --- /dev/null +++ b/storage/connect/mysql-test/connect/t/xml_grant.test @@ -0,0 +1,23 @@ +-- source include/not_embedded.inc + +--disable_query_log +--error 0,ER_UNKNOWN_ERROR +CREATE TABLE t1 (a VARCHAR(10)) +ENGINE=CONNECT TABLE_TYPE=XML OPTION_LIST='xmlsup=libxml2'; +if (!`SELECT count(*) FROM INFORMATION_SCHEMA.TABLES + WHERE TABLE_SCHEMA='test' AND TABLE_NAME='t1' + AND ENGINE='CONNECT' + AND CREATE_OPTIONS LIKE '%`table_type`=XML%' + AND CREATE_OPTIONS LIKE '%xmlsup=libxml2%'`) +{ + Skip Need LIBXML2; +} +DROP TABLE t1; +--enable_query_log + + +let $MYSQLD_DATADIR= `select @@datadir`; + +let $TABLE_OPTIONS=TABLE_TYPE=XML OPTION_LIST='xmlsup=libxml2,rownode=row'; +let $FILE_EXT=XML; +--source grant.inc diff --git a/storage/connect/plgdbsem.h b/storage/connect/plgdbsem.h index 6884c1c4176..dfa46a650a6 100644 --- a/storage/connect/plgdbsem.h +++ b/storage/connect/plgdbsem.h @@ -577,5 +577,6 @@ DllExport void NewPointer(PTABS, void *, void *); FILE *global_fopen(GLOBAL *g, int msgid, const char *path, const char *mode); int global_open(GLOBAL *g, int msgid, const char *filename, int flags); int global_open(GLOBAL *g, int msgid, const char *filename, int flags, int mode); +DllExport LPCSTR PlugSetPath(LPSTR to, LPCSTR name, LPCSTR dir); bool PushWarning(PGLOBAL, PTDBASE); diff --git a/storage/connect/plugutil.c b/storage/connect/plugutil.c index 67947e3042b..e8098bb2512 100644 --- a/storage/connect/plugutil.c +++ b/storage/connect/plugutil.c @@ -219,11 +219,23 @@ LPSTR PlugRemoveType(LPSTR pBuff, LPCSTR FileName) return pBuff; } // end of PlugRemoveType + +BOOL PlugIsAbsolutePath(LPCSTR path) +{ +#if defined(WIN32) + return ((path[0] >= 'a' && path[0] <= 'z') || + (path[0] >= 'A' && path[0] <= 'Z')) && path[1] == ':'; +#else + return path[0] == '/'; +#endif +} + + /***********************************************************************/ /* Set the full path of a file relatively to a given path. */ /* Note: this routine is not really implemented for Unix. */ /***********************************************************************/ -LPCSTR PlugSetPath(LPSTR pBuff, LPCSTR FileName, LPCSTR defpath) +LPCSTR PlugSetPath(LPSTR pBuff, LPCSTR prefix, LPCSTR FileName, LPCSTR defpath) { char newname[_MAX_PATH]; char direc[_MAX_DIR], defdir[_MAX_DIR]; @@ -240,6 +252,22 @@ LPCSTR PlugSetPath(LPSTR pBuff, LPCSTR FileName, LPCSTR defpath) return pBuff; } // endif + if (PlugIsAbsolutePath(FileName)) + { + strcpy(pBuff, FileName); // FileName includes absolute path + return pBuff; + } // endif + + if (strcmp(prefix, ".") && !PlugIsAbsolutePath(defpath)) + { + char tmp[_MAX_PATH]; + int len= snprintf(tmp, sizeof(tmp) - 1, "%s%s%s", + prefix, defpath, FileName); + memcpy(pBuff, tmp, (size_t) len); + pBuff[len]= '\0'; + return pBuff; + } + _splitpath(FileName, drive, direc, fname, ftype); _splitpath(defpath, defdrv, defdir, NULL, NULL); From aebcd56ca912979c92a32513def44aa121d82bb2 Mon Sep 17 00:00:00 2001 From: Olivier Bertrand Date: Wed, 22 May 2013 13:35:21 +0200 Subject: [PATCH 28/47] - Changing CONNECT version number and date modified: storage/connect/ha_connect.cc storage/connect/mysql-test/connect/r/xml.result - Testing default pivot columns for srcdef Fixing order by MariaDB bug for pivot tables modified: storage/connect/tabmysql.cpp storage/connect/tabmysql.h storage/connect/tabpivot.cpp storage/connect/tabpivot.h --- storage/connect/ha_connect.cc | 2 +- .../connect/mysql-test/connect/r/xml.result | 2 +- storage/connect/tabmysql.cpp | 23 +++ storage/connect/tabmysql.h | 1 + storage/connect/tabpivot.cpp | 151 +++++++++--------- storage/connect/tabpivot.h | 1 + 6 files changed, 100 insertions(+), 80 deletions(-) diff --git a/storage/connect/ha_connect.cc b/storage/connect/ha_connect.cc index 3db86b8e607..5adf8747841 100644 --- a/storage/connect/ha_connect.cc +++ b/storage/connect/ha_connect.cc @@ -158,7 +158,7 @@ extern "C" char nmfile[]; extern "C" char pdebug[]; extern "C" { - char version[]= "Version 1.01.0005 April 27, 2013"; + char version[]= "Version 1.01.0006 Mai 21, 2013"; #if defined(XMSG) char msglang[]; // Default message language diff --git a/storage/connect/mysql-test/connect/r/xml.result b/storage/connect/mysql-test/connect/r/xml.result index 44fab646dcf..67fcc5f121e 100644 --- a/storage/connect/mysql-test/connect/r/xml.result +++ b/storage/connect/mysql-test/connect/r/xml.result @@ -413,7 +413,7 @@ DROP TABLE t1; SET @a=LOAD_FILE('MYSQLD_DATADIR/test/t1.xml'); SELECT CAST(@a AS CHAR CHARACTER SET latin1); CAST(@a AS CHAR CHARACTER SET latin1) - + ÀÁÂÃ diff --git a/storage/connect/tabmysql.cpp b/storage/connect/tabmysql.cpp index 8b97a592d93..f06e8e9bd57 100644 --- a/storage/connect/tabmysql.cpp +++ b/storage/connect/tabmysql.cpp @@ -900,6 +900,29 @@ PCOL TDBMYSQL::MakeFieldColumn(PGLOBAL g, char *name) return colp; } // end of MakeFieldColumn +/***********************************************************************/ +/* Called by Pivot tables to find default column names in a View */ +/* as the name of last field not equal to the passed name. */ +/***********************************************************************/ +char *TDBMYSQL::FindFieldColumn(char *name) + { + int n; + MYSQL_FIELD *fld; + char *cp = NULL; + + for (n = Myc.m_Fields - 1; n >= 0; n--) { + fld = &Myc.m_Res->fields[n]; + + if (!name || stricmp(name, fld->name)) { + cp = fld->name; + break; + } // endif name + + } // endfor n + + return cp; + } // end of FindFieldColumn + /***********************************************************************/ /* Data Base read routine for MYSQL access method. */ /***********************************************************************/ diff --git a/storage/connect/tabmysql.h b/storage/connect/tabmysql.h index 5d8f32e9f21..24f8c4cdef2 100644 --- a/storage/connect/tabmysql.h +++ b/storage/connect/tabmysql.h @@ -90,6 +90,7 @@ class TDBMYSQL : public TDBASE { // Specific routines bool SetColumnRanks(PGLOBAL g); PCOL MakeFieldColumn(PGLOBAL g, char *name); + PSZ FindFieldColumn(char *name); protected: // Internal functions diff --git a/storage/connect/tabpivot.cpp b/storage/connect/tabpivot.cpp index 867689626f9..916a3c2584e 100644 --- a/storage/connect/tabpivot.cpp +++ b/storage/connect/tabpivot.cpp @@ -161,6 +161,42 @@ PCOL TDBPIVOT::MakeCol(PGLOBAL g, PCOLDEF cdp, PCOL cprec, int n) return colp; } // end of MakeCol +/***********************************************************************/ +/* Find default fonction and pivot columns. */ +/***********************************************************************/ +bool TDBPIVOT::FindDefaultColumns(PGLOBAL g) + { + PCOLDEF cdp; + PTABDEF defp = Tdbp->GetDef(); + + if (!Fncol) { + for (cdp = defp->GetCols(); cdp; cdp = cdp->GetNext()) + if (!Picol || stricmp(Picol, cdp->GetName())) + Fncol = cdp->GetName(); + + if (!Fncol) { + strcpy(g->Message, MSG(NO_DEF_FNCCOL)); + return true; + } // endif Fncol + + } // endif Fncol + + if (!Picol) { + // Find default Picol as the last one not equal to Fncol + for (cdp = defp->GetCols(); cdp; cdp = cdp->GetNext()) + if (stricmp(Fncol, cdp->GetName())) + Picol = cdp->GetName(); + + if (!Picol) { + strcpy(g->Message, MSG(NO_DEF_PIVOTCOL)); + return true; + } // endif Picol + + } // endif Picol + + return false; + } // end of FindDefaultColumns + /***********************************************************************/ /* Prepare the source table Query. */ /***********************************************************************/ @@ -174,69 +210,45 @@ bool TDBPIVOT::GetSourceTable(PGLOBAL g) if (!(Tdbp = GetSubTable(g, ((PPIVOTDEF)To_Def)->Tablep, true))) return true; - if (!Tdbp->IsView()) { + if (!GBdone) { + char *colist; PCOLDEF cdp; - PTABDEF defp = Tdbp->GetDef(); - if (!Fncol) { - for (cdp = defp->GetCols(); cdp; cdp = cdp->GetNext()) - if (!Picol || stricmp(Picol, cdp->GetName())) - Fncol = cdp->GetName(); + if (FindDefaultColumns(g)) + return true; - if (!Fncol) { - strcpy(g->Message, MSG(NO_DEF_FNCCOL)); - return true; - } // endif Fncol + // Locate the suballocated colist (size is not known yet) + *(colist = (char*)PlugSubAlloc(g, NULL, 0)) = 0; - } // endif Fncol + // Make the column list + for (cdp = To_Def->GetCols(); cdp; cdp = cdp->GetNext()) + if (!cdp->GetOffset()) + strcat(strcat(colist, cdp->GetName()), ", "); - if (!Picol) { - // Find default Picol as the last one not equal to Fncol - for (cdp = defp->GetCols(); cdp; cdp = cdp->GetNext()) - if (!Fncol || stricmp(Fncol, cdp->GetName())) - Picol = cdp->GetName(); + // Add the Pivot column at the end of the list + strcat(colist, Picol); - if (!Picol) { - strcpy(g->Message, MSG(NO_DEF_PIVOTCOL)); - return true; - } // endif Picol + // Now we know how much was suballocated + PlugSubAlloc(g, NULL, strlen(colist)); - } // endif Picol + // Locate the source string (size is not known yet) + Tabsrc = (char*)PlugSubAlloc(g, NULL, 0); - if (!GBdone) { - char *colist; + // Start making the definition + strcat(strcat(strcpy(Tabsrc, "SELECT "), colist), ", "); - // Locate the suballocated colist (size is not known yet) - *(colist = (char*)PlugSubAlloc(g, NULL, 0)) = 0; + // Make it suitable for Pivot by doing the group by + strcat(strcat(Tabsrc, Function), "("); + strcat(strcat(strcat(Tabsrc, Fncol), ") "), Fncol); + strcat(strcat(Tabsrc, " FROM "), Tabname); + strcat(strcat(Tabsrc, " GROUP BY "), colist); - // Make the column list - for (cdp = To_Def->GetCols(); cdp; cdp = cdp->GetNext()) - if (!cdp->GetOffset()) - strcat(strcat(colist, cdp->GetName()), ", "); - - // Add the Pivot column at the end of the list - strcat(colist, Picol); - - // Now we know how much was suballocated - PlugSubAlloc(g, NULL, strlen(colist)); - - // Locate the source string (size is not known yet) - Tabsrc = (char*)PlugSubAlloc(g, NULL, 0); - - // Start making the definition - strcat(strcat(strcpy(Tabsrc, "SELECT "), colist), ", "); - - // Make it suitable for Pivot by doing the group by - strcat(strcat(Tabsrc, Function), "("); - strcat(strcat(strcat(Tabsrc, Fncol), ") "), Fncol); - strcat(strcat(Tabsrc, " FROM "), Tabname); - strcat(strcat(Tabsrc, " GROUP BY "), colist); - - // Now we know how much was suballocated - PlugSubAlloc(g, NULL, strlen(Tabsrc)); - } // endif !GBdone + if (Tdbp->IsView()) // Until MariaDB bug is fixed + strcat(strcat(Tabsrc, " ORDER BY "), colist); - } // endif IsView + // Now we know how much was suballocated + PlugSubAlloc(g, NULL, strlen(Tabsrc)); + } // endif !GBdone } else if (!Tabsrc) { strcpy(g->Message, MSG(SRC_TABLE_UNDEF)); @@ -263,6 +275,10 @@ bool TDBPIVOT::GetSourceTable(PGLOBAL g) bool TDBPIVOT::MakePivotColumns(PGLOBAL g) { if (!Tdbp->IsView()) { + // This was not done yet if GBdone is true + if (FindDefaultColumns(g)) + return true; + // Now it is time to allocate the pivot and function columns if (!(Fcolp = Tdbp->ColDB(g, Fncol, 0))) { // Function column not found in table @@ -309,36 +325,15 @@ bool TDBPIVOT::MakeViewColumns(PGLOBAL g) } else tdbp = (PTDBMY)Tdbp; - if (!Fncol || !Picol) { - strcpy(g->Message, "Missing Function or Pivot column"); + if (!Fncol && !(Fncol = tdbp->FindFieldColumn(Picol))) { + strcpy(g->Message, MSG(NO_DEF_FNCCOL)); return true; - } // endif -#if 0 - if (!Fncol) { - for (crp = qryp->Colresp; crp; crp = crp->Next) - if (!Picol || stricmp(Picol, crp->Name)) - Fncol = crp->Name; - - if (!Fncol) { - strcpy(g->Message, MSG(NO_DEF_FNCCOL)); - return true; - } // endif Fncol - } // endif Fncol - if (!Picol) { - // Find default Picol as the last one not equal to Fncol - for (crp = qryp->Colresp; crp; crp = crp->Next) - if (!Fncol || stricmp(Fncol, crp->Name)) - Picol = crp->Name; - - if (!Picol) { - strcpy(g->Message, MSG(NO_DEF_PIVOTCOL)); - return true; - } // endif Picol - + if (!Picol && !(Picol = tdbp->FindFieldColumn(Fncol))) { + strcpy(g->Message, MSG(NO_DEF_PIVOTCOL)); + return true; } // endif Picol -#endif // 0 // Now it is time to allocate the pivot and function columns if (!(Fcolp = tdbp->MakeFieldColumn(g, Fncol))) diff --git a/storage/connect/tabpivot.h b/storage/connect/tabpivot.h index e869d1cae6c..1617801298b 100644 --- a/storage/connect/tabpivot.h +++ b/storage/connect/tabpivot.h @@ -78,6 +78,7 @@ class TDBPIVOT : public TDBPRX { protected: // Internal routines + bool FindDefaultColumns(PGLOBAL g); bool GetSourceTable(PGLOBAL g); bool MakePivotColumns(PGLOBAL g); bool MakeViewColumns(PGLOBAL g); From 7ef4c5df470e2c1ee0d5e7b57e05deebdcad753e Mon Sep 17 00:00:00 2001 From: Alexander Barkov Date: Thu, 23 May 2013 12:04:52 +0400 Subject: [PATCH 29/47] Connect: fixing non thread-safe code. Passing "struct tm" buffer to GetGmTime() instead of using a static bufer. modified: storage/connect/tabodbc.cpp storage/connect/value.cpp storage/connect/value.h --- storage/connect/tabodbc.cpp | 2 +- storage/connect/value.cpp | 17 ++++++++--------- storage/connect/value.h | 2 +- 3 files changed, 10 insertions(+), 11 deletions(-) diff --git a/storage/connect/tabodbc.cpp b/storage/connect/tabodbc.cpp index 909fcda4abf..599f9c7e80f 100644 --- a/storage/connect/tabodbc.cpp +++ b/storage/connect/tabodbc.cpp @@ -895,7 +895,7 @@ void ODBCCOL::WriteColumn(PGLOBAL g) Value->SetValue_pval(To_Val, false); // Convert the inserted value if (Buf_Type == TYPE_DATE) { - struct tm *dbtime = ((DTVAL*)Value)->GetGmTime(); + struct tm tm, *dbtime = ((DTVAL*)Value)->GetGmTime(&tm); Sqlbuf->second = dbtime->tm_sec; Sqlbuf->minute = dbtime->tm_min; diff --git a/storage/connect/value.cpp b/storage/connect/value.cpp index 6152fdc238f..20e8f58a61c 100644 --- a/storage/connect/value.cpp +++ b/storage/connect/value.cpp @@ -1251,9 +1251,8 @@ static struct tm *gmtime_mysql(const time_t *timep, struct tm *tm) } -struct tm *DTVAL::GetGmTime(void) +struct tm *DTVAL::GetGmTime(struct tm *tm_buffer) { - static struct tm tm_static; /* TODO: Move as a parameter to GetGmTime() */ struct tm *datm; time_t t = (time_t)Tval; @@ -1263,13 +1262,13 @@ struct tm *DTVAL::GetGmTime(void) for (n = 0; t < 0; n += 4) t += FOURYEARS; - datm = gmtime_mysql(&t, &tm_static); + datm = gmtime_mysql(&t, tm_buffer); if (datm) datm->tm_year -= n; } else - datm = gmtime_mysql(&t, &tm_static); + datm = gmtime_mysql(&t, tm_buffer); return datm; } // end of GetGmTime @@ -1519,7 +1518,7 @@ char *DTVAL::GetCharString(char *p) { if (Pdtp) { size_t n = 0; - struct tm *ptm = GetGmTime(); + struct tm tm, *ptm= GetGmTime(&tm); if (ptm) n = strftime(Sdate, Len + 1, Pdtp->OutFmt, ptm); @@ -1545,7 +1544,7 @@ char *DTVAL::ShowValue(char *buf, int len) if (Pdtp) { char *p; size_t m, n = 0; - struct tm *ptm = GetGmTime(); + struct tm tm, *ptm = GetGmTime(&tm); if (Len < len) { p = buf; @@ -1575,7 +1574,7 @@ char *DTVAL::ShowValue(char *buf, int len) bool DTVAL::GetTmMember(OPVAL op, int& mval) { bool rc = false; - struct tm *ptm = GetGmTime(); + struct tm tm, *ptm = GetGmTime(&tm); switch (op) { case OP_MDAY: mval = ptm->tm_mday; break; @@ -1603,7 +1602,7 @@ bool DTVAL::WeekNum(PGLOBAL g, int& nval) { // w is the start of the week SUN=0, MON=1, etc. int m, n, w = nval % 7; - struct tm *ptm = GetGmTime(); + struct tm tm, *ptm = GetGmTime(&tm); // Which day is January 4th of this year? m = (367 + ptm->tm_wday - ptm->tm_yday) % 7; @@ -1627,7 +1626,7 @@ bool DTVAL::WeekNum(PGLOBAL g, int& nval) bool DTVAL::FormatValue(PVAL vp, char *fmt) { char *buf = (char*)vp->GetTo_Val(); // Should be big enough - struct tm *ptm = GetGmTime(); + struct tm tm, *ptm = GetGmTime(&tm); if (trace) htrc("FormatValue: ptm=%p len=%d\n", ptm, vp->GetValLen()); diff --git a/storage/connect/value.h b/storage/connect/value.h index 95d69dae92f..62b4ea4617a 100644 --- a/storage/connect/value.h +++ b/storage/connect/value.h @@ -288,7 +288,7 @@ class DllExport DTVAL : public TYPVAL { bool MakeDate(PGLOBAL g, int *val, int nval); bool WeekNum(PGLOBAL g, int& nval); - struct tm *GetGmTime(void); + struct tm *GetGmTime(struct tm *); protected: // Default constructor not to be used From 33b95315680e42754d41f63f72a003f0d69959d3 Mon Sep 17 00:00:00 2001 From: Olivier Bertrand Date: Fri, 24 May 2013 00:19:26 +0200 Subject: [PATCH 30/47] - Fix setting default type to MYSQL->PROXY->DOS in some places where it was not done correctly. - Fix a bug causing add_field to generate a syntax error on DOUBLE columns with a 0 decimal value. - Column can be undefined when Srcdef is specified. modified: storage/connect/ha_connect.cc storage/connect/mycat.cc storage/connect/tabmysql.cpp storage/connect/tabutil.cpp storage/connect/tabutil.h --- storage/connect/ha_connect.cc | 49 ++++++++++++++++++++++------------- storage/connect/mycat.cc | 31 ++++++++++++---------- storage/connect/tabmysql.cpp | 2 +- storage/connect/tabutil.cpp | 10 ++++--- storage/connect/tabutil.h | 2 +- 5 files changed, 57 insertions(+), 37 deletions(-) diff --git a/storage/connect/ha_connect.cc b/storage/connect/ha_connect.cc index 5adf8747841..38b5e74c38c 100644 --- a/storage/connect/ha_connect.cc +++ b/storage/connect/ha_connect.cc @@ -680,6 +680,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, "Type")) // Default type + opval= (!options) ? NULL : + (options->srcdef) ? "MYSQL" : + (options->tabname) ? "PROXY" : "DOS"; else if (!stricmp(opname, "User")) // Connected user opval= table->in_use->main_security_ctx.user; else if (!stricmp(opname, "Host")) // Connected user host @@ -2671,7 +2675,9 @@ int ha_connect::delete_all_rows() bool ha_connect::check_privileges(THD *thd, PTOS options) { if (!options->type) { - if (options->tabname) + if (options->srcdef) + options->type= "MYSQL"; + else if (options->tabname) options->type= "PROXY"; else options->type= "DOS"; @@ -3336,7 +3342,7 @@ static bool add_field(String *sql, const char *field_name, const char *type, if (len) { error|= sql->append('('); error|= sql->append_ulonglong(len); - if (dec) { + if (dec || !strcmp(type, "DOUBLE")) { error|= sql->append(','); error|= sql->append_ulonglong(dec); } @@ -3379,7 +3385,7 @@ static int connect_assisted_discovery(handlerton *hton, THD* thd, #endif // WIN32 int port= 0, hdr= 0, mxr= 0, b= 0; uint tm, fnc= FNC_NO, supfnc= (FNC_NO | FNC_COL); - bool ok= false, dbf= false; + bool bif, ok= false, dbf= false; TABTYPE ttp= TAB_UNDEF; MEM_ROOT *mem= thd->mem_root; PQRYRES qrp; @@ -3546,6 +3552,11 @@ static int connect_assisted_discovery(handlerton *hton, THD* thd, ok= false; } // endif supfnc + if (src && fnc != FNC_NO) { + strcpy(g->Message, "Cannot make catalog table from srcdef"); + ok= false; + } // endif src + // Here we should test the flag column options when // this function is called in case of CREATE .. SELECT @@ -3561,7 +3572,7 @@ static int connect_assisted_discovery(handlerton *hton, THD* thd, else return HA_ERR_INTERNAL_ERROR; // Should never happen - if (src && fnc == FNC_NO) + if (src) qrp= SrcColumns(g, host, db, user, pwd, src, port); else switch (ttp) { case TAB_DBF: @@ -3606,7 +3617,12 @@ static int connect_assisted_discovery(handlerton *hton, THD* thd, case TAB_PRX: case TAB_TBL: case TAB_XCL: - qrp= TabColumns(g, thd, db, tab, fnc == FNC_COL); + bif= fnc == FNC_COL; + qrp= TabColumns(g, thd, db, tab, bif); + + if (!qrp && bif && fnc != FNC_COL) // tab is a view + qrp= MyColumns(g, host, db, user, pwd, tab, NULL, port, false); + break; default: strcpy(g->Message, "System error during assisted discovery"); @@ -3624,9 +3640,10 @@ static int connect_assisted_discovery(handlerton *hton, THD* thd, cnm= encode(g, crp->Name); type= PLGtoMYSQLtype(crp->Type, dbf); len= crp->Length; + dec= crp->Prec; // Now add the field - if (add_field(&sql, cnm, type, len, 0, NOT_NULL_FLAG, 0)) + if (add_field(&sql, cnm, type, len, dec, NOT_NULL_FLAG, 0)) b= HA_ERR_OUT_OF_MEM; } // endfor crp @@ -3780,6 +3797,9 @@ static int connect_assisted_discovery(handlerton *hton, THD* thd, } // endif charset + if (xtrace) + printf("s_init: %.*s\n", sql.length(), sql.ptr()); + if (!b) b= table_s->init_from_sql_statement_string(thd, true, sql.ptr(), sql.length()); @@ -3837,18 +3857,11 @@ int ha_connect::create(const char *name, TABLE *table_arg, // Check table type if (type == TAB_UNDEF) { - if (!options->tabname) { - strcpy(g->Message, "No table_type. Will be set to DOS"); - push_warning(thd, MYSQL_ERROR::WARN_LEVEL_WARN, 0, g->Message); - type= TAB_DOS; - options->type= "DOS"; - } else { - strcpy(g->Message, "No table_type. Will be set to PROXY"); - push_warning(thd, MYSQL_ERROR::WARN_LEVEL_WARN, 0, g->Message); - type= TAB_PRX; - options->type= "PROXY"; - } // endif fnc - + options->type= (options->srcdef) ? "MYSQL" : + (options->tabname) ? "PROXY" : "DOS"; + type= GetTypeID(options->type); + sprintf(g->Message, "No table_type. Will be set to %s", options->type); + push_warning(thd, MYSQL_ERROR::WARN_LEVEL_WARN, 0, g->Message); } else if (type == TAB_NIY) { sprintf(g->Message, "Unsupported table type %s", options->type); my_message(ER_UNKNOWN_ERROR, g->Message, MYF(0)); diff --git a/storage/connect/mycat.cc b/storage/connect/mycat.cc index b5767b02180..e243a706f01 100644 --- a/storage/connect/mycat.cc +++ b/storage/connect/mycat.cc @@ -390,20 +390,23 @@ char *MYCAT::GetStringCatInfo(PGLOBAL g, PSZ what, PSZ sdef) strcpy(sval, s); } else if (!stricmp(what, "filename")) { // Return default file name - char *ftype= Hc->GetStringOption("Type", "dos"); + char *ftype= Hc->GetStringOption("Type", "*"); int i, n; - sval= (char*)PlugSubAlloc(g, NULL, strlen(Hc->GetTableName()) + 12); - strcat(strcpy(sval, Hc->GetTableName()), "."); - n= strlen(sval); + if (IsFileType(GetTypeID(ftype))) { + sval= (char*)PlugSubAlloc(g, NULL, strlen(Hc->GetTableName()) + 12); + strcat(strcpy(sval, Hc->GetTableName()), "."); + n= strlen(sval); + + // Fold ftype to lower case + for (i= 0; i < 12; i++) + if (!ftype[i]) { + sval[n+i]= 0; + break; + } else + sval[n+i]= tolower(ftype[i]); - // Fold ftype to lower case - for (i= 0; i < 12; i++) - if (!ftype[i]) { - sval[n+i]= 0; - break; - } else - sval[n+i]= tolower(ftype[i]); + } // endif FileType } else sval = NULL; @@ -416,7 +419,7 @@ char *MYCAT::GetStringCatInfo(PGLOBAL g, PSZ what, PSZ sdef) /***********************************************************************/ int MYCAT::GetColCatInfo(PGLOBAL g, PTABDEF defp) { - char *type= GetStringCatInfo(g, "Type", "DOS"); + char *type= GetStringCatInfo(g, "Type", "*"); int i, loff, poff, nof, nlg; void *field= NULL; TABTYPE tc; @@ -598,8 +601,8 @@ PRELDEF MYCAT::GetTableDesc(PGLOBAL g, LPCSTR name, printf("GetTableDesc: name=%s am=%s\n", name, SVP(type)); // If not specified get the type of this table - if (!type && !(type= Hc->GetStringOption("Type"))) - type= (Hc->GetStringOption("Tabname")) ? "PROXY" : "DOS"; + if (!type) + type= Hc->GetStringOption("Type","*"); return MakeTableDesc(g, name, type); } // end of GetTableDesc diff --git a/storage/connect/tabmysql.cpp b/storage/connect/tabmysql.cpp index f06e8e9bd57..1a19b4cbf33 100644 --- a/storage/connect/tabmysql.cpp +++ b/storage/connect/tabmysql.cpp @@ -790,7 +790,7 @@ bool TDBMYSQL::OpenDB(PGLOBAL g) } // endif m_Res #endif // 0 - if (Srcdef) + if (!m_Rc && Srcdef) if (SetColumnRanks(g)) return true; diff --git a/storage/connect/tabutil.cpp b/storage/connect/tabutil.cpp index 5c4b428b09a..04271d1a460 100644 --- a/storage/connect/tabutil.cpp +++ b/storage/connect/tabutil.cpp @@ -120,7 +120,7 @@ TABLE_SHARE *GetTableShare(PGLOBAL g, THD *thd, const char *db, /* of the object table that will be retrieved by GetData commands. */ /************************************************************************/ PQRYRES TabColumns(PGLOBAL g, THD *thd, const char *db, - const char *name, bool info) + const char *name, bool& info) { static int buftyp[] = {TYPE_STRING, TYPE_SHORT, TYPE_STRING, TYPE_INT, TYPE_INT, TYPE_SHORT, TYPE_SHORT, TYPE_SHORT, @@ -143,7 +143,9 @@ PQRYRES TabColumns(PGLOBAL g, THD *thd, const char *db, if (!(s = GetTableShare(g, thd, db, name, mysql))) { return NULL; } else if (s->is_view) { - strcpy(g->Message, "Cannot retreive Proxy columns from a view"); + strcpy(g->Message, "Use MYSQL type to see columns from a view"); + info = true; // To tell caller name is a view + free_table_share(s); return NULL; } else n = s->fieldnames.count; @@ -615,6 +617,8 @@ TDBTBC::TDBTBC(PPRXDEF tdp) : TDBCAT(tdp) /***********************************************************************/ PQRYRES TDBTBC::GetResult(PGLOBAL g) { - return TabColumns(g, current_thd, Db, Tab, false); + bool b = false; + + return TabColumns(g, current_thd, Db, Tab, b); } // end of GetResult diff --git a/storage/connect/tabutil.h b/storage/connect/tabutil.h index 1405ef211c7..ddf6c2eb601 100644 --- a/storage/connect/tabutil.h +++ b/storage/connect/tabutil.h @@ -18,7 +18,7 @@ typedef class TDBTBC *PTDBTBC; 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); + const char *name, bool& info); void Remove_tshp(PCATLG cat); From f2e147365353070539851f016a0eb975780ebd23 Mon Sep 17 00:00:00 2001 From: Alexander Barkov Date: Fri, 24 May 2013 09:56:04 +0400 Subject: [PATCH 31/47] Removing direct access to thd, using functions: - thd_query_string() insted of thd->query_string - thd_sql_command() instead ot thd->lex->sql_command - table_share->s.db.str instead of thd->db modified: storage/connect/connect.cc storage/connect/ha_connect.cc --- storage/connect/connect.cc | 1 - storage/connect/ha_connect.cc | 27 ++++++++++++++------------- 2 files changed, 14 insertions(+), 14 deletions(-) diff --git a/storage/connect/connect.cc b/storage/connect/connect.cc index 7d9456c3259..41fb061bd7f 100644 --- a/storage/connect/connect.cc +++ b/storage/connect/connect.cc @@ -31,7 +31,6 @@ /* global.h is header containing all global declarations. */ /* plgdbsem.h is header containing the DB applic. declarations. */ /***********************************************************************/ -#define MYSQL_SERVER 1 #define DONT_DEFINE_VOID #include "handler.h" #undef OFFSET diff --git a/storage/connect/ha_connect.cc b/storage/connect/ha_connect.cc index 38b5e74c38c..f3f0fbfba90 100644 --- a/storage/connect/ha_connect.cc +++ b/storage/connect/ha_connect.cc @@ -2794,6 +2794,8 @@ int ha_connect::external_lock(THD *thd, int lock_type) PGLOBAL g= GetPlug(thd, xp); DBUG_ENTER("ha_connect::external_lock"); + DBUG_ASSERT(thd == current_thd); + if (xtrace) printf("%p external_lock: lock_type=%d\n", this, lock_type); @@ -2914,16 +2916,16 @@ int ha_connect::external_lock(THD *thd, int lock_type) } // endif MODE_ANY if (xtrace) { - printf("%p external_lock: cmdtype=%d\n", this, thd->lex->sql_command); - printf("Cmd=%.*s\n", (int) thd->query_string.length(), - thd->query_string.str()); + LEX_STRING *query_string= thd_query_string(thd); + printf("%p external_lock: cmdtype=%d\n", this, thd_sql_command(thd)); + printf("Cmd=%.*s\n", (int) query_string->length, query_string->str); } // endif xtrace // Next code is temporarily replaced until sql_command is set stop= false; if (newmode == MODE_WRITE) { - switch (thd->lex->sql_command) { + switch (thd_sql_command(thd)) { case SQLCOM_CREATE_TABLE: case SQLCOM_INSERT: case SQLCOM_LOAD: @@ -2963,13 +2965,13 @@ int ha_connect::external_lock(THD *thd, int lock_type) newmode= MODE_ANY; break; default: - printf("Unsupported sql_command=%d", thd->lex->sql_command); - sprintf(g->Message, "Unsupported sql_command=%d", thd->lex->sql_command); + printf("Unsupported sql_command=%d", thd_sql_command(thd)); + sprintf(g->Message, "Unsupported sql_command=%d", thd_sql_command(thd)); DBUG_RETURN(HA_ERR_INTERNAL_ERROR); } // endswitch newmode } else if (newmode == MODE_READ) { - switch (thd->lex->sql_command) { + switch (thd_sql_command(thd)) { case SQLCOM_CREATE_TABLE: xcheck= true; cras= true; @@ -3000,8 +3002,8 @@ int ha_connect::external_lock(THD *thd, int lock_type) newmode= MODE_ANY; break; default: - printf("Unsupported sql_command=%d", thd->lex->sql_command); - sprintf(g->Message, "Unsupported sql_command=%d", thd->lex->sql_command); + printf("Unsupported sql_command=%d", thd_sql_command(thd)); + sprintf(g->Message, "Unsupported sql_command=%d", thd_sql_command(thd)); DBUG_RETURN(HA_ERR_INTERNAL_ERROR); } // endswitch newmode @@ -3387,7 +3389,6 @@ static int connect_assisted_discovery(handlerton *hton, THD* thd, uint tm, fnc= FNC_NO, supfnc= (FNC_NO | FNC_COL); bool bif, ok= false, dbf= false; TABTYPE ttp= TAB_UNDEF; - MEM_ROOT *mem= thd->mem_root; PQRYRES qrp; PCOLRES crp; PGLOBAL g= GetPlug(thd, NULL); @@ -3436,7 +3437,7 @@ static int connect_assisted_discovery(handlerton *hton, THD* thd, } // endif option_list if (!db) - db= thd->db; // Default value + db= table_s->db.str; // Default value // Check table type if (ttp == TAB_UNDEF) { @@ -3568,7 +3569,7 @@ static int connect_assisted_discovery(handlerton *hton, THD* thd, PCATLG cat= (dup) ? dup->Catalog : NULL; if (cat) - cat->SetDataPath(g, thd->db); + cat->SetDataPath(g, table_s->db.str); else return HA_ERR_INTERNAL_ERROR; // Should never happen @@ -3907,7 +3908,7 @@ int ha_connect::create(const char *name, TABLE *table_arg, push_warning(thd, MYSQL_ERROR::WARN_LEVEL_WARN, 0, g->Message); } else if (options->tabname) { if (!stricmp(options->tabname, create_info->alias) && - (!options->dbname || !stricmp(options->dbname, thd->db))) { + (!options->dbname || !stricmp(options->dbname, table_arg->s->db.str))) { sprintf(g->Message, "A %s table cannot refer to itself", options->type); my_message(ER_UNKNOWN_ERROR, g->Message, MYF(0)); From 5b0e3a5332d789ea7d9e05d6030065cbb54d41be Mon Sep 17 00:00:00 2001 From: Alexander Barkov Date: Fri, 24 May 2013 11:31:43 +0400 Subject: [PATCH 32/47] Removing more cases of direct use of thd. Also, TABLE_TYPE=MySQL now uses "root@localhost" by default, instead of current user and current host name. modified: storage/connect/ha_connect.cc --- storage/connect/ha_connect.cc | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/storage/connect/ha_connect.cc b/storage/connect/ha_connect.cc index f3f0fbfba90..ba96f99e28a 100644 --- a/storage/connect/ha_connect.cc +++ b/storage/connect/ha_connect.cc @@ -685,9 +685,9 @@ char *ha_connect::GetStringOption(char *opname, char *sdef) (options->srcdef) ? "MYSQL" : (options->tabname) ? "PROXY" : "DOS"; else if (!stricmp(opname, "User")) // Connected user - opval= table->in_use->main_security_ctx.user; + opval= (char *) "root"; else if (!stricmp(opname, "Host")) // Connected user host - opval= table->in_use->main_security_ctx.host; + opval= (char *) "localhost"; else opval= sdef; // Caller default @@ -3528,7 +3528,7 @@ static int connect_assisted_discovery(handlerton *hton, THD* thd, ok= false; } else if (!user) - user= thd->main_security_ctx.user; + user= "root"; break; #endif // MYSQL_SUPPORT @@ -4121,7 +4121,7 @@ int ha_connect::create(const char *name, TABLE *table_arg, PIXDEF xdp; // We should be in CREATE TABLE - if (table->in_use->lex->sql_command != SQLCOM_CREATE_TABLE) + if (thd_sql_command(table->in_use) != SQLCOM_CREATE_TABLE) push_warning(thd, MYSQL_ERROR::WARN_LEVEL_WARN, 0, "Wrong command in create, please contact CONNECT team"); @@ -4131,7 +4131,7 @@ int ha_connect::create(const char *name, TABLE *table_arg, PCATLG cat= (dup) ? dup->Catalog : NULL; if (cat) { - cat->SetDataPath(g, table_arg->in_use->db); + cat->SetDataPath(g, table_arg->s->db.str); if ((rc= optimize(table->in_use, NULL))) { printf("Create rc=%d %s\n", rc, g->Message); From aa505ea3218b6b2d9753a854ffbc8b3728121447 Mon Sep 17 00:00:00 2001 From: Alexander Barkov Date: Fri, 24 May 2013 15:21:06 +0400 Subject: [PATCH 33/47] Splitting SQLite3 tests into two parts: 1. for both server and embedded 2. for server only added: storage/connect/mysql-test/connect/r/odbc_sqlite3_grant.result storage/connect/mysql-test/connect/t/have_odbc_sqlite3.inc storage/connect/mysql-test/connect/t/odbc_sqlite3_grant.test modified: storage/connect/mysql-test/connect/r/odbc_sqlite3.result storage/connect/mysql-test/connect/t/odbc_sqlite3.test --- .../mysql-test/connect/r/odbc_sqlite3.result | 69 +++++----------- .../connect/r/odbc_sqlite3_grant.result | 72 +++++++++++++++++ .../connect/t/have_odbc_sqlite3.inc | 15 ++++ .../mysql-test/connect/t/odbc_sqlite3.test | 71 ++--------------- .../connect/t/odbc_sqlite3_grant.test | 79 +++++++++++++++++++ 5 files changed, 193 insertions(+), 113 deletions(-) create mode 100644 storage/connect/mysql-test/connect/r/odbc_sqlite3_grant.result create mode 100644 storage/connect/mysql-test/connect/t/have_odbc_sqlite3.inc create mode 100644 storage/connect/mysql-test/connect/t/odbc_sqlite3_grant.test diff --git a/storage/connect/mysql-test/connect/r/odbc_sqlite3.result b/storage/connect/mysql-test/connect/r/odbc_sqlite3.result index 87f7803166c..339dbb6a53d 100644 --- a/storage/connect/mysql-test/connect/r/odbc_sqlite3.result +++ b/storage/connect/mysql-test/connect/r/odbc_sqlite3.result @@ -4,20 +4,6 @@ t1 CREATE TABLE `t1` ( `Attributes` varchar(256) NOT NULL ) ENGINE=CONNECT DEFAULT CHARSET=latin1 `TABLE_TYPE`='ODBC' `CATFUNC`='Drivers' SET NAMES utf8; -GRANT ALL PRIVILEGES ON *.* TO user@localhost; -REVOKE FILE ON *.* FROM user@localhost; -SELECT user(); -user() -user@localhost -CREATE TABLE t1 (a INT NOT NULL) ENGINE=CONNECT TABLE_TYPE=ODBC; -ERROR 28000: Access denied for user 'user'@'localhost' (using password: NO) -CREATE TABLE t1 (a INT NOT NULL) ENGINE=CONNECT TABLE_TYPE=ODBC CATFUNC=Drivers; -ERROR 28000: Access denied for user 'user'@'localhost' (using password: NO) -CREATE TABLE t1 (a INT NOT NULL) ENGINE=CONNECT TABLE_TYPE=ODBC CATFUNC=Sources; -ERROR 28000: Access denied for user 'user'@'localhost' (using password: NO) -SELECT user(); -user() -root@localhost CREATE TABLE t1 ENGINE=CONNECT TABLE_TYPE=ODBC CONNECTION='Driver=SQLite3 ODBC Driver;Database=MTR_SUITE_DIR/std_data/test.sqlite3;NoWCHAR=yes' CHARSET=utf8 DATA_CHARSET=utf8;; SHOW CREATE TABLE t1; Table Create Table @@ -31,42 +17,27 @@ test2 тест1 тест2 ÆÇÈÉË -SELECT user(); -user() -user@localhost -SELECT * FROM t1; -ERROR 28000: Access denied for user 'user'@'localhost' (using password: NO) -INSERT INTO t1 VALUES ('xxx'); -ERROR 28000: Access denied for user 'user'@'localhost' (using password: NO) -DELETE FROM t1 WHERE a='xxx'; -ERROR 28000: Access denied for user 'user'@'localhost' (using password: NO) -UPDATE t1 SET a='yyy' WHERE a='xxx'; -ERROR 28000: Access denied for user 'user'@'localhost' (using password: NO) -TRUNCATE TABLE t1; -ERROR 28000: Access denied for user 'user'@'localhost' (using password: NO) -ALTER TABLE t1 READONLY=1; -ERROR 28000: Access denied for user 'user'@'localhost' (using password: NO) +CREATE TABLE t2 AS SELECT * FROM t1; +SHOW CREATE TABLE t2; +Table Create Table +t2 CREATE TABLE `t2` ( + `a` varchar(64) CHARACTER SET utf8 DEFAULT NULL +) ENGINE=MyISAM DEFAULT CHARSET=latin1 +SELECT * FROM t2; +a +test1 +test2 +тест1 +тест2 +ÆÇÈÉË +DROP TABLE t2; CREATE VIEW v1 AS SELECT * FROM t1; -ERROR 28000: Access denied for user 'user'@'localhost' (using password: NO) -# Testing a VIEW created with FILE privileges but accessed with no FILE -SELECT user(); -user() -root@localhost -CREATE VIEW v1 AS SELECT * FROM t1; -SELECT user(); -user() -user@localhost SELECT * FROM v1; -ERROR 28000: Access denied for user 'user'@'localhost' (using password: NO) -INSERT INTO v1 VALUES (2); -ERROR 28000: Access denied for user 'user'@'localhost' (using password: NO) -UPDATE v1 SET a=123; -ERROR 28000: Access denied for user 'user'@'localhost' (using password: NO) -DELETE FROM v1; -ERROR 28000: Access denied for user 'user'@'localhost' (using password: NO) -SELECT user(); -user() -root@localhost +a +test1 +test2 +тест1 +тест2 +ÆÇÈÉË DROP VIEW v1; DROP TABLE t1; -DROP USER user@localhost; diff --git a/storage/connect/mysql-test/connect/r/odbc_sqlite3_grant.result b/storage/connect/mysql-test/connect/r/odbc_sqlite3_grant.result new file mode 100644 index 00000000000..87f7803166c --- /dev/null +++ b/storage/connect/mysql-test/connect/r/odbc_sqlite3_grant.result @@ -0,0 +1,72 @@ +Table Create Table +t1 CREATE TABLE `t1` ( + `Description` varchar(128) NOT NULL, + `Attributes` varchar(256) NOT NULL +) ENGINE=CONNECT DEFAULT CHARSET=latin1 `TABLE_TYPE`='ODBC' `CATFUNC`='Drivers' +SET NAMES utf8; +GRANT ALL PRIVILEGES ON *.* TO user@localhost; +REVOKE FILE ON *.* FROM user@localhost; +SELECT user(); +user() +user@localhost +CREATE TABLE t1 (a INT NOT NULL) ENGINE=CONNECT TABLE_TYPE=ODBC; +ERROR 28000: Access denied for user 'user'@'localhost' (using password: NO) +CREATE TABLE t1 (a INT NOT NULL) ENGINE=CONNECT TABLE_TYPE=ODBC CATFUNC=Drivers; +ERROR 28000: Access denied for user 'user'@'localhost' (using password: NO) +CREATE TABLE t1 (a INT NOT NULL) ENGINE=CONNECT TABLE_TYPE=ODBC CATFUNC=Sources; +ERROR 28000: Access denied for user 'user'@'localhost' (using password: NO) +SELECT user(); +user() +root@localhost +CREATE TABLE t1 ENGINE=CONNECT TABLE_TYPE=ODBC CONNECTION='Driver=SQLite3 ODBC Driver;Database=MTR_SUITE_DIR/std_data/test.sqlite3;NoWCHAR=yes' CHARSET=utf8 DATA_CHARSET=utf8;; +SHOW CREATE TABLE t1; +Table Create Table +t1 CREATE TABLE `t1` ( + `a` varchar(64) DEFAULT NULL +) ENGINE=CONNECT DEFAULT CHARSET=utf8 CONNECTION='Driver=SQLite3 ODBC Driver;Database=MTR_SUITE_DIR/std_data/test.sqlite3;NoWCHAR=yes' `TABLE_TYPE`='ODBC' `DATA_CHARSET`='utf8' +SELECT * FROM t1; +a +test1 +test2 +тест1 +тест2 +ÆÇÈÉË +SELECT user(); +user() +user@localhost +SELECT * FROM t1; +ERROR 28000: Access denied for user 'user'@'localhost' (using password: NO) +INSERT INTO t1 VALUES ('xxx'); +ERROR 28000: Access denied for user 'user'@'localhost' (using password: NO) +DELETE FROM t1 WHERE a='xxx'; +ERROR 28000: Access denied for user 'user'@'localhost' (using password: NO) +UPDATE t1 SET a='yyy' WHERE a='xxx'; +ERROR 28000: Access denied for user 'user'@'localhost' (using password: NO) +TRUNCATE TABLE t1; +ERROR 28000: Access denied for user 'user'@'localhost' (using password: NO) +ALTER TABLE t1 READONLY=1; +ERROR 28000: Access denied for user 'user'@'localhost' (using password: NO) +CREATE VIEW v1 AS SELECT * FROM t1; +ERROR 28000: Access denied for user 'user'@'localhost' (using password: NO) +# Testing a VIEW created with FILE privileges but accessed with no FILE +SELECT user(); +user() +root@localhost +CREATE VIEW v1 AS SELECT * FROM t1; +SELECT user(); +user() +user@localhost +SELECT * FROM v1; +ERROR 28000: Access denied for user 'user'@'localhost' (using password: NO) +INSERT INTO v1 VALUES (2); +ERROR 28000: Access denied for user 'user'@'localhost' (using password: NO) +UPDATE v1 SET a=123; +ERROR 28000: Access denied for user 'user'@'localhost' (using password: NO) +DELETE FROM v1; +ERROR 28000: Access denied for user 'user'@'localhost' (using password: NO) +SELECT user(); +user() +root@localhost +DROP VIEW v1; +DROP TABLE t1; +DROP USER user@localhost; diff --git a/storage/connect/mysql-test/connect/t/have_odbc_sqlite3.inc b/storage/connect/mysql-test/connect/t/have_odbc_sqlite3.inc new file mode 100644 index 00000000000..9528e00ff56 --- /dev/null +++ b/storage/connect/mysql-test/connect/t/have_odbc_sqlite3.inc @@ -0,0 +1,15 @@ +--disable_query_log +--error 0,ER_UNKNOWN_ERROR +CREATE TABLE t1 ENGINE=CONNECT TABLE_TYPE=ODBC CATFUNC=Drivers; +if ($mysql_errno) +{ + Skip No ODBC support; +} +if (!`SELECT count(*) FROM t1 WHERE Description='SQLite3 ODBC Driver'`) +{ + DROP TABLE t1; + Skip Need SQLite3 ODBC Driver; +} +SHOW CREATE TABLE t1; +DROP TABLE t1; +--enable_query_log diff --git a/storage/connect/mysql-test/connect/t/odbc_sqlite3.test b/storage/connect/mysql-test/connect/t/odbc_sqlite3.test index 5f6abb0e2bc..f32196e3f04 100644 --- a/storage/connect/mysql-test/connect/t/odbc_sqlite3.test +++ b/storage/connect/mysql-test/connect/t/odbc_sqlite3.test @@ -1,3 +1,5 @@ +--source have_odbc_sqlite3.inc + # # To run this test, install SQLite3 ODBC Driver from # http://www.ch-werner.de/sqliteodbc/ @@ -18,42 +20,11 @@ # Note, the test does not need a DSN to be created. # ---disable_query_log ---error 0,ER_UNKNOWN_ERROR -CREATE TABLE t1 ENGINE=CONNECT TABLE_TYPE=ODBC CATFUNC=Drivers; -if ($mysql_errno) -{ - Skip No ODBC support; -} -if (!`SELECT count(*) FROM t1 WHERE Description='SQLite3 ODBC Driver'`) -{ - DROP TABLE t1; - Skip Need SQLite3 ODBC Driver; -} -SHOW CREATE TABLE t1; -DROP TABLE t1; ---enable_query_log - SET NAMES utf8; let $MYSQLD_DATADIR= `select @@datadir`; -GRANT ALL PRIVILEGES ON *.* TO user@localhost; -REVOKE FILE ON *.* FROM user@localhost; ---connect(user,localhost,user,,) ---connection user -SELECT user(); ---error ER_ACCESS_DENIED_ERROR -CREATE TABLE t1 (a INT NOT NULL) ENGINE=CONNECT TABLE_TYPE=ODBC; ---error ER_ACCESS_DENIED_ERROR -CREATE TABLE t1 (a INT NOT NULL) ENGINE=CONNECT TABLE_TYPE=ODBC CATFUNC=Drivers; ---error ER_ACCESS_DENIED_ERROR -CREATE TABLE t1 (a INT NOT NULL) ENGINE=CONNECT TABLE_TYPE=ODBC CATFUNC=Sources; ---connection default -SELECT user(); - - # # For some reasons Windows does not allow to remove the data base # file after "DROP TABLE t1". So unlike in odbc_xls.test we won't copy @@ -66,42 +37,14 @@ let $Database=$MTR_SUITE_DIR/std_data/test.sqlite3; --replace_result $MTR_SUITE_DIR MTR_SUITE_DIR SHOW CREATE TABLE t1; SELECT * FROM t1; ---connection user -SELECT user(); ---error ER_ACCESS_DENIED_ERROR -SELECT * FROM t1; ---error ER_ACCESS_DENIED_ERROR -INSERT INTO t1 VALUES ('xxx'); ---error ER_ACCESS_DENIED_ERROR -DELETE FROM t1 WHERE a='xxx'; ---error ER_ACCESS_DENIED_ERROR -UPDATE t1 SET a='yyy' WHERE a='xxx'; ---error ER_ACCESS_DENIED_ERROR -TRUNCATE TABLE t1; ---error ER_ACCESS_DENIED_ERROR -ALTER TABLE t1 READONLY=1; ---error ER_ACCESS_DENIED_ERROR -CREATE VIEW v1 AS SELECT * FROM t1; ---echo # Testing a VIEW created with FILE privileges but accessed with no FILE ---connection default -SELECT user(); +CREATE TABLE t2 AS SELECT * FROM t1; +SHOW CREATE TABLE t2; +SELECT * FROM t2; +DROP TABLE t2; + CREATE VIEW v1 AS SELECT * FROM t1; ---connection user -SELECT user(); ---error ER_ACCESS_DENIED_ERROR SELECT * FROM v1; ---error ER_ACCESS_DENIED_ERROR -INSERT INTO v1 VALUES (2); ---error ER_ACCESS_DENIED_ERROR -UPDATE v1 SET a=123; ---error ER_ACCESS_DENIED_ERROR -DELETE FROM v1; ---disconnect user ---connection default -SELECT user(); DROP VIEW v1; DROP TABLE t1; - -DROP USER user@localhost; diff --git a/storage/connect/mysql-test/connect/t/odbc_sqlite3_grant.test b/storage/connect/mysql-test/connect/t/odbc_sqlite3_grant.test new file mode 100644 index 00000000000..7664a4473ba --- /dev/null +++ b/storage/connect/mysql-test/connect/t/odbc_sqlite3_grant.test @@ -0,0 +1,79 @@ +-- source include/not_embedded.inc +-- source have_odbc_sqlite3.inc + +# +# For the instructions on how to setup SQLite3 ODBC DSN, +# please see odbc_sqlite3.test +# + +SET NAMES utf8; + +let $MYSQLD_DATADIR= `select @@datadir`; + + +GRANT ALL PRIVILEGES ON *.* TO user@localhost; +REVOKE FILE ON *.* FROM user@localhost; +--connect(user,localhost,user,,) +--connection user +SELECT user(); +--error ER_ACCESS_DENIED_ERROR +CREATE TABLE t1 (a INT NOT NULL) ENGINE=CONNECT TABLE_TYPE=ODBC; +--error ER_ACCESS_DENIED_ERROR +CREATE TABLE t1 (a INT NOT NULL) ENGINE=CONNECT TABLE_TYPE=ODBC CATFUNC=Drivers; +--error ER_ACCESS_DENIED_ERROR +CREATE TABLE t1 (a INT NOT NULL) ENGINE=CONNECT TABLE_TYPE=ODBC CATFUNC=Sources; +--connection default +SELECT user(); + + +# +# For some reasons Windows does not allow to remove the data base +# file after "DROP TABLE t1". So unlike in odbc_xls.test we won't copy +# the data file, we'll use directly the file in std_data. +# As we do not do any modifications in the database, this should be OK. +# +let $Database=$MTR_SUITE_DIR/std_data/test.sqlite3; +--replace_result $MTR_SUITE_DIR MTR_SUITE_DIR +--eval CREATE TABLE t1 ENGINE=CONNECT TABLE_TYPE=ODBC CONNECTION='Driver=SQLite3 ODBC Driver;Database=$Database;NoWCHAR=yes' CHARSET=utf8 DATA_CHARSET=utf8; +--replace_result $MTR_SUITE_DIR MTR_SUITE_DIR +SHOW CREATE TABLE t1; +SELECT * FROM t1; +--connection user +SELECT user(); +--error ER_ACCESS_DENIED_ERROR +SELECT * FROM t1; +--error ER_ACCESS_DENIED_ERROR +INSERT INTO t1 VALUES ('xxx'); +--error ER_ACCESS_DENIED_ERROR +DELETE FROM t1 WHERE a='xxx'; +--error ER_ACCESS_DENIED_ERROR +UPDATE t1 SET a='yyy' WHERE a='xxx'; +--error ER_ACCESS_DENIED_ERROR +TRUNCATE TABLE t1; +--error ER_ACCESS_DENIED_ERROR +ALTER TABLE t1 READONLY=1; +--error ER_ACCESS_DENIED_ERROR +CREATE VIEW v1 AS SELECT * FROM t1; + +--echo # Testing a VIEW created with FILE privileges but accessed with no FILE +--connection default +SELECT user(); +CREATE VIEW v1 AS SELECT * FROM t1; +--connection user +SELECT user(); +--error ER_ACCESS_DENIED_ERROR +SELECT * FROM v1; +--error ER_ACCESS_DENIED_ERROR +INSERT INTO v1 VALUES (2); +--error ER_ACCESS_DENIED_ERROR +UPDATE v1 SET a=123; +--error ER_ACCESS_DENIED_ERROR +DELETE FROM v1; + +--disconnect user +--connection default +SELECT user(); +DROP VIEW v1; +DROP TABLE t1; + +DROP USER user@localhost; From 74be65c6d8f3541dc4a83666e32f043a7b6b49fe Mon Sep 17 00:00:00 2001 From: Alexander Barkov Date: Fri, 24 May 2013 15:27:20 +0400 Subject: [PATCH 34/47] Do not run mysql.test in case of embedded server. We need a running MySQL server for this test. modified: storage/connect/mysql-test/connect/t/mysql.test --- storage/connect/mysql-test/connect/t/mysql.test | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/storage/connect/mysql-test/connect/t/mysql.test b/storage/connect/mysql-test/connect/t/mysql.test index 7c90acdd149..c7eacbd3d06 100644 --- a/storage/connect/mysql-test/connect/t/mysql.test +++ b/storage/connect/mysql-test/connect/t/mysql.test @@ -1,3 +1,10 @@ +-- source include/not_embedded.inc + +# +# TODO: consider a possibility to run this test +# against some remote MySQL server +# + let $PORT= `select @@port`; --disable_query_log From 32bd0c7d1fd3e996bf4431ed2c2e22cc1bcde4cd Mon Sep 17 00:00:00 2001 From: Alexander Barkov Date: Fri, 24 May 2013 19:09:59 +0400 Subject: [PATCH 35/47] Adding the timezone plugin service, to convert between MYSQL_TIME and my_time_t and back. Using the new service instead of direct access to thd. added: include/mysql/service_thd_timezone.h libservices/thd_timezone_service.c modified: include/my_time.h include/mysql.h.pp include/mysql/plugin.h include/mysql/plugin_audit.h.pp include/mysql/plugin_auth.h.pp include/mysql/plugin_ftparser.h.pp include/mysql/services.h include/mysql_time.h include/service_versions.h libservices/CMakeLists.txt sql/sql_class.cc sql/sql_plugin_services.h storage/connect/value.cpp --- include/my_time.h | 10 ---- include/mysql.h.pp | 1 + include/mysql/plugin.h | 2 +- include/mysql/plugin_audit.h.pp | 22 +++++++++ include/mysql/plugin_auth.h.pp | 22 +++++++++ include/mysql/plugin_ftparser.h.pp | 22 +++++++++ include/mysql/service_thd_timezone.h | 74 ++++++++++++++++++++++++++++ include/mysql/services.h | 1 + include/mysql_time.h | 11 +++++ include/service_versions.h | 2 +- libservices/CMakeLists.txt | 1 + libservices/thd_timezone_service.c | 18 +++++++ sql/sql_class.cc | 21 ++++++++ sql/sql_plugin_services.h | 8 ++- storage/connect/value.cpp | 5 +- 15 files changed, 203 insertions(+), 17 deletions(-) create mode 100644 include/mysql/service_thd_timezone.h create mode 100644 libservices/thd_timezone_service.c diff --git a/include/my_time.h b/include/my_time.h index 9bd545bb850..046b5c94923 100644 --- a/include/my_time.h +++ b/include/my_time.h @@ -29,16 +29,6 @@ C_MODE_START extern ulonglong log_10_int[20]; extern uchar days_in_month[]; -/* - Portable time_t replacement. - Should be signed and hold seconds for 1902 -- 2038-01-19 range - i.e at least a 32bit variable - - Using the system built in time_t is not an option as - we rely on the above requirements in the time functions -*/ -typedef long my_time_t; - #define MY_TIME_T_MAX LONG_MAX #define MY_TIME_T_MIN LONG_MIN diff --git a/include/mysql.h.pp b/include/mysql.h.pp index d33822b2021..02eb62655df 100644 --- a/include/mysql.h.pp +++ b/include/mysql.h.pp @@ -143,6 +143,7 @@ const char *mysql_errno_to_sqlstate(unsigned int mysql_errno); my_bool my_thread_init(void); void my_thread_end(void); #include "mysql_time.h" +typedef long my_time_t; enum enum_mysql_timestamp_type { MYSQL_TIMESTAMP_NONE= -2, MYSQL_TIMESTAMP_ERROR= -1, diff --git a/include/mysql/plugin.h b/include/mysql/plugin.h index 38573180232..db9b8e2aa9a 100644 --- a/include/mysql/plugin.h +++ b/include/mysql/plugin.h @@ -72,7 +72,7 @@ typedef struct st_mysql_xid MYSQL_XID; #define MYSQL_PLUGIN_INTERFACE_VERSION 0x0103 /* MariaDB plugin interface version */ -#define MARIA_PLUGIN_INTERFACE_VERSION 0x0104 +#define MARIA_PLUGIN_INTERFACE_VERSION 0x0105 /* The allowable types of plugins diff --git a/include/mysql/plugin_audit.h.pp b/include/mysql/plugin_audit.h.pp index 1c4b46c2a01..8592eb9f852 100644 --- a/include/mysql/plugin_audit.h.pp +++ b/include/mysql/plugin_audit.h.pp @@ -85,6 +85,28 @@ extern struct kill_statement_service_st { enum thd_kill_levels (*thd_kill_level_func)(const void*); } *thd_kill_statement_service; enum thd_kill_levels thd_kill_level(const void*); +#include +typedef char my_bool; +#include "mysql_time.h" +typedef long my_time_t; +enum enum_mysql_timestamp_type +{ + MYSQL_TIMESTAMP_NONE= -2, MYSQL_TIMESTAMP_ERROR= -1, + MYSQL_TIMESTAMP_DATE= 0, MYSQL_TIMESTAMP_DATETIME= 1, MYSQL_TIMESTAMP_TIME= 2 +}; +typedef struct st_mysql_time +{ + unsigned int year, month, day, hour, minute, second; + unsigned long second_part; + my_bool neg; + enum enum_mysql_timestamp_type time_type; +} MYSQL_TIME; +extern struct thd_timezone_service_st { + my_time_t (*thd_TIME_to_gmt_sec)(void* thd, const MYSQL_TIME *ltime, unsigned int *errcode); + void (*thd_gmt_sec_to_TIME)(void* thd, MYSQL_TIME *ltime, my_time_t t); +} *thd_timezone_service; +my_time_t thd_TIME_to_gmt_sec(void* thd, const MYSQL_TIME *ltime, uint *errcode); +void thd_gmt_sec_to_TIME(void* thd, MYSQL_TIME *ltime, my_time_t t); struct st_mysql_xid { long formatID; long gtrid_length; diff --git a/include/mysql/plugin_auth.h.pp b/include/mysql/plugin_auth.h.pp index ac6e5e3b13d..81b717acc8f 100644 --- a/include/mysql/plugin_auth.h.pp +++ b/include/mysql/plugin_auth.h.pp @@ -85,6 +85,28 @@ extern struct kill_statement_service_st { enum thd_kill_levels (*thd_kill_level_func)(const void*); } *thd_kill_statement_service; enum thd_kill_levels thd_kill_level(const void*); +#include +typedef char my_bool; +#include "mysql_time.h" +typedef long my_time_t; +enum enum_mysql_timestamp_type +{ + MYSQL_TIMESTAMP_NONE= -2, MYSQL_TIMESTAMP_ERROR= -1, + MYSQL_TIMESTAMP_DATE= 0, MYSQL_TIMESTAMP_DATETIME= 1, MYSQL_TIMESTAMP_TIME= 2 +}; +typedef struct st_mysql_time +{ + unsigned int year, month, day, hour, minute, second; + unsigned long second_part; + my_bool neg; + enum enum_mysql_timestamp_type time_type; +} MYSQL_TIME; +extern struct thd_timezone_service_st { + my_time_t (*thd_TIME_to_gmt_sec)(void* thd, const MYSQL_TIME *ltime, unsigned int *errcode); + void (*thd_gmt_sec_to_TIME)(void* thd, MYSQL_TIME *ltime, my_time_t t); +} *thd_timezone_service; +my_time_t thd_TIME_to_gmt_sec(void* thd, const MYSQL_TIME *ltime, uint *errcode); +void thd_gmt_sec_to_TIME(void* thd, MYSQL_TIME *ltime, my_time_t t); struct st_mysql_xid { long formatID; long gtrid_length; diff --git a/include/mysql/plugin_ftparser.h.pp b/include/mysql/plugin_ftparser.h.pp index f5d6ac3b849..f28a508d62b 100644 --- a/include/mysql/plugin_ftparser.h.pp +++ b/include/mysql/plugin_ftparser.h.pp @@ -85,6 +85,28 @@ extern struct kill_statement_service_st { enum thd_kill_levels (*thd_kill_level_func)(const void*); } *thd_kill_statement_service; enum thd_kill_levels thd_kill_level(const void*); +#include +typedef char my_bool; +#include "mysql_time.h" +typedef long my_time_t; +enum enum_mysql_timestamp_type +{ + MYSQL_TIMESTAMP_NONE= -2, MYSQL_TIMESTAMP_ERROR= -1, + MYSQL_TIMESTAMP_DATE= 0, MYSQL_TIMESTAMP_DATETIME= 1, MYSQL_TIMESTAMP_TIME= 2 +}; +typedef struct st_mysql_time +{ + unsigned int year, month, day, hour, minute, second; + unsigned long second_part; + my_bool neg; + enum enum_mysql_timestamp_type time_type; +} MYSQL_TIME; +extern struct thd_timezone_service_st { + my_time_t (*thd_TIME_to_gmt_sec)(void* thd, const MYSQL_TIME *ltime, unsigned int *errcode); + void (*thd_gmt_sec_to_TIME)(void* thd, MYSQL_TIME *ltime, my_time_t t); +} *thd_timezone_service; +my_time_t thd_TIME_to_gmt_sec(void* thd, const MYSQL_TIME *ltime, uint *errcode); +void thd_gmt_sec_to_TIME(void* thd, MYSQL_TIME *ltime, my_time_t t); struct st_mysql_xid { long formatID; long gtrid_length; diff --git a/include/mysql/service_thd_timezone.h b/include/mysql/service_thd_timezone.h new file mode 100644 index 00000000000..e6d92e73ece --- /dev/null +++ b/include/mysql/service_thd_timezone.h @@ -0,0 +1,74 @@ +#ifndef MYSQL_SERVICE_THD_TIMEZONE_INCLUDED +/* Copyright (C) 2013 MariaDB Foundation. + + 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 + the Free Software Foundation; version 2 of the License. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA */ + +/** + @file + This service provdes functions to convert between my_time_t and + MYSQL_TIME taking into account the current value of the time_zone + session variable. + + The values of the my_time_t type are in Unix timestamp format, + i.e. the number of seconds since "1970-01-01 00:00:00 UTC". + + The values of the MYSQL_TIME type are in the current time zone, + according to thd->variables.time_zone. + + If the MYSQL_THD parameter is NULL, then global_system_variables.time_zone + is used for conversion. +*/ + +#ifndef MYSQL_ABI_CHECK +/* + This service currently does not depend on any system headers. + If it needs system headers in the future, make sure to put + them inside this ifndef. +*/ +#endif + +typedef char my_bool; +#include "mysql_time.h" + +#ifdef __cplusplus +extern "C" { +#endif + + +extern struct thd_timezone_service_st { + my_time_t (*thd_TIME_to_gmt_sec)(MYSQL_THD thd, const MYSQL_TIME *ltime, unsigned int *errcode); + void (*thd_gmt_sec_to_TIME)(MYSQL_THD thd, MYSQL_TIME *ltime, my_time_t t); +} *thd_timezone_service; + +#ifdef MYSQL_DYNAMIC_PLUGIN + +#define thd_TIME_to_gmt_sec(thd, ltime, errcode) \ + (thd_timezone_service->thd_TIME_to_gmt_sec((thd), (ltime), (errcode))) + +#define thd_gmt_sec_to_TIME(thd, ltime, t) \ + (thd_timezone_service->thd_gmt_sec_to_TIME((thd), (ltime), (t))) + +#else + +my_time_t thd_TIME_to_gmt_sec(MYSQL_THD thd, const MYSQL_TIME *ltime, uint *errcode); +void thd_gmt_sec_to_TIME(MYSQL_THD thd, MYSQL_TIME *ltime, my_time_t t); + +#endif + +#ifdef __cplusplus +} +#endif + +#define MYSQL_SERVICE_THD_TIMEZONE_INCLUDED +#endif diff --git a/include/mysql/services.h b/include/mysql/services.h index e14523f4fa1..1145d19872b 100644 --- a/include/mysql/services.h +++ b/include/mysql/services.h @@ -25,6 +25,7 @@ extern "C" { #include #include #include +#include #ifdef __cplusplus } diff --git a/include/mysql_time.h b/include/mysql_time.h index 0a3f17a81fb..baa236e891e 100644 --- a/include/mysql_time.h +++ b/include/mysql_time.h @@ -16,6 +16,17 @@ #ifndef _mysql_time_h_ #define _mysql_time_h_ +/* + Portable time_t replacement. + Should be signed and hold seconds for 1902 -- 2038-01-19 range + i.e at least a 32bit variable + + Using the system built in time_t is not an option as + we rely on the above requirements in the time functions +*/ +typedef long my_time_t; + + /* Time declarations shared between the server and client API: you should not add anything to this header unless it's used diff --git a/include/service_versions.h b/include/service_versions.h index e0a717fea9e..2dffa7cf863 100644 --- a/include/service_versions.h +++ b/include/service_versions.h @@ -26,4 +26,4 @@ #define VERSION_progress_report 0x0100 #define VERSION_debug_sync 0x1000 #define VERSION_kill_statement 0x1000 - +#define VERSION_thd_timezone 0x0100 diff --git a/libservices/CMakeLists.txt b/libservices/CMakeLists.txt index 86ed3493993..e7dcf20e547 100644 --- a/libservices/CMakeLists.txt +++ b/libservices/CMakeLists.txt @@ -19,6 +19,7 @@ SET(MYSQLSERVICES_SOURCES my_snprintf_service.c thd_alloc_service.c thd_wait_service.c + thd_timezone_service.c progress_report_service.c debug_sync_service.c kill_statement_service.c) diff --git a/libservices/thd_timezone_service.c b/libservices/thd_timezone_service.c new file mode 100644 index 00000000000..2c93453f8ca --- /dev/null +++ b/libservices/thd_timezone_service.c @@ -0,0 +1,18 @@ +/* Copyright (C) 2013 MariaDB Foundation + Use is subject to license terms. + + 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 + the Free Software Foundation; version 2 of the License. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA */ + +#include +SERVICE_VERSION thd_timezone_service= (void *) VERSION_thd_timezone; diff --git a/sql/sql_class.cc b/sql/sql_class.cc index 238bf46e528..016cff9c2d9 100644 --- a/sql/sql_class.cc +++ b/sql/sql_class.cc @@ -35,6 +35,7 @@ #include "sql_cache.h" // query_cache_abort #include "sql_base.h" // close_thread_tables #include "sql_time.h" // date_time_format_copy +#include "tztime.h" // MYSQL_TIME <-> my_time_t #include "sql_acl.h" // NO_ACCESS, // acl_getroot_no_password #include "sql_base.h" // close_temporary_tables @@ -1261,6 +1262,26 @@ void thd_get_xid(const MYSQL_THD thd, MYSQL_XID *xid) *xid = *(MYSQL_XID *) &thd->transaction.xid_state.xid; } + +extern "C" +my_time_t thd_TIME_to_gmt_sec(MYSQL_THD thd, const MYSQL_TIME *ltime, + unsigned int *errcode) +{ + Time_zone *tz= thd ? thd->variables.time_zone : + global_system_variables.time_zone; + return tz->TIME_to_gmt_sec(ltime, errcode); +} + + +extern "C" +void thd_gmt_sec_to_TIME(MYSQL_THD thd, MYSQL_TIME *ltime, my_time_t t) +{ + Time_zone *tz= thd ? thd->variables.time_zone : + global_system_variables.time_zone; + tz->gmt_sec_to_TIME(ltime, t); +} + + #ifdef _WIN32 extern "C" THD *_current_thd_noinline(void) { diff --git a/sql/sql_plugin_services.h b/sql/sql_plugin_services.h index d2f60a6e08c..838b994b6e8 100644 --- a/sql/sql_plugin_services.h +++ b/sql/sql_plugin_services.h @@ -54,6 +54,11 @@ static struct kill_statement_service_st thd_kill_statement_handler= { thd_kill_level }; +static struct thd_timezone_service_st thd_timezone_handler= { + thd_TIME_to_gmt_sec, + thd_gmt_sec_to_TIME +}; + static struct st_service_ref list_of_services[]= { { "my_snprintf_service", VERSION_my_snprintf, &my_snprintf_handler }, @@ -61,6 +66,7 @@ static struct st_service_ref list_of_services[]= { "thd_wait_service", VERSION_thd_wait, &thd_wait_handler }, { "progress_report_service", VERSION_progress_report, &progress_report_handler }, { "debug_sync_service", VERSION_debug_sync, 0 }, // updated in plugin_init() - { "thd_kill_statement_service", VERSION_kill_statement, &thd_kill_statement_handler } + { "thd_kill_statement_service", VERSION_kill_statement, &thd_kill_statement_handler }, + { "thd_timezone_service", VERSION_thd_timezone, &thd_timezone_handler }, }; diff --git a/storage/connect/value.cpp b/storage/connect/value.cpp index 20e8f58a61c..1c8182b6b8d 100644 --- a/storage/connect/value.cpp +++ b/storage/connect/value.cpp @@ -1224,9 +1224,6 @@ void DTVAL::SetTimeShift(void) /* though the gmtime C function. The purpose of this function is to */ /* extend the range of valid dates by accepting negative time values. */ /***********************************************************************/ -#define MYSQL_SERVER 1 -#include "tztime.h" -#include "sql_priv.h" #include "sql_class.h" #include "sql_time.h" @@ -1245,7 +1242,7 @@ static void TIME_to_localtime(struct tm *tm, const MYSQL_TIME *ltime) static struct tm *gmtime_mysql(const time_t *timep, struct tm *tm) { MYSQL_TIME ltime; - current_thd->variables.time_zone->gmt_sec_to_TIME(<ime, (my_time_t) *timep); + thd_gmt_sec_to_TIME(current_thd, <ime, (my_time_t) *timep); TIME_to_localtime(tm, <ime); return tm; } From 73d62e2cb158811157b66b82501d42ef3dda0613 Mon Sep 17 00:00:00 2001 From: Olivier Bertrand Date: Mon, 27 May 2013 00:17:04 +0200 Subject: [PATCH 36/47] - Fix Windows compile error modified: include/mysql/service_thd_timezone.h --- include/mysql/service_thd_timezone.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/include/mysql/service_thd_timezone.h b/include/mysql/service_thd_timezone.h index e6d92e73ece..f8bddba68bb 100644 --- a/include/mysql/service_thd_timezone.h +++ b/include/mysql/service_thd_timezone.h @@ -61,7 +61,7 @@ extern struct thd_timezone_service_st { #else -my_time_t thd_TIME_to_gmt_sec(MYSQL_THD thd, const MYSQL_TIME *ltime, uint *errcode); +my_time_t thd_TIME_to_gmt_sec(MYSQL_THD thd, const MYSQL_TIME *ltime, unsigned int *errcode); void thd_gmt_sec_to_TIME(MYSQL_THD thd, MYSQL_TIME *ltime, my_time_t t); #endif From d9f90dc0ccef2fca12a1aa5ad41118b8ddf13bf7 Mon Sep 17 00:00:00 2001 From: Alexander Barkov Date: Mon, 27 May 2013 12:38:15 +0400 Subject: [PATCH 37/47] Fixing ABI template, to take into account the latest change in the thd_time_zone_service. modified: include/mysql/plugin_audit.h.pp --- include/mysql/plugin_audit.h.pp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/include/mysql/plugin_audit.h.pp b/include/mysql/plugin_audit.h.pp index 8592eb9f852..8648bd6383d 100644 --- a/include/mysql/plugin_audit.h.pp +++ b/include/mysql/plugin_audit.h.pp @@ -105,7 +105,7 @@ extern struct thd_timezone_service_st { my_time_t (*thd_TIME_to_gmt_sec)(void* thd, const MYSQL_TIME *ltime, unsigned int *errcode); void (*thd_gmt_sec_to_TIME)(void* thd, MYSQL_TIME *ltime, my_time_t t); } *thd_timezone_service; -my_time_t thd_TIME_to_gmt_sec(void* thd, const MYSQL_TIME *ltime, uint *errcode); +my_time_t thd_TIME_to_gmt_sec(void* thd, const MYSQL_TIME *ltime, unsigned int *errcode); void thd_gmt_sec_to_TIME(void* thd, MYSQL_TIME *ltime, my_time_t t); struct st_mysql_xid { long formatID; From 941a20a48a4115123ed749c5b5d4234cb5656ec2 Mon Sep 17 00:00:00 2001 From: Alexander Barkov Date: Mon, 27 May 2013 12:42:39 +0400 Subject: [PATCH 38/47] Fixing ABI template, to take into account the latest change in the thd_time_zone_service. modified: include/mysql/plugin_auth.h.pp include/mysql/plugin_ftparser.h.pp --- include/mysql/plugin_auth.h.pp | 2 +- include/mysql/plugin_ftparser.h.pp | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/include/mysql/plugin_auth.h.pp b/include/mysql/plugin_auth.h.pp index 81b717acc8f..d291a87012a 100644 --- a/include/mysql/plugin_auth.h.pp +++ b/include/mysql/plugin_auth.h.pp @@ -105,7 +105,7 @@ extern struct thd_timezone_service_st { my_time_t (*thd_TIME_to_gmt_sec)(void* thd, const MYSQL_TIME *ltime, unsigned int *errcode); void (*thd_gmt_sec_to_TIME)(void* thd, MYSQL_TIME *ltime, my_time_t t); } *thd_timezone_service; -my_time_t thd_TIME_to_gmt_sec(void* thd, const MYSQL_TIME *ltime, uint *errcode); +my_time_t thd_TIME_to_gmt_sec(void* thd, const MYSQL_TIME *ltime, unsigned int *errcode); void thd_gmt_sec_to_TIME(void* thd, MYSQL_TIME *ltime, my_time_t t); struct st_mysql_xid { long formatID; diff --git a/include/mysql/plugin_ftparser.h.pp b/include/mysql/plugin_ftparser.h.pp index f28a508d62b..b0143db4784 100644 --- a/include/mysql/plugin_ftparser.h.pp +++ b/include/mysql/plugin_ftparser.h.pp @@ -105,7 +105,7 @@ extern struct thd_timezone_service_st { my_time_t (*thd_TIME_to_gmt_sec)(void* thd, const MYSQL_TIME *ltime, unsigned int *errcode); void (*thd_gmt_sec_to_TIME)(void* thd, MYSQL_TIME *ltime, my_time_t t); } *thd_timezone_service; -my_time_t thd_TIME_to_gmt_sec(void* thd, const MYSQL_TIME *ltime, uint *errcode); +my_time_t thd_TIME_to_gmt_sec(void* thd, const MYSQL_TIME *ltime, unsigned int *errcode); void thd_gmt_sec_to_TIME(void* thd, MYSQL_TIME *ltime, my_time_t t); struct st_mysql_xid { long formatID; From 8b6e7f66aecc198a6d4156060a2c3359c4b853cd Mon Sep 17 00:00:00 2001 From: Alexander Barkov Date: Mon, 27 May 2013 17:42:59 +0400 Subject: [PATCH 39/47] - Fixing embedded verision of the Connect engine when handling table_type=MySQL (and some other types) to connect only to remote MySQL server, do not try to establish embedded connections from the running embedded connection. - Disabling "mtr --embedded" for the tests that need a remote MySQL server. modified: storage/connect/myconn.cpp storage/connect/mysql-test/connect/t/occur.test storage/connect/mysql-test/connect/t/pivot.test storage/connect/mysql-test/connect/t/tbl.test --- storage/connect/myconn.cpp | 1 + storage/connect/mysql-test/connect/t/occur.test | 2 ++ storage/connect/mysql-test/connect/t/pivot.test | 2 ++ storage/connect/mysql-test/connect/t/tbl.test | 2 ++ 4 files changed, 7 insertions(+) diff --git a/storage/connect/myconn.cpp b/storage/connect/myconn.cpp index 5320171beeb..220be7ca0be 100644 --- a/storage/connect/myconn.cpp +++ b/storage/connect/myconn.cpp @@ -316,6 +316,7 @@ int MYSQLC::Open(PGLOBAL g, const char *host, const char *db, // This is critical, because the server will not accept the // client's options, and vice versa. mysql_options(m_DB, MYSQL_READ_DEFAULT_GROUP, "PlugDB_CLIENT"); + mysql_options(m_DB, MYSQL_OPT_USE_REMOTE_CONNECTION, NULL); #if 0 if (pwd && !strcmp(pwd, "*")) { diff --git a/storage/connect/mysql-test/connect/t/occur.test b/storage/connect/mysql-test/connect/t/occur.test index 5b237742fd8..36a4caafda1 100644 --- a/storage/connect/mysql-test/connect/t/occur.test +++ b/storage/connect/mysql-test/connect/t/occur.test @@ -1,3 +1,5 @@ +-- source include/not_embedded.inc + let $MYSQLD_DATADIR= `select @@datadir`; let $PORT= `select @@port`; --copy_file $MTR_SUITE_DIR/std_data/employee.dat $MYSQLD_DATADIR/test/employee.dat diff --git a/storage/connect/mysql-test/connect/t/pivot.test b/storage/connect/mysql-test/connect/t/pivot.test index e66d927bad5..7679434bca8 100644 --- a/storage/connect/mysql-test/connect/t/pivot.test +++ b/storage/connect/mysql-test/connect/t/pivot.test @@ -1,3 +1,5 @@ +-- source include/not_embedded.inc + let $MYSQLD_DATADIR= `select @@datadir`; let $PORT= `select @@port`; --copy_file $MTR_SUITE_DIR/std_data/expenses.txt $MYSQLD_DATADIR/test/expenses.txt diff --git a/storage/connect/mysql-test/connect/t/tbl.test b/storage/connect/mysql-test/connect/t/tbl.test index 143c7643afd..bdd928366ef 100644 --- a/storage/connect/mysql-test/connect/t/tbl.test +++ b/storage/connect/mysql-test/connect/t/tbl.test @@ -1,3 +1,5 @@ +-- source include/not_embedded.inc + let $MYSQLD_DATADIR= `select @@datadir`; let $PORT= `select @@port`; From cc8174db48942a7a81cb6a74265c8212afe03591 Mon Sep 17 00:00:00 2001 From: Alexander Barkov Date: Tue, 28 May 2013 13:11:45 +0400 Subject: [PATCH 40/47] Recording test results forgotten in the commit adding thd_timezone_service. modified: mysql-test/r/handlersocket.result mysql-test/r/plugin.result mysql-test/suite/plugins/r/show_all_plugins.result --- mysql-test/r/handlersocket.result | 2 +- mysql-test/r/plugin.result | 6 +++--- mysql-test/suite/plugins/r/show_all_plugins.result | 4 ++-- 3 files changed, 6 insertions(+), 6 deletions(-) diff --git a/mysql-test/r/handlersocket.result b/mysql-test/r/handlersocket.result index 9e5d273cbb6..765d954d3dc 100644 --- a/mysql-test/r/handlersocket.result +++ b/mysql-test/r/handlersocket.result @@ -5,7 +5,7 @@ plugin_version 1.0 plugin_status ACTIVE plugin_type DAEMON plugin_library handlersocket.so -plugin_library_version 1.4 +plugin_library_version 1.5 plugin_author higuchi dot akira at dena dot jp plugin_description Direct access into InnoDB plugin_license BSD diff --git a/mysql-test/r/plugin.result b/mysql-test/r/plugin.result index 0eb49584c4a..e175d59cbac 100644 --- a/mysql-test/r/plugin.result +++ b/mysql-test/r/plugin.result @@ -15,7 +15,7 @@ PLUGIN_STATUS ACTIVE PLUGIN_TYPE STORAGE ENGINE PLUGIN_TYPE_VERSION # PLUGIN_LIBRARY ha_example.so -PLUGIN_LIBRARY_VERSION 1.4 +PLUGIN_LIBRARY_VERSION 1.5 PLUGIN_AUTHOR Brian Aker, MySQL AB PLUGIN_DESCRIPTION Example storage engine PLUGIN_LICENSE GPL @@ -28,7 +28,7 @@ PLUGIN_STATUS ACTIVE PLUGIN_TYPE DAEMON PLUGIN_TYPE_VERSION # PLUGIN_LIBRARY ha_example.so -PLUGIN_LIBRARY_VERSION 1.4 +PLUGIN_LIBRARY_VERSION 1.5 PLUGIN_AUTHOR Sergei Golubchik PLUGIN_DESCRIPTION Unusable Daemon PLUGIN_LICENSE GPL @@ -60,7 +60,7 @@ PLUGIN_STATUS DELETED PLUGIN_TYPE STORAGE ENGINE PLUGIN_TYPE_VERSION # PLUGIN_LIBRARY ha_example.so -PLUGIN_LIBRARY_VERSION 1.4 +PLUGIN_LIBRARY_VERSION 1.5 PLUGIN_AUTHOR Brian Aker, MySQL AB PLUGIN_DESCRIPTION Example storage engine PLUGIN_LICENSE GPL diff --git a/mysql-test/suite/plugins/r/show_all_plugins.result b/mysql-test/suite/plugins/r/show_all_plugins.result index f9cbbd849e2..b5703ffa739 100644 --- a/mysql-test/suite/plugins/r/show_all_plugins.result +++ b/mysql-test/suite/plugins/r/show_all_plugins.result @@ -4,8 +4,8 @@ Variable_name Value Opened_plugin_libraries 0 select * from information_schema.all_plugins where plugin_library='ha_example.so'; PLUGIN_NAME PLUGIN_VERSION PLUGIN_STATUS PLUGIN_TYPE PLUGIN_TYPE_VERSION PLUGIN_LIBRARY PLUGIN_LIBRARY_VERSION PLUGIN_AUTHOR PLUGIN_DESCRIPTION PLUGIN_LICENSE LOAD_OPTION PLUGIN_MATURITY PLUGIN_AUTH_VERSION -EXAMPLE 0.1 NOT INSTALLED STORAGE ENGINE 100002.0 ha_example.so 1.4 Brian Aker, MySQL AB Example storage engine GPL OFF Experimental 0.1 -UNUSABLE 3.14 NOT INSTALLED DAEMON 100002.0 ha_example.so 1.4 Sergei Golubchik Unusable Daemon GPL OFF Experimental 3.14.15.926 +EXAMPLE 0.1 NOT INSTALLED STORAGE ENGINE 100002.0 ha_example.so 1.5 Brian Aker, MySQL AB Example storage engine GPL OFF Experimental 0.1 +UNUSABLE 3.14 NOT INSTALLED DAEMON 100002.0 ha_example.so 1.5 Sergei Golubchik Unusable Daemon GPL OFF Experimental 3.14.15.926 show status like '%libraries%'; Variable_name Value Opened_plugin_libraries 1 From 9f7c3fedfacdc62a30e1c9cd4ef2cdf900abffba Mon Sep 17 00:00:00 2001 From: Olivier Bertrand Date: Tue, 28 May 2013 17:22:38 +0200 Subject: [PATCH 41/47] - Extending connect_assisted_discovery column automatic definition to OCCUR and PIVOT table types. modified: storage/connect/ha_connect.cc storage/connect/myconn.cpp storage/connect/myconn.h storage/connect/plgdbsem.h storage/connect/plgdbutl.cpp storage/connect/taboccur.cpp storage/connect/taboccur.h storage/connect/tabpivot.cpp storage/connect/tabpivot.h - Fix wrong definition of GetVlen for TYPE template modified: storage/connect/valblk.h --- storage/connect/ha_connect.cc | 76 ++++++++--- storage/connect/myconn.cpp | 9 +- storage/connect/myconn.h | 2 + storage/connect/plgdbsem.h | 1 + storage/connect/plgdbutl.cpp | 1 + storage/connect/taboccur.cpp | 234 ++++++++++++++++++++++++++++++---- storage/connect/taboccur.h | 1 - storage/connect/tabpivot.cpp | 178 +++++++++++++++++++++++++- storage/connect/tabpivot.h | 36 +++++- storage/connect/valblk.h | 3 +- 10 files changed, 494 insertions(+), 47 deletions(-) diff --git a/storage/connect/ha_connect.cc b/storage/connect/ha_connect.cc index ba96f99e28a..db789dda5bd 100644 --- a/storage/connect/ha_connect.cc +++ b/storage/connect/ha_connect.cc @@ -27,11 +27,12 @@ ha_connect will let you create/open/delete tables, the created table can be done specifying an already existing file, the drop table command will just suppress the table definition but not the eventual data file. - Indexes are not yet supported but data can be inserted, updated or deleted. + Indexes are not supported for all table types but data can be inserted, + updated or deleted. You can enable the CONNECT storage engine in your build by doing the following during your build process:
./configure - --with-connect-storage-engine (not implemented yet) + --with-connect-storage-engine You can install the CONNECT handler as all other storage handlers. @@ -166,6 +167,16 @@ extern "C" { int trace= 0; // The general trace value } // extern "C" +bool OcrColumns(PGLOBAL g, PQRYRES qrp, const char *col, + const char *ocr, const char *rank); +bool OcrSrcCols(PGLOBAL g, PQRYRES qrp, const char *col, + const char *ocr, const char *rank); +PQRYRES PivotColumns(PGLOBAL g, const char *tab, const char *src, + const char *picol, const char *fncol, + const char *host, const char *db, + const char *user, const char *pwd, + int port); + /****************************************************************************/ /* Initialize the ha_connect static members. */ /****************************************************************************/ @@ -3333,7 +3344,7 @@ static char *encode(PGLOBAL g, char *cnm) */ static bool add_field(String *sql, const char *field_name, const char *type, - int len, int dec, uint tm, const char *rem) + int len, int dec, uint tm, const char *rem, int flag) { bool error= false; @@ -3341,15 +3352,18 @@ static bool add_field(String *sql, const char *field_name, const char *type, error|= sql->append(field_name); error|= sql->append("` "); error|= sql->append(type); + if (len) { error|= sql->append('('); error|= sql->append_ulonglong(len); + if (dec || !strcmp(type, "DOUBLE")) { error|= sql->append(','); error|= sql->append_ulonglong(dec); - } + } // endif dec + error|= sql->append(')'); - } + } // endif len if (tm) error|= sql->append(STRING_WITH_LEN(" NOT NULL"), system_charset_info); @@ -3358,10 +3372,14 @@ static bool add_field(String *sql, const char *field_name, const char *type, error|= sql->append(" COMMENT '"); error|= sql->append_for_single_quote(rem, strlen(rem)); error|= sql->append("'"); - } + } // endif rem + + if (flag) { + error|= sql->append(" FLAG="); + error|= sql->append_ulonglong(flag); + } // endif flag sql->append(','); - return error; } // end of add_field @@ -3381,6 +3399,7 @@ static int connect_assisted_discovery(handlerton *hton, THD* thd, char spc= ',', qch= 0; const char *fncn= "?"; const char *user, *fn, *db, *host, *pwd, *prt, *sep, *tbl, *src; + const char *col, *ocl, *rnk, *pic, *fcl; char *tab, *dsn; #if defined(WIN32) char *nsp= NULL, *cls= NULL; @@ -3402,7 +3421,7 @@ static int connect_assisted_discovery(handlerton *hton, THD* thd, sql.copy(STRING_WITH_LEN("CREATE TABLE whatever ("), system_charset_info); - user= host= pwd= prt= tbl= src= dsn= NULL; + user= host= pwd= prt= tbl= src= col= ocl= pic= fcl= rnk= dsn= NULL; // Get the useful create options ttp= GetTypeID(topt->type); @@ -3417,12 +3436,18 @@ static int connect_assisted_discovery(handlerton *hton, THD* thd, qch= topt->qchar ? *topt->qchar : topt->quoted >= 0 ? '"' : 0; hdr= (int)topt->header; tbl= topt->tablist; + col= topt->colist; 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); + col= GetListOption(g,"colist", topt->oplist, col); + ocl= GetListOption(g,"occurcol", topt->oplist, NULL); + pic= GetListOption(g,"pivotcol", topt->oplist, NULL); + fcl= GetListOption(g,"fnccol", topt->oplist, NULL); + rnk= GetListOption(g,"rankcol", topt->oplist, NULL); pwd= GetListOption(g,"password", topt->oplist); prt= GetListOption(g,"port", topt->oplist); port= (prt) ? atoi(prt) : 0; @@ -3537,9 +3562,12 @@ static int connect_assisted_discovery(handlerton *hton, THD* thd, ok= true; break; #endif // WIN32 + case TAB_PIVOT: + supfnc = FNC_NO; case TAB_PRX: case TAB_TBL: case TAB_XCL: + case TAB_OCCUR: ok= true; break; default: @@ -3563,7 +3591,7 @@ static int connect_assisted_discovery(handlerton *hton, THD* thd, if (ok) { char *cnm, *rem; - int i, len, dec, typ; + int i, len, dec, typ, flg; const char *type; PDBUSER dup= PlgGetUser(g); PCATLG cat= (dup) ? dup->Catalog : NULL; @@ -3573,9 +3601,16 @@ static int connect_assisted_discovery(handlerton *hton, THD* thd, else return HA_ERR_INTERNAL_ERROR; // Should never happen - if (src) + if (src && ttp != TAB_PIVOT) { qrp= SrcColumns(g, host, db, user, pwd, src, port); - else switch (ttp) { + + if (ttp == TAB_OCCUR) + if (OcrSrcCols(g, qrp, col, ocl, rnk)) { + my_message(ER_UNKNOWN_ERROR, g->Message, MYF(0)); + return HA_ERR_INTERNAL_ERROR; + } // endif OcrSrcCols + + } else switch (ttp) { case TAB_DBF: qrp= DBFColumns(g, fn, fnc == FNC_COL); break; @@ -3618,12 +3653,22 @@ static int connect_assisted_discovery(handlerton *hton, THD* thd, case TAB_PRX: case TAB_TBL: case TAB_XCL: + case TAB_OCCUR: bif= fnc == FNC_COL; qrp= TabColumns(g, thd, db, tab, bif); if (!qrp && bif && fnc != FNC_COL) // tab is a view qrp= MyColumns(g, host, db, user, pwd, tab, NULL, port, false); + if (ttp == TAB_OCCUR && fnc != FNC_COL) + if (OcrColumns(g, qrp, col, ocl, rnk)) { + my_message(ER_UNKNOWN_ERROR, g->Message, MYF(0)); + return HA_ERR_INTERNAL_ERROR; + } // endif OcrColumns + + break; + case TAB_PIVOT: + qrp= PivotColumns(g, tab, src, pic, fcl, host, db, user, pwd, port); break; default: strcpy(g->Message, "System error during assisted discovery"); @@ -3635,16 +3680,17 @@ static int connect_assisted_discovery(handlerton *hton, THD* thd, return HA_ERR_INTERNAL_ERROR; } // endif qrp - if (fnc != FNC_NO || src) { - // Catalog table + if (fnc != FNC_NO || src || ttp == TAB_PIVOT) { + // Catalog like table for (crp=qrp->Colresp; !b && crp; crp= crp->Next) { cnm= encode(g, crp->Name); type= PLGtoMYSQLtype(crp->Type, dbf); len= crp->Length; dec= crp->Prec; + flg= crp->Flag; // Now add the field - if (add_field(&sql, cnm, type, len, dec, NOT_NULL_FLAG, 0)) + if (add_field(&sql, cnm, type, len, dec, NOT_NULL_FLAG, 0, flg)) b= HA_ERR_OUT_OF_MEM; } // endfor crp @@ -3714,7 +3760,7 @@ static int connect_assisted_discovery(handlerton *hton, THD* thd, len= 0; // Now add the field - if (add_field(&sql, cnm, type, len, dec, tm, rem)) + if (add_field(&sql, cnm, type, len, dec, tm, rem, 0)) b= HA_ERR_OUT_OF_MEM; } // endfor i diff --git a/storage/connect/myconn.cpp b/storage/connect/myconn.cpp index 220be7ca0be..9ebf77ff35a 100644 --- a/storage/connect/myconn.cpp +++ b/storage/connect/myconn.cpp @@ -64,6 +64,12 @@ static char *server_groups[] = { extern "C" int trace; extern MYSQL_PLUGIN_IMPORT uint mysqld_port; +// Returns the current used port +uint GetDefaultPort(void) +{ + return mysqld_port; +} // end of GetDefaultPort + /************************************************************************/ /* MyColumns: constructs the result blocks containing all columns */ /* of a MySQL table or view. */ @@ -673,6 +679,7 @@ PQRYRES MYSQLC::GetResult(PGLOBAL g, bool pdb) *pcrp = (PCOLRES)PlugSubAlloc(g, NULL, sizeof(COLRES)); crp = *pcrp; pcrp = &crp->Next; + memset(crp, 0, sizeof(COLRES)); crp->Ncol = ++qrp->Nbcol; crp->Name = (char*)PlugSubAlloc(g, NULL, fld->name_length + 1); @@ -686,7 +693,7 @@ PQRYRES MYSQLC::GetResult(PGLOBAL g, bool pdb) // For direct MySQL connection, display the MySQL date string crp->Type = TYPE_STRING; - crp->Prec = fld->decimals; + crp->Prec = (crp->Type == TYPE_FLOAT) ? fld->decimals : 0; crp->Length = fld->max_length; crp->Clen = GetTypeSize(crp->Type, crp->Length); diff --git a/storage/connect/myconn.h b/storage/connect/myconn.h index 8148630b812..f8c8c3dcbae 100644 --- a/storage/connect/myconn.h +++ b/storage/connect/myconn.h @@ -44,6 +44,8 @@ PQRYRES SrcColumns(PGLOBAL g, const char *host, const char *db, const char *user, const char *pwd, const char *srcdef, int port); +uint GetDefaultPort(void); + /* -------------------------- MYCONN class --------------------------- */ /***********************************************************************/ diff --git a/storage/connect/plgdbsem.h b/storage/connect/plgdbsem.h index dfa46a650a6..919f3452a4d 100644 --- a/storage/connect/plgdbsem.h +++ b/storage/connect/plgdbsem.h @@ -518,6 +518,7 @@ typedef struct _colres { int Clen; /* Data individual internal size */ int Length; /* Data individual print length */ int Prec; /* Precision */ + int Flag; /* Flag option value */ XFLD Fld; /* Type of field info */ } COLRES; diff --git a/storage/connect/plgdbutl.cpp b/storage/connect/plgdbutl.cpp index 598075ac52a..73b468c9209 100644 --- a/storage/connect/plgdbutl.cpp +++ b/storage/connect/plgdbutl.cpp @@ -298,6 +298,7 @@ PQRYRES PlgAllocResult(PGLOBAL g, int ncol, int maxres, int ids, *pcrp = (PCOLRES)PlugSubAlloc(g, NULL, sizeof(COLRES)); crp = *pcrp; pcrp = &crp->Next; + memset(crp, 0, sizeof(COLRES)); crp->Colp = NULL; crp->Ncol = ++qrp->Nbcol; crp->Type = buftyp[i]; diff --git a/storage/connect/taboccur.cpp b/storage/connect/taboccur.cpp index 6c33aefbb68..065da269caa 100644 --- a/storage/connect/taboccur.cpp +++ b/storage/connect/taboccur.cpp @@ -1,5 +1,5 @@ /************ TabOccur CPP Declares Source Code File (.CPP) ************/ -/* Name: TABOCCUR.CPP Version 1.0 */ +/* Name: TABOCCUR.CPP Version 1.1 */ /* */ /* (C) Copyright to the author Olivier BERTRAND 2013 */ /* */ @@ -53,6 +53,210 @@ extern "C" int trace; +/***********************************************************************/ +/* Prepare and count columns in the column list. */ +/***********************************************************************/ +int PrepareColist(char *colist) + { + char *p, *pn; + int n = 0; + + // Count the number of columns and change separator into null char + for (pn = colist; ; pn += (strlen(pn) + 1)) + // Separator can be ; if colist was specified in the option_list + if ((p = strchr(pn, ',')) || (p = strchr(pn, ';'))) { + *p++ = '\0'; + n++; + } else { + if (*pn) + n++; + + break; + } // endif p + + return n; + } // end of PrepareColist + +/************************************************************************/ +/* OcrColumns: constructs the result blocks containing all the columns */ +/* of the object table that will be retrieved by GetData commands. */ +/************************************************************************/ +bool OcrColumns(PGLOBAL g, PQRYRES qrp, const char *col, + const char *ocr, const char *rank) + { + char *pn, *colist; + int i, k, m, n = 0, c = 0, j = qrp->Nblin; + bool rk, b = false; + PCOLRES crp; + + if (!col || !*col) { + strcpy(g->Message, "Missing colist"); + return true; + } // endif col + + // Prepare the column list + colist = (char*)PlugSubAlloc(g, NULL, strlen(col) + 1); + strcpy(colist, col); + m = PrepareColist(colist); + + if ((rk = (rank && *rank))) { + if (m == 1) { + strcpy(g->Message, "Cannot handle one column colist and rank"); + return true; + } // endif m + + for (k = 0, pn = colist; k < m; k++, pn += (strlen(pn) + 1)) + n = max(n, (signed)strlen(pn)); + + } // endif k + + // Default occur column name is the 1st colist column name + if (!ocr || !*ocr) + ocr = colist; + + /**********************************************************************/ + /* Replace the columns of the colist by the rank and occur columns. */ + /**********************************************************************/ + for (i = 0; i < qrp->Nblin; i++) { + for (k = 0, pn = colist; k < m; k++, pn += (strlen(pn) + 1)) + if (!stricmp(pn, qrp->Colresp->Kdata->GetCharValue(i))) + break; + + if (k < m) { + // This column belongs to colist + if (rk) { + // Place the rank column here + for (crp = qrp->Colresp; crp; crp = crp->Next) + switch (crp->Fld) { + case FLD_NAME: crp->Kdata->SetValue((char*)rank, i); break; + case FLD_TYPE: crp->Kdata->SetValue(TYPE_STRING, i); break; + case FLD_PREC: crp->Kdata->SetValue(n, i); break; + case FLD_SCALE: crp->Kdata->SetValue(0, i); break; + case FLD_NULL: crp->Kdata->SetValue(0, i); break; + case FLD_REM: crp->Kdata->Reset(i); break; + default: ; // Ignored by CONNECT + } // endswich Fld + + rk = false; + } else if (!b) { + // First remaining listed column, will be the occur column + for (crp = qrp->Colresp; crp; crp = crp->Next) + switch (crp->Fld) { + case FLD_NAME: crp->Kdata->SetValue((char*)ocr, i); break; + case FLD_REM: crp->Kdata->Reset(i); break; + default: ; // Nothing to do + } // endswich Fld + + b = true; + } else if (j == qrp->Nblin) + j = i; // Column to remove + + c++; + } else if (j < i) { + // Move this column in empty spot + for (crp = qrp->Colresp; crp; crp = crp->Next) + crp->Kdata->Move(i, j); + + j++; + } // endif k + + } // endfor i + + // Check whether all columns of the list where found + if (c < m) { + strcpy(g->Message, "Some colist columns are not in the source table"); + return true; + } // endif crp + + /**********************************************************************/ + /* Set the number of columns of the table. */ + /**********************************************************************/ + qrp->Nblin = j; + return false; + } // end of OcrColumns + +/************************************************************************/ +/* OcrSrcCols: constructs the result blocks containing all the columns */ +/* of the object table that will be retrieved by GetData commands. */ +/************************************************************************/ +bool OcrSrcCols(PGLOBAL g, PQRYRES qrp, const char *col, + const char *ocr, const char *rank) + { + char *pn, *colist; + int i, k, m, n = 0, c = 0; + bool rk, b = false; + PCOLRES crp, rcrp, *pcrp; + + if (!col || !*col) { + strcpy(g->Message, "Missing colist"); + return true; + } // endif col + + // Prepare the column list + colist = (char*)PlugSubAlloc(g, NULL, strlen(col) + 1); + strcpy(colist, col); + m = PrepareColist(colist); + + if ((rk = (rank && *rank))) + for (k = 0, pn = colist; k < m; k++, pn += (strlen(pn) + 1)) + n = max(n, (signed)strlen(pn)); + + // Default occur column name is the 1st colist column name + if (!ocr || !*ocr) + ocr = colist; + + /**********************************************************************/ + /* Replace the columns of the colist by the rank and occur columns. */ + /**********************************************************************/ + for (i = 0, pcrp = &qrp->Colresp; crp = *pcrp; ) { + for (k = 0, pn = colist; k < m; k++, pn += (strlen(pn) + 1)) + if (!stricmp(pn, crp->Name)) + break; + + if (k < m) { + // This column belongs to colist + c++; + + if (!b) { + if (rk) { + // Add the rank column here + rcrp = (PCOLRES)PlugSubAlloc(g, NULL, sizeof(COLRES)); + memset(rcrp, 0, sizeof(COLRES)); + rcrp->Next = crp; + rcrp->Name = (char*)rank; + rcrp->Type = TYPE_STRING; + rcrp->Length = n; + rcrp->Ncol = ++i; + *pcrp = rcrp; + } // endif rk + + // First remaining listed column, will be the occur column + crp->Name = (char*)ocr; + b = true; + } else { + *pcrp = crp->Next; // Remove this column + continue; + } // endif b + + } // endif k + + crp->Ncol = ++i; + pcrp = &crp->Next; + } // endfor pcrp + + // Check whether all columns of the list where found + if (c < m) { + strcpy(g->Message, "Some colist columns are not in the source table"); + return true; + } // endif crp + + /**********************************************************************/ + /* Set the number of columns of the table. */ + /**********************************************************************/ + qrp->Nblin = i; + return false; + } // end of OcrSrcCols + /* -------------- Implementation of the OCCUR classes ---------------- */ /***********************************************************************/ @@ -60,9 +264,9 @@ extern "C" int trace; /***********************************************************************/ bool OCCURDEF::DefineAM(PGLOBAL g, LPCSTR am, int poff) { - Xcol = Cat->GetStringCatInfo(g, "OccurCol", ""); Rcol = Cat->GetStringCatInfo(g, "RankCol", ""); Colist = Cat->GetStringCatInfo(g, "Colist", ""); + Xcol = Cat->GetStringCatInfo(g, "OccurCol", Colist); return PRXDEF::DefineAM(g, am, poff); } // end of DefineAM @@ -92,36 +296,12 @@ TDBOCCUR::TDBOCCUR(POCCURDEF tdp) : TDBPRX(tdp) Rcolumn = tdp->Rcol; // Rank column name Xcolp = NULL; // To the OCCURCOL column Col = NULL; // To source column blocks array - Mult = PrepareColist(); // Multiplication factor + Mult = PrepareColist(Colist); // 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 -/***********************************************************************/ -/* Prepare and count columns in the column list. */ -/***********************************************************************/ -int TDBOCCUR::PrepareColist(void) - { - char *p, *pn; - int n = 0; - - // Count the number of columns and change separator into null char - for (pn = Colist; ; pn += (strlen(pn) + 1)) - // Separator can be ; if colist was specified in the option_list - if ((p = strchr(pn, ',')) || (p = strchr(pn, ';'))) { - *p++ = '\0'; - n++; - } else { - if (*pn) - n++; - - break; - } // endif p - - return n; - } // end of PrepareColist - /***********************************************************************/ /* Allocate OCCUR/SRC column description block. */ /***********************************************************************/ diff --git a/storage/connect/taboccur.h b/storage/connect/taboccur.h index b7d51e05b7d..10f94329703 100644 --- a/storage/connect/taboccur.h +++ b/storage/connect/taboccur.h @@ -58,7 +58,6 @@ class TDBOCCUR : public TDBPRX { // Methods virtual void ResetDB(void) {N = 0; Tdbp->ResetDB();} virtual int RowNumber(PGLOBAL g, bool b = FALSE); - int PrepareColist(void); bool MakeColumnList(PGLOBAL g); bool ViewColumnList(PGLOBAL g); diff --git a/storage/connect/tabpivot.cpp b/storage/connect/tabpivot.cpp index 916a3c2584e..dbe702c7462 100644 --- a/storage/connect/tabpivot.cpp +++ b/storage/connect/tabpivot.cpp @@ -1,7 +1,7 @@ /************ TabPivot C++ Program Source Code File (.CPP) *************/ /* PROGRAM NAME: TABPIVOT */ /* ------------- */ -/* Version 1.5 */ +/* Version 1.6 */ /* */ /* COPYRIGHT: */ /* ---------- */ @@ -53,6 +53,182 @@ extern "C" int trace; +/***********************************************************************/ +/* Make the Pivot table column list. */ +/***********************************************************************/ +PQRYRES PivotColumns(PGLOBAL g, const char *tab, const char *src, + const char *picol, const char *fncol, + const char *host, const char *db, + const char *user, const char *pwd, + int port) + { + PIVAID pvd(tab, src, picol, fncol, host, db, user, pwd, port); + + return pvd.MakePivotColumns(g); + } // end of PivotColumns + +/* --------------- Implementation of the PIVAID classe --------------- */ + +/***********************************************************************/ +/* PIVAID constructor. */ +/***********************************************************************/ +PIVAID::PIVAID(const char *tab, const char *src, const char *picol, + const char *fncol, const char *host, const char *db, + const char *user, const char *pwd, int port) + : CSORT(false) + { + Host = (char*)host; + User = (char*)user; + Pwd = (char*)pwd; + Qryp = NULL; + Database = (char*)db; + Tabname = (char*)tab; + Tabsrc = (char*)src; + Picol = (char*)picol; + Fncol = (char*)fncol; + Rblkp = NULL; + Port = (port) ? port : GetDefaultPort(); + } // end of PIVAID constructor + +/***********************************************************************/ +/* Make the Pivot table column list. */ +/***********************************************************************/ +PQRYRES PIVAID::MakePivotColumns(PGLOBAL g) + { + char *query, *colname, buf[32]; + int ndif, nblin, w = 0; + PVAL valp; + PCOLRES *pcrp, crp, fncrp = NULL; + + if (!Tabsrc && Tabname) { + // Locate the query + query = (char*)PlugSubAlloc(g, NULL, strlen(Tabname) + 16); + sprintf(query, "SELECT * FROM %s", Tabname); + } else if (!Tabsrc) { + strcpy(g->Message, MSG(SRC_TABLE_UNDEF)); + return NULL; + } else + query = Tabsrc; + + // Open a MySQL connection for this table + if (Myc.Open(g, Host, Database, User, Pwd, Port)) + return NULL; + + // Send the source command to MySQL + if (Myc.ExecSQL(g, query, &w) == RC_FX) { + Myc.Close(); + return NULL; + } // endif Exec + + // We must have a storage query to get pivot column values + Qryp = Myc.GetResult(g); + Myc.Close(); + + if (!Fncol) { + for (crp = Qryp->Colresp; crp; crp = crp->Next) + if (!Picol || stricmp(Picol, crp->Name)) + Fncol = crp->Name; + + if (!Fncol) { + strcpy(g->Message, MSG(NO_DEF_FNCCOL)); + return NULL; + } // endif Fncol + + } // endif Fncol + + if (!Picol) { + // Find default Picol as the last one not equal to Fncol + for (crp = Qryp->Colresp; crp; crp = crp->Next) + if (stricmp(Fncol, crp->Name)) + Picol = crp->Name; + + if (!Picol) { + strcpy(g->Message, MSG(NO_DEF_PIVOTCOL)); + return NULL; + } // endif Picol + + } // endif picol + + // Prepare the column list + for (pcrp = &Qryp->Colresp; crp = *pcrp; ) + if (!stricmp(Picol, crp->Name)) { + Rblkp = crp->Kdata; + *pcrp = crp->Next; + } else if (!stricmp(Fncol, crp->Name)) { + fncrp = crp; + *pcrp = crp->Next; + } else + pcrp = &crp->Next; + + if (!Rblkp) { + strcpy(g->Message, MSG(NO_DEF_PIVOTCOL)); + return NULL; + } else if (!fncrp) { + strcpy(g->Message, MSG(NO_DEF_FNCCOL)); + return NULL; + } // endif + + // Before calling sort, initialize all + nblin = Qryp->Nblin; + + Index.Size = nblin * sizeof(int); + Index.Sub = TRUE; // Should be small enough + + if (!PlgDBalloc(g, NULL, Index)) + return NULL; + + Offset.Size = (nblin + 1) * sizeof(int); + Offset.Sub = TRUE; // Should be small enough + + if (!PlgDBalloc(g, NULL, Offset)) + return NULL; + + ndif = Qsort(g, nblin); + + if (ndif < 0) // error + return NULL; + + // Allocate the Value used to retieve column names + if (!(valp = AllocateValue(g, Rblkp->GetType(), + Rblkp->GetVlen(), + Rblkp->GetPrec()))) + return NULL; + + // Now make the functional columns + for (int i = 0; i < ndif; i++) { + if (i) { + crp = (PCOLRES)PlugSubAlloc(g, NULL, sizeof(COLRES)); + memcpy(crp, fncrp, sizeof(COLRES)); + } else + crp = fncrp; + + // Get the value that will be the generated column name + valp->SetValue_pvblk(Rblkp, Pex[Pof[i]]); + colname = valp->GetCharString(buf); + crp->Name = (char*)PlugSubAlloc(g, NULL, strlen(colname) + 1); + strcpy(crp->Name, colname); + crp->Flag = 1; + + // Add this column + *pcrp = crp; + crp->Next = NULL; + pcrp = &crp->Next; + } // endfor i + + // We added ndif columns and removed 2 (picol and fncol) + Qryp->Nbcol += (ndif - 2); + return Qryp; + } // end of MakePivotColumns + +/***********************************************************************/ +/* PIVAID: Compare routine for sorting pivot column values. */ +/***********************************************************************/ +int PIVAID::Qcompare(int *i1, int *i2) + { + // TODO: the actual comparison between pivot column result values. + return Rblkp->CompVal(*i1, *i2); + } // end of Qcompare + /* --------------- Implementation of the PIVOT classes --------------- */ /***********************************************************************/ diff --git a/storage/connect/tabpivot.h b/storage/connect/tabpivot.h index 1617801298b..4a766700162 100644 --- a/storage/connect/tabpivot.h +++ b/storage/connect/tabpivot.h @@ -1,5 +1,5 @@ /************** TabPivot H Declares Source Code File (.H) **************/ -/* Name: TABPIVOT.H Version 1.4 */ +/* Name: TABPIVOT.H Version 1.5 */ /* */ /* (C) Copyright to the author Olivier BERTRAND 2005-2013 */ /* */ @@ -10,6 +10,40 @@ typedef class TDBPIVOT *PTDBPIVOT; typedef class FNCCOL *PFNCCOL; typedef class SRCCOL *PSRCCOL; +/***********************************************************************/ +/* This class is used to generate PIVOT table column definitions. */ +/***********************************************************************/ +class PIVAID : public CSORT { + friend class FNCCOL; + friend class SRCCOL; + public: + // Constructor + PIVAID(const char *tab, const char *src, const char *picol, + const char *fncol, const char *host, const char *db, + const char *user, const char *pwd, int port); + + // Methods + PQRYRES MakePivotColumns(PGLOBAL g); + + // The sorting function + virtual int Qcompare(int *, int *); + + protected: + // Members + MYSQLC Myc; // MySQL connection class + char *Host; // Host machine to use + char *User; // User logon info + char *Pwd; // Password logon info + char *Database; // Database to be used by server + PQRYRES Qryp; // Points to Query result block + char *Tabname; // Name of source table + char *Tabsrc; // SQL of source table + char *Picol; // Pivot column name + char *Fncol; // Function column name + PVBLK Rblkp; // The value block of the pivot column + int Port; // MySQL port number + }; // end of class PIVAID + /* -------------------------- PIVOT classes -------------------------- */ /***********************************************************************/ diff --git a/storage/connect/valblk.h b/storage/connect/valblk.h index a7b1b5046d7..d9286b72f9f 100644 --- a/storage/connect/valblk.h +++ b/storage/connect/valblk.h @@ -36,6 +36,7 @@ class VALBLK : public BLOCK { void *GetValPointer(void) {return Blkp;} void SetValPointer(void *mp) {Blkp = mp;} int GetType(void) {return Type;} + int GetPrec(void) {return Prec;} void SetCheck(bool b) {Check = b;} void MoveNull(int i, int j) {if (To_Nulls) To_Nulls[j] = To_Nulls[j];} @@ -110,7 +111,7 @@ class TYPBLK : public VALBLK { // Implementation virtual void Init(PGLOBAL g, bool check); - virtual int GetVlen(void) {return sizeof(int);} + virtual int GetVlen(void) {return sizeof(TYPE);} //virtual PSZ GetCharValue(int n); virtual short GetShortValue(int n) {return (short)Typp[n];} virtual int GetIntValue(int n) {return (int)Typp[n];} From 0aa4fb73a49993d3a73550ee624b62d7556f8515 Mon Sep 17 00:00:00 2001 From: Olivier Bertrand Date: Tue, 28 May 2013 21:06:15 +0200 Subject: [PATCH 42/47] - Fix crash when a null qrp is returned for OCCUR tables in connect_assisted_discovery modified: storage/connect/ha_connect.cc - Change CRLF line endings to LF modified: storage/connect/tabpivot.cpp storage/connect/tabpivot.h --- storage/connect/ha_connect.cc | 4 +- storage/connect/tabpivot.cpp | 104 +++++++++++++++++----------------- storage/connect/tabpivot.h | 64 ++++++++++----------- 3 files changed, 86 insertions(+), 86 deletions(-) diff --git a/storage/connect/ha_connect.cc b/storage/connect/ha_connect.cc index db789dda5bd..829c194b61d 100644 --- a/storage/connect/ha_connect.cc +++ b/storage/connect/ha_connect.cc @@ -3604,7 +3604,7 @@ static int connect_assisted_discovery(handlerton *hton, THD* thd, if (src && ttp != TAB_PIVOT) { qrp= SrcColumns(g, host, db, user, pwd, src, port); - if (ttp == TAB_OCCUR) + if (qrp && ttp == TAB_OCCUR) if (OcrSrcCols(g, qrp, col, ocl, rnk)) { my_message(ER_UNKNOWN_ERROR, g->Message, MYF(0)); return HA_ERR_INTERNAL_ERROR; @@ -3660,7 +3660,7 @@ static int connect_assisted_discovery(handlerton *hton, THD* thd, if (!qrp && bif && fnc != FNC_COL) // tab is a view qrp= MyColumns(g, host, db, user, pwd, tab, NULL, port, false); - if (ttp == TAB_OCCUR && fnc != FNC_COL) + if (qrp && ttp == TAB_OCCUR && fnc != FNC_COL) if (OcrColumns(g, qrp, col, ocl, rnk)) { my_message(ER_UNKNOWN_ERROR, g->Message, MYF(0)); return HA_ERR_INTERNAL_ERROR; diff --git a/storage/connect/tabpivot.cpp b/storage/connect/tabpivot.cpp index dbe702c7462..9beca56e773 100644 --- a/storage/connect/tabpivot.cpp +++ b/storage/connect/tabpivot.cpp @@ -63,7 +63,7 @@ PQRYRES PivotColumns(PGLOBAL g, const char *tab, const char *src, int port) { PIVAID pvd(tab, src, picol, fncol, host, db, user, pwd, port); - + return pvd.MakePivotColumns(g); } // end of PivotColumns @@ -96,8 +96,8 @@ PIVAID::PIVAID(const char *tab, const char *src, const char *picol, PQRYRES PIVAID::MakePivotColumns(PGLOBAL g) { char *query, *colname, buf[32]; - int ndif, nblin, w = 0; - PVAL valp; + int ndif, nblin, w = 0; + PVAL valp; PCOLRES *pcrp, crp, fncrp = NULL; if (!Tabsrc && Tabname) { @@ -110,20 +110,20 @@ PQRYRES PIVAID::MakePivotColumns(PGLOBAL g) } else query = Tabsrc; - // Open a MySQL connection for this table - if (Myc.Open(g, Host, Database, User, Pwd, Port)) - return NULL; - - // Send the source command to MySQL - if (Myc.ExecSQL(g, query, &w) == RC_FX) { - Myc.Close(); - return NULL; - } // endif Exec - - // We must have a storage query to get pivot column values - Qryp = Myc.GetResult(g); - Myc.Close(); - + // Open a MySQL connection for this table + if (Myc.Open(g, Host, Database, User, Pwd, Port)) + return NULL; + + // Send the source command to MySQL + if (Myc.ExecSQL(g, query, &w) == RC_FX) { + Myc.Close(); + return NULL; + } // endif Exec + + // We must have a storage query to get pivot column values + Qryp = Myc.GetResult(g); + Myc.Close(); + if (!Fncol) { for (crp = Qryp->Colresp; crp; crp = crp->Next) if (!Picol || stricmp(Picol, crp->Name)) @@ -168,33 +168,33 @@ PQRYRES PIVAID::MakePivotColumns(PGLOBAL g) return NULL; } // endif - // Before calling sort, initialize all + // Before calling sort, initialize all nblin = Qryp->Nblin; - Index.Size = nblin * sizeof(int); - Index.Sub = TRUE; // Should be small enough - - if (!PlgDBalloc(g, NULL, Index)) - return NULL; - - Offset.Size = (nblin + 1) * sizeof(int); - Offset.Sub = TRUE; // Should be small enough - - if (!PlgDBalloc(g, NULL, Offset)) - return NULL; - - ndif = Qsort(g, nblin); - - if (ndif < 0) // error - return NULL; - - // Allocate the Value used to retieve column names + Index.Size = nblin * sizeof(int); + Index.Sub = TRUE; // Should be small enough + + if (!PlgDBalloc(g, NULL, Index)) + return NULL; + + Offset.Size = (nblin + 1) * sizeof(int); + Offset.Sub = TRUE; // Should be small enough + + if (!PlgDBalloc(g, NULL, Offset)) + return NULL; + + ndif = Qsort(g, nblin); + + if (ndif < 0) // error + return NULL; + + // Allocate the Value used to retieve column names if (!(valp = AllocateValue(g, Rblkp->GetType(), - Rblkp->GetVlen(), - Rblkp->GetPrec()))) - return NULL; - - // Now make the functional columns + Rblkp->GetVlen(), + Rblkp->GetPrec()))) + return NULL; + + // Now make the functional columns for (int i = 0; i < ndif; i++) { if (i) { crp = (PCOLRES)PlugSubAlloc(g, NULL, sizeof(COLRES)); @@ -202,8 +202,8 @@ PQRYRES PIVAID::MakePivotColumns(PGLOBAL g) } else crp = fncrp; - // Get the value that will be the generated column name - valp->SetValue_pvblk(Rblkp, Pex[Pof[i]]); + // Get the value that will be the generated column name + valp->SetValue_pvblk(Rblkp, Pex[Pof[i]]); colname = valp->GetCharString(buf); crp->Name = (char*)PlugSubAlloc(g, NULL, strlen(colname) + 1); strcpy(crp->Name, colname); @@ -220,15 +220,15 @@ PQRYRES PIVAID::MakePivotColumns(PGLOBAL g) return Qryp; } // end of MakePivotColumns -/***********************************************************************/ -/* PIVAID: Compare routine for sorting pivot column values. */ -/***********************************************************************/ -int PIVAID::Qcompare(int *i1, int *i2) - { - // TODO: the actual comparison between pivot column result values. - return Rblkp->CompVal(*i1, *i2); - } // end of Qcompare - +/***********************************************************************/ +/* PIVAID: Compare routine for sorting pivot column values. */ +/***********************************************************************/ +int PIVAID::Qcompare(int *i1, int *i2) + { + // TODO: the actual comparison between pivot column result values. + return Rblkp->CompVal(*i1, *i2); + } // end of Qcompare + /* --------------- Implementation of the PIVOT classes --------------- */ /***********************************************************************/ diff --git a/storage/connect/tabpivot.h b/storage/connect/tabpivot.h index 4a766700162..170c6b67ea4 100644 --- a/storage/connect/tabpivot.h +++ b/storage/connect/tabpivot.h @@ -10,40 +10,40 @@ typedef class TDBPIVOT *PTDBPIVOT; typedef class FNCCOL *PFNCCOL; typedef class SRCCOL *PSRCCOL; -/***********************************************************************/ -/* This class is used to generate PIVOT table column definitions. */ -/***********************************************************************/ -class PIVAID : public CSORT { - friend class FNCCOL; - friend class SRCCOL; - public: - // Constructor +/***********************************************************************/ +/* This class is used to generate PIVOT table column definitions. */ +/***********************************************************************/ +class PIVAID : public CSORT { + friend class FNCCOL; + friend class SRCCOL; + public: + // Constructor PIVAID(const char *tab, const char *src, const char *picol, const char *fncol, const char *host, const char *db, - const char *user, const char *pwd, int port); - - // Methods - PQRYRES MakePivotColumns(PGLOBAL g); - - // The sorting function - virtual int Qcompare(int *, int *); - - protected: - // Members - MYSQLC Myc; // MySQL connection class - char *Host; // Host machine to use - char *User; // User logon info - char *Pwd; // Password logon info - char *Database; // Database to be used by server - PQRYRES Qryp; // Points to Query result block - char *Tabname; // Name of source table - char *Tabsrc; // SQL of source table - char *Picol; // Pivot column name - char *Fncol; // Function column name - PVBLK Rblkp; // The value block of the pivot column - int Port; // MySQL port number - }; // end of class PIVAID - + const char *user, const char *pwd, int port); + + // Methods + PQRYRES MakePivotColumns(PGLOBAL g); + + // The sorting function + virtual int Qcompare(int *, int *); + + protected: + // Members + MYSQLC Myc; // MySQL connection class + char *Host; // Host machine to use + char *User; // User logon info + char *Pwd; // Password logon info + char *Database; // Database to be used by server + PQRYRES Qryp; // Points to Query result block + char *Tabname; // Name of source table + char *Tabsrc; // SQL of source table + char *Picol; // Pivot column name + char *Fncol; // Function column name + PVBLK Rblkp; // The value block of the pivot column + int Port; // MySQL port number + }; // end of class PIVAID + /* -------------------------- PIVOT classes -------------------------- */ /***********************************************************************/ From 1fe92fb87db4a59ca0a4ac1ab1223e3cbe2b8232 Mon Sep 17 00:00:00 2001 From: Alexander Barkov Date: Mon, 3 Jun 2013 11:57:34 +0400 Subject: [PATCH 43/47] Fixing the problem with my_bool_t defined two times. (it worked fine with the modern gcc, but failed on some other compilers). modified: include/my_global.h include/mysql/plugin.h include/mysql/plugin_audit.h.pp include/mysql/plugin_auth.h.pp include/mysql/plugin_ftparser.h.pp include/mysql/service_thd_timezone.h sql/item_func.cc sql/mysqld.cc sql/set_var.cc sql/sql_plugin.cc sql/sql_plugin.h sql/sql_show.cc sql/sys_vars.cc storage/perfschema/ha_perfschema.cc --- include/my_global.h | 3 ++- include/mysql/plugin.h | 2 ++ include/mysql/plugin_audit.h.pp | 2 +- include/mysql/plugin_auth.h.pp | 2 +- include/mysql/plugin_ftparser.h.pp | 2 +- include/mysql/service_thd_timezone.h | 1 - sql/item_func.cc | 4 +--- sql/mysqld.cc | 2 +- sql/set_var.cc | 2 +- sql/sql_plugin.cc | 2 +- sql/sql_plugin.h | 3 +-- sql/sql_show.cc | 2 +- sql/sys_vars.cc | 2 +- storage/perfschema/ha_perfschema.cc | 4 +--- 14 files changed, 15 insertions(+), 18 deletions(-) diff --git a/include/my_global.h b/include/my_global.h index b3c7819c9a5..b50db1fc5f3 100644 --- a/include/my_global.h +++ b/include/my_global.h @@ -1002,8 +1002,9 @@ typedef struct st_mysql_lex_string LEX_STRING; #define SOCKET_EMFILE EMFILE #endif +#include /* my_bool */ + typedef ulong myf; /* Type of MyFlags in my_funcs */ -typedef char my_bool; /* Small bool */ #define MYF(v) (myf) (v) diff --git a/include/mysql/plugin.h b/include/mysql/plugin.h index db9b8e2aa9a..a96e3e72b7b 100644 --- a/include/mysql/plugin.h +++ b/include/mysql/plugin.h @@ -45,6 +45,8 @@ class Item; #define MYSQL_THD void* #endif +typedef char my_bool; + #include #define MYSQL_XIDDATASIZE 128 diff --git a/include/mysql/plugin_audit.h.pp b/include/mysql/plugin_audit.h.pp index 8648bd6383d..e51cbc4b851 100644 --- a/include/mysql/plugin_audit.h.pp +++ b/include/mysql/plugin_audit.h.pp @@ -1,4 +1,5 @@ #include "plugin.h" +typedef char my_bool; #include #include extern struct my_snprintf_service_st { @@ -86,7 +87,6 @@ extern struct kill_statement_service_st { } *thd_kill_statement_service; enum thd_kill_levels thd_kill_level(const void*); #include -typedef char my_bool; #include "mysql_time.h" typedef long my_time_t; enum enum_mysql_timestamp_type diff --git a/include/mysql/plugin_auth.h.pp b/include/mysql/plugin_auth.h.pp index d291a87012a..28172286fb3 100644 --- a/include/mysql/plugin_auth.h.pp +++ b/include/mysql/plugin_auth.h.pp @@ -1,4 +1,5 @@ #include +typedef char my_bool; #include #include extern struct my_snprintf_service_st { @@ -86,7 +87,6 @@ extern struct kill_statement_service_st { } *thd_kill_statement_service; enum thd_kill_levels thd_kill_level(const void*); #include -typedef char my_bool; #include "mysql_time.h" typedef long my_time_t; enum enum_mysql_timestamp_type diff --git a/include/mysql/plugin_ftparser.h.pp b/include/mysql/plugin_ftparser.h.pp index b0143db4784..532e049cf53 100644 --- a/include/mysql/plugin_ftparser.h.pp +++ b/include/mysql/plugin_ftparser.h.pp @@ -1,4 +1,5 @@ #include "plugin.h" +typedef char my_bool; #include #include extern struct my_snprintf_service_st { @@ -86,7 +87,6 @@ extern struct kill_statement_service_st { } *thd_kill_statement_service; enum thd_kill_levels thd_kill_level(const void*); #include -typedef char my_bool; #include "mysql_time.h" typedef long my_time_t; enum enum_mysql_timestamp_type diff --git a/include/mysql/service_thd_timezone.h b/include/mysql/service_thd_timezone.h index f8bddba68bb..f44f011b891 100644 --- a/include/mysql/service_thd_timezone.h +++ b/include/mysql/service_thd_timezone.h @@ -38,7 +38,6 @@ */ #endif -typedef char my_bool; #include "mysql_time.h" #ifdef __cplusplus diff --git a/sql/item_func.cc b/sql/item_func.cc index d0fca63688a..d412032fa0f 100644 --- a/sql/item_func.cc +++ b/sql/item_func.cc @@ -25,7 +25,7 @@ #pragma implementation // gcc: Class implementation #endif -#include "my_global.h" /* NO_EMBEDDED_ACCESS_CHECKS */ +#include "sql_plugin.h" #include "sql_priv.h" /* It is necessary to include set_var.h instead of item.h because there @@ -52,8 +52,6 @@ #include "sp.h" #include "set_var.h" #include "debug_sync.h" -#include -#include #ifdef NO_EMBEDDED_ACCESS_CHECKS #define sp_restore_security_context(A,B) while (0) {} diff --git a/sql/mysqld.cc b/sql/mysqld.cc index fd8b990b6c3..38d58babd64 100644 --- a/sql/mysqld.cc +++ b/sql/mysqld.cc @@ -14,7 +14,7 @@ along with this program; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ -#include "my_global.h" /* NO_EMBEDDED_ACCESS_CHECKS */ +#include "sql_plugin.h" #include "sql_priv.h" #include "unireg.h" #include diff --git a/sql/set_var.cc b/sql/set_var.cc index 18d86a13998..5f5faa83a45 100644 --- a/sql/set_var.cc +++ b/sql/set_var.cc @@ -16,7 +16,7 @@ /* variable declarations are in sys_vars.cc now !!! */ -#include "my_global.h" /* NO_EMBEDDED_ACCESS_CHECKS */ +#include "sql_plugin.h" #include "sql_class.h" // set_var.h: session_var_ptr #include "set_var.h" #include "sql_priv.h" diff --git a/sql/sql_plugin.cc b/sql/sql_plugin.cc index 72f16ba7837..3c827ddda3b 100644 --- a/sql/sql_plugin.cc +++ b/sql/sql_plugin.cc @@ -15,9 +15,9 @@ along with this program; if not, write to the Free Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA */ +#include "sql_plugin.h" #include "sql_priv.h" // SHOW_MY_BOOL #include "unireg.h" -#include "my_global.h" // REQUIRED by m_string.h #include "sql_class.h" // set_var.h: THD #include "sys_vars_shared.h" #include "sql_locale.h" diff --git a/sql/sql_plugin.h b/sql/sql_plugin.h index 906ff20ddb7..5327b27e97c 100644 --- a/sql/sql_plugin.h +++ b/sql/sql_plugin.h @@ -17,7 +17,6 @@ #ifndef _sql_plugin_h #define _sql_plugin_h -#include /* the following #define adds server-only members to enum_mysql_show_type, @@ -27,7 +26,7 @@ SHOW_LONG_STATUS, SHOW_DOUBLE_STATUS, \ SHOW_HAVE, SHOW_MY_BOOL, SHOW_HA_ROWS, SHOW_SYS, \ SHOW_LONG_NOFLUSH, SHOW_LONGLONG_STATUS, SHOW_LEX_STRING -#include +#include #undef SHOW_always_last #include "m_string.h" /* LEX_STRING */ diff --git a/sql/sql_show.cc b/sql/sql_show.cc index 48fb926bfcc..623f737a62b 100644 --- a/sql/sql_show.cc +++ b/sql/sql_show.cc @@ -17,7 +17,7 @@ /* Function with list databases, tables or fields */ -#include "my_global.h" /* NO_EMBEDDED_ACCESS_CHECKS */ +#include "sql_plugin.h" #include "sql_priv.h" #include "unireg.h" #include "sql_acl.h" // fill_schema_*_privileges diff --git a/sql/sys_vars.cc b/sql/sys_vars.cc index 8c5a6c92a6b..cff36ac3bdd 100644 --- a/sql/sys_vars.cc +++ b/sql/sys_vars.cc @@ -31,7 +31,7 @@ (for example in storage/myisam/ha_myisam.cc) ! */ -#include "my_global.h" /* NO_EMBEDDED_ACCESS_CHECKS */ +#include "sql_plugin.h" #include "sql_priv.h" #include "sql_class.h" // set_var.h: THD #include "sys_vars.h" diff --git a/storage/perfschema/ha_perfschema.cc b/storage/perfschema/ha_perfschema.cc index c6c967ceb9d..aca5ad8c731 100644 --- a/storage/perfschema/ha_perfschema.cc +++ b/storage/perfschema/ha_perfschema.cc @@ -18,11 +18,9 @@ Performance schema storage engine (implementation). */ -#include "my_global.h" +#include "sql_plugin.h" #include "my_pthread.h" #include "my_atomic.h" -#include "sql_plugin.h" -#include "mysql/plugin.h" #include "ha_perfschema.h" #include "pfs_engine_table.h" #include "pfs_column_values.h" From 0a01953c1a6e586f286d44222f9371a46da1ac45 Mon Sep 17 00:00:00 2001 From: Sergei Golubchik Date: Mon, 3 Jun 2013 14:43:47 +0200 Subject: [PATCH 44/47] compiler warnings --- storage/connect/ha_connect.cc | 13 ++++++------- storage/connect/tabutil.cpp | 4 ++-- 2 files changed, 8 insertions(+), 9 deletions(-) diff --git a/storage/connect/ha_connect.cc b/storage/connect/ha_connect.cc index 829c194b61d..10e415d2f6a 100644 --- a/storage/connect/ha_connect.cc +++ b/storage/connect/ha_connect.cc @@ -693,8 +693,8 @@ char *ha_connect::GetStringOption(char *opname, char *sdef) opval= (char*)GetDBName(NULL); // Current database else if (!stricmp(opname, "Type")) // Default type opval= (!options) ? NULL : - (options->srcdef) ? "MYSQL" : - (options->tabname) ? "PROXY" : "DOS"; + (options->srcdef) ? (char*)"MYSQL" : + (options->tabname) ? (char*)"PROXY" : (char*)"DOS"; else if (!stricmp(opname, "User")) // Connected user opval= (char *) "root"; else if (!stricmp(opname, "Host")) // Connected user host @@ -792,7 +792,7 @@ int ha_connect::GetIntegerOption(char *opname) else if (!stricmp(opname, "Compressed")) opval= (options->compressed); - if (opval == NO_IVAL && options && options->oplist) + if (opval == (ulonglong)NO_IVAL && options && options->oplist) if ((pv= GetListOption(xp->g, opname, options->oplist))) opval= (unsigned)atoll(pv); @@ -2799,7 +2799,7 @@ bool ha_connect::IsSameIndex(PIXDEF xp1, PIXDEF xp2) int ha_connect::external_lock(THD *thd, int lock_type) { int rc= 0; - bool del= false, xcheck=false, cras= false; + bool xcheck=false, cras= false; MODE newmode; PTOS options= GetTableOptionStruct(table); PGLOBAL g= GetPlug(thd, xp); @@ -2949,7 +2949,6 @@ int ha_connect::external_lock(THD *thd, int lock_type) // break; case SQLCOM_DELETE: case SQLCOM_DELETE_MULTI: - del= true; case SQLCOM_TRUNCATE: newmode= MODE_DELETE; break; @@ -3207,7 +3206,7 @@ int ha_connect::delete_or_rename_table(const char *name, const char *to) /* We have to retrieve the information about this table options. */ ha_table_option_struct *pos; char key[MAX_DBKEY_LENGTH], db[128], tabname[128]; - int rc; + int rc = 0; uint key_length; TABLE_SHARE *share; THD *thd= current_thd; @@ -3253,7 +3252,7 @@ int ha_connect::delete_or_rename_table(const char *name, const char *to) err: free_table_share(share); fin: - DBUG_RETURN(0); + DBUG_RETURN(rc); } // end of delete_or_rename_table int ha_connect::delete_table(const char *name) diff --git a/storage/connect/tabutil.cpp b/storage/connect/tabutil.cpp index 04271d1a460..21dee4e1856 100644 --- a/storage/connect/tabutil.cpp +++ b/storage/connect/tabutil.cpp @@ -78,8 +78,8 @@ TABLE_SHARE *GetTableShare(PGLOBAL g, THD *thd, const char *db, //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); + k = sprintf(key, "%s", db) + 1; + k += sprintf(key + k, "%s", name); key[++k] = 0; if (!(s = alloc_table_share(db, name, key, ++k))) { From 9df57eba9f7b9bbee19bba5e880cbf611ef82d5b Mon Sep 17 00:00:00 2001 From: Olivier Bertrand Date: Tue, 4 Jun 2013 17:18:33 +0200 Subject: [PATCH 45/47] - Adding parallelism to the TBL table type modified: storage/connect/tabcol.h storage/connect/tabtbl.cpp storage/connect/tabtbl.h storage/connect/value.cpp --- storage/connect/tabcol.h | 1 + storage/connect/tabtbl.cpp | 286 ++++++++++++++++++++++++++++++++++++- storage/connect/tabtbl.h | 73 +++++++++- storage/connect/value.cpp | 18 +-- 4 files changed, 358 insertions(+), 20 deletions(-) diff --git a/storage/connect/tabcol.h b/storage/connect/tabcol.h index 20e23b80225..c5ebfdbb10d 100644 --- a/storage/connect/tabcol.h +++ b/storage/connect/tabcol.h @@ -17,6 +17,7 @@ /***********************************************************************/ class DllExport XTAB: public BLOCK { // Table Name-Owner-Srcdef block. friend class TDBPRX; + friend class TDBTBM; public: // Constructors XTAB(LPCSTR name, LPCSTR srcdef = NULL); diff --git a/storage/connect/tabtbl.cpp b/storage/connect/tabtbl.cpp index 9207ad636cf..61f9c8628d9 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.5 */ +/* Version 1.6 */ /* */ /* COPYRIGHT: */ /* ---------- */ @@ -77,6 +77,16 @@ #include "ha_connect.h" #include "mycat.h" // For GetHandler +#if defined(WIN32) +#if defined(__BORLANDC__) +#define SYSEXIT void _USERENTRY +#else +#define SYSEXIT void +#endif +#else // !WIN32 +#define SYSEXIT void * +#endif // !WIN32 + extern "C" int trace; /* ---------------------------- Class TBLDEF ---------------------------- */ @@ -87,6 +97,9 @@ extern "C" int trace; TBLDEF::TBLDEF(void) { //To_Tables = NULL; + Accept = false; + Thread = false; + Maxerr = 0; Ntables = 0; Pseudo = 3; } // end of TBLDEF constructor @@ -143,8 +156,9 @@ bool TBLDEF::DefineAM(PGLOBAL g, LPCSTR am, int poff) } // endfor pdb Maxerr = Cat->GetIntCatInfo("Maxerr", 0); - Accept = (Cat->GetBoolCatInfo("Accept", 0) != 0); - } // endif fsec || tablist + Accept = Cat->GetBoolCatInfo("Accept", false); + Thread = Cat->GetBoolCatInfo("Thread", false); + } // endif tablist return FALSE; } // end of DefineAM @@ -156,6 +170,8 @@ PTDB TBLDEF::GetTable(PGLOBAL g, MODE m) { if (Catfunc == FNC_COL) return new(g) TDBTBC(this); + else if (Thread) + return new(g) TDBTBM(this); else return new(g) TDBTBL(this); @@ -173,7 +189,7 @@ TDBTBL::TDBTBL(PTBLDEF tdp) : TDBPRX(tdp) //Tdbp = NULL; Accept = tdp->Accept; Maxerr = tdp->Maxerr; - Nbf = 0; + Nbc = 0; Rows = 0; Crp = 0; // NTables = 0; @@ -227,7 +243,7 @@ bool TDBTBL::InitTableList(PGLOBAL g) // Get the table description block of this table if (!(Tdbp = GetSubTable(g, tabp))) { - if (++Nbf > Maxerr) + if (++Nbc > Maxerr) return TRUE; // Error return else continue; // Skip this table @@ -389,7 +405,7 @@ bool TDBTBL::OpenDB(PGLOBAL g) /*********************************************************************/ if (To_Filter && Tablist) { Tablist = NULL; - Nbf = 0; + Nbc = 0; } // endif To_Filter /*********************************************************************/ @@ -497,4 +513,262 @@ void TBTBLK::ReadColumn(PGLOBAL g) } // end of ReadColumn +/* ------------------------- Class TDBTBM ---------------------------- */ + +/***********************************************************************/ +/* Thread routine that check and open one remote connection. */ +/***********************************************************************/ +pthread_handler_t ThreadOpen(void *p) + { + PTBMT cmp = (PTBMT)p; + + if (!my_thread_init()) { + set_current_thd(cmp->Thd); + + // Try to open the connection + if (!cmp->Tap->GetTo_Tdb()->OpenDB(cmp->G)) { + cmp->Ready = true; + } else + cmp->Rc = RC_FX; + + my_thread_end(); + } else + cmp->Rc = RC_FX; + + return NULL; + } // end of ThreadOpen + +/***********************************************************************/ +/* TDBTBM constructors. */ +/***********************************************************************/ +TDBTBM::TDBTBM(PTBLDEF tdp) : TDBTBL(tdp) + { + Tmp = NULL; // To data table TBMT structures + Cmp = NULL; // Current data table TBMT + Bmp = NULL; // To bad (unconnected) TBMT structures + Done = false; // TRUE after first GetAllResults + Nrc = 0; // Number of remote connections + Nlc = 0; // Number of local connections + } // end of TDBTBL standard constructor + +/***********************************************************************/ +/* Reset read/write position values. */ +/***********************************************************************/ +void TDBTBM::ResetDB(void) + { + for (PCOL colp = Columns; colp; colp = colp->GetNext()) + if (colp->GetAmType() == TYPE_AM_TABID) + colp->COLBLK::Reset(); + + for (PTABLE tabp = Tablist; tabp; tabp = tabp->GetNext()) + ((PTDBASE)tabp->GetTo_Tdb())->ResetDB(); + + Tdbp = (PTDBASE)Tablist->GetTo_Tdb(); + Crp = 0; + } // end of ResetDB + +/***********************************************************************/ +/* Returns RowId if b is false or Rownum if b is true. */ +/***********************************************************************/ +int TDBTBM::RowNumber(PGLOBAL g, bool b) + { + return Tdbp->RowNumber(g) + ((b) ? 0 : Rows); + } // end of RowNumber + +/***********************************************************************/ +/* Initialyze table parallel processing. */ +/***********************************************************************/ +bool TDBTBM::OpenTables(PGLOBAL g) + { + int k; + THD *thd = current_thd; + PTABLE tabp, *ptabp = &Tablist; + PTBMT tp, *ptp = &Tmp; + + // Allocates the TBMT blocks for the tables + for (tabp = Tablist; tabp; tabp = tabp->Next) + if (tabp->GetTo_Tdb()->GetAmType() == TYPE_AM_MYSQL) { + // Remove remote table from the local list + *ptabp = tabp->Next; + + // Make the remote table block + tp = (PTBMT)PlugSubAlloc(g, NULL, sizeof(TBMT)); + memset(tp, 0, sizeof(TBMT)); + tp->G = g; + tp->Tap = tabp; + tp->Thd = thd; + + // Create the thread that will do the table opening. + pthread_attr_init(&tp->attr); +// pthread_attr_setdetachstate(&tp->attr, PTHREAD_CREATE_JOINABLE); + + if ((k = pthread_create(&tp->Tid, &tp->attr, ThreadOpen, tp))) { + sprintf(g->Message, "pthread_create error %d", k); + Nbc++; + continue; + } // endif k + + // Add it to the remote list + *ptp = tp; + ptp = &tp->Next; + Nrc++; // Number of remote connections + } else { + ptabp = &tabp->Next; + Nlc++; // Number of local connections + } // endif Type + + return false; + } // end of OpenTables + +/***********************************************************************/ +/* TBL Access Method opening routine. */ +/* Open first file, other will be opened sequencially when reading. */ +/***********************************************************************/ +bool TDBTBM::OpenDB(PGLOBAL g) + { + if (trace) + htrc("TBM OpenDB: tdbp=%p tdb=R%d use=%d key=%p mode=%d\n", + this, Tdb_No, Use, To_Key_Col, Mode); + + if (Use == USE_OPEN) { + /*******************************************************************/ + /* Table already open, replace it at its beginning. */ + /*******************************************************************/ + ResetDB(); + return Tdbp->OpenDB(g); // Re-open fist table + } // endif use + +#if 0 + /*********************************************************************/ + /* When GetMaxsize was called, To_Filter was not set yet. */ + /*********************************************************************/ + if (To_Filter && Tablist) { + Tablist = NULL; + Nbc = 0; + } // endif To_Filter +#endif // 0 + + /*********************************************************************/ + /* Make the table list. */ + /*********************************************************************/ + if (/*!Tablist &&*/ InitTableList(g)) + return TRUE; + + /*********************************************************************/ + /* Open all remote tables of the list. */ + /*********************************************************************/ + if (OpenTables(g)) + return TRUE; + + /*********************************************************************/ + /* Proceed with local tables. */ + /*********************************************************************/ + if ((CurTable = Tablist)) { + Tdbp = (PTDBASE)CurTable->GetTo_Tdb(); + Tdbp->SetMode(Mode); + + // Check and initialize the subtable columns + for (PCOL cp = Columns; cp; cp = cp->GetNext()) + if (cp->GetAmType() == TYPE_AM_TABID) + cp->COLBLK::Reset(); + else if (((PPRXCOL)cp)->Init(g) && !Accept) + return TRUE; + + if (trace) + htrc("Opening subtable %s\n", Tdbp->GetName()); + + // Now we can safely open the table + if (Tdbp->OpenDB(g)) + return TRUE; + + } // endif *Tablist + + Use = USE_OPEN; + return FALSE; + } // end of OpenDB + +/***********************************************************************/ +/* ReadDB: Data Base read routine for MUL access method. */ +/***********************************************************************/ +int TDBTBM::ReadDB(PGLOBAL g) + { + int rc; + + if (!Done) { + // Get result from local tables + if ((rc = TDBTBL::ReadDB(g)) != RC_EF) + return rc; + else if ((rc = ReadNextRemote(g)) != RC_OK) + return rc; + + Done = true; + } // endif Done + + /*********************************************************************/ + /* Now start the reading process of remote tables. */ + /*********************************************************************/ + retry: + rc = Tdbp->ReadDB(g); + + if (rc == RC_EF) { + // Total number of rows met so far + Rows += Tdbp->RowNumber(g) - 1; + Crp += Tdbp->GetProgMax(g); + Cmp->Complete = true; + + if ((rc = ReadNextRemote(g)) == RC_OK) + goto retry; + + } else if (rc == RC_FX) + strcat(strcat(strcat(g->Message, " ("), Tdbp->GetName()), ")"); + + return rc; + } // end of ReadDB + +/***********************************************************************/ +/* ReadNext: Continue reading from next table. */ +/***********************************************************************/ +int TDBTBM::ReadNextRemote(PGLOBAL g) + { + bool b = false; + + if (Tdbp) + Tdbp->CloseDB(g); + + Cmp = NULL; + + retry: + // Search for a remote table having its result set + for (PTBMT tp = Tmp; tp; tp = tp->Next) + if (tp->Ready) { + if (!tp->Complete) + Cmp = tp; + + } else + b = true; + + if (!Cmp) { + if (b) { // more result to come +// sleep(20); + goto retry; + } else + return RC_EF; + + } // endif Curtable + + Tdbp = (PTDBASE)Cmp->Tap->GetTo_Tdb(); + + // Check and initialize the subtable columns + for (PCOL cp = Columns; cp; cp = cp->GetNext()) + if (cp->GetAmType() == TYPE_AM_TABID) + cp->COLBLK::Reset(); + else if (((PPRXCOL)cp)->Init(g) && !Accept) + return RC_FX; + + if (trace) + htrc("Reading subtable %s\n", Tdbp->GetName()); + + return RC_OK; + } // end of ReadNextRemote + /* ------------------------------------------------------------------- */ diff --git a/storage/connect/tabtbl.h b/storage/connect/tabtbl.h index 69b862ebe4e..cdd84a1dd29 100644 --- a/storage/connect/tabtbl.h +++ b/storage/connect/tabtbl.h @@ -1,5 +1,5 @@ /*************** TabTbl H Declares Source Code File (.H) ***************/ -/* Name: TABTBL.H Version 1.2 */ +/* Name: TABTBL.H Version 1.3 */ /* */ /* (C) Copyright to the author Olivier BERTRAND 2008-2013 */ /* */ @@ -11,7 +11,29 @@ typedef class TBLDEF *PTBLDEF; typedef class TDBTBL *PTDBTBL; +typedef class TDBTBM *PTDBTBM; +typedef class MYSQLC *PMYC; +/***********************************************************************/ +/* Defines the structures used for distributed TBM tables. */ +/***********************************************************************/ +typedef struct _TBMtable *PTBMT; + +typedef struct _TBMtable { + PTBMT Next; // Points to next data table struct + PTABLE Tap; // Points to the sub table + PGLOBAL G; // Needed in thread routine + bool Complete; // TRUE when all results are read + bool Ready; // TRUE when results are there + int Rows; // Total number of rows read so far + int ProgCur; // Current pos + int ProgMax; // Max pos + int Rc; // Return code + THD *Thd; + pthread_attr_t attr; // ??? + pthread_t Tid; // CheckOpen thread ID + } TBMT; + /***********************************************************************/ /* TBL table. */ /***********************************************************************/ @@ -32,6 +54,7 @@ class DllExport TBLDEF : public PRXDEF { /* Logical table description */ protected: // Members bool Accept; /* TRUE if bad tables are accepted */ + bool Thread; /* Use thread for remote tables */ int Maxerr; /* Maximum number of bad tables */ int Ntables; /* Number of tables */ }; // end of TBLDEF @@ -41,7 +64,6 @@ class DllExport TBLDEF : public PRXDEF { /* Logical table description */ /***********************************************************************/ class DllExport TDBTBL : public TDBPRX { friend class TBTBLK; - friend class TDBPLG; public: // Constructor TDBTBL(PTBLDEF tdp = NULL); @@ -51,8 +73,8 @@ class DllExport TDBTBL : public TDBPRX { // Methods virtual void ResetDB(void); - virtual int GetRecpos(void) {return Rows;} - virtual int GetBadLines(void) {return (int)Nbf;} + virtual int GetRecpos(void) {return Rows;} + virtual int GetBadLines(void) {return (int)Nbc;} // Database routines virtual PCOL MakeCol(PGLOBAL g, PCOLDEF cdp, PCOL cprec, int n); @@ -72,7 +94,7 @@ class DllExport TDBTBL : public TDBPRX { PTABLE CurTable; // Points to the current table bool Accept; // TRUE if bad tables are accepted int Maxerr; // Maximum number of bad tables - int Nbf; // Number of bad connections + int Nbc; // Number of bad connections int Rows; // Used for RowID int Crp; // Used for CurPos }; // end of class TDBTBL @@ -100,3 +122,44 @@ class TBTBLK : public TIDBLK { protected: // Must not have additional members }; // end of class TBTBLK + +/***********************************************************************/ +/* This is the TBM Access Method class declaration. */ +/***********************************************************************/ +class DllExport TDBTBM : public TDBTBL { + friend class TBTBLK; + public: + // Constructor + TDBTBM(PTBLDEF tdp = NULL); + + // Implementation +//virtual AMT GetAmType(void) {return TYPE_AM_TBL;} + + // Methods + virtual void ResetDB(void); +//virtual int GetRecpos(void) {return Rows;} +//virtual int GetBadLines(void) {return (int)Nbc;} + + // Database routines +//virtual PCOL MakeCol(PGLOBAL g, PCOLDEF cdp, PCOL cprec, int n); + virtual int GetMaxSize(PGLOBAL g) {return 10;} // Temporary + 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); + + protected: + // Internal functions +//bool InitTableList(PGLOBAL g); +//bool TestFil(PGLOBAL g, PFIL filp, PTABLE tabp); + bool OpenTables(PGLOBAL g); + int ReadNextRemote(PGLOBAL g); + + // Members + PTBMT Tmp; // To data table TBMT structures + PTBMT Cmp; // Current data table PLGF (to move to TDBTBL) + PTBMT Bmp; // To bad (unconnected) PLGF structures + bool Done; // TRUE after first GetAllResults + int Nrc; // Number of remote connections + int Nlc; // Number of local connections + }; // end of class TDBTBM diff --git a/storage/connect/value.cpp b/storage/connect/value.cpp index 1c8182b6b8d..a770ac819c9 100644 --- a/storage/connect/value.cpp +++ b/storage/connect/value.cpp @@ -566,7 +566,7 @@ void TYPVAL::SetValue_char(char *p, int n) if (minus && Tval) Tval = - Tval; - if (trace) + if (trace > 1) htrc(strcat(strcat(strcpy(buf, " setting %s to: "), Fmt), "\n"), GetTypeName(Type), Tval); @@ -585,7 +585,7 @@ void TYPVAL::SetValue_char(char *p, int n) buf[n] = '\0'; Tval = atof(buf); - if (trace) + if (trace > 1) htrc(" setting double: '%s' -> %lf\n", buf, Tval); Null = false; @@ -900,7 +900,7 @@ void TYPVAL::SetValue_char(char *p, int n) *(++p) = '\0'; - if (trace) + if (trace > 1) htrc(" Setting string to: '%s'\n", Strp); Null = false; @@ -1291,7 +1291,7 @@ bool DTVAL::MakeTime(struct tm *ptm) int n, y = ptm->tm_year; time_t t = mktime_mysql(ptm); - if (trace) + if (trace > 1) htrc("MakeTime from (%d,%d,%d,%d,%d,%d)\n", ptm->tm_year, ptm->tm_mon, ptm->tm_mday, ptm->tm_hour, ptm->tm_min, ptm->tm_sec); @@ -1314,7 +1314,7 @@ bool DTVAL::MakeTime(struct tm *ptm) } Tval= (int) t; - if (trace) + if (trace > 1) htrc("MakeTime Ival=%d\n", Tval); return false; @@ -1334,7 +1334,7 @@ bool DTVAL::MakeDate(PGLOBAL g, int *val, int nval) datm.tm_mon=0; datm.tm_year=70; - if (trace) + if (trace > 1) htrc("MakeDate from(%d,%d,%d,%d,%d,%d) nval=%d\n", val[0], val[1], val[2], val[3], val[4], val[5], nval); @@ -1398,7 +1398,7 @@ bool DTVAL::MakeDate(PGLOBAL g, int *val, int nval) } // endfor i - if (trace) + if (trace > 1) htrc("MakeDate datm=(%d,%d,%d,%d,%d,%d)\n", datm.tm_year, datm.tm_mon, datm.tm_mday, datm.tm_hour, datm.tm_min, datm.tm_sec); @@ -1459,7 +1459,7 @@ void DTVAL::SetValue_char(char *p, int n) ndv = ExtractDate(Sdate, Pdtp, DefYear, dval); MakeDate(NULL, dval, ndv); - if (trace) + if (trace > 1) htrc(" setting date: '%s' -> %d\n", Sdate, Tval); Null = false; @@ -1483,7 +1483,7 @@ void DTVAL::SetValue_psz(PSZ p) ndv = ExtractDate(Sdate, Pdtp, DefYear, dval); MakeDate(NULL, dval, ndv); - if (trace) + if (trace > 1) htrc(" setting date: '%s' -> %d\n", Sdate, Tval); Null = false; From e227d50203d6e6c94ad5727155a2df80114cb4a5 Mon Sep 17 00:00:00 2001 From: Olivier Bertrand Date: Wed, 5 Jun 2013 00:46:06 +0200 Subject: [PATCH 46/47] - Change CRLF line endings to LF modified: storage/connect/tabtbl.cpp storage/connect/tabtbl.h --- storage/connect/tabtbl.cpp | 90 +++++++++++++++++++------------------- storage/connect/tabtbl.h | 50 ++++++++++----------- 2 files changed, 70 insertions(+), 70 deletions(-) diff --git a/storage/connect/tabtbl.cpp b/storage/connect/tabtbl.cpp index 61f9c8628d9..89acc53fd4a 100644 --- a/storage/connect/tabtbl.cpp +++ b/storage/connect/tabtbl.cpp @@ -77,15 +77,15 @@ #include "ha_connect.h" #include "mycat.h" // For GetHandler -#if defined(WIN32) -#if defined(__BORLANDC__) -#define SYSEXIT void _USERENTRY -#else -#define SYSEXIT void -#endif -#else // !WIN32 -#define SYSEXIT void * -#endif // !WIN32 +#if defined(WIN32) +#if defined(__BORLANDC__) +#define SYSEXIT void _USERENTRY +#else +#define SYSEXIT void +#endif +#else // !WIN32 +#define SYSEXIT void * +#endif // !WIN32 extern "C" int trace; @@ -515,40 +515,40 @@ void TBTBLK::ReadColumn(PGLOBAL g) /* ------------------------- Class TDBTBM ---------------------------- */ -/***********************************************************************/ -/* Thread routine that check and open one remote connection. */ -/***********************************************************************/ -pthread_handler_t ThreadOpen(void *p) - { - PTBMT cmp = (PTBMT)p; - - if (!my_thread_init()) { +/***********************************************************************/ +/* Thread routine that check and open one remote connection. */ +/***********************************************************************/ +pthread_handler_t ThreadOpen(void *p) + { + PTBMT cmp = (PTBMT)p; + + if (!my_thread_init()) { set_current_thd(cmp->Thd); - // Try to open the connection - if (!cmp->Tap->GetTo_Tdb()->OpenDB(cmp->G)) { - cmp->Ready = true; - } else - cmp->Rc = RC_FX; - - my_thread_end(); - } else - cmp->Rc = RC_FX; - - return NULL; - } // end of ThreadOpen - + // Try to open the connection + if (!cmp->Tap->GetTo_Tdb()->OpenDB(cmp->G)) { + cmp->Ready = true; + } else + cmp->Rc = RC_FX; + + my_thread_end(); + } else + cmp->Rc = RC_FX; + + return NULL; + } // end of ThreadOpen + /***********************************************************************/ /* TDBTBM constructors. */ /***********************************************************************/ TDBTBM::TDBTBM(PTBLDEF tdp) : TDBTBL(tdp) { - Tmp = NULL; // To data table TBMT structures - Cmp = NULL; // Current data table TBMT - Bmp = NULL; // To bad (unconnected) TBMT structures - Done = false; // TRUE after first GetAllResults - Nrc = 0; // Number of remote connections - Nlc = 0; // Number of local connections + Tmp = NULL; // To data table TBMT structures + Cmp = NULL; // Current data table TBMT + Bmp = NULL; // To bad (unconnected) TBMT structures + Done = false; // TRUE after first GetAllResults + Nrc = 0; // Number of remote connections + Nlc = 0; // Number of local connections } // end of TDBTBL standard constructor /***********************************************************************/ @@ -580,8 +580,8 @@ int TDBTBM::RowNumber(PGLOBAL g, bool b) /***********************************************************************/ bool TDBTBM::OpenTables(PGLOBAL g) { - int k; - THD *thd = current_thd; + int k; + THD *thd = current_thd; PTABLE tabp, *ptabp = &Tablist; PTBMT tp, *ptp = &Tmp; @@ -598,16 +598,16 @@ bool TDBTBM::OpenTables(PGLOBAL g) tp->Tap = tabp; tp->Thd = thd; - // Create the thread that will do the table opening. + // Create the thread that will do the table opening. pthread_attr_init(&tp->attr); // pthread_attr_setdetachstate(&tp->attr, PTHREAD_CREATE_JOINABLE); - if ((k = pthread_create(&tp->Tid, &tp->attr, ThreadOpen, tp))) { - sprintf(g->Message, "pthread_create error %d", k); - Nbc++; - continue; - } // endif k - + if ((k = pthread_create(&tp->Tid, &tp->attr, ThreadOpen, tp))) { + sprintf(g->Message, "pthread_create error %d", k); + Nbc++; + continue; + } // endif k + // Add it to the remote list *ptp = tp; ptp = &tp->Next; diff --git a/storage/connect/tabtbl.h b/storage/connect/tabtbl.h index cdd84a1dd29..7cc2ff0b92c 100644 --- a/storage/connect/tabtbl.h +++ b/storage/connect/tabtbl.h @@ -14,26 +14,26 @@ typedef class TDBTBL *PTDBTBL; typedef class TDBTBM *PTDBTBM; typedef class MYSQLC *PMYC; -/***********************************************************************/ -/* Defines the structures used for distributed TBM tables. */ -/***********************************************************************/ -typedef struct _TBMtable *PTBMT; - -typedef struct _TBMtable { - PTBMT Next; // Points to next data table struct - PTABLE Tap; // Points to the sub table - PGLOBAL G; // Needed in thread routine - bool Complete; // TRUE when all results are read - bool Ready; // TRUE when results are there - int Rows; // Total number of rows read so far - int ProgCur; // Current pos - int ProgMax; // Max pos - int Rc; // Return code - THD *Thd; +/***********************************************************************/ +/* Defines the structures used for distributed TBM tables. */ +/***********************************************************************/ +typedef struct _TBMtable *PTBMT; + +typedef struct _TBMtable { + PTBMT Next; // Points to next data table struct + PTABLE Tap; // Points to the sub table + PGLOBAL G; // Needed in thread routine + bool Complete; // TRUE when all results are read + bool Ready; // TRUE when results are there + int Rows; // Total number of rows read so far + int ProgCur; // Current pos + int ProgMax; // Max pos + int Rc; // Return code + THD *Thd; pthread_attr_t attr; // ??? - pthread_t Tid; // CheckOpen thread ID - } TBMT; - + pthread_t Tid; // CheckOpen thread ID + } TBMT; + /***********************************************************************/ /* TBL table. */ /***********************************************************************/ @@ -156,10 +156,10 @@ class DllExport TDBTBM : public TDBTBL { int ReadNextRemote(PGLOBAL g); // Members - PTBMT Tmp; // To data table TBMT structures - PTBMT Cmp; // Current data table PLGF (to move to TDBTBL) - PTBMT Bmp; // To bad (unconnected) PLGF structures - bool Done; // TRUE after first GetAllResults - int Nrc; // Number of remote connections - int Nlc; // Number of local connections + PTBMT Tmp; // To data table TBMT structures + PTBMT Cmp; // Current data table PLGF (to move to TDBTBL) + PTBMT Bmp; // To bad (unconnected) PLGF structures + bool Done; // TRUE after first GetAllResults + int Nrc; // Number of remote connections + int Nlc; // Number of local connections }; // end of class TDBTBM From ffa2eb43560faca9f7d05c79d4c54657d33c62a6 Mon Sep 17 00:00:00 2001 From: Alexander Barkov Date: Sat, 8 Jun 2013 00:24:27 +0400 Subject: [PATCH 47/47] Fixing a few compiler warnings modified: storage/connect/ha_connect.cc storage/connect/value.cpp --- storage/connect/ha_connect.cc | 6 +++--- storage/connect/value.cpp | 2 ++ 2 files changed, 5 insertions(+), 3 deletions(-) diff --git a/storage/connect/ha_connect.cc b/storage/connect/ha_connect.cc index 10e415d2f6a..7d37b79bae8 100644 --- a/storage/connect/ha_connect.cc +++ b/storage/connect/ha_connect.cc @@ -228,8 +228,8 @@ ha_create_table_option connect_table_option_list[]= //HA_TOPTION_NUMBER("ESTIMATE", estimate, 0, 0, INT_MAX32, 1), HA_TOPTION_NUMBER("MULTIPLE", multiple, 0, 0, 2, 1), HA_TOPTION_NUMBER("HEADER", header, 0, 0, 3, 1), - HA_TOPTION_NUMBER("QUOTED", quoted, -1, 0, 3, 1), - HA_TOPTION_NUMBER("ENDING", ending, -1, 0, INT_MAX32, 1), + HA_TOPTION_NUMBER("QUOTED", quoted, (ulonglong) -1, 0, 3, 1), + HA_TOPTION_NUMBER("ENDING", ending, (ulonglong) -1, 0, INT_MAX32, 1), HA_TOPTION_NUMBER("COMPRESS", compressed, 0, 0, 2, 1), //HA_TOPTION_BOOL("COMPRESS", compressed, 0), HA_TOPTION_BOOL("MAPPED", mapped, 0), @@ -249,7 +249,7 @@ ha_create_table_option connect_table_option_list[]= */ ha_create_table_option connect_field_option_list[]= { - HA_FOPTION_NUMBER("FLAG", offset, -1, 0, INT_MAX32, 1), + HA_FOPTION_NUMBER("FLAG", offset, (ulonglong) -1, 0, INT_MAX32, 1), HA_FOPTION_NUMBER("FREQUENCY", freq, 0, 0, INT_MAX32, 1), // not used HA_FOPTION_NUMBER("OPT_VALUE", opt, 0, 0, 2, 1), // used for indexing HA_FOPTION_NUMBER("FIELD_LENGTH", fldlen, 0, 0, INT_MAX32, 1), diff --git a/storage/connect/value.cpp b/storage/connect/value.cpp index a770ac819c9..e60f3889ef5 100644 --- a/storage/connect/value.cpp +++ b/storage/connect/value.cpp @@ -88,6 +88,7 @@ PSZ strlwr(PSZ s); } #endif // !WIN32 +#ifdef NOT_USED /***********************************************************************/ /* Returns the bitmap representing the conditions that must not be */ /* met when returning from TestValue for a given operator. */ @@ -113,6 +114,7 @@ static BYTE OpBmp(PGLOBAL g, OPVAL opc) return bt; } // end of OpBmp +#endif /***********************************************************************/ /* GetTypeName: returns the PlugDB internal type name. */