Commit c035bde3 authored by Olivier Bertrand's avatar Olivier Bertrand

- Allowing views and queries as parameters for PROXY base tables

  NOTE: Checking for looping references cannot be done when using views
  as parameters. This should not be allowed on production servers and
  should be dependant on a system variable and/or on speciel grant.

modified:
  storage/connect/CMakeLists.txt
  storage/connect/connect.cc
  storage/connect/ha_connect.cc
  storage/connect/myconn.cpp
  storage/connect/myconn.h
  storage/connect/mysql-test/connect/r/fmt.result
  storage/connect/mysql-test/connect/r/pivot.result
  storage/connect/mysql-test/connect/t/fmt.test
  storage/connect/mysql-test/connect/t/pivot.test
  storage/connect/plgdbsem.h
  storage/connect/plugutil.c
  storage/connect/tabcol.cpp
  storage/connect/tabcol.h
  storage/connect/tabfmt.cpp
  storage/connect/tabmysql.cpp
  storage/connect/tabmysql.h
  storage/connect/taboccur.cpp
  storage/connect/taboccur.h
  storage/connect/tabpivot.cpp
  storage/connect/tabpivot.h
  storage/connect/tabtbl.cpp
  storage/connect/tabutil.cpp
  storage/connect/tabutil.h
  storage/connect/xtable.h
parent 3c76e0e2
...@@ -178,7 +178,7 @@ OPTION(CONNECT_WITH_MYSQL ...@@ -178,7 +178,7 @@ OPTION(CONNECT_WITH_MYSQL
IF(CONNECT_WITH_MYSQL) IF(CONNECT_WITH_MYSQL)
SET(CONNECT_SOURCES ${CONNECT_SOURCES} SET(CONNECT_SOURCES ${CONNECT_SOURCES}
myconn.cpp myconn.h tabmysql.cpp tabxml.h) myconn.cpp myconn.h tabmysql.cpp tabmysql.h)
add_definitions(-DMYSQL_SUPPORT) add_definitions(-DMYSQL_SUPPORT)
IF(NOT UNIX) IF(NOT UNIX)
# #
......
...@@ -71,10 +71,7 @@ int rename_file_ext(const char *from, const char *to,const char *ext); ...@@ -71,10 +71,7 @@ int rename_file_ext(const char *from, const char *to,const char *ext);
PGLOBAL CntExit(PGLOBAL g) PGLOBAL CntExit(PGLOBAL g)
{ {
if (g) { if (g) {
PDBUSER dup= PlgGetUser(g);
CntEndDB(g); CntEndDB(g);
free(dup);
if (g->Activityp) if (g->Activityp)
delete g->Activityp; delete g->Activityp;
...@@ -94,13 +91,10 @@ void CntEndDB(PGLOBAL g) ...@@ -94,13 +91,10 @@ void CntEndDB(PGLOBAL g)
PDBUSER dbuserp= PlgGetUser(g); PDBUSER dbuserp= PlgGetUser(g);
if (dbuserp) { if (dbuserp) {
if (dbuserp->Catalog) { if (dbuserp->Catalog)
delete dbuserp->Catalog; delete dbuserp->Catalog;
dbuserp->Catalog= NULL;
} // endif Catalog
*dbuserp->Name= '\0'; free(dbuserp);
// *dbuserp->Work= '\0';
} // endif dbuserp } // endif dbuserp
} // end of CntEndDB } // end of CntEndDB
...@@ -258,10 +252,12 @@ bool CntOpenTable(PGLOBAL g, PTDB tdbp, MODE mode, char *c1, char *c2, ...@@ -258,10 +252,12 @@ bool CntOpenTable(PGLOBAL g, PTDB tdbp, MODE mode, char *c1, char *c2,
return true; return true;
} // endif tdbp } // endif tdbp
if (!c1) if (!c1) {
// Allocate all column blocks for that table if (mode == MODE_INSERT)
tdbp->ColDB(g, NULL, 0); // Allocate all column blocks for that table
else for (p= c1; *p; p+= n) { tdbp->ColDB(g, NULL, 0);
} else for (p= c1; *p; p+= n) {
// Allocate only used column blocks // Allocate only used column blocks
if (xtrace) if (xtrace)
printf("Allocating column %s\n", p); printf("Allocating column %s\n", p);
......
...@@ -696,7 +696,9 @@ bool ha_connect::GetBooleanOption(char *opname, bool bdef) ...@@ -696,7 +696,9 @@ bool ha_connect::GetBooleanOption(char *opname, bool bdef)
char *pv; char *pv;
PTOS options= GetTableOptionStruct(table); PTOS options= GetTableOptionStruct(table);
if (!options) if (!stricmp(opname, "View"))
opval= (tshp) ? tshp->is_view : table->s->is_view;
else if (!options)
; ;
else if (!stricmp(opname, "Mapped")) else if (!stricmp(opname, "Mapped"))
opval= options->mapped; opval= options->mapped;
...@@ -838,7 +840,7 @@ void *ha_connect::GetColumnOption(void *field, PCOLINFO pcf) ...@@ -838,7 +840,7 @@ void *ha_connect::GetColumnOption(void *field, PCOLINFO pcf)
} else } else
fldp= (tshp) ? tshp->field : table->field; fldp= (tshp) ? tshp->field : table->field;
if (!(fp= *fldp)) if (!fldp || !(fp= *fldp))
return NULL; return NULL;
// Get the CONNECT field options structure // Get the CONNECT field options structure
...@@ -1843,11 +1845,13 @@ int ha_connect::open(const char *name, int mode, uint test_if_locked) ...@@ -1843,11 +1845,13 @@ int ha_connect::open(const char *name, int mode, uint test_if_locked)
// Try to get the user if possible // Try to get the user if possible
xp= GetUser(ha_thd(), xp); xp= GetUser(ha_thd(), xp);
PGLOBAL g= xp->g; PGLOBAL g= (xp) ? xp->g : NULL;
// Try to set the database environment // Try to set the database environment
if (g) if (g)
rc= (CntCheckDB(g, this, name)) ? (-2) : 0; rc= (CntCheckDB(g, this, name)) ? (-2) : 0;
else
rc= HA_ERR_INTERNAL_ERROR;
DBUG_RETURN(rc); DBUG_RETURN(rc);
} // end of open } // end of open
...@@ -2809,6 +2813,10 @@ int ha_connect::external_lock(THD *thd, int lock_type) ...@@ -2809,6 +2813,10 @@ int ha_connect::external_lock(THD *thd, int lock_type)
bool oldsep= ((PCHK)g->Xchk)->oldsep; bool oldsep= ((PCHK)g->Xchk)->oldsep;
bool newsep= ((PCHK)g->Xchk)->newsep; bool newsep= ((PCHK)g->Xchk)->newsep;
PTDBDOS tdp= (PTDBDOS)(tdbp ? tdbp : GetTDB(g)); PTDBDOS tdp= (PTDBDOS)(tdbp ? tdbp : GetTDB(g));
if (!tdp)
DBUG_RETURN(HA_ERR_INTERNAL_ERROR);
PDOSDEF ddp= (PDOSDEF)tdp->GetDef(); PDOSDEF ddp= (PDOSDEF)tdp->GetDef();
PIXDEF xp, xp1, xp2, drp=NULL, adp= NULL; PIXDEF xp, xp1, xp2, drp=NULL, adp= NULL;
PIXDEF oldpix= ((PCHK)g->Xchk)->oldpix; PIXDEF oldpix= ((PCHK)g->Xchk)->oldpix;
...@@ -3300,7 +3308,7 @@ static int connect_assisted_discovery(handlerton *hton, THD* thd, ...@@ -3300,7 +3308,7 @@ static int connect_assisted_discovery(handlerton *hton, THD* thd,
{ {
char spc= ',', qch= 0; char spc= ',', qch= 0;
const char *fncn= "?"; const char *fncn= "?";
const char *user, *fn, *db, *host, *pwd, *prt, *sep, *tbl; // *csn; const char *user, *fn, *db, *host, *pwd, *prt, *sep, *tbl, *src;
char *tab, *dsn; char *tab, *dsn;
#if defined(WIN32) #if defined(WIN32)
char *nsp= NULL, *cls= NULL; char *nsp= NULL, *cls= NULL;
...@@ -3324,16 +3332,17 @@ static int connect_assisted_discovery(handlerton *hton, THD* thd, ...@@ -3324,16 +3332,17 @@ static int connect_assisted_discovery(handlerton *hton, THD* thd,
sql.copy(STRING_WITH_LEN("CREATE TABLE whatever ("), system_charset_info); sql.copy(STRING_WITH_LEN("CREATE TABLE whatever ("), system_charset_info);
user= host= pwd= prt= tbl= dsn= NULL; user= host= pwd= prt= tbl= src= dsn= NULL;
// Get the useful create options // Get the useful create options
ttp= GetTypeID(topt->type); ttp= GetTypeID(topt->type);
fn= topt->filename; fn= topt->filename;
tab= (char*)topt->tabname; tab= (char*)topt->tabname;
db= topt->dbname; src= topt->srcdef;
db= topt->dbname;
fncn= topt->catfunc; fncn= topt->catfunc;
fnc= GetFuncID(fncn); fnc= GetFuncID(fncn);
sep= topt->separator; sep= topt->separator;
spc= (!sep || !strcmp(sep, "\\t")) ? '\t' : *sep; spc= (!sep || !strcmp(sep, "\\t")) ? '\t' : *sep;
qch= topt->qchar ? *topt->qchar : topt->quoted >= 0 ? '"' : 0; qch= topt->qchar ? *topt->qchar : topt->quoted >= 0 ? '"' : 0;
hdr= (int)topt->header; hdr= (int)topt->header;
...@@ -3352,25 +3361,20 @@ static int connect_assisted_discovery(handlerton *hton, THD* thd, ...@@ -3352,25 +3361,20 @@ static int connect_assisted_discovery(handlerton *hton, THD* thd,
cls= GetListOption(g,"class", topt->oplist); cls= GetListOption(g,"class", topt->oplist);
#endif // WIN32 #endif // WIN32
mxr= atoi(GetListOption(g,"maxerr", topt->oplist, "0")); mxr= atoi(GetListOption(g,"maxerr", topt->oplist, "0"));
} // endif option_list } else {
host= "localhost";
user= "root";
} // endif option_list
if (!db) if (!db)
db= thd->db; // Default value db= thd->db; // Default value
// Check table type // Check table type
if (ttp == TAB_UNDEF) { if (ttp == TAB_UNDEF) {
if (!tab) { topt->type= (src) ? "MYSQL" : (tab) ? "PROXY" : "DOS";
strcpy(g->Message, "No table_type. Was set to DOS"); ttp= GetTypeID(topt->type);
push_warning(thd, MYSQL_ERROR::WARN_LEVEL_WARN, 0, g->Message); sprintf(g->Message, "No table_type. Was set to %s", topt->type);
ttp= TAB_DOS; push_warning(thd, MYSQL_ERROR::WARN_LEVEL_WARN, 0, g->Message);
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) { } else if (ttp == TAB_NIY) {
sprintf(g->Message, "Unsupported table type %s", topt->type); sprintf(g->Message, "Unsupported table type %s", topt->type);
my_message(ER_UNKNOWN_ERROR, g->Message, MYF(0)); my_message(ER_UNKNOWN_ERROR, g->Message, MYF(0));
...@@ -3494,7 +3498,9 @@ static int connect_assisted_discovery(handlerton *hton, THD* thd, ...@@ -3494,7 +3498,9 @@ static int connect_assisted_discovery(handlerton *hton, THD* thd,
else else
return HA_ERR_INTERNAL_ERROR; // Should never happen return HA_ERR_INTERNAL_ERROR; // Should never happen
switch (ttp) { if (src && fnc == FNC_NO)
qrp= SrcColumns(g, host, db, user, pwd, src, port);
else switch (ttp) {
case TAB_DBF: case TAB_DBF:
qrp= DBFColumns(g, fn, fnc == FNC_COL); qrp= DBFColumns(g, fn, fnc == FNC_COL);
break; break;
...@@ -3523,7 +3529,7 @@ static int connect_assisted_discovery(handlerton *hton, THD* thd, ...@@ -3523,7 +3529,7 @@ static int connect_assisted_discovery(handlerton *hton, THD* thd,
#if defined(MYSQL_SUPPORT) #if defined(MYSQL_SUPPORT)
case TAB_MYSQL: case TAB_MYSQL:
qrp= MyColumns(g, host, db, user, pwd, tab, qrp= MyColumns(g, host, db, user, pwd, tab,
NULL, port, false, fnc == FNC_COL); NULL, port, fnc == FNC_COL);
break; break;
#endif // MYSQL_SUPPORT #endif // MYSQL_SUPPORT
case TAB_CSV: case TAB_CSV:
...@@ -3549,7 +3555,7 @@ static int connect_assisted_discovery(handlerton *hton, THD* thd, ...@@ -3549,7 +3555,7 @@ static int connect_assisted_discovery(handlerton *hton, THD* thd,
return HA_ERR_INTERNAL_ERROR; return HA_ERR_INTERNAL_ERROR;
} // endif qrp } // endif qrp
if (fnc != FNC_NO) { if (fnc != FNC_NO || src) {
// Catalog table // Catalog table
for (crp=qrp->Colresp; !b && crp; crp= crp->Next) { for (crp=qrp->Colresp; !b && crp; crp= crp->Next) {
cnm= encode(g, crp->Name); cnm= encode(g, crp->Name);
...@@ -3821,13 +3827,23 @@ int ha_connect::create(const char *name, TABLE *table_arg, ...@@ -3821,13 +3827,23 @@ int ha_connect::create(const char *name, TABLE *table_arg,
case TAB_PRX: case TAB_PRX:
case TAB_XCL: case TAB_XCL:
case TAB_OCCUR: case TAB_OCCUR:
if (!stricmp(options->tabname, create_info->alias) && if (options->srcdef) {
(!options->dbname || !stricmp(options->dbname, thd->db))) { strcpy(g->Message, "Cannot check looping reference");
sprintf(g->Message, "A %s table cannot refer to itself", push_warning(thd, MYSQL_ERROR::WARN_LEVEL_WARN, 0, g->Message);
options->type); } else if (options->tabname) {
if (!stricmp(options->tabname, create_info->alias) &&
(!options->dbname || !stricmp(options->dbname, thd->db))) {
sprintf(g->Message, "A %s table cannot refer to itself",
options->type);
my_message(ER_UNKNOWN_ERROR, g->Message, MYF(0));
DBUG_RETURN(HA_ERR_INTERNAL_ERROR);
} // endif tab
} else {
strcpy(g->Message, "Missing object table name or definition");
my_message(ER_UNKNOWN_ERROR, g->Message, MYF(0)); my_message(ER_UNKNOWN_ERROR, g->Message, MYF(0));
return HA_ERR_INTERNAL_ERROR; DBUG_RETURN(HA_ERR_INTERNAL_ERROR);
} // endif tab } // endif tabname
} // endswitch ttp } // endswitch ttp
......
...@@ -66,13 +66,13 @@ extern MYSQL_PLUGIN_IMPORT uint mysqld_port; ...@@ -66,13 +66,13 @@ extern MYSQL_PLUGIN_IMPORT uint mysqld_port;
/************************************************************************/ /************************************************************************/
/* MyColumns: constructs the result blocks containing all columns */ /* MyColumns: constructs the result blocks containing all columns */
/* of a MySQL table that will be retrieved by GetData commands. */ /* of a MySQL table or view. */
/* key = TRUE when called from Create Table to get key informations. */ /* info = TRUE to get catalog column informations. */
/************************************************************************/ /************************************************************************/
PQRYRES MyColumns(PGLOBAL g, const char *host, const char *db, PQRYRES MyColumns(PGLOBAL g, const char *host, const char *db,
const char *user, const char *pwd, const char *user, const char *pwd,
const char *table, const char *colpat, const char *table, const char *colpat,
int port, bool key, bool info) int port, bool info)
{ {
static int buftyp[] = {TYPE_STRING, TYPE_SHORT, TYPE_STRING, TYPE_INT, static int buftyp[] = {TYPE_STRING, TYPE_SHORT, TYPE_STRING, TYPE_INT,
TYPE_STRING, TYPE_SHORT, TYPE_SHORT, TYPE_SHORT, TYPE_STRING, TYPE_SHORT, TYPE_SHORT, TYPE_SHORT,
...@@ -124,9 +124,6 @@ PQRYRES MyColumns(PGLOBAL g, const char *host, const char *db, ...@@ -124,9 +124,6 @@ PQRYRES MyColumns(PGLOBAL g, const char *host, const char *db,
length[0] = 128; length[0] = 128;
} // endif info } // endif info
//if (!key) // We are not called from Create table
// ncol--; // No date format column yet
/**********************************************************************/ /**********************************************************************/
/* Allocate the structures used to refer to the result set. */ /* Allocate the structures used to refer to the result set. */
/**********************************************************************/ /**********************************************************************/
...@@ -219,6 +216,7 @@ PQRYRES MyColumns(PGLOBAL g, const char *host, const char *db, ...@@ -219,6 +216,7 @@ PQRYRES MyColumns(PGLOBAL g, const char *host, const char *db,
crp->Kdata->SetValue(fld, i); crp->Kdata->SetValue(fld, i);
} // endfor i } // endfor i
#if 0
if (k > 1) { if (k > 1) {
// Multicolumn primary key // Multicolumn primary key
PVBLK vbp = qrp->Colresp->Next->Next->Next->Next->Kdata; PVBLK vbp = qrp->Colresp->Next->Next->Next->Next->Kdata;
...@@ -228,6 +226,7 @@ PQRYRES MyColumns(PGLOBAL g, const char *host, const char *db, ...@@ -228,6 +226,7 @@ PQRYRES MyColumns(PGLOBAL g, const char *host, const char *db,
vbp->SetValue(k, i); vbp->SetValue(k, i);
} // endif k } // endif k
#endif // 0
/**********************************************************************/ /**********************************************************************/
/* Close MySQL connection. */ /* Close MySQL connection. */
...@@ -240,6 +239,33 @@ PQRYRES MyColumns(PGLOBAL g, const char *host, const char *db, ...@@ -240,6 +239,33 @@ PQRYRES MyColumns(PGLOBAL g, const char *host, const char *db,
return qrp; return qrp;
} // end of MyColumns } // end of MyColumns
/************************************************************************/
/* SrcColumns: constructs the result blocks containing all columns */
/* resulting from an SQL source definition query execution. */
/************************************************************************/
PQRYRES SrcColumns(PGLOBAL g, const char *host, const char *db,
const char *user, const char *pwd,
const char *srcdef, int port)
{
int w;
MYSQLC myc;
PQRYRES qrp = NULL;
if (!port)
port = mysqld_port;
// Open a MySQL connection for this table
if (myc.Open(g, host, db, user, pwd, port))
return NULL;
// Send the source command to MySQL
if (myc.ExecSQL(g, srcdef, &w) == RC_OK)
qrp = myc.GetResult(g);
myc.Close();
return qrp;
} // end of SrcColumns
/* -------------------------- Class MYSQLC --------------------------- */ /* -------------------------- Class MYSQLC --------------------------- */
/***********************************************************************/ /***********************************************************************/
......
...@@ -38,7 +38,11 @@ typedef class MYSQLC *PMYC; ...@@ -38,7 +38,11 @@ typedef class MYSQLC *PMYC;
PQRYRES MyColumns(PGLOBAL g, const char *host, const char *db, PQRYRES MyColumns(PGLOBAL g, const char *host, const char *db,
const char *user, const char *pwd, const char *user, const char *pwd,
const char *table, const char *colpat, const char *table, const char *colpat,
int port, bool key, bool info); int port, bool info);
PQRYRES SrcColumns(PGLOBAL g, const char *host, const char *db,
const char *user, const char *pwd,
const char *srcdef, int port);
/* -------------------------- MYCONN class --------------------------- */ /* -------------------------- MYCONN class --------------------------- */
...@@ -47,6 +51,7 @@ PQRYRES MyColumns(PGLOBAL g, const char *host, const char *db, ...@@ -47,6 +51,7 @@ PQRYRES MyColumns(PGLOBAL g, const char *host, const char *db,
/***********************************************************************/ /***********************************************************************/
class DllItem MYSQLC { class DllItem MYSQLC {
friend class TDBMYSQL; friend class TDBMYSQL;
friend class MYSQLCOL;
// Construction // Construction
public: public:
MYSQLC(void); MYSQLC(void);
......
...@@ -18,7 +18,7 @@ CREATE TABLE t1 ...@@ -18,7 +18,7 @@ CREATE TABLE t1
id INT NOT NULL field_format=' %n%d%n' id INT NOT NULL field_format=' %n%d%n'
) ENGINE=CONNECT TABLE_TYPE=FMT FILE_NAME='t1.txt'; ) ENGINE=CONNECT TABLE_TYPE=FMT FILE_NAME='t1.txt';
INSERT INTO t1 VALUES (10),(20); INSERT INTO t1 VALUES (10),(20);
ERROR HY000: Got error 122 'Writing FMT files is not implemented yet' from CONNECT ERROR HY000: Got error 174 'Writing FMT files is not implemented yet' from CONNECT
DROP TABLE t1; DROP TABLE t1;
# #
# Testing manual examples # Testing manual examples
...@@ -59,7 +59,7 @@ ID NAME DEPNO SALARY ...@@ -59,7 +59,7 @@ ID NAME DEPNO SALARY
56 POIROT-DELMOTTE 0 18009.00 56 POIROT-DELMOTTE 0 18009.00
345 67 19000.25 345 67 19000.25
UPDATE t1 SET SALARY=1234; UPDATE t1 SET SALARY=1234;
ERROR HY000: Got error 122 'Writing FMT files is not implemented yet' from CONNECT ERROR HY000: Got error 174 'Writing FMT files is not implemented yet' from CONNECT
DELETE FROM t1 WHERE ID=56; DELETE FROM t1 WHERE ID=56;
SELECT * FROM t1; SELECT * FROM t1;
ID NAME DEPNO SALARY ID NAME DEPNO SALARY
......
...@@ -77,8 +77,8 @@ Beer DOUBLE(8,2) FLAG=1, ...@@ -77,8 +77,8 @@ Beer DOUBLE(8,2) FLAG=1,
Car DOUBLE(8,2) FLAG=1, Car DOUBLE(8,2) FLAG=1,
Food DOUBLE(8,2) FLAG=1) Food DOUBLE(8,2) FLAG=1)
ENGINE=CONNECT TABLE_TYPE=PIVOT ENGINE=CONNECT TABLE_TYPE=PIVOT
SRCDEF='select who, week, what, sum(amount) from expenses where week in (4,5) group by who, week, what'; SRCDEF='select who, week, what, sum(amount) as amount from expenses where week in (4,5) group by who, week, what';
ALTER TABLE pivex OPTION_LIST='port=PORT'; ALTER TABLE pivex OPTION_LIST='PivotCol=what,FncCol=amount,port=PORT';
Warnings: Warnings:
Warning 1105 The current version of CONNECT did not check what you changed in ALTER. Use at your own risk Warning 1105 The current version of CONNECT did not check what you changed in ALTER. Use at your own risk
SELECT * FROM pivex; SELECT * FROM pivex;
...@@ -125,7 +125,7 @@ Middle DOUBLE(8,2) FLAG=1, ...@@ -125,7 +125,7 @@ Middle DOUBLE(8,2) FLAG=1,
Last DOUBLE(8,2) FLAG=1) Last DOUBLE(8,2) FLAG=1)
ENGINE=CONNECT TABLE_TYPE=PIVOT ENGINE=CONNECT TABLE_TYPE=PIVOT
SRCDEF='select who, what, case when week=3 then ''First'' when week=5 then ''Last'' else ''Middle'' end as wk, sum(amount) * 6.56 as amnt from expenses group by who, what, wk'; SRCDEF='select who, what, case when week=3 then ''First'' when week=5 then ''Last'' else ''Middle'' end as wk, sum(amount) * 6.56 as amnt from expenses group by who, what, wk';
ALTER TABLE pivex OPTION_LIST='PivotCol=wk,port=PORT'; ALTER TABLE pivex OPTION_LIST='PivotCol=wk,FncCol=amnt,port=PORT';
Warnings: Warnings:
Warning 1105 The current version of CONNECT did not check what you changed in ALTER. Use at your own risk Warning 1105 The current version of CONNECT did not check what you changed in ALTER. Use at your own risk
SELECT * FROM pivex; SELECT * FROM pivex;
......
let $MYSQLD_DATADIR= `select @@datadir`; let $MYSQLD_DATADIR= `select @@datadir`;
--copy_file $MTR_SUITE_DIR/std_data/funny.txt $MYSQLD_DATADIR/test/funny.txt --copy_file $MTR_SUITE_DIR/std_data/funny.txt $MYSQLD_DATADIR/test/funny.txt
--copy_file $MTR_SUITE_DIR/std_data/funny2.txt $MYSQLD_DATADIR/test/funny2.txt --copy_file $MTR_SUITE_DIR/std_data/funny2.txt $MYSQLD_DATADIR/test/funny2.txt
--echo # --echo #
--echo # Testing errors --echo # Testing errors
--echo # --echo #
CREATE TABLE t1 CREATE TABLE t1
( (
ID INT NOT NULL field_format=' %n%d%n' ID INT NOT NULL field_format=' %n%d%n'
) Engine=CONNECT table_type=FMT file_name='nonexistent.txt'; ) Engine=CONNECT table_type=FMT file_name='nonexistent.txt';
--replace_regex /on .*test.nonexistent.txt/on DATADIR\/test\/nonexistent.txt/ --replace_regex /on .*test.nonexistent.txt/on DATADIR\/test\/nonexistent.txt/
# TODO: check why this is needed for Windows # TODO: check why this is needed for Windows
--replace_result Open(rt) Open(rb) --replace_result Open(rt) Open(rb)
SELECT * FROM t1; SELECT * FROM t1;
DROP TABLE t1; DROP TABLE t1;
--echo # --echo #
--echo # Testing update on FMT tables --echo # Testing update on FMT tables
--echo # --echo #
CREATE TABLE t1 CREATE TABLE t1
( (
id INT NOT NULL field_format=' %n%d%n' id INT NOT NULL field_format=' %n%d%n'
) ENGINE=CONNECT TABLE_TYPE=FMT FILE_NAME='t1.txt'; ) ENGINE=CONNECT TABLE_TYPE=FMT FILE_NAME='t1.txt';
--error ER_GET_ERRMSG --error ER_GET_ERRMSG
INSERT INTO t1 VALUES (10),(20); INSERT INTO t1 VALUES (10),(20);
# TODO: # TODO:
#--error ER_GET_ERRMSG #--error ER_GET_ERRMSG
#UPDATE t1 SET id=20; #UPDATE t1 SET id=20;
#TRUNCATE TABLE t1; #TRUNCATE TABLE t1;
#DELETE FROM t1 WHERE id=10; #DELETE FROM t1 WHERE id=10;
#SELECT * FROM t1; #SELECT * FROM t1;
DROP TABLE t1; DROP TABLE t1;
--remove_file $MYSQLD_DATADIR/test/t1.txt #--remove_file $MYSQLD_DATADIR/test/t1.txt
--echo # --echo #
--echo # Testing manual examples --echo # Testing manual examples
--echo # --echo #
CREATE TABLE t1 CREATE TABLE t1
( (
ID Integer(5) not null field_format=' %n%d%n', ID Integer(5) not null field_format=' %n%d%n',
NAME Char(16) not null field_format=" , '%n%[^']%n'", NAME Char(16) not null field_format=" , '%n%[^']%n'",
DEPNO Integer(4) not null field_format=' , #%n%d%n', DEPNO Integer(4) not null field_format=' , #%n%d%n',
SALARY Double(12,2) not null field_format=' ; %n%f%n' SALARY Double(12,2) not null field_format=' ; %n%f%n'
) Engine=CONNECT table_type=FMT file_name='funny.txt'; ) Engine=CONNECT table_type=FMT file_name='funny.txt';
SELECT * FROM t1; SELECT * FROM t1;
DROP TABLE t1; DROP TABLE t1;
# #
# TODO: shoudn't a warning instead of error be returned on bad format? # TODO: shoudn't a warning instead of error be returned on bad format?
# #
CREATE TABLE t1 CREATE TABLE t1
( (
ID Integer(5) not null field_format=' %n%d%n', ID Integer(5) not null field_format=' %n%d%n',
NAME Char(16) not null field_format=" , '%n%[^']%n'", NAME Char(16) not null field_format=" , '%n%[^']%n'",
DEPNO Integer(4) not null field_format=' , #%n%d%n', DEPNO Integer(4) not null field_format=' , #%n%d%n',
SALARY Double(12,2) not null field_format=' ; %n%f%n' SALARY Double(12,2) not null field_format=' ; %n%f%n'
) Engine=CONNECT table_type=FMT file_name='funny2.txt'; ) Engine=CONNECT table_type=FMT file_name='funny2.txt';
--error ER_GET_ERRMSG --error ER_GET_ERRMSG
SELECT * FROM t1; SELECT * FROM t1;
DROP TABLE t1; DROP TABLE t1;
CREATE TABLE t1 CREATE TABLE t1
( (
ID Integer(5) not null field_format=' %n%d%n', ID Integer(5) not null field_format=' %n%d%n',
NAME Char(16) not null field_format=' , ''%n%[^'']%m', NAME Char(16) not null field_format=' , ''%n%[^'']%m',
DEPNO Integer(4) not null field_format=''' , #%n%d%m', DEPNO Integer(4) not null field_format=''' , #%n%d%m',
SALARY Double(12,2) not null field_format=' ; %n%f%n' SALARY Double(12,2) not null field_format=' ; %n%f%n'
) Engine=CONNECT table_type=FMT file_name='funny2.txt'; ) Engine=CONNECT table_type=FMT file_name='funny2.txt';
SELECT * FROM t1; SELECT * FROM t1;
--error ER_GET_ERRMSG --error ER_GET_ERRMSG
UPDATE t1 SET SALARY=1234; UPDATE t1 SET SALARY=1234;
# TODO: this query crashes # TODO: this query crashes
# UPDATE t1 SET SALARY=1234 WHERE ID=56; # UPDATE t1 SET SALARY=1234 WHERE ID=56;
DELETE FROM t1 WHERE ID=56; DELETE FROM t1 WHERE ID=56;
SELECT * FROM t1; SELECT * FROM t1;
DROP TABLE t1; DROP TABLE t1;
# #
# Clean up # Clean up
# #
--remove_file $MYSQLD_DATADIR/test/funny.txt --remove_file $MYSQLD_DATADIR/test/funny.txt
--remove_file $MYSQLD_DATADIR/test/funny2.txt --remove_file $MYSQLD_DATADIR/test/funny2.txt
let $MYSQLD_DATADIR= `select @@datadir`; let $MYSQLD_DATADIR= `select @@datadir`;
let $PORT= `select @@port`; let $PORT= `select @@port`;
--copy_file $MTR_SUITE_DIR/std_data/expenses.txt $MYSQLD_DATADIR/test/expenses.txt --copy_file $MTR_SUITE_DIR/std_data/expenses.txt $MYSQLD_DATADIR/test/expenses.txt
--copy_file $MTR_SUITE_DIR/std_data/connect.ini $MYSQLD_DATADIR/test/connect.ini
--echo #
--echo # Testing the PIVOT table type --echo #
--echo # --echo # Testing the PIVOT table type
CREATE TABLE expenses ( --echo #
Who CHAR(10) NOT NULL, CREATE TABLE expenses (
Week INT(2) NOT NULL, Who CHAR(10) NOT NULL,
What CHAR(12) NOT NULL, Week INT(2) NOT NULL,
Amount DOUBLE(8,2)) What CHAR(12) NOT NULL,
ENGINE=CONNECT TABLE_TYPE=FIX FILE_NAME='expenses.txt' ENDING=2; Amount DOUBLE(8,2))
SELECT * FROM expenses; ENGINE=CONNECT TABLE_TYPE=FIX FILE_NAME='expenses.txt' ENDING=2;
SELECT * FROM expenses;
--echo #
--echo # Pivoting from What --echo #
--echo # --echo # Pivoting from What
CREATE TABLE pivex ( --echo #
Who CHAR(10) NOT NULL, CREATE TABLE pivex (
Week INT(2) NOT NULL, Who CHAR(10) NOT NULL,
Beer DOUBLE(8,2) FLAG=1, Week INT(2) NOT NULL,
Car DOUBLE(8,2) FLAG=1, Beer DOUBLE(8,2) FLAG=1,
Food DOUBLE(8,2) FLAG=1) Car DOUBLE(8,2) FLAG=1,
ENGINE=CONNECT TABLE_TYPE=PIVOT TABNAME=expenses; Food DOUBLE(8,2) FLAG=1)
--replace_result $PORT PORT ENGINE=CONNECT TABLE_TYPE=PIVOT TABNAME=expenses;
--eval ALTER TABLE pivex OPTION_LIST='port=$PORT' --replace_result $PORT PORT
SELECT * FROM pivex; --eval ALTER TABLE pivex OPTION_LIST='port=$PORT'
SELECT * FROM pivex;
--echo #
--echo # Restricting the columns in a Pivot Table --echo #
--echo # --echo # Restricting the columns in a Pivot Table
ALTER TABLE pivex DROP COLUMN week; --echo #
SELECT * FROM pivex; ALTER TABLE pivex DROP COLUMN week;
SELECT * FROM pivex;
--echo #
--echo # Using a source definition --echo #
--echo # --echo # Using a source definition
DROP TABLE pivex; --echo #
CREATE TABLE pivex ( DROP TABLE pivex;
Who CHAR(10) NOT NULL, CREATE TABLE pivex (
Week INT(2) NOT NULL, Who CHAR(10) NOT NULL,
Beer DOUBLE(8,2) FLAG=1, Week INT(2) NOT NULL,
Car DOUBLE(8,2) FLAG=1, Beer DOUBLE(8,2) FLAG=1,
Food DOUBLE(8,2) FLAG=1) Car DOUBLE(8,2) FLAG=1,
ENGINE=CONNECT TABLE_TYPE=PIVOT Food DOUBLE(8,2) FLAG=1)
SRCDEF='select who, week, what, sum(amount) from expenses where week in (4,5) group by who, week, what'; ENGINE=CONNECT TABLE_TYPE=PIVOT
--replace_result $PORT PORT SRCDEF='select who, week, what, sum(amount) as amount from expenses where week in (4,5) group by who, week, what';
--eval ALTER TABLE pivex OPTION_LIST='port=$PORT' --replace_result $PORT PORT
SELECT * FROM pivex; --eval ALTER TABLE pivex OPTION_LIST='PivotCol=what,FncCol=amount,port=$PORT'
SELECT * FROM pivex;
--echo #
--echo # Pivoting from Week --echo #
--echo # --echo # Pivoting from Week
DROP TABLE pivex; --echo #
CREATE TABLE pivex ( DROP TABLE pivex;
Who CHAR(10) NOT NULL, CREATE TABLE pivex (
What CHAR(12) NOT NULL, Who CHAR(10) NOT NULL,
`3` DOUBLE(8,2) FLAG=1, What CHAR(12) NOT NULL,
`4` DOUBLE(8,2) FLAG=1, `3` DOUBLE(8,2) FLAG=1,
`5` DOUBLE(8,2) FLAG=1) `4` DOUBLE(8,2) FLAG=1,
ENGINE=CONNECT TABLE_TYPE=PIVOT TABNAME=expenses; `5` DOUBLE(8,2) FLAG=1)
--replace_result $PORT PORT ENGINE=CONNECT TABLE_TYPE=PIVOT TABNAME=expenses;
--eval ALTER TABLE pivex OPTION_LIST='PivotCol=Week,port=$PORT' --replace_result $PORT PORT
SELECT * FROM pivex; --eval ALTER TABLE pivex OPTION_LIST='PivotCol=Week,port=$PORT'
SELECT * FROM pivex;
--echo #
--echo # Using scalar functions and expresssions --echo #
--echo # --echo # Using scalar functions and expresssions
DROP TABLE pivex; --echo #
CREATE TABLE pivex ( DROP TABLE pivex;
Who CHAR(10) NOT NULL, CREATE TABLE pivex (
What CHAR(12) NOT NULL, Who CHAR(10) NOT NULL,
First DOUBLE(8,2) FLAG=1, What CHAR(12) NOT NULL,
Middle DOUBLE(8,2) FLAG=1, First DOUBLE(8,2) FLAG=1,
Last DOUBLE(8,2) FLAG=1) Middle DOUBLE(8,2) FLAG=1,
ENGINE=CONNECT TABLE_TYPE=PIVOT Last DOUBLE(8,2) FLAG=1)
SRCDEF='select who, what, case when week=3 then ''First'' when week=5 then ''Last'' else ''Middle'' end as wk, sum(amount) * 6.56 as amnt from expenses group by who, what, wk'; ENGINE=CONNECT TABLE_TYPE=PIVOT
--replace_result $PORT PORT SRCDEF='select who, what, case when week=3 then ''First'' when week=5 then ''Last'' else ''Middle'' end as wk, sum(amount) * 6.56 as amnt from expenses group by who, what, wk';
--eval ALTER TABLE pivex OPTION_LIST='PivotCol=wk,port=$PORT' --replace_result $PORT PORT
SELECT * FROM pivex; --eval ALTER TABLE pivex OPTION_LIST='PivotCol=wk,FncCol=amnt,port=$PORT'
DROP TABLE pivex; SELECT * FROM pivex;
DROP TABLE expenses; DROP TABLE pivex;
DROP TABLE expenses;
--echo #
--echo # Make the PETS table --echo #
--echo # --echo # Make the PETS table
CREATE TABLE pets ( --echo #
Name VARCHAR(12) NOT NULL, CREATE TABLE pets (
Race CHAR(6) NOT NULL, Name VARCHAR(12) NOT NULL,
Number INT NOT NULL) ENGINE=MYISAM; Race CHAR(6) NOT NULL,
INSERT INTO pets VALUES('John','dog',2); Number INT NOT NULL) ENGINE=MYISAM;
INSERT INTO pets VALUES('Bill','cat',1); INSERT INTO pets VALUES('John','dog',2);
INSERT INTO pets VALUES('Mary','dog',1); INSERT INTO pets VALUES('Bill','cat',1);
INSERT INTO pets VALUES('Mary','cat',1); INSERT INTO pets VALUES('Mary','dog',1);
INSERT INTO pets VALUES('Lisbeth','rabbit',2); INSERT INTO pets VALUES('Mary','cat',1);
INSERT INTO pets VALUES('Kevin','cat',2); INSERT INTO pets VALUES('Lisbeth','rabbit',2);
INSERT INTO pets VALUES('Kevin','bird',6); INSERT INTO pets VALUES('Kevin','cat',2);
INSERT INTO pets VALUES('Donald','dog',1); INSERT INTO pets VALUES('Kevin','bird',6);
INSERT INTO pets VALUES('Donald','fish',3); INSERT INTO pets VALUES('Donald','dog',1);
SELECT * FROM pets; INSERT INTO pets VALUES('Donald','fish',3);
SELECT * FROM pets;
--echo #
--echo # Pivot the PETS table --echo #
--echo # --echo # Pivot the PETS table
CREATE TABLE pivet ( --echo #
name VARCHAR(12) NOT NULL, CREATE TABLE pivet (
dog INT NOT NULL DEFAULT 0 FLAG=1, name VARCHAR(12) NOT NULL,
cat INT NOT NULL DEFAULT 0 FLAG=1, dog INT NOT NULL DEFAULT 0 FLAG=1,
rabbit INT NOT NULL DEFAULT 0 FLAG=1, cat INT NOT NULL DEFAULT 0 FLAG=1,
bird INT NOT NULL DEFAULT 0 FLAG=1, rabbit INT NOT NULL DEFAULT 0 FLAG=1,
fish INT NOT NULL DEFAULT 0 FLAG=1) bird INT NOT NULL DEFAULT 0 FLAG=1,
ENGINE=CONNECT TABLE_TYPE=PIVOT TABNAME=pets OPTION_LIST='PivotCol=race,groupby=1'; fish INT NOT NULL DEFAULT 0 FLAG=1)
SELECT * FROM pivet; ENGINE=CONNECT TABLE_TYPE=PIVOT TABNAME=pets OPTION_LIST='PivotCol=race,groupby=1';
DROP TABLE pivet; SELECT * FROM pivet;
DROP TABLE pivet;
--echo #
--echo # Testing the "data" column list --echo #
--echo # --echo # Testing the "data" column list
CREATE TABLE pivet ( --echo #
name VARCHAR(12) NOT NULL, CREATE TABLE pivet (
dog INT NOT NULL DEFAULT 0 FLAG=1, name VARCHAR(12) NOT NULL,
cat INT NOT NULL DEFAULT 0 FLAG=1) dog INT NOT NULL DEFAULT 0 FLAG=1,
ENGINE=CONNECT TABLE_TYPE=PIVOT TABNAME=pets OPTION_LIST='PivotCol=race,groupby=1'; cat INT NOT NULL DEFAULT 0 FLAG=1)
--error ER_GET_ERRMSG ENGINE=CONNECT TABLE_TYPE=PIVOT TABNAME=pets OPTION_LIST='PivotCol=race,groupby=1';
SELECT * FROM pivet; --error ER_GET_ERRMSG
ALTER TABLE pivet OPTION_LIST='PivotCol=race,groupby=1,accept=1'; SELECT * FROM pivet;
SELECT * FROM pivet; ALTER TABLE pivet OPTION_LIST='PivotCol=race,groupby=1,accept=1';
DROP TABLE pivet; SELECT * FROM pivet;
DROP TABLE pivet;
--echo #
--echo # Adding a "dump" column --echo #
--echo # --echo # Adding a "dump" column
CREATE TABLE pivet ( --echo #
name VARCHAR(12) NOT NULL, CREATE TABLE pivet (
dog INT NOT NULL DEFAULT 0 FLAG=1, name VARCHAR(12) NOT NULL,
cat INT NOT NULL DEFAULT 0 FLAG=1, dog INT NOT NULL DEFAULT 0 FLAG=1,
other INT NOT NULL DEFAULT 0 FLAG=2) cat INT NOT NULL DEFAULT 0 FLAG=1,
ENGINE=CONNECT TABLE_TYPE=PIVOT TABNAME=pets OPTION_LIST='PivotCol=race,groupby=1'; other INT NOT NULL DEFAULT 0 FLAG=2)
SELECT * FROM pivet; ENGINE=CONNECT TABLE_TYPE=PIVOT TABNAME=pets OPTION_LIST='PivotCol=race,groupby=1';
SELECT * FROM pivet;
DROP TABLE pivet;
DROP TABLE pets; DROP TABLE pivet;
--remove_file $MYSQLD_DATADIR/test/expenses.txt DROP TABLE pets;
--remove_file $MYSQLD_DATADIR/test/expenses.txt
...@@ -24,8 +24,8 @@ ...@@ -24,8 +24,8 @@
#define DOS_BUFF_LEN 100 /* Number of lines in binary file buffer */ #define DOS_BUFF_LEN 100 /* Number of lines in binary file buffer */
#undef DOMAIN /* For Unix version */ #undef DOMAIN /* For Unix version */
enum BLKTYP {TYPE_TABLE = 50, /* Table Name/Correl Block */ enum BLKTYP {TYPE_TABLE = 50, /* Table Name/Srcdef/... Block */
TYPE_COLUMN = 51, /* Column Name/Correl Block */ TYPE_COLUMN = 51, /* Column Name/Qualifier Block */
// TYPE_OPVAL = 52, /* Operator value (OPVAL) */ // TYPE_OPVAL = 52, /* Operator value (OPVAL) */
TYPE_TDB = 53, /* Table Description Block */ TYPE_TDB = 53, /* Table Description Block */
TYPE_COLBLK = 54, /* Column Description Block */ TYPE_COLBLK = 54, /* Column Description Block */
......
...@@ -147,6 +147,7 @@ PGLOBAL PlugInit(LPCSTR Language, uint worksize) ...@@ -147,6 +147,7 @@ PGLOBAL PlugInit(LPCSTR Language, uint worksize)
if (!(g = malloc(sizeof(GLOBAL)))) { if (!(g = malloc(sizeof(GLOBAL)))) {
fprintf(stderr, MSG(GLOBAL_ERROR), (int)sizeof(GLOBAL)); fprintf(stderr, MSG(GLOBAL_ERROR), (int)sizeof(GLOBAL));
return NULL;
} else { } else {
g->Sarea_Size = worksize; g->Sarea_Size = worksize;
g->Trace = 0; g->Trace = 0;
...@@ -180,7 +181,9 @@ int PlugExit(PGLOBAL g) ...@@ -180,7 +181,9 @@ int PlugExit(PGLOBAL g)
if (!g) if (!g)
return rc; return rc;
free(g->Sarea); if (g->Sarea)
free(g->Sarea);
free(g); free(g);
return rc; return rc;
} /* end of PlugExit */ } /* end of PlugExit */
......
/************* TabCol C++ Functions Source Code File (.CPP) ************/ /************* TabCol C++ Functions Source Code File (.CPP) ************/
/* Name: TABCOL.CPP Version 2.6 */ /* Name: TABCOL.CPP Version 2.7 */
/* */ /* */
/* (C) Copyright to the author Olivier BERTRAND 1998-2012 */ /* (C) Copyright to the author Olivier BERTRAND 1998-2013 */
/* */ /* */
/* This file contains the PlugDB++ XTAB, COLUMN and XORDER methods. */ /* This file contains the PlugDB++ XTAB, COLUMN and XORDER methods. */
/***********************************************************************/ /***********************************************************************/
...@@ -23,18 +23,18 @@ ...@@ -23,18 +23,18 @@
#include "tabcol.h" #include "tabcol.h"
/***********************************************************************/ /***********************************************************************/
/* XTAB public constructor (in which Correl defaults to Name). */ /* XTAB public constructor. */
/***********************************************************************/ /***********************************************************************/
XTAB::XTAB(LPCSTR name, LPCSTR correl) : Name(name) XTAB::XTAB(LPCSTR name, LPCSTR srcdef) : Name(name)
{ {
Next = NULL; Next = NULL;
To_Tdb = NULL; To_Tdb = NULL;
Correl = (correl) ? correl : name; Srcdef = srcdef;
Creator = NULL; Creator = NULL;
Qualifier = NULL; Qualifier = NULL;
#ifdef DEBTRACE #ifdef DEBTRACE
htrc(" making new TABLE %s %s\n", Name, Correl); htrc(" making new TABLE %s %s\n", Name, Srcdef);
#endif #endif
} // end of XTAB constructor } // end of XTAB constructor
...@@ -45,12 +45,12 @@ XTAB::XTAB(PTABLE tp) : Name(tp->Name) ...@@ -45,12 +45,12 @@ XTAB::XTAB(PTABLE tp) : Name(tp->Name)
{ {
Next = NULL; Next = NULL;
To_Tdb = NULL; To_Tdb = NULL;
Correl = tp->Correl; Srcdef = tp->Srcdef;
Creator = tp->Creator; Creator = tp->Creator;
Qualifier = tp->Qualifier; Qualifier = tp->Qualifier;
#ifdef DEBTRACE #ifdef DEBTRACE
htrc(" making copy TABLE %s %s\n", Name, Correl); htrc(" making copy TABLE %s %s\n", Name, Srcdef);
#endif #endif
} // end of XTAB constructor } // end of XTAB constructor
...@@ -83,7 +83,7 @@ void XTAB::Print(PGLOBAL g, FILE *f, uint n) ...@@ -83,7 +83,7 @@ void XTAB::Print(PGLOBAL g, FILE *f, uint n)
for (PTABLE tp = this; tp; tp = tp->Next) { for (PTABLE tp = this; tp; tp = tp->Next) {
fprintf(f, "%sTABLE: %s.%s %s\n", fprintf(f, "%sTABLE: %s.%s %s\n",
m, SVP(tp->Creator), tp->Name, SVP(tp->Correl)); m, SVP(tp->Creator), tp->Name, SVP(tp->Srcdef));
PlugPutOut(g, f, TYPE_TDB, tp->To_Tdb, n + 2); PlugPutOut(g, f, TYPE_TDB, tp->To_Tdb, n + 2);
} /* endfor tp */ } /* endfor tp */
...@@ -101,7 +101,7 @@ void XTAB::Print(PGLOBAL g, char *ps, uint z) ...@@ -101,7 +101,7 @@ void XTAB::Print(PGLOBAL g, char *ps, uint z)
for (PTABLE tp = this; tp && n > 0; tp = tp->Next) { for (PTABLE tp = this; tp && n > 0; tp = tp->Next) {
i = sprintf(buf, "TABLE: %s.%s %s To_Tdb=%p ", i = sprintf(buf, "TABLE: %s.%s %s To_Tdb=%p ",
SVP(tp->Creator), tp->Name, SVP(tp->Correl), tp->To_Tdb); SVP(tp->Creator), tp->Name, SVP(tp->Srcdef), tp->To_Tdb);
strncat(ps, buf, n); strncat(ps, buf, n);
n -= i; n -= i;
} // endif tp } // endif tp
......
/*************** TabCol H Declares Source Code File (.H) ***************/ /*************** TabCol H Declares Source Code File (.H) ***************/
/* Name: TABCOL.H Version 2.7 */ /* Name: TABCOL.H Version 2.8 */
/* */ /* */
/* (C) Copyright to the author Olivier BERTRAND 1998-2012 */ /* (C) Copyright to the author Olivier BERTRAND 1998-2013 */
/* */ /* */
/* This file contains the XTAB, COLUMN and XORDER class definitions. */ /* This file contains the XTAB, COLUMN and XORDER class definitions. */
/***********************************************************************/ /***********************************************************************/
...@@ -15,23 +15,23 @@ ...@@ -15,23 +15,23 @@
/***********************************************************************/ /***********************************************************************/
/* Definition of class XTAB with all its method functions. */ /* Definition of class XTAB with all its method functions. */
/***********************************************************************/ /***********************************************************************/
class DllExport XTAB: public BLOCK { // Table Name-Owner-Correl block. class DllExport XTAB: public BLOCK { // Table Name-Owner-Srcdef block.
friend class TDBPRX; friend class TDBPRX;
public: public:
// Constructors // Constructors
XTAB(LPCSTR name, LPCSTR correl = NULL); XTAB(LPCSTR name, LPCSTR srcdef = NULL);
XTAB(PTABLE tp); XTAB(PTABLE tp);
// Implementation // Implementation
PTABLE GetNext(void) {return Next;} PTABLE GetNext(void) {return Next;}
PTDB GetTo_Tdb(void) {return To_Tdb;} PTDB GetTo_Tdb(void) {return To_Tdb;}
LPCSTR GetName(void) {return Name;} LPCSTR GetName(void) {return Name;}
LPCSTR GetCorrel(void) {return Correl;} LPCSTR GetSrc(void) {return Srcdef;}
LPCSTR GetCreator(void) {return Creator;} LPCSTR GetCreator(void) {return Creator;}
LPCSTR GetQualifier(void) {return Qualifier;} LPCSTR GetQualifier(void) {return Qualifier;}
void SetTo_Tdb(PTDB tdbp) {To_Tdb = tdbp;} void SetTo_Tdb(PTDB tdbp) {To_Tdb = tdbp;}
void SetName(LPCSTR name) {Name = name;} void SetName(LPCSTR name) {Name = name;}
void SetCorrel(LPCSTR correl) {Correl = correl;} void SetSrc(LPCSTR srcdef) {Srcdef = srcdef;}
void SetCreator(LPCSTR crname) {Creator = crname;} void SetCreator(LPCSTR crname) {Creator = crname;}
void SetQualifier(LPCSTR qname) {Qualifier = qname;} void SetQualifier(LPCSTR qname) {Qualifier = qname;}
...@@ -44,8 +44,8 @@ class DllExport XTAB: public BLOCK { // Table Name-Owner-Correl block. ...@@ -44,8 +44,8 @@ class DllExport XTAB: public BLOCK { // Table Name-Owner-Correl block.
// Members // Members
PTABLE Next; // Points to next table in chain PTABLE Next; // Points to next table in chain
PTDB To_Tdb; // Points to Table description Block PTDB To_Tdb; // Points to Table description Block
LPCSTR Name; // Table name (can be changed by LNA and PLG) LPCSTR Name; // Table name
LPCSTR Correl; // Correlation name LPCSTR Srcdef; // Table Source definition
LPCSTR Creator; // Creator name LPCSTR Creator; // Creator name
LPCSTR Qualifier; // Qualifier name LPCSTR Qualifier; // Qualifier name
}; // end of class XTAB }; // end of class XTAB
......
...@@ -1088,7 +1088,12 @@ bool TDBFMT::OpenDB(PGLOBAL g) ...@@ -1088,7 +1088,12 @@ bool TDBFMT::OpenDB(PGLOBAL g)
{ {
Linenum = 0; Linenum = 0;
if (Use != USE_OPEN && (Columns || Mode == MODE_UPDATE)) { if (Mode == MODE_INSERT || Mode == MODE_UPDATE) {
sprintf(g->Message, MSG(FMT_WRITE_NIY), "FMT");
return true; // NIY
} // endif Mode
if (Use != USE_OPEN && Columns) {
// Make the formats used to read records // Make the formats used to read records
PSZ pfm; PSZ pfm;
int i, n; int i, n;
...@@ -1096,17 +1101,12 @@ bool TDBFMT::OpenDB(PGLOBAL g) ...@@ -1096,17 +1101,12 @@ bool TDBFMT::OpenDB(PGLOBAL g)
PCOLDEF cdp; PCOLDEF cdp;
PDOSDEF tdp = (PDOSDEF)To_Def; PDOSDEF tdp = (PDOSDEF)To_Def;
// if (Mode != MODE_UPDATE) { for (colp = (PCSVCOL)Columns; colp; colp = (PCSVCOL)colp->Next)
for (colp = (PCSVCOL)Columns; colp; colp = (PCSVCOL)colp->Next) if (!colp->IsSpecial()) // Not a pseudo column
if (!colp->IsSpecial()) // Not a pseudo column Fields = max(Fields, (int)colp->Fldnum);
Fields = max(Fields, (int)colp->Fldnum);
if (Columns)
Fields++; // Fldnum was 0 based
// } else if (Columns)
// for (cdp = tdp->GetCols(); cdp; cdp = cdp->GetNext()) Fields++; // Fldnum was 0 based
// Fields++;
To_Fld = PlugSubAlloc(g, NULL, Lrecl + 1); To_Fld = PlugSubAlloc(g, NULL, Lrecl + 1);
FldFormat = (PSZ*)PlugSubAlloc(g, NULL, sizeof(PSZ) * Fields); FldFormat = (PSZ*)PlugSubAlloc(g, NULL, sizeof(PSZ) * Fields);
......
This diff is collapsed.
...@@ -30,6 +30,7 @@ class MYSQLDEF : public TABDEF {/* Logical table description */ ...@@ -30,6 +30,7 @@ class MYSQLDEF : public TABDEF {/* Logical table description */
inline PSZ GetHostname(void) {return Hostname;}; inline PSZ GetHostname(void) {return Hostname;};
inline PSZ GetDatabase(void) {return Database;}; inline PSZ GetDatabase(void) {return Database;};
inline PSZ GetTabname(void) {return Tabname;} inline PSZ GetTabname(void) {return Tabname;}
inline PSZ GetSrcdef(void) {return Srcdef;}
inline PSZ GetUsername(void) {return Username;}; inline PSZ GetUsername(void) {return Username;};
inline PSZ GetPassword(void) {return Password;}; inline PSZ GetPassword(void) {return Password;};
inline int GetPortnumber(void) {return Portnumber;} inline int GetPortnumber(void) {return Portnumber;}
...@@ -44,9 +45,11 @@ class MYSQLDEF : public TABDEF {/* Logical table description */ ...@@ -44,9 +45,11 @@ class MYSQLDEF : public TABDEF {/* Logical table description */
PSZ Hostname; /* Host machine to use */ PSZ Hostname; /* Host machine to use */
PSZ Database; /* Database to be used by server */ PSZ Database; /* Database to be used by server */
PSZ Tabname; /* External table name */ PSZ Tabname; /* External table name */
PSZ Srcdef; /* The source table SQL definition */
PSZ Username; /* User logon name */ PSZ Username; /* User logon name */
PSZ Password; /* Password logon info */ PSZ Password; /* Password logon info */
int Portnumber; /* MySQL port number (0 = default) */ int Portnumber; /* MySQL port number (0 = default) */
bool Isview; /* TRUE if this table is a MySQL view */
bool Bind; /* Use prepared statement on insert */ bool Bind; /* Use prepared statement on insert */
bool Delayed; /* Delayed insert */ bool Delayed; /* Delayed insert */
}; // end of MYSQLDEF }; // end of MYSQLDEF
...@@ -72,6 +75,7 @@ class TDBMYSQL : public TDBASE { ...@@ -72,6 +75,7 @@ class TDBMYSQL : public TDBASE {
virtual int GetProgMax(PGLOBAL g); virtual int GetProgMax(PGLOBAL g);
virtual void ResetDB(void) {N = 0;} virtual void ResetDB(void) {N = 0;}
virtual int RowNumber(PGLOBAL g, bool b = FALSE); virtual int RowNumber(PGLOBAL g, bool b = FALSE);
virtual bool IsView(void) {return Isview;}
void SetDatabase(LPCSTR db) {Database = (char*)db;} void SetDatabase(LPCSTR db) {Database = (char*)db;}
// Database routines // Database routines
...@@ -83,6 +87,10 @@ class TDBMYSQL : public TDBASE { ...@@ -83,6 +87,10 @@ class TDBMYSQL : public TDBASE {
virtual int DeleteDB(PGLOBAL g, int irc); virtual int DeleteDB(PGLOBAL g, int irc);
virtual void CloseDB(PGLOBAL g); virtual void CloseDB(PGLOBAL g);
// Specific routines
bool SetColumnRanks(PGLOBAL g);
PCOL MakeFieldColumn(PGLOBAL g, char *name);
protected: protected:
// Internal functions // Internal functions
bool MakeSelect(PGLOBAL g); bool MakeSelect(PGLOBAL g);
...@@ -99,9 +107,11 @@ class TDBMYSQL : public TDBASE { ...@@ -99,9 +107,11 @@ class TDBMYSQL : public TDBASE {
char *Pwd; // Password logon info char *Pwd; // Password logon info
char *Database; // Database to be used by server char *Database; // Database to be used by server
char *Tabname; // External table name char *Tabname; // External table name
char *Srcdef; // The source table SQL definition
char *Query; // Points to SQL query char *Query; // Points to SQL query
char *Qbuf; // Used for not prepared insert char *Qbuf; // Used for not prepared insert
bool Fetched; // True when fetch was done bool Fetched; // True when fetch was done
bool Isview; // True if this table is a MySQL view
bool Prep; // Use prepared statement on insert bool Prep; // Use prepared statement on insert
bool Delayed; // Use delayed insert bool Delayed; // Use delayed insert
int m_Rc; // Return code from command int m_Rc; // Return code from command
...@@ -119,6 +129,7 @@ class MYSQLCOL : public COLBLK { ...@@ -119,6 +129,7 @@ class MYSQLCOL : public COLBLK {
public: public:
// Constructors // Constructors
MYSQLCOL(PCOLDEF cdp, PTDB tdbp, PCOL cprec, int i, PSZ am = "MYSQL"); MYSQLCOL(PCOLDEF cdp, PTDB tdbp, PCOL cprec, int i, PSZ am = "MYSQL");
MYSQLCOL(MYSQL_FIELD *fld, PTDB tdbp, int i, PSZ am = "MYSQL");
MYSQLCOL(MYSQLCOL *colp, PTDB tdbp); // Constructor used in copy process MYSQLCOL(MYSQLCOL *colp, PTDB tdbp); // Constructor used in copy process
// Implementation // Implementation
...@@ -129,6 +140,7 @@ class MYSQLCOL : public COLBLK { ...@@ -129,6 +140,7 @@ class MYSQLCOL : public COLBLK {
virtual bool SetBuffer(PGLOBAL g, PVAL value, bool ok, bool check); virtual bool SetBuffer(PGLOBAL g, PVAL value, bool ok, bool check);
virtual void ReadColumn(PGLOBAL g); virtual void ReadColumn(PGLOBAL g);
virtual void WriteColumn(PGLOBAL g); virtual void WriteColumn(PGLOBAL g);
bool FindRank(PGLOBAL g);
protected: protected:
// Default constructor not to be used // Default constructor not to be used
......
...@@ -85,19 +85,43 @@ PTDB OCCURDEF::GetTable(PGLOBAL g, MODE m) ...@@ -85,19 +85,43 @@ PTDB OCCURDEF::GetTable(PGLOBAL g, MODE m)
/***********************************************************************/ /***********************************************************************/
TDBOCCUR::TDBOCCUR(POCCURDEF tdp) : TDBPRX(tdp) TDBOCCUR::TDBOCCUR(POCCURDEF tdp) : TDBPRX(tdp)
{ {
//Tdbp = NULL; // Source table //Tdbp = NULL; // Source table (in TDBPRX)
Tabname = tdp->Tablep->GetName(); // Name of source table Tabname = tdp->Tablep->GetName(); // Name of source table
Colist = tdp->Colist; // List of source columns Colist = tdp->Colist; // List of source columns
Xcolumn = tdp->Xcol; // Occur column name Xcolumn = tdp->Xcol; // Occur column name
Rcolumn = tdp->Rcol; // Rank column name Rcolumn = tdp->Rcol; // Rank column name
Xcolp = NULL; // To the OCCURCOL column Xcolp = NULL; // To the OCCURCOL column
Col = NULL; // To source column blocks array Col = NULL; // To source column blocks array
Mult = -1; // Multiplication factor Mult = PrepareColist(); // Multiplication factor
N = 0; // The current table index N = 0; // The current table index
M = 0; // The occurence rank M = 0; // The occurence rank
RowFlag = 0; // 0: Ok, 1: Same, 2: Skip RowFlag = 0; // 0: Ok, 1: Same, 2: Skip
} // end of TDBOCCUR constructor } // end of TDBOCCUR constructor
/***********************************************************************/
/* Prepare and count columns in the column list. */
/***********************************************************************/
int TDBOCCUR::PrepareColist(void)
{
char *p, *pn;
int n = 0;
// Count the number of columns and change separator into null char
for (pn = Colist; ; pn += (strlen(pn) + 1))
// Separator can be ; if colist was specified in the option_list
if ((p = strchr(pn, ',')) || (p = strchr(pn, ';'))) {
*p++ = '\0';
n++;
} else {
if (*pn)
n++;
break;
} // endif p
return n;
} // end of PrepareColist
/***********************************************************************/ /***********************************************************************/
/* Allocate OCCUR/SRC column description block. */ /* Allocate OCCUR/SRC column description block. */
/***********************************************************************/ /***********************************************************************/
...@@ -111,14 +135,8 @@ PCOL TDBOCCUR::MakeCol(PGLOBAL g, PCOLDEF cdp, PCOL cprec, int n) ...@@ -111,14 +135,8 @@ PCOL TDBOCCUR::MakeCol(PGLOBAL g, PCOLDEF cdp, PCOL cprec, int n)
} else if (!stricmp(cdp->GetName(), Xcolumn)) { } else if (!stricmp(cdp->GetName(), Xcolumn)) {
// Allocate the OCCUR column // Allocate the OCCUR column
colp = Xcolp = new(g) OCCURCOL(cdp, this, n); colp = Xcolp = new(g) OCCURCOL(cdp, this, n);
} else { } else
colp = new(g) PRXCOL(cdp, this, cprec, n); return new(g) PRXCOL(cdp, this, cprec, n);
if (((PPRXCOL)colp)->Init(g))
return NULL;
return colp;
} //endif name
if (cprec) { if (cprec) {
colp->SetNext(cprec->GetNext()); colp->SetNext(cprec->GetNext());
...@@ -136,75 +154,100 @@ PCOL TDBOCCUR::MakeCol(PGLOBAL g, PCOLDEF cdp, PCOL cprec, int n) ...@@ -136,75 +154,100 @@ PCOL TDBOCCUR::MakeCol(PGLOBAL g, PCOLDEF cdp, PCOL cprec, int n)
/***********************************************************************/ /***********************************************************************/
bool TDBOCCUR::InitTable(PGLOBAL g) bool TDBOCCUR::InitTable(PGLOBAL g)
{ {
if (!Tdbp) { if (!Tdbp)
// Get the table description block of this table // Get the table description block of this table
if (!(Tdbp = (PTDBASE)GetSubTable(g, ((POCCURDEF)To_Def)->Tablep))) if (!(Tdbp = GetSubTable(g, ((POCCURDEF)To_Def)->Tablep, TRUE)))
return TRUE; return TRUE;
if (MakeColumnList(g) < 0) if (!Tdbp->IsView())
if (MakeColumnList(g))
return TRUE; return TRUE;
} // endif Tdbp
return FALSE; return FALSE;
} // end of InitTable } // end of InitTable
/***********************************************************************/ /***********************************************************************/
/* Allocate OCCUR column description block. */ /* Allocate OCCUR column description block. */
/***********************************************************************/ /***********************************************************************/
int TDBOCCUR::MakeColumnList(PGLOBAL g) bool TDBOCCUR::MakeColumnList(PGLOBAL g)
{ {
if (Mult < 0) { char *pn;
char *p, *pn; int i;
int i; PCOL colp;
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 = strchr(pn, ';'))) {
*p++ = '\0';
n++;
} else {
if (*pn)
n++;
break;
} // endif p
Col = (PCOL*)PlugSubAlloc(g, NULL, n * sizeof(PCOL)); for (colp = Columns; colp; colp = colp->GetNext())
if (colp->GetAmType() == TYPE_AM_PRX)
if (((PPRXCOL)colp)->Init(g))
return true;
for (i = 0, pn = Colist; i < n; i++, pn += (strlen(pn) + 1)) { Col = (PCOL*)PlugSubAlloc(g, NULL, Mult * sizeof(PCOL));
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)) { for (i = 0, pn = Colist; i < Mult; i++, pn += (strlen(pn) + 1)) {
strcpy(g->Message, "OCCUR InitValue failed"); if (!(Col[i] = Tdbp->ColDB(g, pn, 0))) {
return -1; // Column not found in table
} // endif InitValue sprintf(g->Message, MSG(COL_ISNOT_TABLE), pn, Tabname);
return true;
} // endif Col
} // endfor i if (Col[i]->InitValue(g)) {
strcpy(g->Message, "OCCUR InitValue failed");
return true;
} // endif InitValue
// OCCUR column name defaults to the name of the list first column } // endfor i
if (!Xcolumn)
Xcolumn = Colist;
Mult = n; return false;
} // endif Mult
return Mult;
} // end of MakeColumnList } // end of MakeColumnList
/***********************************************************************/
/* Allocate OCCUR column description block for a view. */
/***********************************************************************/
bool TDBOCCUR::ViewColumnList(PGLOBAL g)
{
char *pn;
int i;
PCOL colp, cp;
PTDBMY tdbp;
if (!Tdbp->IsView())
return false;
if (Tdbp->GetAmType() != TYPE_AM_MYSQL) {
strcpy(g->Message, "View is not MySQL");
return true;
} else
tdbp = (PTDBMY)Tdbp;
for (cp = Columns; cp; cp = cp->GetNext())
if (cp->GetAmType() == TYPE_AM_PRX) {
if ((colp = tdbp->MakeFieldColumn(g, cp->GetName()))) {
((PPRXCOL)cp)->Colp = colp;
((PPRXCOL)cp)->To_Val = colp->GetValue();
} else
return true;
} // endif Type
Col = (PCOL*)PlugSubAlloc(g, NULL, Mult * sizeof(PCOL));
for (i = 0, pn = Colist; i < Mult; i++, pn += (strlen(pn) + 1))
if (!(Col[i] = tdbp->MakeFieldColumn(g, pn))) {
// Column not found in table
sprintf(g->Message, MSG(COL_ISNOT_TABLE), pn, Tabname);
return true;
} // endif Col
return false;
} // end of ViewColumnList
/***********************************************************************/ /***********************************************************************/
/* OCCUR GetMaxSize: returns the maximum number of rows in the table. */ /* OCCUR GetMaxSize: returns the maximum number of rows in the table. */
/***********************************************************************/ /***********************************************************************/
int TDBOCCUR::GetMaxSize(PGLOBAL g) int TDBOCCUR::GetMaxSize(PGLOBAL g)
{ {
if (MaxSize < 0) { if (MaxSize < 0) {
if (InitTable(g)) if (!(Tdbp = GetSubTable(g, ((POCCURDEF)To_Def)->Tablep, TRUE)))
return NULL; return 0;
MaxSize = Mult * Tdbp->GetMaxSize(g); MaxSize = Mult * Tdbp->GetMaxSize(g);
} // endif MaxSize } // endif MaxSize
...@@ -252,7 +295,7 @@ bool TDBOCCUR::OpenDB(PGLOBAL g) ...@@ -252,7 +295,7 @@ bool TDBOCCUR::OpenDB(PGLOBAL g)
/* Do it here if not done yet. */ /* Do it here if not done yet. */
/*********************************************************************/ /*********************************************************************/
if (InitTable(g)) if (InitTable(g))
return NULL; return TRUE;
if (Xcolp) if (Xcolp)
// Lock this column so it is evaluated by its table only // Lock this column so it is evaluated by its table only
...@@ -269,7 +312,10 @@ bool TDBOCCUR::OpenDB(PGLOBAL g) ...@@ -269,7 +312,10 @@ bool TDBOCCUR::OpenDB(PGLOBAL g)
/*********************************************************************/ /*********************************************************************/
/* Do open the source table. */ /* Do open the source table. */
/*********************************************************************/ /*********************************************************************/
return Tdbp->OpenDB(g); if (Tdbp->OpenDB(g))
return TRUE;
return ViewColumnList(g);
} // end of OpenDB } // end of OpenDB
/***********************************************************************/ /***********************************************************************/
......
...@@ -52,21 +52,22 @@ class TDBOCCUR : public TDBPRX { ...@@ -52,21 +52,22 @@ class TDBOCCUR : public TDBPRX {
TDBOCCUR(POCCURDEF tdp); TDBOCCUR(POCCURDEF tdp);
// Implementation // Implementation
virtual AMT GetAmType(void) {return TYPE_AM_OCCUR;} virtual AMT GetAmType(void) {return TYPE_AM_OCCUR;}
void SetTdbp(PTDBASE tdbp) {Tdbp = tdbp;} void SetTdbp(PTDBASE tdbp) {Tdbp = tdbp;}
// Methods // Methods
virtual void ResetDB(void) {N = 0; Tdbp->ResetDB();} virtual void ResetDB(void) {N = 0; Tdbp->ResetDB();}
virtual int RowNumber(PGLOBAL g, bool b = FALSE); virtual int RowNumber(PGLOBAL g, bool b = FALSE);
PTDB GetSourceTable(PGLOBAL g); int PrepareColist(void);
int MakeColumnList(PGLOBAL g); bool MakeColumnList(PGLOBAL g);
bool ViewColumnList(PGLOBAL g);
// Database routines // Database routines
virtual PCOL MakeCol(PGLOBAL g, PCOLDEF cdp, PCOL cprec, int n); virtual PCOL MakeCol(PGLOBAL g, PCOLDEF cdp, PCOL cprec, int n);
virtual bool InitTable(PGLOBAL g); virtual bool InitTable(PGLOBAL g);
virtual int GetMaxSize(PGLOBAL g); virtual int GetMaxSize(PGLOBAL g);
virtual bool OpenDB(PGLOBAL g); virtual bool OpenDB(PGLOBAL g);
virtual int ReadDB(PGLOBAL g); virtual int ReadDB(PGLOBAL g);
protected: protected:
// Members // Members
......
This diff is collapsed.
/************** TabPivot H Declares Source Code File (.H) **************/ /************** TabPivot H Declares Source Code File (.H) **************/
/* Name: TABPIVOT.H Version 1.3 */ /* Name: TABPIVOT.H Version 1.4 */
/* */ /* */
/* (C) Copyright to the author Olivier BERTRAND 2005-2012 */ /* (C) Copyright to the author Olivier BERTRAND 2005-2013 */
/* */ /* */
/* This file contains the PIVOT classes declares. */ /* This file contains the PIVOT classes declares. */
/***********************************************************************/ /***********************************************************************/
typedef class PIVOTDEF *PPIVOTDEF;
typedef class TDBPIVOT *PTDBPIVOT; typedef class TDBPIVOT *PTDBPIVOT;
typedef class FNCCOL *PFNCCOL; typedef class FNCCOL *PFNCCOL;
typedef class SRCCOL *PSRCCOL; typedef class SRCCOL *PSRCCOL;
typedef class TDBQRS *PTDBQRS;
typedef class QRSCOL *PQRSCOL;
/* -------------------------- PIVOT classes -------------------------- */ /* -------------------------- PIVOT classes -------------------------- */
...@@ -22,7 +21,6 @@ typedef class QRSCOL *PQRSCOL; ...@@ -22,7 +21,6 @@ typedef class QRSCOL *PQRSCOL;
/***********************************************************************/ /***********************************************************************/
/* PIVOT table. */ /* PIVOT table. */
/***********************************************************************/ /***********************************************************************/
//ass DllExport PIVOTDEF : public PRXDEF {/* Logical table description */
class PIVOTDEF : public PRXDEF { /* Logical table description */ class PIVOTDEF : public PRXDEF { /* Logical table description */
friend class TDBPIVOT; friend class TDBPIVOT;
public: public:
...@@ -55,22 +53,16 @@ class PIVOTDEF : public PRXDEF { /* Logical table description */ ...@@ -55,22 +53,16 @@ class PIVOTDEF : public PRXDEF { /* Logical table description */
/***********************************************************************/ /***********************************************************************/
/* This is the class declaration for the PIVOT table. */ /* This is the class declaration for the PIVOT table. */
/***********************************************************************/ /***********************************************************************/
//ass DllExport TDBPIVOT : public TDBASE, public CSORT {
class TDBPIVOT : public TDBPRX { class TDBPIVOT : public TDBPRX {
friend class FNCCOL; friend class FNCCOL;
//friend class SRCCOL;
public: public:
// Constructor // Constructor
TDBPIVOT(PPIVOTDEF tdp); TDBPIVOT(PPIVOTDEF tdp);
//TDBPIVOT(PTDBPIVOT tdbp);
// Implementation // Implementation
virtual AMT GetAmType(void) {return TYPE_AM_PIVOT;} virtual AMT GetAmType(void) {return TYPE_AM_PIVOT;}
//virtual PTDB Duplicate(PGLOBAL g) {return (PTDB)new(g) TDBPIVOT(this);}
// void SetTdbp(PTDB tdbp) {Tdbp = tdbp;}
// Methods // Methods
//virtual PTDB CopyOne(PTABS t);
virtual int GetRecpos(void) {return N;} virtual int GetRecpos(void) {return N;}
virtual void ResetDB(void) {N = 0;} virtual void ResetDB(void) {N = 0;}
virtual int RowNumber(PGLOBAL g, bool b = FALSE); virtual int RowNumber(PGLOBAL g, bool b = FALSE);
...@@ -84,22 +76,17 @@ class TDBPIVOT : public TDBPRX { ...@@ -84,22 +76,17 @@ class TDBPIVOT : public TDBPRX {
virtual int DeleteDB(PGLOBAL g, int irc); virtual int DeleteDB(PGLOBAL g, int irc);
virtual void CloseDB(PGLOBAL g); virtual void CloseDB(PGLOBAL g);
// The sorting function
//virtual int Qcompare(int *, int *);
protected: protected:
bool GetSourceTable(PGLOBAL g); // Internal routines
//int MakePivotColumns(PGLOBAL g); bool GetSourceTable(PGLOBAL g);
//bool UpdateTableFields(PGLOBAL g, int n); bool MakePivotColumns(PGLOBAL g);
bool MakeViewColumns(PGLOBAL g);
// Members // Members
//MYSQLC Myc; // MySQL connection class
//PTDBQRS Tqrp; // To the source table result
char *Host; // Host machine to use char *Host; // Host machine to use
char *User; // User logon info char *User; // User logon info
char *Pwd; // Password logon info char *Pwd; // Password logon info
char *Database; // Database to be used by server char *Database; // Database to be used by server
//PQRYRES Qryp; // Points to Query result block
char *Tabname; // Name of source table char *Tabname; // Name of source table
char *Tabsrc; // SQL of source table char *Tabsrc; // SQL of source table
char *Picol; // Pivot column name char *Picol; // Pivot column name
...@@ -108,9 +95,6 @@ class TDBPIVOT : public TDBPRX { ...@@ -108,9 +95,6 @@ class TDBPIVOT : public TDBPRX {
PCOL Fcolp; // To the function column in source PCOL Fcolp; // To the function column in source
PCOL Xcolp; // To the pivot column in source PCOL Xcolp; // To the pivot column in source
PCOL Dcolp; // To the dump column PCOL Dcolp; // To the dump column
//PCOLRES Xresp; // To the pivot result column
//PCOLRES To_Sort; // Saved Qryp To_Sort pointer
//PVBLK Rblkp; // The value block of the pivot column
bool GBdone; // True when subtable is "Group by" bool GBdone; // True when subtable is "Group by"
bool Accept; // TRUE if no match is accepted bool Accept; // TRUE if no match is accepted
int Mult; // Multiplication factor int Mult; // Multiplication factor
...@@ -168,75 +152,4 @@ class SRCCOL : public PRXCOL { ...@@ -168,75 +152,4 @@ class SRCCOL : public PRXCOL {
SRCCOL(void) {} SRCCOL(void) {}
// Members // Members
//PVAL Cnval;
}; // end of class SRCCOL }; // end of class SRCCOL
/***********************************************************************/
/* TDBQRS: This is the Access Method class declaration for the Query */
/* Result stored in memory in the current work area (volatil). */
/***********************************************************************/
class DllExport TDBQRS : public TDBASE {
friend class QRSCOL;
public:
// Constructor
TDBQRS(PQRYRES qrp) : TDBASE() {Qrp = qrp; CurPos = 0;}
TDBQRS(PTDBQRS tdbp);
// Implementation
virtual AMT GetAmType(void) {return TYPE_AM_QRS;}
virtual PTDB Duplicate(PGLOBAL g)
{return (PTDB)new(g) TDBQRS(this);}
PQRYRES GetQrp(void) {return Qrp;}
// Methods
virtual PTDB CopyOne(PTABS t);
virtual int RowNumber(PGLOBAL g, BOOL b = FALSE);
virtual int GetRecpos(void);
//virtual PCATLG GetCat(void);
//virtual PSZ GetPath(void);
virtual int GetBadLines(void) {return Qrp->BadLines;}
// Database routines
virtual PCOL ColDB(PGLOBAL g, PSZ name, int num);
virtual int GetMaxSize(PGLOBAL g);
virtual bool OpenDB(PGLOBAL g);
virtual int ReadDB(PGLOBAL g);
virtual int WriteDB(PGLOBAL g);
virtual int DeleteDB(PGLOBAL g, int irc);
virtual void CloseDB(PGLOBAL g);
private:
TDBQRS(void) : TDBASE() {} // Standard constructor not to be used
protected:
// Members
PQRYRES Qrp; // Points to Query Result block
int CurPos; // Current line position
}; // end of class TDBQRS
/***********************************************************************/
/* Class QRSCOL: QRS access method column descriptor. */
/***********************************************************************/
class DllExport QRSCOL : public COLBLK {
friend class TDBQRS;
public:
// Constructors
QRSCOL(PGLOBAL g, PCOLRES crp, PTDB tdbp, PCOL cprec, int i);
QRSCOL(QRSCOL *colp, PTDB tdbp); // Constructor used in copy process
// Implementation
virtual int GetAmType(void) {return TYPE_AM_QRS;}
PCOLRES GetCrp(void) {return Crp;}
void *GetQrsData(void) {return Crp->Kdata;}
// Methods
virtual void ReadColumn(PGLOBAL g);
virtual void Print(PGLOBAL g, FILE *, uint);
protected:
QRSCOL(void) {} // Default constructor not to be used
// Members
PCOLRES Crp;
}; // end of class QRSCOL
...@@ -216,7 +216,7 @@ bool TDBTBL::InitTableList(PGLOBAL g) ...@@ -216,7 +216,7 @@ bool TDBTBL::InitTableList(PGLOBAL g)
{ {
int n; int n;
PTABLE tp, tabp; PTABLE tp, tabp;
PTDB tdbp; PTDBASE tdbp;
PCOL colp; PCOL colp;
PTBLDEF tdp = (PTBLDEF)To_Def; PTBLDEF tdp = (PTBLDEF)To_Def;
...@@ -252,7 +252,7 @@ bool TDBTBL::InitTableList(PGLOBAL g) ...@@ -252,7 +252,7 @@ bool TDBTBL::InitTableList(PGLOBAL g)
n++; n++;
} // endif filp } // endif filp
} // endfor tblp } // endfor tp
//NumTables = n; //NumTables = n;
To_Filter = NULL; // To avoid doing it several times To_Filter = NULL; // To avoid doing it several times
......
...@@ -90,20 +90,21 @@ TABLE_SHARE *GetTableShare(PGLOBAL g, THD *thd, const char *db, ...@@ -90,20 +90,21 @@ TABLE_SHARE *GetTableShare(PGLOBAL g, THD *thd, const char *db,
// 1 2 4 8 // 1 2 4 8
//flags = GTS_TABLE | GTS_VIEW | GTS_NOLOCK | GTS_FORCE_DISCOVERY; //flags = GTS_TABLE | GTS_VIEW | GTS_NOLOCK | GTS_FORCE_DISCOVERY;
if (!open_table_def(thd, s, GTS_TABLE)) { if (!open_table_def(thd, s, GTS_TABLE | GTS_VIEW)) {
#ifdef DBUG_OFF if (!s->is_view) {
if (stricmp(s->db_plugin->name.str, "connect")) { if (stricmp(plugin_name(s->db_plugin)->str, "connect")) {
#else
if (stricmp((*s->db_plugin)->name.str, "connect")) {
#endif
#if defined(MYSQL_SUPPORT) #if defined(MYSQL_SUPPORT)
mysql = true; mysql = true;
#else // !MYSQL_SUPPORT #else // !MYSQL_SUPPORT
sprintf(g->Message, "%s.%s is not a CONNECT table", db, name); sprintf(g->Message, "%s.%s is not a CONNECT table", db, name);
return NULL; return NULL;
#endif // MYSQL_SUPPORT #endif // MYSQL_SUPPORT
} else } else
mysql = false; mysql = false;
} else {
mysql = true;
} // endif is_view
} else { } else {
sprintf(g->Message, "Error %d opening share\n", s->error); sprintf(g->Message, "Error %d opening share\n", s->error);
...@@ -139,9 +140,12 @@ PQRYRES TabColumns(PGLOBAL g, THD *thd, const char *db, ...@@ -139,9 +140,12 @@ PQRYRES TabColumns(PGLOBAL g, THD *thd, const char *db,
PCOLRES crp; PCOLRES crp;
if (!info) { if (!info) {
if (!(s = GetTableShare(g, thd, db, name, mysql))) if (!(s = GetTableShare(g, thd, db, name, mysql))) {
return NULL; return NULL;
else } else if (s->is_view) {
strcpy(g->Message, "Cannot retreive Proxy columns from a view");
return NULL;
} else
n = s->fieldnames.count; n = s->fieldnames.count;
} else { } else {
...@@ -257,23 +261,27 @@ PRXDEF::PRXDEF(void) ...@@ -257,23 +261,27 @@ PRXDEF::PRXDEF(void)
/***********************************************************************/ /***********************************************************************/
bool PRXDEF::DefineAM(PGLOBAL g, LPCSTR am, int poff) bool PRXDEF::DefineAM(PGLOBAL g, LPCSTR am, int poff)
{ {
char *pn, *db, *tab; char *pn, *db, *tab, *def = NULL;
db = Cat->GetStringCatInfo(g, "Dbname", "*"); db = Cat->GetStringCatInfo(g, "Dbname", "*");
def = Cat->GetStringCatInfo(g, "Srcdef", NULL);
if (!(tab = Cat->GetStringCatInfo(g, "Tabname", NULL))) { if (!(tab = Cat->GetStringCatInfo(g, "Tabname", NULL))) {
strcpy(g->Message, "Missing object table name"); if (!def) {
return TRUE; strcpy(g->Message, "Missing object table definition");
} // endif tab return TRUE;
} else
tab = "Noname";
// Analyze the table name, it may have the format: [dbname.]tabname } else
if ((pn = strchr(tab, '.'))) { // Analyze the table name, it may have the format: [dbname.]tabname
*pn++ = 0; if ((pn = strchr(tab, '.'))) {
db = tab; *pn++ = 0;
tab = pn; db = tab;
} // endif pn tab = pn;
} // endif pn
Tablep = new(g) XTAB(tab); Tablep = new(g) XTAB(tab, def);
Tablep->SetQualifier(db); Tablep->SetQualifier(db);
return FALSE; return FALSE;
} // end of DefineAM } // end of DefineAM
...@@ -303,12 +311,13 @@ TDBPRX::TDBPRX(PPRXDEF tdp) : TDBASE(tdp) ...@@ -303,12 +311,13 @@ TDBPRX::TDBPRX(PPRXDEF tdp) : TDBASE(tdp)
/***********************************************************************/ /***********************************************************************/
/* Get the PTDB of the sub-table. */ /* Get the PTDB of the sub-table. */
/***********************************************************************/ /***********************************************************************/
PTDB TDBPRX::GetSubTable(PGLOBAL g, PTABLE tabp) PTDBASE TDBPRX::GetSubTable(PGLOBAL g, PTABLE tabp, bool b)
{ {
char *db, *name; char *db, *name;
bool mysql; bool mysql = true;
PTDB tdbp = NULL; PTDB tdbp = NULL;
TABLE_SHARE *s; TABLE_SHARE *s = NULL;
Field* *fp;
PCATLG cat = To_Def->GetCat(); PCATLG cat = To_Def->GetCat();
PHC hc = ((MYCAT*)cat)->GetHandler(); PHC hc = ((MYCAT*)cat)->GetHandler();
LPCSTR cdb, curdb = hc->GetDBName(NULL); LPCSTR cdb, curdb = hc->GetDBName(NULL);
...@@ -328,10 +337,20 @@ PTDB TDBPRX::GetSubTable(PGLOBAL g, PTABLE tabp) ...@@ -328,10 +337,20 @@ PTDB TDBPRX::GetSubTable(PGLOBAL g, PTABLE tabp)
} // endfor tp } // endfor tp
if (!(s = GetTableShare(g, thd, db, name, mysql))) if (!tabp->GetSrc()) {
return NULL; if (!(s = GetTableShare(g, thd, db, name, mysql)))
return NULL;
if (s->is_view && !b)
s->field = hc->get_table()->s->field;
hc->tshp = s; hc->tshp = s;
} else if (b) {
// Don't use caller's columns
fp = hc->get_table()->field;
hc->get_table()->field = NULL;
hc->get_table()->s->option_struct->srcdef = tabp->GetSrc();
} // endif srcdef
if (mysql) { if (mysql) {
#if defined(MYSQL_SUPPORT) #if defined(MYSQL_SUPPORT)
...@@ -355,15 +374,23 @@ PTDB TDBPRX::GetSubTable(PGLOBAL g, PTABLE tabp) ...@@ -355,15 +374,23 @@ PTDB TDBPRX::GetSubTable(PGLOBAL g, PTABLE tabp)
tdbp = cat->GetTable(g, tabp); tdbp = cat->GetTable(g, tabp);
} // endif mysql } // endif mysql
hc->tshp = NULL; if (s) {
if (s->is_view && !b)
s->field = NULL;
hc->tshp = NULL;
} else if (b)
hc->get_table()->field = fp;
if (trace && tdbp) if (trace && tdbp)
htrc("Subtable %s in %s\n", htrc("Subtable %s in %s\n",
name, SVP(((PTDBASE)tdbp)->GetDef()->GetDB())); name, SVP(((PTDBASE)tdbp)->GetDef()->GetDB()));
err: err:
free_table_share(s); if (s)
return tdbp; free_table_share(s);
return (PTDBASE)tdbp;
} // end of GetSubTable } // end of GetSubTable
/***********************************************************************/ /***********************************************************************/
...@@ -373,7 +400,7 @@ bool TDBPRX::InitTable(PGLOBAL g) ...@@ -373,7 +400,7 @@ bool TDBPRX::InitTable(PGLOBAL g)
{ {
if (!Tdbp) { if (!Tdbp) {
// Get the table description block of this table // Get the table description block of this table
if (!(Tdbp = (PTDBASE)GetSubTable(g, ((PPRXDEF)To_Def)->Tablep))) if (!(Tdbp = GetSubTable(g, ((PPRXDEF)To_Def)->Tablep)))
return TRUE; return TRUE;
} // endif Tdbp } // endif Tdbp
......
...@@ -78,7 +78,7 @@ class DllExport TDBPRX : public TDBASE { ...@@ -78,7 +78,7 @@ class DllExport TDBPRX : public TDBASE {
virtual int WriteDB(PGLOBAL g); virtual int WriteDB(PGLOBAL g);
virtual int DeleteDB(PGLOBAL g, int irc); virtual int DeleteDB(PGLOBAL g, int irc);
virtual void CloseDB(PGLOBAL g) {if (Tdbp) Tdbp->CloseDB(g);} virtual void CloseDB(PGLOBAL g) {if (Tdbp) Tdbp->CloseDB(g);}
PTDB GetSubTable(PGLOBAL g, PTABLE tabp); PTDBASE GetSubTable(PGLOBAL g, PTABLE tabp, bool b = false);
void RemoveNext(PTABLE tp); void RemoveNext(PTABLE tp);
protected: protected:
...@@ -93,6 +93,7 @@ class DllExport TDBPRX : public TDBASE { ...@@ -93,6 +93,7 @@ class DllExport TDBPRX : public TDBASE {
class DllExport PRXCOL : public COLBLK { class DllExport PRXCOL : public COLBLK {
friend class TDBPRX; friend class TDBPRX;
friend class TDBTBL; friend class TDBTBL;
friend class TDBOCCUR;
public: public:
// Constructors // Constructors
PRXCOL(PCOLDEF cdp, PTDB tdbp, PCOL cprec, int i, PSZ am = "PRX"); PRXCOL(PCOLDEF cdp, PTDB tdbp, PCOL cprec, int i, PSZ am = "PRX");
......
...@@ -173,6 +173,7 @@ class DllExport TDBASE : public TDB { ...@@ -173,6 +173,7 @@ class DllExport TDBASE : public TDB {
virtual int GetRecpos(void) = 0; virtual int GetRecpos(void) = 0;
virtual bool SetRecpos(PGLOBAL g, int recpos); virtual bool SetRecpos(PGLOBAL g, int recpos);
virtual bool IsReadOnly(void) {return Read_Only;} virtual bool IsReadOnly(void) {return Read_Only;}
virtual bool IsView(void) {return FALSE;}
virtual CHARSET_INFO *data_charset() virtual CHARSET_INFO *data_charset()
{ {
/* /*
......
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