Commit 4fd74200 authored by Olivier Bertrand's avatar Olivier Bertrand

- 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
parent bc80fb07
......@@ -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
......
/* 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;
......
/************ 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
// 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
/************* 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;
/*********************************************************************/
/* Allocate a TDB of the proper type. */
/* Column blocks will be allocated only when needed. */
/*********************************************************************/
tdbp = new(g) TDBTBL(this);
if (Catfunc == FNC_COL)
return new(g) TDBTBC(this);
else
return new(g) TDBTBL(this);
return tdbp;
} // end of GetTable
/* ------------------------- Class TDBTBL ---------------------------- */
......@@ -169,11 +166,11 @@ PTDB TBLDEF::GetTable(PGLOBAL g, MODE m)
/***********************************************************************/
/* TDBTBL constructors. */
/***********************************************************************/
TDBTBL::TDBTBL(PTBLDEF tdp) : TDBASE(tdp)
TDBTBL::TDBTBL(PTBLDEF tdp) : TDBPRX(tdp)
{
Tablist = NULL;
CurTable = NULL;
Tdbp = NULL;
//Tdbp = NULL;
Accept = tdp->Accept;
Maxerr = tdp->Maxerr;
Nbf = 0;
......@@ -188,7 +185,7 @@ TDBTBL::TDBTBL(PTBLDEF tdp) : TDBASE(tdp)
/***********************************************************************/
PCOL TDBTBL::MakeCol(PGLOBAL g, PCOLDEF cdp, PCOL cprec, int n)
{
return new(g) TBLCOL(cdp, this, cprec, n);
return new(g) PRXCOL(cdp, this, cprec, n);
} // end of MakeCol
/***********************************************************************/
......@@ -212,13 +209,14 @@ PCOL TDBTBL::InsertSpecialColumn(PGLOBAL g, PCOL scp)
return colp;
} // end of InsertSpecialColumn
#if 0
/***********************************************************************/
/* Get the PTDB of a table of the list. */
/***********************************************************************/
PTDB TDBTBL::GetSubTable(PGLOBAL g, PTBL tblp, PTABLE tabp)
{
char *db, key[256];
uint k;
//char *db;
bool mysql;
PTDB tdbp = NULL;
TABLE_SHARE *s;
PCATLG cat = To_Def->GetCat();
......@@ -228,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);
k = sprintf(key, "%s", db) + 1;
k += sprintf(key + k, "%s", tblp->Name);
key[++k] = 0;
//if (tblp->DB)
// db = tblp->DB;
//else
// db = (char*)hc->GetDBName(NULL);
if (!(s = alloc_table_share(db, tblp->Name, key, ++k))) {
strcpy(g->Message, "Error allocating share\n");
//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 ------------------------------- */
......
/*************** 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. */
......
/************* 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
// 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
/************* 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
// 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);
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment