mirror of
https://github.com/MariaDB/server.git
synced 2025-08-08 11:22:35 +03:00
- 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
This commit is contained in:
@@ -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
|
||||
|
@@ -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,7 +735,7 @@ bool ha_connect::SetBooleanOption(char *opname, bool b)
|
||||
/****************************************************************************/
|
||||
int ha_connect::GetIntegerOption(char *opname)
|
||||
{
|
||||
int opval= NO_IVAL;
|
||||
ulonglong opval= NO_IVAL;
|
||||
char *pv;
|
||||
PTOS options= GetTableOptionStruct(table);
|
||||
|
||||
@@ -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)
|
||||
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,19 +3311,21 @@ 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");
|
||||
@@ -3364,26 +3339,74 @@ 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"));
|
||||
} // endelse option_list
|
||||
} // 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
|
||||
|
||||
} 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)))
|
||||
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)
|
||||
case TAB_ODBC:
|
||||
@@ -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);
|
||||
|
||||
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);
|
||||
|
||||
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);
|
||||
|
||||
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
|
||||
|
@@ -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);
|
||||
}
|
||||
|
||||
|
@@ -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;
|
||||
|
||||
|
@@ -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. */
|
||||
|
@@ -507,7 +507,7 @@ DROP TABLE t1;
|
||||
SET @a=LOAD_FILE('test/t1.xml');
|
||||
SELECT CAST(@a AS CHAR CHARACTER SET latin1);
|
||||
CAST(@a AS CHAR CHARACTER SET latin1) <?xml version="1.0" encoding="iso-8859-1"?>
|
||||
<!-- Created by CONNECT Version 1.01.0004 April 10, 2013 -->
|
||||
<!-- Created by CONNECT Version 1.01.0005 April 27, 2013 -->
|
||||
<t1>
|
||||
<line>
|
||||
<node>ÀÁÂÃ</node>
|
||||
|
@@ -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) */
|
||||
|
@@ -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;
|
||||
|
||||
|
375
storage/connect/taboccur.cpp
Normal file
375
storage/connect/taboccur.cpp
Normal file
@@ -0,0 +1,375 @@
|
||||
/************ TabOccur CPP Declares Source Code File (.CPP) ************/
|
||||
/* Name: TABOCCUR.CPP Version 1.0 */
|
||||
/* */
|
||||
/* (C) Copyright to the author Olivier BERTRAND 2013 */
|
||||
/* */
|
||||
/* OCCUR: Table that provides a view of a source table where the */
|
||||
/* contain of several columns of the source table is placed in only */
|
||||
/* one column, the OCCUR column, this resulting into several rows. */
|
||||
/***********************************************************************/
|
||||
|
||||
/***********************************************************************/
|
||||
/* Include relevant section of system dependant header files. */
|
||||
/***********************************************************************/
|
||||
#include "my_global.h"
|
||||
#if defined(WIN32)
|
||||
#include <stdlib.h>
|
||||
#include <stdio.h>
|
||||
#if defined(__BORLANDC__)
|
||||
#define __MFC_COMPAT__ // To define min/max as macro
|
||||
#endif
|
||||
//#include <windows.h>
|
||||
#else
|
||||
#if defined(UNIX)
|
||||
#include <fnmatch.h>
|
||||
#include <errno.h>
|
||||
#include <stdlib.h>
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
#include "osutil.h"
|
||||
#else
|
||||
//#include <io.h>
|
||||
#endif
|
||||
//#include <fcntl.h>
|
||||
#endif
|
||||
|
||||
/***********************************************************************/
|
||||
/* Include application header files: */
|
||||
/***********************************************************************/
|
||||
#include "table.h" // MySQL table definitions
|
||||
#include "global.h"
|
||||
#include "plgdbsem.h"
|
||||
#include "reldef.h"
|
||||
#include "filamtxt.h"
|
||||
#include "tabdos.h"
|
||||
#include "tabcol.h"
|
||||
#include "taboccur.h"
|
||||
#include "xtable.h"
|
||||
#if defined(MYSQL_SUPPORT)
|
||||
#include "tabmysql.h"
|
||||
#endif // MYSQL_SUPPORT
|
||||
#include "ha_connect.h"
|
||||
#include "mycat.h"
|
||||
|
||||
extern "C" int trace;
|
||||
|
||||
/* -------------- Implementation of the OCCUR classes ---------------- */
|
||||
|
||||
/***********************************************************************/
|
||||
/* DefineAM: define specific AM block values from OCCUR table. */
|
||||
/***********************************************************************/
|
||||
bool OCCURDEF::DefineAM(PGLOBAL g, LPCSTR am, int poff)
|
||||
{
|
||||
//Tabname = Cat->GetStringCatInfo(g, "SrcTable", "");
|
||||
Xcol = Cat->GetStringCatInfo(g, "OccurCol", "");
|
||||
Rcol = Cat->GetStringCatInfo(g, "RankCol", "");
|
||||
Colist = Cat->GetStringCatInfo(g, "Colist", "");
|
||||
return PRXDEF::DefineAM(g, am, poff);
|
||||
} // end of DefineAM
|
||||
|
||||
/***********************************************************************/
|
||||
/* GetTable: makes a new TDB of the proper type. */
|
||||
/***********************************************************************/
|
||||
PTDB OCCURDEF::GetTable(PGLOBAL g, MODE m)
|
||||
{
|
||||
if (Catfunc != FNC_COL) {
|
||||
PTDB tdbp;
|
||||
PTDBOCCUR tocp = new(g) TDBOCCUR(this);
|
||||
|
||||
// Check that the source table is available
|
||||
if (!tocp || !(tdbp = tocp->GetSubTable(g, Tablep)))
|
||||
return NULL;
|
||||
|
||||
// Set Tdbp now
|
||||
tocp->SetTdbp((PTDBASE)tdbp);
|
||||
|
||||
if (tocp->MakeColumnList(g) < 0)
|
||||
return NULL;
|
||||
|
||||
return tocp;
|
||||
} else
|
||||
return new(g) TDBTBC(this);
|
||||
|
||||
} // end of GetTable
|
||||
|
||||
/* ------------------------------------------------------------------- */
|
||||
|
||||
/***********************************************************************/
|
||||
/* Implementation of the TDBOCCUR class. */
|
||||
/***********************************************************************/
|
||||
TDBOCCUR::TDBOCCUR(POCCURDEF tdp) : TDBPRX(tdp)
|
||||
{
|
||||
//Tdbp = NULL; // Source table
|
||||
Tabname = tdp->Tablep->GetName(); // Name of source table
|
||||
Colist = tdp->Colist; // List of source columns
|
||||
Xcolumn = tdp->Xcol; // Occur column name
|
||||
Rcolumn = tdp->Rcol; // Rank column name
|
||||
Xcolp = NULL; // To the OCCURCOL column
|
||||
Col = NULL; // To source column blocks array
|
||||
Mult = -1; // Multiplication factor
|
||||
N = 0; // The current table index
|
||||
M = 0; // The occurence rank
|
||||
RowFlag = 0; // 0: Ok, 1: Same, 2: Skip
|
||||
} // end of TDBOCCUR constructor
|
||||
|
||||
/***********************************************************************/
|
||||
/* Allocate OCCUR/SRC column description block. */
|
||||
/***********************************************************************/
|
||||
PCOL TDBOCCUR::MakeCol(PGLOBAL g, PCOLDEF cdp, PCOL cprec, int n)
|
||||
{
|
||||
PCOL colp = NULL;
|
||||
|
||||
if (!stricmp(cdp->GetName(), Rcolumn)) {
|
||||
// Allocate a RANK column
|
||||
colp = new(g) RANKCOL(cdp, this, n);
|
||||
} else if (!stricmp(cdp->GetName(), Xcolumn)) {
|
||||
// Allocate the OCCUR column
|
||||
colp = Xcolp = new(g) OCCURCOL(cdp, this, n);
|
||||
} else {
|
||||
colp = new(g) PRXCOL(cdp, this, cprec, n);
|
||||
|
||||
if (((PPRXCOL)colp)->Init(g))
|
||||
return NULL;
|
||||
|
||||
return colp;
|
||||
} //endif name
|
||||
|
||||
if (cprec) {
|
||||
colp->SetNext(cprec->GetNext());
|
||||
cprec->SetNext(colp);
|
||||
} else {
|
||||
colp->SetNext(Columns);
|
||||
Columns = colp;
|
||||
} // endif cprec
|
||||
|
||||
return colp;
|
||||
} // end of MakeCol
|
||||
|
||||
/***********************************************************************/
|
||||
/* Allocate OCCUR column description block. */
|
||||
/***********************************************************************/
|
||||
int TDBOCCUR::MakeColumnList(PGLOBAL g)
|
||||
{
|
||||
if (Mult < 0) {
|
||||
char *p, *pn;
|
||||
int i;
|
||||
int n = 0;
|
||||
|
||||
// Count the number of columns and change separator into null char
|
||||
for (pn = Colist; ; pn += (strlen(pn) + 1))
|
||||
if ((p = strchr(pn, ';'))) {
|
||||
*p++ = '\0';
|
||||
n++;
|
||||
} else {
|
||||
if (*pn)
|
||||
n++;
|
||||
|
||||
break;
|
||||
} // endif p
|
||||
|
||||
Col = (PCOL*)PlugSubAlloc(g, NULL, n * sizeof(PCOL));
|
||||
|
||||
for (i = 0, pn = Colist; i < n; i++, pn += (strlen(pn) + 1)) {
|
||||
if (!(Col[i] = Tdbp->ColDB(g, pn, 0))) {
|
||||
// Column not found in table
|
||||
sprintf(g->Message, MSG(COL_ISNOT_TABLE), pn, Tabname);
|
||||
return -1;
|
||||
} // endif Col
|
||||
|
||||
if (Col[i]->InitValue(g)) {
|
||||
strcpy(g->Message, "OCCUR InitValue failed");
|
||||
return -1;
|
||||
} // endif InitValue
|
||||
|
||||
} // endfor i
|
||||
|
||||
// OCCUR column name defaults to the name of the list first column
|
||||
if (!Xcolumn)
|
||||
Xcolumn = Colist;
|
||||
|
||||
Mult = n;
|
||||
} // endif Mult
|
||||
|
||||
return Mult;
|
||||
} // end of MakeColumnList
|
||||
|
||||
/***********************************************************************/
|
||||
/* OCCUR GetMaxSize: returns the maximum number of rows in the table. */
|
||||
/***********************************************************************/
|
||||
int TDBOCCUR::GetMaxSize(PGLOBAL g)
|
||||
{
|
||||
if (MaxSize < 0) {
|
||||
// Mult = MakeColumnList(g);
|
||||
MaxSize = Mult * Tdbp->GetMaxSize(g);
|
||||
} // endif MaxSize
|
||||
|
||||
return MaxSize;
|
||||
} // end of GetMaxSize
|
||||
|
||||
/***********************************************************************/
|
||||
/* In this sample, ROWID will be the (virtual) row number, */
|
||||
/* while ROWNUM will be the occurence rank in the multiple column. */
|
||||
/***********************************************************************/
|
||||
int TDBOCCUR::RowNumber(PGLOBAL g, bool b)
|
||||
{
|
||||
return (b) ? M : N;
|
||||
} // end of RowNumber
|
||||
|
||||
/***********************************************************************/
|
||||
/* OCCUR Access Method opening routine. */
|
||||
/***********************************************************************/
|
||||
bool TDBOCCUR::OpenDB(PGLOBAL g)
|
||||
{
|
||||
if (Use == USE_OPEN) {
|
||||
/*******************************************************************/
|
||||
/* Table already open, just replace it at its beginning. */
|
||||
/*******************************************************************/
|
||||
N = M = 0;
|
||||
RowFlag = 0;
|
||||
|
||||
if (Xcolp)
|
||||
Xcolp->Xreset();
|
||||
|
||||
return Tdbp->OpenDB(g);
|
||||
} // endif use
|
||||
|
||||
/*********************************************************************/
|
||||
/* Do it here if not done yet. */
|
||||
/*********************************************************************/
|
||||
// if (MakeColumnList(g) < 0)
|
||||
// return TRUE;
|
||||
|
||||
if (Mode != MODE_READ) {
|
||||
/*******************************************************************/
|
||||
/* Currently OCCUR tables cannot be modified. */
|
||||
/*******************************************************************/
|
||||
strcpy(g->Message, "OCCUR tables are read only");
|
||||
return TRUE;
|
||||
} // endif Mode
|
||||
|
||||
#if 0
|
||||
/*********************************************************************/
|
||||
/* Be sure OCCUR column exist. */
|
||||
/*********************************************************************/
|
||||
if (!Xcolp) {
|
||||
if (!(Xcolp = (POCCURCOL)ColDB(g, Xcolumn, 0))) {
|
||||
sprintf(g->Message, "OCCUR column %s definition error", Xcolumn);
|
||||
return TRUE;
|
||||
} else if (Xcolp->InitValue(g)) {
|
||||
strcpy(g->Message, "OCCUR InitValue failed");
|
||||
return TRUE;
|
||||
} // endif's Xcolp
|
||||
|
||||
} // endif Xcolp
|
||||
#endif // 0
|
||||
|
||||
if (Xcolp)
|
||||
// Lock this column so it is evaluated by its table only
|
||||
Xcolp->AddStatus(BUF_READ);
|
||||
|
||||
if (To_Key_Col || To_Kindex) {
|
||||
/*******************************************************************/
|
||||
/* Direct access of OCCUR tables is not implemented yet. */
|
||||
/*******************************************************************/
|
||||
strcpy(g->Message, "No direct access to OCCUR tables");
|
||||
return TRUE;
|
||||
} // endif To_Key_Col
|
||||
|
||||
/*********************************************************************/
|
||||
/* Do open the source table. */
|
||||
/*********************************************************************/
|
||||
return Tdbp->OpenDB(g);
|
||||
} // end of OpenDB
|
||||
|
||||
/***********************************************************************/
|
||||
/* Data Base read routine for OCCUR access method. */
|
||||
/***********************************************************************/
|
||||
int TDBOCCUR::ReadDB(PGLOBAL g)
|
||||
{
|
||||
int rc = RC_OK;
|
||||
|
||||
/*********************************************************************/
|
||||
/* Now start the multi reading process. */
|
||||
/*********************************************************************/
|
||||
do {
|
||||
if (RowFlag != 1)
|
||||
if ((rc = Tdbp->ReadDB(g)) != RC_OK)
|
||||
break;
|
||||
|
||||
if (Xcolp) {
|
||||
RowFlag = 0;
|
||||
Xcolp->ReadColumn(g);
|
||||
M = Xcolp->GetI();
|
||||
} // endif Xcolp
|
||||
|
||||
} while (RowFlag == 2);
|
||||
|
||||
N++;
|
||||
return rc;
|
||||
} // end of ReadDB
|
||||
|
||||
// ------------------------ OCCURCOL functions ----------------------------
|
||||
|
||||
/***********************************************************************/
|
||||
/* OCCURCOL public constructor. */
|
||||
/***********************************************************************/
|
||||
OCCURCOL::OCCURCOL(PCOLDEF cdp, PTDBOCCUR tdbp, int n)
|
||||
: COLBLK(cdp, tdbp, n)
|
||||
{
|
||||
// Set additional OCCUR access method information for column.
|
||||
I = 0;
|
||||
} // end of OCCURCOL constructor
|
||||
|
||||
/***********************************************************************/
|
||||
/* ReadColumn: what this routine does is to access the columns of */
|
||||
/* list, extract their value and convert it to buffer type. */
|
||||
/***********************************************************************/
|
||||
void OCCURCOL::ReadColumn(PGLOBAL g)
|
||||
{
|
||||
PTDBOCCUR tdbp = (PTDBOCCUR)To_Tdb;
|
||||
PCOL *col = tdbp->Col;
|
||||
|
||||
for (; I < tdbp->Mult; I++) {
|
||||
col[I]->ReadColumn(g);
|
||||
|
||||
if (Nullable || !col[I]->GetValue()->IsZero())
|
||||
break;
|
||||
|
||||
} // endfor I
|
||||
|
||||
if (I == tdbp->Mult) {
|
||||
// No more values, go to next source row
|
||||
tdbp->RowFlag = 2;
|
||||
I = 0;
|
||||
return;
|
||||
} // endif I
|
||||
|
||||
// Set the OCCUR column value from the Ith source column value
|
||||
Value->SetValue_pval(col[I++]->GetValue());
|
||||
tdbp->RowFlag = 1;
|
||||
} // end of ReadColumn
|
||||
|
||||
|
||||
// ------------------------ RANKCOL functions ---------------------------
|
||||
|
||||
/***********************************************************************/
|
||||
/* ReadColumn: what this routine does is to access the Mth columns of */
|
||||
/* list, extract its name and set to it the rank column value. */
|
||||
/***********************************************************************/
|
||||
void RANKCOL::ReadColumn(PGLOBAL g)
|
||||
{
|
||||
PTDBOCCUR tdbp = (PTDBOCCUR)To_Tdb;
|
||||
PCOL *col = tdbp->Col;
|
||||
|
||||
// Set the RANK column value from the Mth source column name
|
||||
if (tdbp->M)
|
||||
Value->SetValue_psz(col[tdbp->M - 1]->GetName());
|
||||
else {
|
||||
Value->Reset();
|
||||
|
||||
if (Nullable)
|
||||
Value->SetNull(true);
|
||||
|
||||
} // endelse
|
||||
|
||||
} // end of ReadColumn
|
145
storage/connect/taboccur.h
Normal file
145
storage/connect/taboccur.h
Normal file
@@ -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
|
||||
|
@@ -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;
|
||||
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,27 +226,21 @@ 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 = alloc_table_share(db, tblp->Name, key, ++k))) {
|
||||
strcpy(g->Message, "Error allocating share\n");
|
||||
//if (!(s = GetTableShare(g, thd, db, tblp->Name, mysql)))
|
||||
if (!(s = GetTableShare(g, thd, tblp->DB, tblp->Name, mysql)))
|
||||
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;
|
||||
sprintf(g->Message, "Cannot access %s.%s", tblp->DB, tblp->Name);
|
||||
goto err;
|
||||
} // endif Define
|
||||
|
||||
if (tabp->GetQualifier())
|
||||
@@ -257,7 +249,7 @@ PTDB TDBTBL::GetSubTable(PGLOBAL g, PTBL tblp, PTABLE tabp)
|
||||
#else // !MYSQL_SUPPORT
|
||||
sprintf(g->Message, "%s.%s is not a CONNECT table",
|
||||
db, tblp->Name);
|
||||
return NULL;
|
||||
goto err;
|
||||
#endif // MYSQL_SUPPORT
|
||||
} else {
|
||||
// Sub-table is a CONNECT table
|
||||
@@ -266,16 +258,15 @@ PTDB TDBTBL::GetSubTable(PGLOBAL g, PTBL tblp, PTABLE tabp)
|
||||
hc->tshp = NULL;
|
||||
} // endif plugin
|
||||
|
||||
} else
|
||||
sprintf(g->Message, "Error %d opening share\n", s->error);
|
||||
|
||||
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,22 +275,19 @@ 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
|
||||
@@ -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;
|
||||
|
||||
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 ------------------------------- */
|
||||
|
||||
|
@@ -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. */
|
||||
|
596
storage/connect/tabutil.cpp
Normal file
596
storage/connect/tabutil.cpp
Normal file
@@ -0,0 +1,596 @@
|
||||
/************* Tabutil cpp Declares Source Code File (.H) **************/
|
||||
/* Name: TABUTIL.CPP Version 1.0 */
|
||||
/* */
|
||||
/* (C) Copyright to the author Olivier BERTRAND 2013 */
|
||||
/* */
|
||||
/* Utility function used by TBL and PRX tables. */
|
||||
/***********************************************************************/
|
||||
|
||||
/***********************************************************************/
|
||||
/* Include relevant section of system dependant header files. */
|
||||
/***********************************************************************/
|
||||
#include "my_global.h"
|
||||
#include "sql_class.h"
|
||||
#include "table.h"
|
||||
#include "field.h"
|
||||
#if defined(WIN32)
|
||||
#include <stdlib.h>
|
||||
#include <stdio.h>
|
||||
#if defined(__BORLANDC__)
|
||||
#define __MFC_COMPAT__ // To define min/max as macro
|
||||
#endif
|
||||
//#include <windows.h>
|
||||
#else
|
||||
#if defined(UNIX)
|
||||
#include <fnmatch.h>
|
||||
#include <errno.h>
|
||||
#include <stdlib.h>
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
#include "osutil.h"
|
||||
#else
|
||||
//#include <io.h>
|
||||
#endif
|
||||
//#include <fcntl.h>
|
||||
#endif
|
||||
|
||||
/***********************************************************************/
|
||||
/* Include application header files: */
|
||||
/***********************************************************************/
|
||||
#include "table.h" // MySQL table definitions
|
||||
#include "global.h"
|
||||
#include "plgdbsem.h"
|
||||
#include "plgcnx.h" // For DB types
|
||||
#include "myutil.h"
|
||||
#include "mycat.h"
|
||||
#include "valblk.h"
|
||||
#include "resource.h"
|
||||
#include "reldef.h"
|
||||
#include "xtable.h"
|
||||
#if defined(MYSQL_SUPPORT)
|
||||
#include "tabmysql.h"
|
||||
#endif // MYSQL_SUPPORT
|
||||
#include "tabcol.h"
|
||||
#include "tabutil.h"
|
||||
#include "ha_connect.h"
|
||||
|
||||
extern "C" int trace;
|
||||
|
||||
/************************************************************************/
|
||||
/* GetTableShare: allocates and open a table share. */
|
||||
/************************************************************************/
|
||||
TABLE_SHARE *GetTableShare(PGLOBAL g, THD *thd, const char *db,
|
||||
const char *name, bool& mysql)
|
||||
{
|
||||
char key[256];
|
||||
uint k;
|
||||
//TABLE_LIST table_list;
|
||||
TABLE_SHARE *s;
|
||||
|
||||
//table_list.init_one_table(db, strlen(db), name, strlen(name),
|
||||
// NULL, TL_IGNORE);
|
||||
k = sprintf(key, "%s", db);
|
||||
k += sprintf(key + ++k, "%s", name);
|
||||
key[++k] = 0;
|
||||
|
||||
if (!(s = alloc_table_share(db, name, key, ++k))) {
|
||||
strcpy(g->Message, "Error allocating share\n");
|
||||
return NULL;
|
||||
} // endif s
|
||||
|
||||
// 1 2 4 8
|
||||
//flags = GTS_TABLE | GTS_VIEW | GTS_NOLOCK | GTS_FORCE_DISCOVERY;
|
||||
|
||||
if (!open_table_def(thd, s, GTS_TABLE)) {
|
||||
#ifdef DBUG_OFF
|
||||
if (stricmp(s->db_plugin->name.str, "connect")) {
|
||||
#else
|
||||
if (stricmp((*s->db_plugin)->name.str, "connect")) {
|
||||
#endif
|
||||
#if defined(MYSQL_SUPPORT)
|
||||
mysql = true;
|
||||
#else // !MYSQL_SUPPORT
|
||||
sprintf(g->Message, "%s.%s is not a CONNECT table", db, name);
|
||||
return NULL;
|
||||
#endif // MYSQL_SUPPORT
|
||||
} else
|
||||
mysql = false;
|
||||
|
||||
} else {
|
||||
sprintf(g->Message, "Error %d opening share\n", s->error);
|
||||
free_table_share(s);
|
||||
return NULL;
|
||||
} // endif open_table_def
|
||||
|
||||
return s;
|
||||
} // end of GetTableShare
|
||||
|
||||
/************************************************************************/
|
||||
/* TabColumns: constructs the result blocks containing all the columns */
|
||||
/* of the object table that will be retrieved by GetData commands. */
|
||||
/* key = TRUE when called from Create Table to get key informations. */
|
||||
/************************************************************************/
|
||||
PQRYRES TabColumns(PGLOBAL g, THD *thd, const char *db,
|
||||
const char *name, bool info)
|
||||
{
|
||||
static int dbtype[] = {DB_CHAR, DB_SHORT, DB_CHAR, DB_INT,
|
||||
DB_INT, DB_SHORT, DB_SHORT, DB_SHORT,
|
||||
DB_CHAR, DB_CHAR, DB_CHAR};
|
||||
static int buftyp[] = {TYPE_STRING, TYPE_SHORT, TYPE_STRING, TYPE_INT,
|
||||
TYPE_INT, TYPE_SHORT, TYPE_SHORT, TYPE_SHORT,
|
||||
TYPE_STRING, TYPE_STRING, TYPE_STRING};
|
||||
static XFLD fldtyp[] = {FLD_NAME, FLD_TYPE, FLD_TYPENAME, FLD_PREC,
|
||||
FLD_LENGTH, FLD_SCALE, FLD_RADIX, FLD_NULL,
|
||||
FLD_REM, FLD_NO, FLD_CHARSET};
|
||||
static unsigned int length[] = {0, 4, 16, 4, 4, 4, 4, 4, 256, 32, 32};
|
||||
char *fld, *fmt;
|
||||
int i, n, ncol = sizeof(dbtype) / sizeof(int);
|
||||
int len, type, prec;
|
||||
bool mysql;
|
||||
TABLE_SHARE *s;
|
||||
Field* *field;
|
||||
Field *fp;
|
||||
PQRYRES qrp;
|
||||
PCOLRES crp;
|
||||
|
||||
if (!info) {
|
||||
if (!(s = GetTableShare(g, thd, db, name, mysql)))
|
||||
return NULL;
|
||||
else
|
||||
n = s->fieldnames.count;
|
||||
|
||||
} else {
|
||||
n = 0;
|
||||
length[0] = 128;
|
||||
} // endif info
|
||||
|
||||
/**********************************************************************/
|
||||
/* Allocate the structures used to refer to the result set. */
|
||||
/**********************************************************************/
|
||||
qrp = PlgAllocResult(g, ncol, n, IDS_COLUMNS + 3,
|
||||
dbtype, buftyp, fldtyp, length, true, true);
|
||||
|
||||
// Some columns must be renamed
|
||||
for (i = 0, crp = qrp->Colresp; crp; crp = crp->Next)
|
||||
switch (++i) {
|
||||
case 10: crp->Name = "Date_fmt"; break;
|
||||
case 11: crp->Name = "Collation"; break;
|
||||
} // endswitch i
|
||||
|
||||
if (info)
|
||||
return qrp;
|
||||
|
||||
/**********************************************************************/
|
||||
/* Now get the results into blocks. */
|
||||
/**********************************************************************/
|
||||
for (i = 0, field= s->field; *field; i++, field++) {
|
||||
fp= *field;
|
||||
|
||||
// Get column name
|
||||
crp = qrp->Colresp; // Column_Name
|
||||
fld = (char *)fp->field_name;
|
||||
crp->Kdata->SetValue(fld, i);
|
||||
|
||||
if ((type = MYSQLtoPLG(fp->type())) == TYPE_ERROR) {
|
||||
sprintf(g->Message, "Unsupported column type %s", GetTypeName(type));
|
||||
qrp = NULL;
|
||||
break;
|
||||
} // endif type
|
||||
|
||||
crp = crp->Next; // Data_Type
|
||||
crp->Kdata->SetValue(type, i);
|
||||
crp = crp->Next; // Type_Name
|
||||
crp->Kdata->SetValue(GetTypeName(type), i);
|
||||
|
||||
if (type == TYPE_DATE) {
|
||||
// When creating tables we do need info about date columns
|
||||
if (mysql) {
|
||||
fmt = MyDateFmt(fp->type());
|
||||
len = strlen(fmt);
|
||||
} else {
|
||||
fmt = (char*)fp->option_struct->dateformat;
|
||||
len = fp->field_length;
|
||||
} // endif mysql
|
||||
|
||||
} else {
|
||||
fmt = NULL;
|
||||
len = fp->char_length();
|
||||
} // endif type
|
||||
|
||||
crp = crp->Next; // Precision
|
||||
crp->Kdata->SetValue(len, i);
|
||||
|
||||
crp = crp->Next; // Length
|
||||
len = fp->field_length;
|
||||
crp->Kdata->SetValue(len, i);
|
||||
|
||||
prec = (type == TYPE_FLOAT) ? fp->decimals() : 0;
|
||||
crp = crp->Next; // Scale
|
||||
crp->Kdata->SetValue(prec, i);
|
||||
|
||||
crp = crp->Next; // Radix
|
||||
crp->Kdata->SetValue(0, i);
|
||||
|
||||
crp = crp->Next; // Nullable
|
||||
crp->Kdata->SetValue((fp->null_ptr != 0) ? 1 : 0, i);
|
||||
|
||||
crp = crp->Next; // Remark
|
||||
fld = fp->comment.str;
|
||||
crp->Kdata->SetValue(fld, fp->comment.length, i);
|
||||
|
||||
crp = crp->Next; // New
|
||||
crp->Kdata->SetValue((fmt) ? fmt : (char*) "", i);
|
||||
|
||||
crp = crp->Next; // New (charset)
|
||||
fld = (char *)fp->charset()->name;
|
||||
crp->Kdata->SetValue(fld, i);
|
||||
|
||||
// Add this item
|
||||
qrp->Nblin++;
|
||||
} // endfor field
|
||||
|
||||
/**********************************************************************/
|
||||
/* Return the result pointer for use by GetData routines. */
|
||||
/**********************************************************************/
|
||||
free_table_share(s);
|
||||
return qrp;
|
||||
} // end of TabColumns
|
||||
|
||||
/* -------------- Implementation of the XCOL classes ---------------- */
|
||||
|
||||
/***********************************************************************/
|
||||
/* PRXDEF constructor. */
|
||||
/***********************************************************************/
|
||||
PRXDEF::PRXDEF(void)
|
||||
{
|
||||
Tablep = NULL;
|
||||
Pseudo = 3;
|
||||
} // end of PRXDEF constructor
|
||||
|
||||
/***********************************************************************/
|
||||
/* DefineAM: define specific AM block values from XCOL file. */
|
||||
/***********************************************************************/
|
||||
bool PRXDEF::DefineAM(PGLOBAL g, LPCSTR am, int poff)
|
||||
{
|
||||
char *pn, *db, *tab;
|
||||
|
||||
db = Cat->GetStringCatInfo(g, "Dbname", "*");
|
||||
tab = Cat->GetStringCatInfo(g, "Tabname", NULL);
|
||||
|
||||
// Analyze the table name, it may have the format: [dbname.]tabname
|
||||
if ((pn = strchr(tab, '.'))) {
|
||||
*pn++ = 0;
|
||||
db = tab;
|
||||
tab = pn;
|
||||
} // endif pn
|
||||
|
||||
Tablep = new(g) XTAB(tab);
|
||||
Tablep->SetQualifier(db);
|
||||
return FALSE;
|
||||
} // end of DefineAM
|
||||
|
||||
/***********************************************************************/
|
||||
/* GetTable: makes a new TDB of the proper type. */
|
||||
/***********************************************************************/
|
||||
PTDB PRXDEF::GetTable(PGLOBAL g, MODE mode)
|
||||
{
|
||||
if (Catfunc == FNC_COL)
|
||||
return new(g) TDBTBC(this);
|
||||
else
|
||||
return new(g) TDBPRX(this);
|
||||
|
||||
} // end of GetTable
|
||||
|
||||
/* ------------------------------------------------------------------- */
|
||||
|
||||
/***********************************************************************/
|
||||
/* Implementation of the TDBPRX class. */
|
||||
/***********************************************************************/
|
||||
TDBPRX::TDBPRX(PPRXDEF tdp) : TDBASE(tdp)
|
||||
{
|
||||
Tdbp = NULL; // The object table
|
||||
} // end of TDBPRX constructor
|
||||
|
||||
/***********************************************************************/
|
||||
/* Get the PTDB of the sub-table. */
|
||||
/***********************************************************************/
|
||||
PTDB TDBPRX::GetSubTable(PGLOBAL g, PTABLE tabp)
|
||||
{
|
||||
char *db, *name;
|
||||
bool mysql;
|
||||
PTDB tdbp = NULL;
|
||||
TABLE_SHARE *s;
|
||||
PCATLG cat = To_Def->GetCat();
|
||||
PHC hc = ((MYCAT*)cat)->GetHandler();
|
||||
THD *thd = (hc->GetTable())->in_use;
|
||||
|
||||
db = (char*)tabp->GetQualifier();
|
||||
name = (char*)tabp->GetName();
|
||||
|
||||
if (!(s = GetTableShare(g, thd, db, name, mysql)))
|
||||
return NULL;
|
||||
|
||||
hc->tshp = s;
|
||||
|
||||
if (mysql) {
|
||||
#if defined(MYSQL_SUPPORT)
|
||||
// Access sub-table via MySQL API
|
||||
if (!(tdbp= cat->GetTable(g, tabp, MODE_READ, "MYSQL"))) {
|
||||
sprintf(g->Message, "Cannot access %s.%s", db, name);
|
||||
goto err;
|
||||
} // endif Define
|
||||
|
||||
if (db)
|
||||
((PTDBMY)tdbp)->SetDatabase(tabp->GetQualifier());
|
||||
|
||||
#else // !MYSQL_SUPPORT
|
||||
sprintf(g->Message, "%s.%s is not a CONNECT table",
|
||||
db, tblp->Name);
|
||||
goto err;
|
||||
#endif // MYSQL_SUPPORT
|
||||
} else
|
||||
// Sub-table is a CONNECT table
|
||||
tdbp = cat->GetTable(g, tabp);
|
||||
|
||||
hc->tshp = NULL;
|
||||
|
||||
if (trace && tdbp)
|
||||
htrc("Subtable %s in %s\n",
|
||||
name, SVP(((PTDBASE)tdbp)->GetDef()->GetDB()));
|
||||
|
||||
err:
|
||||
free_table_share(s);
|
||||
return tdbp;
|
||||
} // end of GetSubTable
|
||||
|
||||
/***********************************************************************/
|
||||
/* Initializes the table. */
|
||||
/***********************************************************************/
|
||||
bool TDBPRX::InitTable(PGLOBAL g)
|
||||
{
|
||||
if (!Tdbp) {
|
||||
// Get the table description block of this table
|
||||
if (!(Tdbp = (PTDBASE)GetSubTable(g, ((PPRXDEF)To_Def)->Tablep)))
|
||||
return TRUE;
|
||||
|
||||
} // endif Tdbp
|
||||
|
||||
return FALSE;
|
||||
} // end of InitTable
|
||||
|
||||
/***********************************************************************/
|
||||
/* Allocate PRX column description block. */
|
||||
/***********************************************************************/
|
||||
PCOL TDBPRX::MakeCol(PGLOBAL g, PCOLDEF cdp, PCOL cprec, int n)
|
||||
{
|
||||
return new(g) PRXCOL(cdp, this, cprec, n);
|
||||
} // end of MakeCol
|
||||
|
||||
/***********************************************************************/
|
||||
/* PRX GetMaxSize: returns the maximum number of rows in the table. */
|
||||
/***********************************************************************/
|
||||
int TDBPRX::GetMaxSize(PGLOBAL g)
|
||||
{
|
||||
if (MaxSize < 0) {
|
||||
if (InitTable(g))
|
||||
return NULL;
|
||||
|
||||
MaxSize = Tdbp->GetMaxSize(g);
|
||||
} // endif MaxSize
|
||||
|
||||
return MaxSize;
|
||||
} // end of GetMaxSize
|
||||
|
||||
/***********************************************************************/
|
||||
/* In this sample, ROWID will be the (virtual) row number, */
|
||||
/* while ROWNUM will be the occurence rank in the multiple column. */
|
||||
/***********************************************************************/
|
||||
int TDBPRX::RowNumber(PGLOBAL g, bool b)
|
||||
{
|
||||
return Tdbp->RowNumber(g, b);
|
||||
} // end of RowNumber
|
||||
|
||||
/***********************************************************************/
|
||||
/* XCV Access Method opening routine. */
|
||||
/***********************************************************************/
|
||||
bool TDBPRX::OpenDB(PGLOBAL g)
|
||||
{
|
||||
if (Use == USE_OPEN) {
|
||||
/*******************************************************************/
|
||||
/* Table already open, just replace it at its beginning. */
|
||||
/*******************************************************************/
|
||||
return Tdbp->OpenDB(g);
|
||||
} // endif use
|
||||
|
||||
if (Mode != MODE_READ) {
|
||||
/*******************************************************************/
|
||||
/* Currently XCOL tables cannot be modified. */
|
||||
/*******************************************************************/
|
||||
strcpy(g->Message, "PROXY tables are read only");
|
||||
return TRUE;
|
||||
} // endif Mode
|
||||
|
||||
if (InitTable(g))
|
||||
return NULL;
|
||||
|
||||
/*********************************************************************/
|
||||
/* Check and initialize the subtable columns. */
|
||||
/*********************************************************************/
|
||||
for (PCOL cp = Columns; cp; cp = cp->GetNext())
|
||||
if (((PPRXCOL)cp)->Init(g))
|
||||
return TRUE;
|
||||
|
||||
/*********************************************************************/
|
||||
/* Physically open the object table. */
|
||||
/*********************************************************************/
|
||||
if (Tdbp->OpenDB(g))
|
||||
return TRUE;
|
||||
|
||||
return FALSE;
|
||||
} // end of OpenDB
|
||||
|
||||
/***********************************************************************/
|
||||
/* Data Base read routine for XCV access method. */
|
||||
/***********************************************************************/
|
||||
int TDBPRX::ReadDB(PGLOBAL g)
|
||||
{
|
||||
/*********************************************************************/
|
||||
/* Now start the reading process. */
|
||||
/*********************************************************************/
|
||||
return Tdbp->ReadDB(g);
|
||||
} // end of ReadDB
|
||||
|
||||
/***********************************************************************/
|
||||
/* WriteDB: Data Base write routine for XCV access methods. */
|
||||
/***********************************************************************/
|
||||
int TDBPRX::WriteDB(PGLOBAL g)
|
||||
{
|
||||
sprintf(g->Message, "%s tables are read only", To_Def->GetType());
|
||||
return RC_FX;
|
||||
} // end of WriteDB
|
||||
|
||||
/***********************************************************************/
|
||||
/* Data Base delete line routine for XCV access methods. */
|
||||
/***********************************************************************/
|
||||
int TDBPRX::DeleteDB(PGLOBAL g, int irc)
|
||||
{
|
||||
sprintf(g->Message, "Delete not enabled for %s tables",
|
||||
To_Def->GetType());
|
||||
return RC_FX;
|
||||
} // end of DeleteDB
|
||||
|
||||
/* ---------------------------- PRXCOL ------------------------------- */
|
||||
|
||||
/***********************************************************************/
|
||||
/* PRXCOL public constructor. */
|
||||
/***********************************************************************/
|
||||
PRXCOL::PRXCOL(PCOLDEF cdp, PTDB tdbp, PCOL cprec, int i, PSZ am)
|
||||
: COLBLK(cdp, tdbp, i)
|
||||
{
|
||||
if (cprec) {
|
||||
Next = cprec->GetNext();
|
||||
cprec->SetNext(this);
|
||||
} else {
|
||||
Next = tdbp->GetColumns();
|
||||
tdbp->SetColumns(this);
|
||||
} // endif cprec
|
||||
|
||||
// Set additional Dos access method information for column.
|
||||
Long = cdp->GetLong(); // Useful ???
|
||||
//strcpy(F_Date, cdp->F_Date);
|
||||
Colp = NULL;
|
||||
To_Val = NULL;
|
||||
Pseudo = FALSE;
|
||||
Colnum = cdp->GetOffset(); // If columns are retrieved by number
|
||||
|
||||
if (trace)
|
||||
htrc(" making new %sCOL C%d %s at %p\n", am, Index, Name, this);
|
||||
|
||||
} // end of PRXCOL constructor
|
||||
|
||||
/***********************************************************************/
|
||||
/* PRXCOL initialization routine. */
|
||||
/* Look for the matching column in the object table. */
|
||||
/***********************************************************************/
|
||||
bool PRXCOL::Init(PGLOBAL g)
|
||||
{
|
||||
PTDBPRX tdbp = (PTDBPRX)To_Tdb;
|
||||
|
||||
if (!(Colp = tdbp->Tdbp->ColDB(g, Name, 0)) && Colnum)
|
||||
Colp = tdbp->Tdbp->ColDB(g, NULL, Colnum);
|
||||
|
||||
if (Colp) {
|
||||
Colp->InitValue(g); // May not have been done elsewhere
|
||||
To_Val = Colp->GetValue();
|
||||
} else {
|
||||
sprintf(g->Message, MSG(NO_MATCHING_COL), Name, tdbp->Tdbp->GetName());
|
||||
return TRUE;
|
||||
} // endif Colp
|
||||
|
||||
return FALSE;
|
||||
} // end of Init
|
||||
|
||||
/***********************************************************************/
|
||||
/* ReadColumn: */
|
||||
/***********************************************************************/
|
||||
void PRXCOL::ReadColumn(PGLOBAL g)
|
||||
{
|
||||
if (trace)
|
||||
htrc("PRX ReadColumn: name=%s\n", Name);
|
||||
|
||||
if (Colp) {
|
||||
Colp->ReadColumn(g);
|
||||
Value->SetValue_pval(To_Val);
|
||||
|
||||
// Set null when applicable
|
||||
if (Nullable)
|
||||
Value->SetNull(Value->IsNull());
|
||||
|
||||
} // endif Colp
|
||||
|
||||
} // end of ReadColumn
|
||||
|
||||
#if 0
|
||||
/* ---------------------------TBCDEF class --------------------------- */
|
||||
|
||||
/***********************************************************************/
|
||||
/* DefineAM: define specific AM block values from CATLG table. */
|
||||
/***********************************************************************/
|
||||
bool TBCDEF::DefineAM(PGLOBAL g, LPCSTR am, int poff)
|
||||
{
|
||||
Desc = "Catalog Table";
|
||||
Database = Cat->GetStringCatInfo(g, "Database", "*");
|
||||
Tabname = Cat->GetStringCatInfo(g, "Tabname", Tabname);
|
||||
return FALSE;
|
||||
} // end of DefineAM
|
||||
|
||||
/***********************************************************************/
|
||||
/* GetTable: makes a new TDB of the proper type. */
|
||||
/***********************************************************************/
|
||||
PTDB TBCDEF::GetTable(PGLOBAL g, MODE m)
|
||||
{
|
||||
return new(g) TDBTBC(this);
|
||||
} // end of GetTable
|
||||
#endif // 0
|
||||
|
||||
/* ---------------------------TDBTBC class --------------------------- */
|
||||
|
||||
/***********************************************************************/
|
||||
/* TDBTBC class constructor. */
|
||||
/***********************************************************************/
|
||||
TDBTBC::TDBTBC(PPRXDEF tdp) : TDBCAT(tdp)
|
||||
{
|
||||
// Db = tdp->Database;
|
||||
// Tab = tdp->Tabname;
|
||||
Db = (PSZ)tdp->Tablep->GetQualifier();
|
||||
Tab = (PSZ)tdp->Tablep->GetName();
|
||||
} // end of TDBTBC constructor
|
||||
|
||||
#if 0
|
||||
/***********************************************************************/
|
||||
/* TDBTBC class constructor from TBL table. */
|
||||
/***********************************************************************/
|
||||
TDBTBC::TDBTBC(PTBLDEF tdp) : TDBCAT(tdp)
|
||||
{
|
||||
Db = tdp->To_Tables->DB;
|
||||
Tab = tdp->To_Tables->Name;
|
||||
} // end of TDBTBC constructor
|
||||
|
||||
/***********************************************************************/
|
||||
/* TDBTBC class constructor from PRX table. */
|
||||
/***********************************************************************/
|
||||
TDBTBC::TDBTBC(PXCLDEF tdp) : TDBCAT(tdp)
|
||||
{
|
||||
Db = (PSZ)tdp->Tablep->GetQualifier();
|
||||
Tab = (PSZ)tdp->Tablep->GetName();
|
||||
} // end of TDBTBC constructor
|
||||
#endif // 0
|
||||
|
||||
/***********************************************************************/
|
||||
/* GetResult: Get the list the MYSQL table columns. */
|
||||
/***********************************************************************/
|
||||
PQRYRES TDBTBC::GetResult(PGLOBAL g)
|
||||
{
|
||||
return TabColumns(g, current_thd, Db, Tab, false);
|
||||
} // end of GetResult
|
||||
|
181
storage/connect/tabutil.h
Normal file
181
storage/connect/tabutil.h
Normal file
@@ -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
|
376
storage/connect/tabxcl.cpp
Normal file
376
storage/connect/tabxcl.cpp
Normal file
@@ -0,0 +1,376 @@
|
||||
/************* TabXcl CPP Declares Source Code File (.CPP) *************/
|
||||
/* Name: TABXCL.CPP Version 1.0 */
|
||||
/* */
|
||||
/* (C) Copyright to the author Olivier BERTRAND 2013 */
|
||||
/* */
|
||||
/* XCOL: Table having one column containing several values */
|
||||
/* comma separated. When creating the table, the name of the X */
|
||||
/* column is given by the Name option. */
|
||||
/* This first version has one limitation: */
|
||||
/* - The X column has the same length than in the physical file. */
|
||||
/* This tables produces as many rows for a physical row than the */
|
||||
/* number of items in the X column (eventually 0). */
|
||||
/***********************************************************************/
|
||||
|
||||
/***********************************************************************/
|
||||
/* Include relevant section of system dependant header files. */
|
||||
/***********************************************************************/
|
||||
#include "my_global.h"
|
||||
#if defined(WIN32)
|
||||
#include <stdlib.h>
|
||||
#include <stdio.h>
|
||||
#if defined(__BORLANDC__)
|
||||
#define __MFC_COMPAT__ // To define min/max as macro
|
||||
#endif
|
||||
//#include <windows.h>
|
||||
#else
|
||||
#if defined(UNIX)
|
||||
#include <fnmatch.h>
|
||||
#include <errno.h>
|
||||
#include <stdlib.h>
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
#include "osutil.h"
|
||||
#else
|
||||
//#include <io.h>
|
||||
#endif
|
||||
//#include <fcntl.h>
|
||||
#endif
|
||||
|
||||
/***********************************************************************/
|
||||
/* Include application header files: */
|
||||
/***********************************************************************/
|
||||
#include "table.h" // MySQL table definitions
|
||||
#include "global.h"
|
||||
#include "plgdbsem.h"
|
||||
#include "plgcnx.h" // For DB types
|
||||
#include "resource.h"
|
||||
#include "reldef.h"
|
||||
#include "filamtxt.h"
|
||||
#include "tabdos.h"
|
||||
#include "tabcol.h"
|
||||
#include "tabxcl.h"
|
||||
#include "xtable.h"
|
||||
#if defined(MYSQL_SUPPORT)
|
||||
#include "tabmysql.h"
|
||||
#endif // MYSQL_SUPPORT
|
||||
#include "ha_connect.h"
|
||||
#include "mycat.h"
|
||||
|
||||
extern "C" int trace;
|
||||
|
||||
/* -------------- Implementation of the XCOL classes ---------------- */
|
||||
|
||||
/***********************************************************************/
|
||||
/* XCLDEF constructor. */
|
||||
/***********************************************************************/
|
||||
XCLDEF::XCLDEF(void)
|
||||
{
|
||||
Pseudo = 3;
|
||||
Xcol = NULL;
|
||||
Sep = ',';
|
||||
Mult = 10;
|
||||
} // end of XCLDEF constructor
|
||||
|
||||
/***********************************************************************/
|
||||
/* DefineAM: define specific AM block values from XCOL file. */
|
||||
/***********************************************************************/
|
||||
bool XCLDEF::DefineAM(PGLOBAL g, LPCSTR am, int poff)
|
||||
{
|
||||
char buf[8];
|
||||
|
||||
Xcol = Cat->GetStringCatInfo(g, "Colname", "");
|
||||
Cat->GetCharCatInfo("Separator", ",", buf, sizeof(buf));
|
||||
Sep = (strlen(buf) == 2 && buf[0] == '\\' && buf[1] == 't') ? '\t' : *buf;
|
||||
Mult = Cat->GetIntCatInfo("Mult", 10);
|
||||
return PRXDEF::DefineAM(g, am, poff);
|
||||
} // end of DefineAM
|
||||
|
||||
/***********************************************************************/
|
||||
/* GetTable: makes a new TDB of the proper type. */
|
||||
/***********************************************************************/
|
||||
PTDB XCLDEF::GetTable(PGLOBAL g, MODE mode)
|
||||
{
|
||||
if (Catfunc == FNC_COL)
|
||||
return new(g) TDBTBC(this);
|
||||
else
|
||||
return new(g) TDBXCL(this);
|
||||
|
||||
} // end of GetTable
|
||||
|
||||
/* ------------------------------------------------------------------- */
|
||||
|
||||
/***********************************************************************/
|
||||
/* Implementation of the TDBXCL class. */
|
||||
/***********************************************************************/
|
||||
TDBXCL::TDBXCL(PXCLDEF tdp) : TDBPRX(tdp)
|
||||
{
|
||||
//Tdbp = NULL; // The physical table
|
||||
Xcolumn = tdp->Xcol; // CSV column name
|
||||
Xcolp = NULL; // To the XCVCOL column
|
||||
Mult = tdp->Mult; // Multiplication factor
|
||||
N = 0; // The current table index
|
||||
M = 0; // The occurence rank
|
||||
RowFlag = 0; // 0: Ok, 1: Same, 2: Skip
|
||||
New = TRUE; // TRUE for new line
|
||||
Sep = tdp->Sep; // The Xcol separator
|
||||
} // end of TDBXCL constructor
|
||||
|
||||
/***********************************************************************/
|
||||
/* Initializes the table. */
|
||||
/***********************************************************************/
|
||||
bool TDBXCL::InitTable(PGLOBAL g)
|
||||
{
|
||||
if (!Tdbp) {
|
||||
PCOLDEF cdp;
|
||||
|
||||
// Get the table description block of this table
|
||||
if (!(Tdbp = (PTDBASE)GetSubTable(g, ((PXCLDEF)To_Def)->Tablep)))
|
||||
return TRUE;
|
||||
|
||||
for (cdp = Tdbp->GetDef()->GetCols(); cdp; cdp = cdp->GetNext())
|
||||
if (!stricmp(cdp->GetName(), Xcolumn))
|
||||
break;
|
||||
|
||||
if (!cdp) {
|
||||
sprintf(g->Message, "%s is not a %s column",
|
||||
Xcolumn, Tdbp->GetName());
|
||||
return TRUE;
|
||||
} // endif cdp
|
||||
|
||||
} // endif Tdbp
|
||||
|
||||
return FALSE;
|
||||
} // end of InitTable
|
||||
|
||||
/***********************************************************************/
|
||||
/* Allocate XCL column description block. */
|
||||
/***********************************************************************/
|
||||
PCOL TDBXCL::MakeCol(PGLOBAL g, PCOLDEF cdp, PCOL cprec, int n)
|
||||
{
|
||||
PCOL colp;
|
||||
|
||||
if (!stricmp(cdp->GetName(), Xcolumn)) {
|
||||
Xcolp = new(g) XCLCOL(g, cdp, this, cprec, n);
|
||||
colp = Xcolp;
|
||||
} else
|
||||
colp = new(g) PRXCOL(cdp, this, cprec, n);
|
||||
|
||||
return colp;
|
||||
} // end of MakeCol
|
||||
|
||||
/***********************************************************************/
|
||||
/* XCL GetMaxSize: returns the maximum number of rows in the table. */
|
||||
/***********************************************************************/
|
||||
int TDBXCL::GetMaxSize(PGLOBAL g)
|
||||
{
|
||||
if (MaxSize < 0) {
|
||||
if (InitTable(g))
|
||||
return NULL;
|
||||
|
||||
MaxSize = Mult * Tdbp->GetMaxSize(g);
|
||||
} // endif MaxSize
|
||||
|
||||
return MaxSize;
|
||||
} // end of GetMaxSize
|
||||
|
||||
/***********************************************************************/
|
||||
/* In this sample, ROWID will be the (virtual) row number, */
|
||||
/* while ROWNUM will be the occurence rank in the multiple column. */
|
||||
/***********************************************************************/
|
||||
int TDBXCL::RowNumber(PGLOBAL g, bool b)
|
||||
{
|
||||
return (b) ? M : N;
|
||||
} // end of RowNumber
|
||||
|
||||
/***********************************************************************/
|
||||
/* XCV Access Method opening routine. */
|
||||
/***********************************************************************/
|
||||
bool TDBXCL::OpenDB(PGLOBAL g)
|
||||
{
|
||||
if (Use == USE_OPEN) {
|
||||
/*******************************************************************/
|
||||
/* Table already open, just replace it at its beginning. */
|
||||
/*******************************************************************/
|
||||
M = N = 0;
|
||||
RowFlag = 0;
|
||||
New = TRUE;
|
||||
return Tdbp->OpenDB(g);
|
||||
} // endif use
|
||||
|
||||
if (Mode != MODE_READ) {
|
||||
/*******************************************************************/
|
||||
/* Currently XCOL tables cannot be modified. */
|
||||
/*******************************************************************/
|
||||
strcpy(g->Message, "XCOL tables are read only");
|
||||
return TRUE;
|
||||
} // endif Mode
|
||||
|
||||
if (InitTable(g))
|
||||
return NULL;
|
||||
|
||||
/*********************************************************************/
|
||||
/* Check and initialize the subtable columns. */
|
||||
/*********************************************************************/
|
||||
for (PCOL cp = Columns; cp; cp = cp->GetNext())
|
||||
if (((PXCLCOL)cp)->Init(g))
|
||||
return TRUE;
|
||||
|
||||
/*********************************************************************/
|
||||
/* Physically open the object table. */
|
||||
/*********************************************************************/
|
||||
if (Tdbp->OpenDB(g))
|
||||
return TRUE;
|
||||
|
||||
#if 0
|
||||
/*********************************************************************/
|
||||
/* Check for direct access. */
|
||||
/*********************************************************************/
|
||||
if (To_Key_Col)
|
||||
if (!Tdbp->GetDef()->Indexable()) {
|
||||
strcpy(g->Message, "Object table is not indexable");
|
||||
return TRUE;
|
||||
} else {
|
||||
((PTDBX)Tdbp)->To_Key_Col = To_Key_Col;
|
||||
((PTDBX)Tdbp)->To_Link = To_Link;
|
||||
((PTDBX)Tdbp)->Knum = Knum;
|
||||
To_Kindex = (PKXBASE)new(g) KINDEX(Tdbp);
|
||||
|
||||
if (To_Kindex->Init(g))
|
||||
return TRUE;
|
||||
|
||||
((PKINDEX)To_Kindex)->SetMult(Mult);
|
||||
Tdbp->SetKindex(To_Kindex);
|
||||
} // endif Indexable
|
||||
#endif // 0
|
||||
|
||||
return FALSE;
|
||||
} // end of OpenDB
|
||||
|
||||
/***********************************************************************/
|
||||
/* Data Base read routine for XCV access method. */
|
||||
/***********************************************************************/
|
||||
int TDBXCL::ReadDB(PGLOBAL g)
|
||||
{
|
||||
int rc = RC_OK;
|
||||
|
||||
/*********************************************************************/
|
||||
/* Now start the multi reading process. */
|
||||
/*********************************************************************/
|
||||
do {
|
||||
if (RowFlag != 1) {
|
||||
if ((rc = Tdbp->ReadDB(g)) != RC_OK)
|
||||
break;
|
||||
|
||||
New = TRUE;
|
||||
M = 1;
|
||||
} else {
|
||||
New = FALSE;
|
||||
M++;
|
||||
} // endif RowFlag
|
||||
|
||||
if (Xcolp) {
|
||||
RowFlag = 0;
|
||||
Xcolp->ReadColumn(g);
|
||||
} // endif Xcolp
|
||||
|
||||
N++;
|
||||
} while (RowFlag == 2);
|
||||
|
||||
return rc;
|
||||
} // end of ReadDB
|
||||
|
||||
|
||||
// ------------------------ XCLCOL functions ----------------------------
|
||||
|
||||
/***********************************************************************/
|
||||
/* XCLCOL public constructor. */
|
||||
/***********************************************************************/
|
||||
XCLCOL::XCLCOL(PGLOBAL g, PCOLDEF cdp, PTDB tdbp, PCOL cprec, int i)
|
||||
: PRXCOL(cdp, tdbp, cprec, i, "XCL")
|
||||
{
|
||||
// Set additional XXL access method information for column.
|
||||
Cbuf = (char*)PlugSubAlloc(g, NULL, Long + 1);
|
||||
Cp = NULL; // Pointer to current position in Cbuf
|
||||
Sep = ((PTDBXCL)tdbp)->Sep;
|
||||
AddStatus(BUF_READ); // Only evaluated from TDBXCL::ReadDB
|
||||
} // end of XCLCOL constructor
|
||||
|
||||
/***********************************************************************/
|
||||
/* What this routine does is to get the comma-separated string */
|
||||
/* from the source table column, extract the single values and */
|
||||
/* set the flag for the table ReadDB function. */
|
||||
/***********************************************************************/
|
||||
void XCLCOL::ReadColumn(PGLOBAL g)
|
||||
{
|
||||
if (((PTDBXCL)To_Tdb)->New) {
|
||||
Colp->ReadColumn(g);
|
||||
strcpy(Cbuf, To_Val->GetCharValue());
|
||||
Cp = Cbuf;
|
||||
} // endif New
|
||||
|
||||
if (*Cp) {
|
||||
PSZ p;
|
||||
|
||||
// Trim left
|
||||
for (p = Cp; *p == ' '; p++) ;
|
||||
|
||||
if ((Cp = strchr(Cp, Sep)))
|
||||
// Separator is found
|
||||
*Cp++ = '\0';
|
||||
|
||||
Value->SetValue_psz(p);
|
||||
} else if (Nullable) {
|
||||
Value->Reset();
|
||||
Value->SetNull(true);
|
||||
} else
|
||||
// Skip that row
|
||||
((PTDBXCL)To_Tdb)->RowFlag = 2;
|
||||
|
||||
if (Cp && *Cp)
|
||||
// More to come from the same row
|
||||
((PTDBXCL)To_Tdb)->RowFlag = 1;
|
||||
|
||||
} // end of ReadColumn
|
||||
|
||||
#if 0
|
||||
/* -------------- Implementation of the MULINDX class ---------------- */
|
||||
|
||||
/***********************************************************************/
|
||||
/* Returns FALSE if Ok, TRUE if there are no more equal values. */
|
||||
/***********************************************************************/
|
||||
bool MULINDX::HaveSame(void)
|
||||
{
|
||||
return (Op == OP_SAME || Txlp->RowFlag == 1);
|
||||
} // end of HaveSame
|
||||
|
||||
/***********************************************************************/
|
||||
/* Returns FALSE if Ok, TRUE if there are no more equal values. */
|
||||
/***********************************************************************/
|
||||
bool MULINDX::NextVal(bool eq)
|
||||
{
|
||||
return (Pof) ? KINDEX::NextVal(eq) : TRUE;
|
||||
} // end of NextVal
|
||||
|
||||
/***********************************************************************/
|
||||
/* Returns TRUE if there are more same values. */
|
||||
/***********************************************************************/
|
||||
bool MULINDX::MoreVal(void)
|
||||
{
|
||||
Op = OP_SAME; // There may be more equal values
|
||||
return (Pof) ? Pof[Val_K] : Val_K;
|
||||
} // end of MoreVal
|
||||
|
||||
/***********************************************************************/
|
||||
/* Change the index multiple status. */
|
||||
/***********************************************************************/
|
||||
bool MULINDX::Init(PGLOBAL g)
|
||||
{
|
||||
if (KINDEX::Init(g))
|
||||
return TRUE;
|
||||
|
||||
Mul = TRUE;
|
||||
MaxSame *= Txlp->Mult;
|
||||
return FALSE;
|
||||
} // end of Init
|
||||
#endif // 0
|
133
storage/connect/tabxcl.h
Normal file
133
storage/connect/tabxcl.h
Normal file
@@ -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
|
@@ -266,7 +266,7 @@ char TYPBLK<char>::GetTypedValue(PVAL valp)
|
||||
{return valp->GetTinyValue();}
|
||||
|
||||
/***********************************************************************/
|
||||
/* Set one value in a block. */
|
||||
/* Set one value in a block from a zero terminated string. */
|
||||
/***********************************************************************/
|
||||
template <class TYPE>
|
||||
void TYPBLK<TYPE>::SetValue(PSZ p, int n)
|
||||
@@ -294,6 +294,22 @@ double TYPBLK<double>::GetTypedValue(PSZ p) {return atof(p);}
|
||||
template <>
|
||||
char TYPBLK<char>::GetTypedValue(PSZ p) {return (char)atoi(p);}
|
||||
|
||||
/***********************************************************************/
|
||||
/* Set one value in a block from an array of characters. */
|
||||
/***********************************************************************/
|
||||
template <class TYPE>
|
||||
void TYPBLK<TYPE>::SetValue(char *sp, uint len, int n)
|
||||
{
|
||||
PGLOBAL& g = Global;
|
||||
PSZ spz = (PSZ)PlugSubAlloc(g, NULL, 0); // Temporary
|
||||
|
||||
if (sp)
|
||||
memcpy(spz, sp, len);
|
||||
|
||||
spz[len] = 0;
|
||||
SetValue(spz, n);
|
||||
} // end of SetValue
|
||||
|
||||
/***********************************************************************/
|
||||
/* Set one value in a block from a value in another block. */
|
||||
/***********************************************************************/
|
||||
@@ -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)
|
||||
{
|
||||
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
|
||||
|
||||
/***********************************************************************/
|
||||
|
@@ -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);
|
||||
|
Reference in New Issue
Block a user