Commit e2804d9b authored by Olivier Bertrand's avatar Olivier Bertrand

- Fix MDEV-5393 and MDEV-5434. It is a major update of ODBC catalog tables

  processing that takes care of:
  - Drastically reduce the amount of storge needed to process them.
  - Handle longjmp's.
  - Makes the line limit an opion (MAXRES)
  - Schema can also be specified with the DBNAME option.
  - Issue warnings on fetch errors or when result lines have been limited.
  - Change some column names to reflect ODBC version 3 standard.
  The documentation have been updated accordingly

modified:
  storage/connect/filamdbf.cpp
  storage/connect/ha_connect.cc
  storage/connect/myconn.cpp
  storage/connect/mysql-test/connect/r/odbc.result
  storage/connect/mysql-test/connect/r/odbc_postgresql.result
  storage/connect/mysql-test/connect/r/odbc_sqlite3.result
  storage/connect/mysql-test/connect/r/odbc_xls.result
  storage/connect/mysql-test/connect/r/xml.result
  storage/connect/mysql-test/connect/t/odbc_postgresql.test
  storage/connect/odbccat.h
  storage/connect/odbconn.cpp
  storage/connect/odbconn.h
  storage/connect/plgdbsem.h
  storage/connect/plgdbutl.cpp
  storage/connect/rcmsg.c
  storage/connect/tabfmt.cpp
  storage/connect/table.cpp
  storage/connect/tabodbc.cpp
  storage/connect/tabodbc.h
  storage/connect/tabutil.cpp
  storage/connect/tabwmi.cpp
  storage/connect/user_connect.cc
  storage/connect/valblk.cpp
  storage/connect/valblk.h
  storage/connect/value.cpp
parent d8ac8d18
...@@ -228,7 +228,7 @@ PQRYRES DBFColumns(PGLOBAL g, const char *fn, BOOL info) ...@@ -228,7 +228,7 @@ PQRYRES DBFColumns(PGLOBAL g, const char *fn, BOOL info)
qrp = PlgAllocResult(g, ncol, fields, IDS_COLUMNS + 3, qrp = PlgAllocResult(g, ncol, fields, IDS_COLUMNS + 3,
buftyp, fldtyp, length, true, false); buftyp, fldtyp, length, true, false);
if (info) if (info || !qrp)
return qrp; return qrp;
if (trace) { if (trace) {
......
...@@ -165,7 +165,7 @@ extern "C" char nmfile[]; ...@@ -165,7 +165,7 @@ extern "C" char nmfile[];
extern "C" char pdebug[]; extern "C" char pdebug[];
extern "C" { extern "C" {
char version[]= "Version 1.01.0010 November 30, 2013"; char version[]= "Version 1.01.0011 December 15, 2013";
#if defined(XMSG) #if defined(XMSG)
char msglang[]; // Default message language char msglang[]; // Default message language
...@@ -3873,11 +3873,11 @@ static int connect_assisted_discovery(handlerton *hton, THD* thd, ...@@ -3873,11 +3873,11 @@ static int connect_assisted_discovery(handlerton *hton, THD* thd,
const char *fncn= "?"; const char *fncn= "?";
const char *user, *fn, *db, *host, *pwd, *sep, *tbl, *src; const char *user, *fn, *db, *host, *pwd, *sep, *tbl, *src;
const char *col, *ocl, *rnk, *pic, *fcl; const char *col, *ocl, *rnk, *pic, *fcl;
char *tab, *dsn; char *tab, *dsn, *shm;
#if defined(WIN32) #if defined(WIN32)
char *nsp= NULL, *cls= NULL; char *nsp= NULL, *cls= NULL;
#endif // WIN32 #endif // WIN32
int port= 0, hdr= 0, mxr= 0, rc= 0; int port= 0, hdr= 0, mxr= 0, mxe= 0, rc= 0;
int cop __attribute__((unused)) = 0; int cop __attribute__((unused)) = 0;
uint tm, fnc= FNC_NO, supfnc= (FNC_NO | FNC_COL); uint tm, fnc= FNC_NO, supfnc= (FNC_NO | FNC_COL);
bool bif, ok= false, dbf= false; bool bif, ok= false, dbf= false;
...@@ -3933,7 +3933,8 @@ static int connect_assisted_discovery(handlerton *hton, THD* thd, ...@@ -3933,7 +3933,8 @@ 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
port= atoi(GetListOption(g, "port", topt->oplist, "0")); port= atoi(GetListOption(g, "port", topt->oplist, "0"));
mxr= atoi(GetListOption(g,"maxerr", topt->oplist, "0")); mxr= atoi(GetListOption(g,"maxres", topt->oplist, "0"));
mxe= atoi(GetListOption(g,"maxerr", topt->oplist, "0"));
#if defined(PROMPT_OK) #if defined(PROMPT_OK)
cop= atoi(GetListOption(g, "checkdsn", topt->oplist, "0")); cop= atoi(GetListOption(g, "checkdsn", topt->oplist, "0"));
#endif // PROMPT_OK #endif // PROMPT_OK
...@@ -3942,7 +3943,7 @@ static int connect_assisted_discovery(handlerton *hton, THD* thd, ...@@ -3942,7 +3943,7 @@ static int connect_assisted_discovery(handlerton *hton, THD* thd,
user= "root"; user= "root";
} // endif option_list } // endif option_list
if (!db) if (!(shm= (char*)db))
db= table_s->db.str; // Default value db= table_s->db.str; // Default value
// Check table type // Check table type
...@@ -4137,17 +4138,17 @@ static int connect_assisted_discovery(handlerton *hton, THD* thd, ...@@ -4137,17 +4138,17 @@ static int connect_assisted_discovery(handlerton *hton, THD* thd,
qrp= ODBCSrcCols(g, dsn, (char*)src); qrp= ODBCSrcCols(g, dsn, (char*)src);
src= NULL; // for next tests src= NULL; // for next tests
} else } else
qrp= ODBCColumns(g, dsn, (char *) tab, NULL, fnc == FNC_COL); qrp= ODBCColumns(g, dsn, shm, tab, NULL, mxr, fnc == FNC_COL);
break; break;
case FNC_TABLE: case FNC_TABLE:
qrp= ODBCTables(g, dsn, (char *) tab, true); qrp= ODBCTables(g, dsn, shm, tab, mxr, true);
break; break;
case FNC_DSN: case FNC_DSN:
qrp= ODBCDataSources(g, true); qrp= ODBCDataSources(g, mxr, true);
break; break;
case FNC_DRIVER: case FNC_DRIVER:
qrp= ODBCDrivers(g, true); qrp= ODBCDrivers(g, mxr, true);
break; break;
default: default:
sprintf(g->Message, "invalid catfunc %s", fncn); sprintf(g->Message, "invalid catfunc %s", fncn);
...@@ -4163,7 +4164,7 @@ static int connect_assisted_discovery(handlerton *hton, THD* thd, ...@@ -4163,7 +4164,7 @@ static int connect_assisted_discovery(handlerton *hton, THD* thd,
break; break;
#endif // MYSQL_SUPPORT #endif // MYSQL_SUPPORT
case TAB_CSV: case TAB_CSV:
qrp= CSVColumns(g, fn, spc, qch, hdr, mxr, fnc == FNC_COL); qrp= CSVColumns(g, fn, spc, qch, hdr, mxe, fnc == FNC_COL);
break; break;
#if defined(WIN32) #if defined(WIN32)
case TAB_WMI: case TAB_WMI:
...@@ -4813,7 +4814,7 @@ maria_declare_plugin(connect) ...@@ -4813,7 +4814,7 @@ maria_declare_plugin(connect)
&connect_storage_engine, &connect_storage_engine,
"CONNECT", "CONNECT",
"Olivier Bertrand", "Olivier Bertrand",
"Direct access to external data, including many file formats", "Management of External Data (SQL/MED), including many file formats",
PLUGIN_LICENSE_GPL, PLUGIN_LICENSE_GPL,
connect_init_func, /* Plugin Init */ connect_init_func, /* Plugin Init */
connect_done_func, /* Plugin Deinit */ connect_done_func, /* Plugin Deinit */
...@@ -4821,6 +4822,6 @@ maria_declare_plugin(connect) ...@@ -4821,6 +4822,6 @@ maria_declare_plugin(connect)
NULL, /* status variables */ NULL, /* status variables */
NULL, /* system variables */ NULL, /* system variables */
"0.1", /* string version */ "0.1", /* string version */
MariaDB_PLUGIN_MATURITY_ALPHA /* maturity */ MariaDB_PLUGIN_MATURITY_BETA /* maturity */
} }
maria_declare_plugin_end; maria_declare_plugin_end;
...@@ -119,8 +119,9 @@ PQRYRES MyColumns(PGLOBAL g, const char *host, const char *db, ...@@ -119,8 +119,9 @@ PQRYRES MyColumns(PGLOBAL g, const char *host, const char *db,
/**********************************************************************/ /**********************************************************************/
/* Allocate the structures used to refer to the result set. */ /* Allocate the structures used to refer to the result set. */
/**********************************************************************/ /**********************************************************************/
qrp = PlgAllocResult(g, ncol, n, IDS_COLUMNS + 3, if (!(qrp = PlgAllocResult(g, ncol, n, IDS_COLUMNS + 3,
buftyp, fldtyp, length, false, true); buftyp, fldtyp, length, false, true)))
return NULL;
// Some columns must be renamed // Some columns must be renamed
for (i = 0, crp = qrp->Colresp; crp; crp = crp->Next) for (i = 0, crp = qrp->Colresp; crp; crp = crp->Next)
......
...@@ -20,28 +20,28 @@ CREATE TABLE t1 ENGINE=CONNECT TABLE_TYPE=ODBC CATFUNC=Tables CONNECTION='Not im ...@@ -20,28 +20,28 @@ CREATE TABLE t1 ENGINE=CONNECT TABLE_TYPE=ODBC CATFUNC=Tables CONNECTION='Not im
SHOW CREATE TABLE t1; SHOW CREATE TABLE t1;
Table Create Table Table Create Table
t1 CREATE TABLE `t1` ( t1 CREATE TABLE `t1` (
`Table_Qualifier` char(128) NOT NULL, `Table_Cat` char(128) NOT NULL,
`Table_Owner` char(128) NOT NULL, `Table_Schema` char(128) NOT NULL,
`Table_Name` char(128) NOT NULL, `Table_Name` char(128) NOT NULL,
`Table_Type` char(16) NOT NULL, `Table_Type` char(16) NOT NULL,
`Remark` char(128) NOT NULL `Remark` char(255) NOT NULL
) ENGINE=CONNECT DEFAULT CHARSET=latin1 CONNECTION='Not important' `TABLE_TYPE`='ODBC' `CATFUNC`='Tables' ) ENGINE=CONNECT DEFAULT CHARSET=latin1 CONNECTION='Not important' `TABLE_TYPE`='ODBC' `CATFUNC`='Tables'
DROP TABLE t1; DROP TABLE t1;
CREATE TABLE t1 ENGINE=CONNECT TABLE_TYPE=ODBC CATFUNC=Columns CONNECTION='Not important'; CREATE TABLE t1 ENGINE=CONNECT TABLE_TYPE=ODBC CATFUNC=Columns CONNECTION='Not important';
SHOW CREATE TABLE t1; SHOW CREATE TABLE t1;
Table Create Table Table Create Table
t1 CREATE TABLE `t1` ( t1 CREATE TABLE `t1` (
`Table_Qualif` char(128) NOT NULL, `Table_Cat` char(128) NOT NULL,
`Table_Owner` char(128) NOT NULL, `Table_Schema` char(128) NOT NULL,
`Table_Name` char(128) NOT NULL, `Table_Name` char(128) NOT NULL,
`Column_Name` char(128) NOT NULL, `Column_Name` char(128) NOT NULL,
`Data_Type` smallint(6) NOT NULL, `Data_Type` smallint(6) NOT NULL,
`Type_Name` char(20) NOT NULL, `Type_Name` char(30) NOT NULL,
`Precision` int(10) NOT NULL, `Column_Size` int(10) NOT NULL,
`Length` int(10) NOT NULL, `Buffer_Length` int(10) NOT NULL,
`Scale` smallint(6) NOT NULL, `Decimal_Digits` smallint(6) NOT NULL,
`Radix` smallint(6) NOT NULL, `Radix` smallint(6) NOT NULL,
`Nullable` smallint(6) NOT NULL, `Nullable` smallint(6) NOT NULL,
`Remarks` char(128) NOT NULL `Remarks` char(255) NOT NULL
) ENGINE=CONNECT DEFAULT CHARSET=latin1 CONNECTION='Not important' `TABLE_TYPE`='ODBC' `CATFUNC`='Columns' ) ENGINE=CONNECT DEFAULT CHARSET=latin1 CONNECTION='Not important' `TABLE_TYPE`='ODBC' `CATFUNC`='Columns'
DROP TABLE t1; DROP TABLE t1;
...@@ -10,8 +10,8 @@ SET NAMES utf8; ...@@ -10,8 +10,8 @@ SET NAMES utf8;
# All tables in all schemas # All tables in all schemas
CREATE TABLE t1 ENGINE=CONNECT TABLE_TYPE=ODBC CONNECTION='DSN=ConnectEnginePostgresql;UID=mtr;PWD=mtr' CATFUNC=Tables; CREATE TABLE t1 ENGINE=CONNECT TABLE_TYPE=ODBC CONNECTION='DSN=ConnectEnginePostgresql;UID=mtr;PWD=mtr' CATFUNC=Tables;
SELECT * FROM t1 ORDER BY Table_Owner, Table_Name; SELECT * FROM t1 ORDER BY Table_Schema, Table_Name;
Table_Qualifier Table_Owner Table_Name Table_Type Remark Table_Cat Table_Schema Table_Name Table_Type Remark
mtr public t1 TABLE mtr public t1 TABLE
mtr public t2 TABLE mtr public t2 TABLE
mtr public v1 VIEW mtr public v1 VIEW
...@@ -21,8 +21,8 @@ mtr schema1 v1 VIEW ...@@ -21,8 +21,8 @@ mtr schema1 v1 VIEW
DROP TABLE t1; DROP TABLE t1;
# All tables in all schemas # All tables in all schemas
CREATE TABLE t1 ENGINE=CONNECT TABLE_TYPE=ODBC CONNECTION='DSN=ConnectEnginePostgresql;UID=mtr;PWD=mtr' CATFUNC=Tables TABNAME='%.%.%'; CREATE TABLE t1 ENGINE=CONNECT TABLE_TYPE=ODBC CONNECTION='DSN=ConnectEnginePostgresql;UID=mtr;PWD=mtr' CATFUNC=Tables TABNAME='%.%.%';
SELECT * FROM t1 ORDER BY Table_Owner, Table_Name; SELECT * FROM t1 ORDER BY Table_Schema, Table_Name;
Table_Qualifier Table_Owner Table_Name Table_Type Remark Table_Cat Table_Schema Table_Name Table_Type Remark
mtr public t1 TABLE mtr public t1 TABLE
mtr public t2 TABLE mtr public t2 TABLE
mtr public v1 VIEW mtr public v1 VIEW
...@@ -32,8 +32,8 @@ mtr schema1 v1 VIEW ...@@ -32,8 +32,8 @@ mtr schema1 v1 VIEW
DROP TABLE t1; DROP TABLE t1;
# All tables in all schemas # All tables in all schemas
CREATE TABLE t1 ENGINE=CONNECT TABLE_TYPE=ODBC CONNECTION='DSN=ConnectEnginePostgresql;UID=mtr;PWD=mtr' CATFUNC=Tables TABNAME='%.%'; CREATE TABLE t1 ENGINE=CONNECT TABLE_TYPE=ODBC CONNECTION='DSN=ConnectEnginePostgresql;UID=mtr;PWD=mtr' CATFUNC=Tables TABNAME='%.%';
SELECT * FROM t1 ORDER BY Table_Owner, Table_Name; SELECT * FROM t1 ORDER BY Table_Schema, Table_Name;
Table_Qualifier Table_Owner Table_Name Table_Type Remark Table_Cat Table_Schema Table_Name Table_Type Remark
mtr public t1 TABLE mtr public t1 TABLE
mtr public t2 TABLE mtr public t2 TABLE
mtr public v1 VIEW mtr public v1 VIEW
...@@ -43,48 +43,48 @@ mtr schema1 v1 VIEW ...@@ -43,48 +43,48 @@ mtr schema1 v1 VIEW
DROP TABLE t1; DROP TABLE t1;
# All tables in the default schema ("public") # All tables in the default schema ("public")
CREATE TABLE t1 ENGINE=CONNECT TABLE_TYPE=ODBC CONNECTION='DSN=ConnectEnginePostgresql;UID=mtr;PWD=mtr' CATFUNC=Tables TABNAME='%'; CREATE TABLE t1 ENGINE=CONNECT TABLE_TYPE=ODBC CONNECTION='DSN=ConnectEnginePostgresql;UID=mtr;PWD=mtr' CATFUNC=Tables TABNAME='%';
SELECT * FROM t1 ORDER BY Table_Owner, Table_Name; SELECT * FROM t1 ORDER BY Table_Schema, Table_Name;
Table_Qualifier Table_Owner Table_Name Table_Type Remark Table_Cat Table_Schema Table_Name Table_Type Remark
mtr public t1 TABLE mtr public t1 TABLE
mtr public t2 TABLE mtr public t2 TABLE
mtr public v1 VIEW mtr public v1 VIEW
DROP TABLE t1; DROP TABLE t1;
# All tables "t1" in all schemas # All tables "t1" in all schemas
CREATE TABLE t1 ENGINE=CONNECT TABLE_TYPE=ODBC CONNECTION='DSN=ConnectEnginePostgresql;UID=mtr;PWD=mtr' CATFUNC=Tables TABNAME='%.%.t1'; CREATE TABLE t1 ENGINE=CONNECT TABLE_TYPE=ODBC CONNECTION='DSN=ConnectEnginePostgresql;UID=mtr;PWD=mtr' CATFUNC=Tables TABNAME='%.%.t1';
SELECT * FROM t1 ORDER BY Table_Owner, Table_Name; SELECT * FROM t1 ORDER BY Table_Schema, Table_Name;
Table_Qualifier Table_Owner Table_Name Table_Type Remark Table_Cat Table_Schema Table_Name Table_Type Remark
mtr public t1 TABLE mtr public t1 TABLE
mtr schema1 t1 TABLE mtr schema1 t1 TABLE
DROP TABLE t1; DROP TABLE t1;
# All tables "t1" in all schemas # All tables "t1" in all schemas
CREATE TABLE t1 ENGINE=CONNECT TABLE_TYPE=ODBC CONNECTION='DSN=ConnectEnginePostgresql;UID=mtr;PWD=mtr' CATFUNC=Tables TABNAME='%.t1'; CREATE TABLE t1 ENGINE=CONNECT TABLE_TYPE=ODBC CONNECTION='DSN=ConnectEnginePostgresql;UID=mtr;PWD=mtr' CATFUNC=Tables TABNAME='%.t1';
SELECT * FROM t1 ORDER BY Table_Owner, Table_Name; SELECT * FROM t1 ORDER BY Table_Schema, Table_Name;
Table_Qualifier Table_Owner Table_Name Table_Type Remark Table_Cat Table_Schema Table_Name Table_Type Remark
mtr public t1 TABLE mtr public t1 TABLE
mtr schema1 t1 TABLE mtr schema1 t1 TABLE
DROP TABLE t1; DROP TABLE t1;
# Table "t1" in the default schema ("public") # Table "t1" in the default schema ("public")
CREATE TABLE t1 ENGINE=CONNECT TABLE_TYPE=ODBC CONNECTION='DSN=ConnectEnginePostgresql;UID=mtr;PWD=mtr' CATFUNC=Tables TABNAME='t1'; CREATE TABLE t1 ENGINE=CONNECT TABLE_TYPE=ODBC CONNECTION='DSN=ConnectEnginePostgresql;UID=mtr;PWD=mtr' CATFUNC=Tables TABNAME='t1';
SELECT * FROM t1 ORDER BY Table_Owner, Table_Name; SELECT * FROM t1 ORDER BY Table_Schema, Table_Name;
Table_Qualifier Table_Owner Table_Name Table_Type Remark Table_Cat Table_Schema Table_Name Table_Type Remark
mtr public t1 TABLE mtr public t1 TABLE
DROP TABLE t1; DROP TABLE t1;
# Table "t1" in the schema "public" # Table "t1" in the schema "public"
CREATE TABLE t1 ENGINE=CONNECT TABLE_TYPE=ODBC CONNECTION='DSN=ConnectEnginePostgresql;UID=mtr;PWD=mtr' CATFUNC=Tables TABNAME='%.public.t1'; CREATE TABLE t1 ENGINE=CONNECT TABLE_TYPE=ODBC CONNECTION='DSN=ConnectEnginePostgresql;UID=mtr;PWD=mtr' CATFUNC=Tables TABNAME='%.public.t1';
SELECT * FROM t1 ORDER BY Table_Owner, Table_Name; SELECT * FROM t1 ORDER BY Table_Schema, Table_Name;
Table_Qualifier Table_Owner Table_Name Table_Type Remark Table_Cat Table_Schema Table_Name Table_Type Remark
mtr public t1 TABLE mtr public t1 TABLE
DROP TABLE t1; DROP TABLE t1;
# Table "t1" in the schema "schema1" # Table "t1" in the schema "schema1"
CREATE TABLE t1 ENGINE=CONNECT TABLE_TYPE=ODBC CONNECTION='DSN=ConnectEnginePostgresql;UID=mtr;PWD=mtr' CATFUNC=Tables TABNAME='%.schema1.t1'; CREATE TABLE t1 ENGINE=CONNECT TABLE_TYPE=ODBC CONNECTION='DSN=ConnectEnginePostgresql;UID=mtr;PWD=mtr' CATFUNC=Tables TABNAME='%.schema1.t1';
SELECT * FROM t1 ORDER BY Table_Owner, Table_Name; SELECT * FROM t1 ORDER BY Table_Schema, Table_Name;
Table_Qualifier Table_Owner Table_Name Table_Type Remark Table_Cat Table_Schema Table_Name Table_Type Remark
mtr schema1 t1 TABLE mtr schema1 t1 TABLE
DROP TABLE t1; DROP TABLE t1;
# All tables "t1" in all schemas (Catalog name is ignored by PostgreSQL) # All tables "t1" in all schemas (Catalog name is ignored by PostgreSQL)
CREATE TABLE t1 ENGINE=CONNECT TABLE_TYPE=ODBC CONNECTION='DSN=ConnectEnginePostgresql;UID=mtr;PWD=mtr' CATFUNC=Tables TABNAME='xxx.%.t1'; CREATE TABLE t1 ENGINE=CONNECT TABLE_TYPE=ODBC CONNECTION='DSN=ConnectEnginePostgresql;UID=mtr;PWD=mtr' CATFUNC=Tables TABNAME='xxx.%.t1';
SELECT * FROM t1 ORDER BY Table_Owner, Table_Name; SELECT * FROM t1 ORDER BY Table_Schema, Table_Name;
Table_Qualifier Table_Owner Table_Name Table_Type Remark Table_Cat Table_Schema Table_Name Table_Type Remark
mtr public t1 TABLE mtr public t1 TABLE
mtr schema1 t1 TABLE mtr schema1 t1 TABLE
DROP TABLE t1; DROP TABLE t1;
...@@ -94,8 +94,8 @@ DROP TABLE t1; ...@@ -94,8 +94,8 @@ DROP TABLE t1;
# All columns in the schemas "public" and "schema1" # All columns in the schemas "public" and "schema1"
CREATE TABLE t1 ENGINE=CONNECT TABLE_TYPE=ODBC CONNECTION='DSN=ConnectEnginePostgresql;UID=mtr;PWD=mtr' CATFUNC=Columns; CREATE TABLE t1 ENGINE=CONNECT TABLE_TYPE=ODBC CONNECTION='DSN=ConnectEnginePostgresql;UID=mtr;PWD=mtr' CATFUNC=Columns;
SELECT * FROM t1 WHERE Table_Owner IN ('public','schema1') ORDER BY Table_Owner, Table_Name; SELECT * FROM t1 WHERE Table_Schema IN ('public','schema1') ORDER BY Table_Schema, Table_Name;
Table_Qualif Table_Owner Table_Name Column_Name Data_Type Type_Name Precision Length Scale Radix Nullable Remarks Table_Cat Table_Schema Table_Name Column_Name Data_Type Type_Name Column_Size Buffer_Length Decimal_Digits Radix Nullable Remarks
mtr public t1 a 4 int4 10 4 0 10 0 mtr public t1 a 4 int4 10 4 0 10 0
mtr public t2 a 4 int4 10 4 0 10 0 mtr public t2 a 4 int4 10 4 0 10 0
mtr public v1 a 4 int4 10 4 0 10 1 mtr public v1 a 4 int4 10 4 0 10 1
...@@ -105,8 +105,8 @@ mtr schema1 v1 a 1 bpchar 10 60 0 0 1 ...@@ -105,8 +105,8 @@ mtr schema1 v1 a 1 bpchar 10 60 0 0 1
DROP TABLE t1; DROP TABLE t1;
# All columns in the schemas "public" and "schema1" # All columns in the schemas "public" and "schema1"
CREATE TABLE t1 ENGINE=CONNECT TABLE_TYPE=ODBC CONNECTION='DSN=ConnectEnginePostgresql;UID=mtr;PWD=mtr' CATFUNC=Columns TABNAME='%.%.%'; CREATE TABLE t1 ENGINE=CONNECT TABLE_TYPE=ODBC CONNECTION='DSN=ConnectEnginePostgresql;UID=mtr;PWD=mtr' CATFUNC=Columns TABNAME='%.%.%';
SELECT * FROM t1 WHERE Table_Owner IN ('public','schema1') ORDER BY Table_Owner, Table_Name; SELECT * FROM t1 WHERE Table_Schema IN ('public','schema1') ORDER BY Table_Schema, Table_Name;
Table_Qualif Table_Owner Table_Name Column_Name Data_Type Type_Name Precision Length Scale Radix Nullable Remarks Table_Cat Table_Schema Table_Name Column_Name Data_Type Type_Name Column_Size Buffer_Length Decimal_Digits Radix Nullable Remarks
mtr public t1 a 4 int4 10 4 0 10 0 mtr public t1 a 4 int4 10 4 0 10 0
mtr public t2 a 4 int4 10 4 0 10 0 mtr public t2 a 4 int4 10 4 0 10 0
mtr public v1 a 4 int4 10 4 0 10 1 mtr public v1 a 4 int4 10 4 0 10 1
...@@ -116,27 +116,27 @@ mtr schema1 v1 a 1 bpchar 10 60 0 0 1 ...@@ -116,27 +116,27 @@ mtr schema1 v1 a 1 bpchar 10 60 0 0 1
DROP TABLE t1; DROP TABLE t1;
# All tables "t1" in all schemas # All tables "t1" in all schemas
CREATE TABLE t1 ENGINE=CONNECT TABLE_TYPE=ODBC CONNECTION='DSN=ConnectEnginePostgresql;UID=mtr;PWD=mtr' CATFUNC=Columns TABNAME='%.%.t1'; CREATE TABLE t1 ENGINE=CONNECT TABLE_TYPE=ODBC CONNECTION='DSN=ConnectEnginePostgresql;UID=mtr;PWD=mtr' CATFUNC=Columns TABNAME='%.%.t1';
SELECT * FROM t1 ORDER BY Table_Owner, Table_Name; SELECT * FROM t1 ORDER BY Table_Schema, Table_Name;
Table_Qualif Table_Owner Table_Name Column_Name Data_Type Type_Name Precision Length Scale Radix Nullable Remarks Table_Cat Table_Schema Table_Name Column_Name Data_Type Type_Name Column_Size Buffer_Length Decimal_Digits Radix Nullable Remarks
mtr public t1 a 4 int4 10 4 0 10 0 mtr public t1 a 4 int4 10 4 0 10 0
mtr schema1 t1 a 1 bpchar 10 60 0 0 0 mtr schema1 t1 a 1 bpchar 10 60 0 0 0
DROP TABLE t1; DROP TABLE t1;
# Table "t1" in the schema "public" # Table "t1" in the schema "public"
CREATE TABLE t1 ENGINE=CONNECT TABLE_TYPE=ODBC CONNECTION='DSN=ConnectEnginePostgresql;UID=mtr;PWD=mtr' CATFUNC=Columns TABNAME='%.public.t1'; CREATE TABLE t1 ENGINE=CONNECT TABLE_TYPE=ODBC CONNECTION='DSN=ConnectEnginePostgresql;UID=mtr;PWD=mtr' CATFUNC=Columns TABNAME='%.public.t1';
SELECT * FROM t1 ORDER BY Table_Owner, Table_Name; SELECT * FROM t1 ORDER BY Table_Schema, Table_Name;
Table_Qualif Table_Owner Table_Name Column_Name Data_Type Type_Name Precision Length Scale Radix Nullable Remarks Table_Cat Table_Schema Table_Name Column_Name Data_Type Type_Name Column_Size Buffer_Length Decimal_Digits Radix Nullable Remarks
mtr public t1 a 4 int4 10 4 0 10 0 mtr public t1 a 4 int4 10 4 0 10 0
DROP TABLE t1; DROP TABLE t1;
# Table "t1" in the schema "schema1" # Table "t1" in the schema "schema1"
CREATE TABLE t1 ENGINE=CONNECT TABLE_TYPE=ODBC CONNECTION='DSN=ConnectEnginePostgresql;UID=mtr;PWD=mtr' CATFUNC=Columns TABNAME='%.schema1.t1'; CREATE TABLE t1 ENGINE=CONNECT TABLE_TYPE=ODBC CONNECTION='DSN=ConnectEnginePostgresql;UID=mtr;PWD=mtr' CATFUNC=Columns TABNAME='%.schema1.t1';
SELECT * FROM t1 ORDER BY Table_Owner, Table_Name; SELECT * FROM t1 ORDER BY Table_Schema, Table_Name;
Table_Qualif Table_Owner Table_Name Column_Name Data_Type Type_Name Precision Length Scale Radix Nullable Remarks Table_Cat Table_Schema Table_Name Column_Name Data_Type Type_Name Column_Size Buffer_Length Decimal_Digits Radix Nullable Remarks
mtr schema1 t1 a 1 bpchar 10 60 0 0 0 mtr schema1 t1 a 1 bpchar 10 60 0 0 0
DROP TABLE t1; DROP TABLE t1;
# All tables "t1" in all schemas (Catalog name is ignored by PostgreSQL) # All tables "t1" in all schemas (Catalog name is ignored by PostgreSQL)
CREATE TABLE t1 ENGINE=CONNECT TABLE_TYPE=ODBC CONNECTION='DSN=ConnectEnginePostgresql;UID=mtr;PWD=mtr' CATFUNC=Columns TABNAME='xxx.%.t1'; CREATE TABLE t1 ENGINE=CONNECT TABLE_TYPE=ODBC CONNECTION='DSN=ConnectEnginePostgresql;UID=mtr;PWD=mtr' CATFUNC=Columns TABNAME='xxx.%.t1';
SELECT * FROM t1 ORDER BY Table_Owner, Table_Name; SELECT * FROM t1 ORDER BY Table_Schema, Table_Name;
Table_Qualif Table_Owner Table_Name Column_Name Data_Type Type_Name Precision Length Scale Radix Nullable Remarks Table_Cat Table_Schema Table_Name Column_Name Data_Type Type_Name Column_Size Buffer_Length Decimal_Digits Radix Nullable Remarks
mtr public t1 a 4 int4 10 4 0 10 0 mtr public t1 a 4 int4 10 4 0 10 0
mtr schema1 t1 a 1 bpchar 10 60 0 0 0 mtr schema1 t1 a 1 bpchar 10 60 0 0 0
DROP TABLE t1; DROP TABLE t1;
......
...@@ -43,17 +43,17 @@ DROP VIEW v1; ...@@ -43,17 +43,17 @@ DROP VIEW v1;
DROP TABLE t1; DROP TABLE t1;
CREATE TABLE t1 ENGINE=CONNECT CATFUNC=Columns TABNAME='t1' TABLE_TYPE=ODBC CONNECTION='Driver=SQLite3 ODBC Driver;Database=MTR_SUITE_DIR/std_data/test.sqlite3;NoWCHAR=yes' CHARSET=utf8 DATA_CHARSET=utf8; CREATE TABLE t1 ENGINE=CONNECT CATFUNC=Columns TABNAME='t1' TABLE_TYPE=ODBC CONNECTION='Driver=SQLite3 ODBC Driver;Database=MTR_SUITE_DIR/std_data/test.sqlite3;NoWCHAR=yes' CHARSET=utf8 DATA_CHARSET=utf8;
SELECT * FROM t1; SELECT * FROM t1;
Table_Qualif Table_Owner Table_Name Column_Name Data_Type Type_Name Precision Length Scale Radix Nullable Remarks Table_Cat Table_Schema Table_Name Column_Name Data_Type Type_Name Column_Size Buffer_Length Decimal_Digits Radix Nullable Remarks
t1 a 12 varchar(64) 64 64 10 0 1 t1 a 12 varchar(64) 64 64 10 0 1
DROP TABLE t1; DROP TABLE t1;
CREATE TABLE t1 ENGINE=CONNECT CATFUNC=Tables TABNAME='t1' TABLE_TYPE=ODBC CONNECTION='Driver=SQLite3 ODBC Driver;Database=MTR_SUITE_DIR/std_data/test.sqlite3;NoWCHAR=yes' CHARSET=utf8 DATA_CHARSET=utf8; CREATE TABLE t1 ENGINE=CONNECT CATFUNC=Tables TABNAME='t1' TABLE_TYPE=ODBC CONNECTION='Driver=SQLite3 ODBC Driver;Database=MTR_SUITE_DIR/std_data/test.sqlite3;NoWCHAR=yes' CHARSET=utf8 DATA_CHARSET=utf8;
SELECT * FROM t1; SELECT * FROM t1;
Table_Qualifier Table_Owner Table_Name Table_Type Remark Table_Cat Table_Schema Table_Name Table_Type Remark
t1 TABLE t1 TABLE
DROP TABLE t1; DROP TABLE t1;
CREATE TABLE t1 ENGINE=CONNECT CATFUNC=Columns TABLE_TYPE=ODBC CONNECTION='Driver=SQLite3 ODBC Driver;Database=MTR_SUITE_DIR/std_data/test.sqlite3;NoWCHAR=yes' CHARSET=utf8 DATA_CHARSET=utf8; CREATE TABLE t1 ENGINE=CONNECT CATFUNC=Columns TABLE_TYPE=ODBC CONNECTION='Driver=SQLite3 ODBC Driver;Database=MTR_SUITE_DIR/std_data/test.sqlite3;NoWCHAR=yes' CHARSET=utf8 DATA_CHARSET=utf8;
SELECT * FROM t1 ORDER BY Table_name; SELECT * FROM t1 ORDER BY Table_name;
Table_Qualif Table_Owner Table_Name Column_Name Data_Type Type_Name Precision Length Scale Radix Nullable Remarks Table_Cat Table_Schema Table_Name Column_Name Data_Type Type_Name Column_Size Buffer_Length Decimal_Digits Radix Nullable Remarks
t000 a 4 INT 9 10 10 0 1 t000 a 4 INT 9 10 10 0 1
t000 b 4 INT 9 10 10 0 1 t000 b 4 INT 9 10 10 0 1
t000 c 4 INT 9 10 10 0 1 t000 c 4 INT 9 10 10 0 1
...@@ -2058,7 +2058,7 @@ Table_Qualif Table_Owner Table_Name Column_Name Data_Type Type_Name Precision Le ...@@ -2058,7 +2058,7 @@ Table_Qualif Table_Owner Table_Name Column_Name Data_Type Type_Name Precision Le
DROP TABLE t1; DROP TABLE t1;
CREATE TABLE t1 ENGINE=CONNECT CATFUNC=Tables TABLE_TYPE=ODBC CONNECTION='Driver=SQLite3 ODBC Driver;Database=MTR_SUITE_DIR/std_data/test.sqlite3;NoWCHAR=yes' CHARSET=utf8 DATA_CHARSET=utf8; CREATE TABLE t1 ENGINE=CONNECT CATFUNC=Tables TABLE_TYPE=ODBC CONNECTION='Driver=SQLite3 ODBC Driver;Database=MTR_SUITE_DIR/std_data/test.sqlite3;NoWCHAR=yes' CHARSET=utf8 DATA_CHARSET=utf8;
SELECT * FROM t1 ORDER BY Table_name; SELECT * FROM t1 ORDER BY Table_name;
Table_Qualifier Table_Owner Table_Name Table_Type Remark Table_Cat Table_Schema Table_Name Table_Type Remark
t000 TABLE t000 TABLE
t001 TABLE t001 TABLE
t002 TABLE t002 TABLE
......
...@@ -15,12 +15,12 @@ Menseau Eric NULL ...@@ -15,12 +15,12 @@ Menseau Eric NULL
DROP TABLE contact; DROP TABLE contact;
CREATE TABLE t1 ENGINE=CONNECT CATFUNC=Tables TABLE_TYPE=ODBC CONNECTION='DSN=ConnectEngineXLS;DBQ=DATADIR/test/contacts.xls' CHARSET=utf8 DATA_CHARSET=latin1;; CREATE TABLE t1 ENGINE=CONNECT CATFUNC=Tables TABLE_TYPE=ODBC CONNECTION='DSN=ConnectEngineXLS;DBQ=DATADIR/test/contacts.xls' CHARSET=utf8 DATA_CHARSET=latin1;;
SELECT * FROM t1 WHERE Table_name='CONTACT'; SELECT * FROM t1 WHERE Table_name='CONTACT';
Table_Qualifier Table_Owner Table_Name Table_Type Remark Table_Cat Table_Schema Table_Name Table_Type Remark
DATADIR/test/contacts CONTACT TABLE DATADIR/test/contacts CONTACT TABLE
DROP TABLE t1; DROP TABLE t1;
CREATE TABLE t1 ENGINE=CONNECT CATFUNC=Columns TABLE_TYPE=ODBC CONNECTION='DSN=ConnectEngineXLS;DBQ=DATADIR/test/contacts.xls' CHARSET=utf8 DATA_CHARSET=latin1;; CREATE TABLE t1 ENGINE=CONNECT CATFUNC=Columns TABLE_TYPE=ODBC CONNECTION='DSN=ConnectEngineXLS;DBQ=DATADIR/test/contacts.xls' CHARSET=utf8 DATA_CHARSET=latin1;;
SELECT * FROM t1 WHERE Table_name='CONTACT' AND Column_name IN ('Nom','Fonction'); SELECT * FROM t1 WHERE Table_name='CONTACT' AND Column_name IN ('Nom','Fonction');
Table_Qualif Table_Owner Table_Name Column_Name Data_Type Type_Name Precision Length Scale Radix Nullable Remarks Table_Cat Table_Schema Table_Name Column_Name Data_Type Type_Name Column_Size Buffer_Length Decimal_Digits Radix Nullable Remarks
DATADIR/test/contacts CONTACT Nom 12 VARCHAR 255 510 0 0 1 DATADIR/test/contacts CONTACT Nom 12 VARCHAR 255 510 0 0 1
DATADIR/test/contacts CONTACT Fonction 12 VARCHAR 255 510 0 0 1 DATADIR/test/contacts CONTACT Fonction 12 VARCHAR 255 510 0 0 1
DROP TABLE t1; DROP TABLE t1;
...@@ -413,7 +413,7 @@ DROP TABLE t1; ...@@ -413,7 +413,7 @@ DROP TABLE t1;
SET @a=LOAD_FILE('MYSQLD_DATADIR/test/t1.xml'); SET @a=LOAD_FILE('MYSQLD_DATADIR/test/t1.xml');
SELECT CAST(@a AS CHAR CHARACTER SET latin1); SELECT CAST(@a AS CHAR CHARACTER SET latin1);
CAST(@a AS CHAR CHARACTER SET latin1) <?xml version="1.0" encoding="iso-8859-1"?> CAST(@a AS CHAR CHARACTER SET latin1) <?xml version="1.0" encoding="iso-8859-1"?>
<!-- Created by CONNECT Version 1.01.0010 November 30, 2013 --> <!-- Created by CONNECT Version 1.01.0011 December 15, 2013 -->
<t1> <t1>
<line> <line>
<node>ÀÁÂÃ</node> <node>ÀÁÂÃ</node>
......
...@@ -22,7 +22,7 @@ ...@@ -22,7 +22,7 @@
# #
#[ConnectEnginePostgresql] #[ConnectEnginePostgresql]
#Description=PostgreSQL DSN for ConnectSE #Description=PostgreSQL DSN for ConnectSE
#Driver=PostgreSQL #Driver=PostgreSQL (should the path to the driver so file)
#Database=mtr #Database=mtr
#Servername=localhost #Servername=localhost
#Port=5432 #Port=5432
...@@ -36,52 +36,52 @@ SET NAMES utf8; ...@@ -36,52 +36,52 @@ SET NAMES utf8;
--echo --echo
--echo # All tables in all schemas --echo # All tables in all schemas
CREATE TABLE t1 ENGINE=CONNECT TABLE_TYPE=ODBC CONNECTION='DSN=ConnectEnginePostgresql;UID=mtr;PWD=mtr' CATFUNC=Tables; CREATE TABLE t1 ENGINE=CONNECT TABLE_TYPE=ODBC CONNECTION='DSN=ConnectEnginePostgresql;UID=mtr;PWD=mtr' CATFUNC=Tables;
SELECT * FROM t1 ORDER BY Table_Owner, Table_Name; SELECT * FROM t1 ORDER BY Table_Schema, Table_Name;
DROP TABLE t1; DROP TABLE t1;
--echo # All tables in all schemas --echo # All tables in all schemas
CREATE TABLE t1 ENGINE=CONNECT TABLE_TYPE=ODBC CONNECTION='DSN=ConnectEnginePostgresql;UID=mtr;PWD=mtr' CATFUNC=Tables TABNAME='%.%.%'; CREATE TABLE t1 ENGINE=CONNECT TABLE_TYPE=ODBC CONNECTION='DSN=ConnectEnginePostgresql;UID=mtr;PWD=mtr' CATFUNC=Tables TABNAME='%.%.%';
SELECT * FROM t1 ORDER BY Table_Owner, Table_Name; SELECT * FROM t1 ORDER BY Table_Schema, Table_Name;
DROP TABLE t1; DROP TABLE t1;
--echo # All tables in all schemas --echo # All tables in all schemas
CREATE TABLE t1 ENGINE=CONNECT TABLE_TYPE=ODBC CONNECTION='DSN=ConnectEnginePostgresql;UID=mtr;PWD=mtr' CATFUNC=Tables TABNAME='%.%'; CREATE TABLE t1 ENGINE=CONNECT TABLE_TYPE=ODBC CONNECTION='DSN=ConnectEnginePostgresql;UID=mtr;PWD=mtr' CATFUNC=Tables TABNAME='%.%';
SELECT * FROM t1 ORDER BY Table_Owner, Table_Name; SELECT * FROM t1 ORDER BY Table_Schema, Table_Name;
DROP TABLE t1; DROP TABLE t1;
--echo # All tables in the default schema ("public") --echo # All tables in the default schema ("public")
CREATE TABLE t1 ENGINE=CONNECT TABLE_TYPE=ODBC CONNECTION='DSN=ConnectEnginePostgresql;UID=mtr;PWD=mtr' CATFUNC=Tables TABNAME='%'; CREATE TABLE t1 ENGINE=CONNECT TABLE_TYPE=ODBC CONNECTION='DSN=ConnectEnginePostgresql;UID=mtr;PWD=mtr' CATFUNC=Tables TABNAME='%';
SELECT * FROM t1 ORDER BY Table_Owner, Table_Name; SELECT * FROM t1 ORDER BY Table_Schema, Table_Name;
DROP TABLE t1; DROP TABLE t1;
--echo # All tables "t1" in all schemas --echo # All tables "t1" in all schemas
CREATE TABLE t1 ENGINE=CONNECT TABLE_TYPE=ODBC CONNECTION='DSN=ConnectEnginePostgresql;UID=mtr;PWD=mtr' CATFUNC=Tables TABNAME='%.%.t1'; CREATE TABLE t1 ENGINE=CONNECT TABLE_TYPE=ODBC CONNECTION='DSN=ConnectEnginePostgresql;UID=mtr;PWD=mtr' CATFUNC=Tables TABNAME='%.%.t1';
SELECT * FROM t1 ORDER BY Table_Owner, Table_Name; SELECT * FROM t1 ORDER BY Table_Schema, Table_Name;
DROP TABLE t1; DROP TABLE t1;
--echo # All tables "t1" in all schemas --echo # All tables "t1" in all schemas
CREATE TABLE t1 ENGINE=CONNECT TABLE_TYPE=ODBC CONNECTION='DSN=ConnectEnginePostgresql;UID=mtr;PWD=mtr' CATFUNC=Tables TABNAME='%.t1'; CREATE TABLE t1 ENGINE=CONNECT TABLE_TYPE=ODBC CONNECTION='DSN=ConnectEnginePostgresql;UID=mtr;PWD=mtr' CATFUNC=Tables TABNAME='%.t1';
SELECT * FROM t1 ORDER BY Table_Owner, Table_Name; SELECT * FROM t1 ORDER BY Table_Schema, Table_Name;
DROP TABLE t1; DROP TABLE t1;
--echo # Table "t1" in the default schema ("public") --echo # Table "t1" in the default schema ("public")
CREATE TABLE t1 ENGINE=CONNECT TABLE_TYPE=ODBC CONNECTION='DSN=ConnectEnginePostgresql;UID=mtr;PWD=mtr' CATFUNC=Tables TABNAME='t1'; CREATE TABLE t1 ENGINE=CONNECT TABLE_TYPE=ODBC CONNECTION='DSN=ConnectEnginePostgresql;UID=mtr;PWD=mtr' CATFUNC=Tables TABNAME='t1';
SELECT * FROM t1 ORDER BY Table_Owner, Table_Name; SELECT * FROM t1 ORDER BY Table_Schema, Table_Name;
DROP TABLE t1; DROP TABLE t1;
--echo # Table "t1" in the schema "public" --echo # Table "t1" in the schema "public"
CREATE TABLE t1 ENGINE=CONNECT TABLE_TYPE=ODBC CONNECTION='DSN=ConnectEnginePostgresql;UID=mtr;PWD=mtr' CATFUNC=Tables TABNAME='%.public.t1'; CREATE TABLE t1 ENGINE=CONNECT TABLE_TYPE=ODBC CONNECTION='DSN=ConnectEnginePostgresql;UID=mtr;PWD=mtr' CATFUNC=Tables TABNAME='%.public.t1';
SELECT * FROM t1 ORDER BY Table_Owner, Table_Name; SELECT * FROM t1 ORDER BY Table_Schema, Table_Name;
DROP TABLE t1; DROP TABLE t1;
--echo # Table "t1" in the schema "schema1" --echo # Table "t1" in the schema "schema1"
CREATE TABLE t1 ENGINE=CONNECT TABLE_TYPE=ODBC CONNECTION='DSN=ConnectEnginePostgresql;UID=mtr;PWD=mtr' CATFUNC=Tables TABNAME='%.schema1.t1'; CREATE TABLE t1 ENGINE=CONNECT TABLE_TYPE=ODBC CONNECTION='DSN=ConnectEnginePostgresql;UID=mtr;PWD=mtr' CATFUNC=Tables TABNAME='%.schema1.t1';
SELECT * FROM t1 ORDER BY Table_Owner, Table_Name; SELECT * FROM t1 ORDER BY Table_Schema, Table_Name;
DROP TABLE t1; DROP TABLE t1;
--echo # All tables "t1" in all schemas (Catalog name is ignored by PostgreSQL) --echo # All tables "t1" in all schemas (Catalog name is ignored by PostgreSQL)
CREATE TABLE t1 ENGINE=CONNECT TABLE_TYPE=ODBC CONNECTION='DSN=ConnectEnginePostgresql;UID=mtr;PWD=mtr' CATFUNC=Tables TABNAME='xxx.%.t1'; CREATE TABLE t1 ENGINE=CONNECT TABLE_TYPE=ODBC CONNECTION='DSN=ConnectEnginePostgresql;UID=mtr;PWD=mtr' CATFUNC=Tables TABNAME='xxx.%.t1';
SELECT * FROM t1 ORDER BY Table_Owner, Table_Name; SELECT * FROM t1 ORDER BY Table_Schema, Table_Name;
DROP TABLE t1; DROP TABLE t1;
--echo # --echo #
...@@ -92,37 +92,37 @@ DROP TABLE t1; ...@@ -92,37 +92,37 @@ DROP TABLE t1;
# #
# For some reasons SQLColumn (unlike SQLTables) include columns of system # For some reasons SQLColumn (unlike SQLTables) include columns of system
# tables from the schemas like "information_schema", "pg_catalog", "pg_toast". # tables from the schemas like "information_schema", "pg_catalog", "pg_toast".
# So we add the "Table_Owner IN ('public','schema1')" clause into some queries. # So we add the "Table_Schema IN ('public','schema1')" clause into some queries.
# #
--echo # All columns in the schemas "public" and "schema1" --echo # All columns in the schemas "public" and "schema1"
CREATE TABLE t1 ENGINE=CONNECT TABLE_TYPE=ODBC CONNECTION='DSN=ConnectEnginePostgresql;UID=mtr;PWD=mtr' CATFUNC=Columns; CREATE TABLE t1 ENGINE=CONNECT TABLE_TYPE=ODBC CONNECTION='DSN=ConnectEnginePostgresql;UID=mtr;PWD=mtr' CATFUNC=Columns;
SELECT * FROM t1 WHERE Table_Owner IN ('public','schema1') ORDER BY Table_Owner, Table_Name; SELECT * FROM t1 WHERE Table_Schema IN ('public','schema1') ORDER BY Table_Schema, Table_Name;
DROP TABLE t1; DROP TABLE t1;
--echo # All columns in the schemas "public" and "schema1" --echo # All columns in the schemas "public" and "schema1"
CREATE TABLE t1 ENGINE=CONNECT TABLE_TYPE=ODBC CONNECTION='DSN=ConnectEnginePostgresql;UID=mtr;PWD=mtr' CATFUNC=Columns TABNAME='%.%.%'; CREATE TABLE t1 ENGINE=CONNECT TABLE_TYPE=ODBC CONNECTION='DSN=ConnectEnginePostgresql;UID=mtr;PWD=mtr' CATFUNC=Columns TABNAME='%.%.%';
SELECT * FROM t1 WHERE Table_Owner IN ('public','schema1') ORDER BY Table_Owner, Table_Name; SELECT * FROM t1 WHERE Table_Schema IN ('public','schema1') ORDER BY Table_Schema, Table_Name;
DROP TABLE t1; DROP TABLE t1;
--echo # All tables "t1" in all schemas --echo # All tables "t1" in all schemas
CREATE TABLE t1 ENGINE=CONNECT TABLE_TYPE=ODBC CONNECTION='DSN=ConnectEnginePostgresql;UID=mtr;PWD=mtr' CATFUNC=Columns TABNAME='%.%.t1'; CREATE TABLE t1 ENGINE=CONNECT TABLE_TYPE=ODBC CONNECTION='DSN=ConnectEnginePostgresql;UID=mtr;PWD=mtr' CATFUNC=Columns TABNAME='%.%.t1';
SELECT * FROM t1 ORDER BY Table_Owner, Table_Name; SELECT * FROM t1 ORDER BY Table_Schema, Table_Name;
DROP TABLE t1; DROP TABLE t1;
--echo # Table "t1" in the schema "public" --echo # Table "t1" in the schema "public"
CREATE TABLE t1 ENGINE=CONNECT TABLE_TYPE=ODBC CONNECTION='DSN=ConnectEnginePostgresql;UID=mtr;PWD=mtr' CATFUNC=Columns TABNAME='%.public.t1'; CREATE TABLE t1 ENGINE=CONNECT TABLE_TYPE=ODBC CONNECTION='DSN=ConnectEnginePostgresql;UID=mtr;PWD=mtr' CATFUNC=Columns TABNAME='%.public.t1';
SELECT * FROM t1 ORDER BY Table_Owner, Table_Name; SELECT * FROM t1 ORDER BY Table_Schema, Table_Name;
DROP TABLE t1; DROP TABLE t1;
--echo # Table "t1" in the schema "schema1" --echo # Table "t1" in the schema "schema1"
CREATE TABLE t1 ENGINE=CONNECT TABLE_TYPE=ODBC CONNECTION='DSN=ConnectEnginePostgresql;UID=mtr;PWD=mtr' CATFUNC=Columns TABNAME='%.schema1.t1'; CREATE TABLE t1 ENGINE=CONNECT TABLE_TYPE=ODBC CONNECTION='DSN=ConnectEnginePostgresql;UID=mtr;PWD=mtr' CATFUNC=Columns TABNAME='%.schema1.t1';
SELECT * FROM t1 ORDER BY Table_Owner, Table_Name; SELECT * FROM t1 ORDER BY Table_Schema, Table_Name;
DROP TABLE t1; DROP TABLE t1;
--echo # All tables "t1" in all schemas (Catalog name is ignored by PostgreSQL) --echo # All tables "t1" in all schemas (Catalog name is ignored by PostgreSQL)
CREATE TABLE t1 ENGINE=CONNECT TABLE_TYPE=ODBC CONNECTION='DSN=ConnectEnginePostgresql;UID=mtr;PWD=mtr' CATFUNC=Columns TABNAME='xxx.%.t1'; CREATE TABLE t1 ENGINE=CONNECT TABLE_TYPE=ODBC CONNECTION='DSN=ConnectEnginePostgresql;UID=mtr;PWD=mtr' CATFUNC=Columns TABNAME='xxx.%.t1';
SELECT * FROM t1 ORDER BY Table_Owner, Table_Name; SELECT * FROM t1 ORDER BY Table_Schema, Table_Name;
DROP TABLE t1; DROP TABLE t1;
......
...@@ -4,9 +4,10 @@ ...@@ -4,9 +4,10 @@
#if defined(PROMPT_OK) #if defined(PROMPT_OK)
char *ODBCCheckConnection(PGLOBAL g, char *dsn, int cop); char *ODBCCheckConnection(PGLOBAL g, char *dsn, int cop);
#endif // PROMPT_OK #endif // PROMPT_OK
PQRYRES ODBCDataSources(PGLOBAL g, bool info); PQRYRES ODBCDataSources(PGLOBAL g, int maxres, bool info);
PQRYRES ODBCColumns(PGLOBAL g, char *dsn, char *table, PQRYRES ODBCColumns(PGLOBAL g, char *dsn, char *db, char *table,
char *colpat, bool info); char *colpat, int maxres, bool info);
PQRYRES ODBCSrcCols(PGLOBAL g, char *dsn, char *src); PQRYRES ODBCSrcCols(PGLOBAL g, char *dsn, char *src);
PQRYRES ODBCTables(PGLOBAL g, char *dsn, char *tabpat, bool info); PQRYRES ODBCTables(PGLOBAL g, char *dsn, char *db, char *tabpat,
PQRYRES ODBCDrivers(PGLOBAL g, bool info); int maxres, bool info);
PQRYRES ODBCDrivers(PGLOBAL g, int maxres, bool info);
/************ Odbconn C++ Functions Source Code File (.CPP) ************/ /************ Odbconn C++ Functions Source Code File (.CPP) ************/
/* Name: ODBCONN.CPP Version 1.7 */ /* Name: ODBCONN.CPP Version 1.8 */
/* */ /* */
/* (C) Copyright to the author Olivier BERTRAND 1998-2013 */ /* (C) Copyright to the author Olivier BERTRAND 1998-2013 */
/* */ /* */
...@@ -211,7 +211,8 @@ char *ODBCCheckConnection(PGLOBAL g, char *dsn, int cop) ...@@ -211,7 +211,8 @@ char *ODBCCheckConnection(PGLOBAL g, char *dsn, int cop)
/***********************************************************************/ /***********************************************************************/
/* Allocate the structure used to refer to the result set. */ /* Allocate the structure used to refer to the result set. */
/***********************************************************************/ /***********************************************************************/
static CATPARM *AllocCatInfo(PGLOBAL g, CATINFO fid, char *tab, PQRYRES qrp) static CATPARM *AllocCatInfo(PGLOBAL g, CATINFO fid, char *db,
char *tab, PQRYRES qrp)
{ {
size_t i, m, n; size_t i, m, n;
CATPARM *cap; CATPARM *cap;
...@@ -219,12 +220,26 @@ static CATPARM *AllocCatInfo(PGLOBAL g, CATINFO fid, char *tab, PQRYRES qrp) ...@@ -219,12 +220,26 @@ static CATPARM *AllocCatInfo(PGLOBAL g, CATINFO fid, char *tab, PQRYRES qrp)
#if defined(_DEBUG) #if defined(_DEBUG)
assert(qrp); assert(qrp);
#endif #endif
// Save stack and allocation environment and prepare error return
if (g->jump_level == MAX_JUMP) {
strcpy(g->Message, MSG(TOO_MANY_JUMPS));
return NULL;
} // endif jump_level
if (setjmp(g->jumper[++g->jump_level]) != 0) {
printf("%s\n", g->Message);
cap = NULL;
goto fin;
} // endif rc
m = (size_t)qrp->Maxres; m = (size_t)qrp->Maxres;
n = (size_t)qrp->Nbcol; n = (size_t)qrp->Nbcol;
cap = (CATPARM *)PlugSubAlloc(g, NULL, sizeof(CATPARM)); cap = (CATPARM *)PlugSubAlloc(g, NULL, sizeof(CATPARM));
memset(cap, 0, sizeof(CATPARM)); memset(cap, 0, sizeof(CATPARM));
cap->Id = fid; cap->Id = fid;
cap->Qrp = qrp; cap->Qrp = qrp;
cap->DB = (PUCHAR)db;
cap->Tab = (PUCHAR)tab; cap->Tab = (PUCHAR)tab;
cap->Vlen = (SQLLEN* *)PlugSubAlloc(g, NULL, n * sizeof(SQLLEN *)); cap->Vlen = (SQLLEN* *)PlugSubAlloc(g, NULL, n * sizeof(SQLLEN *));
...@@ -232,9 +247,13 @@ static CATPARM *AllocCatInfo(PGLOBAL g, CATINFO fid, char *tab, PQRYRES qrp) ...@@ -232,9 +247,13 @@ static CATPARM *AllocCatInfo(PGLOBAL g, CATINFO fid, char *tab, PQRYRES qrp)
cap->Vlen[i] = (SQLLEN *)PlugSubAlloc(g, NULL, m * sizeof(SQLLEN)); cap->Vlen[i] = (SQLLEN *)PlugSubAlloc(g, NULL, m * sizeof(SQLLEN));
cap->Status = (UWORD *)PlugSubAlloc(g, NULL, m * sizeof(UWORD)); cap->Status = (UWORD *)PlugSubAlloc(g, NULL, m * sizeof(UWORD));
fin:
g->jump_level--;
return cap; return cap;
} // end of AllocCatInfo } // end of AllocCatInfo
#if 0
/***********************************************************************/ /***********************************************************************/
/* Check for nulls and reset them to Null (?) values. */ /* Check for nulls and reset them to Null (?) values. */
/***********************************************************************/ /***********************************************************************/
...@@ -256,25 +275,23 @@ static void ResetNullValues(CATPARM *cap) ...@@ -256,25 +275,23 @@ static void ResetNullValues(CATPARM *cap)
crp->Kdata->Reset(n); crp->Kdata->Reset(n);
} // end of ResetNullValues } // end of ResetNullValues
#endif
/***********************************************************************/ /***********************************************************************/
/* ODBCColumns: constructs the result blocks containing all columns */ /* ODBCColumns: constructs the result blocks containing all columns */
/* of an ODBC table that will be retrieved by GetData commands. */ /* of an ODBC table that will be retrieved by GetData commands. */
/***********************************************************************/ /***********************************************************************/
PQRYRES ODBCColumns(PGLOBAL g, char *dsn, char *table, PQRYRES ODBCColumns(PGLOBAL g, char *dsn, char *db, char *table,
char *colpat, bool info) char *colpat, int maxres, bool info)
{ {
static int buftyp[] = {TYPE_STRING, TYPE_STRING, TYPE_STRING, int buftyp[] = {TYPE_STRING, TYPE_STRING, TYPE_STRING, TYPE_STRING,
TYPE_STRING, TYPE_SHORT, TYPE_STRING, TYPE_SHORT, TYPE_STRING, TYPE_INT, TYPE_INT,
TYPE_INT, TYPE_INT, TYPE_SHORT, TYPE_SHORT, TYPE_SHORT, TYPE_SHORT, TYPE_STRING};
TYPE_SHORT, TYPE_SHORT, TYPE_STRING}; XFLD fldtyp[] = {FLD_QUALIF, FLD_OWNER, FLD_TABNAME, FLD_NAME,
static XFLD fldtyp[] = {FLD_QUALIF, FLD_OWNER, FLD_TABNAME, FLD_TYPE, FLD_TYPENAME, FLD_PREC, FLD_LENGTH,
FLD_NAME, FLD_TYPE, FLD_TYPENAME, FLD_SCALE, FLD_RADIX, FLD_NULL, FLD_REM};
FLD_PREC, FLD_LENGTH, FLD_SCALE, unsigned int length[] = {0, 0, 0, 0, 6, 0, 10, 10, 6, 6, 6, 0};
FLD_RADIX, FLD_NULL, FLD_REM};
static unsigned int length[] = {0, 0, 0, 0, 6, 20, 10, 10, 6, 6, 6, 128};
int n, ncol = 12; int n, ncol = 12;
int maxres;
PQRYRES qrp; PQRYRES qrp;
CATPARM *cap; CATPARM *cap;
ODBConn *ocp = NULL; ODBConn *ocp = NULL;
...@@ -288,15 +305,19 @@ PQRYRES ODBCColumns(PGLOBAL g, char *dsn, char *table, ...@@ -288,15 +305,19 @@ PQRYRES ODBCColumns(PGLOBAL g, char *dsn, char *table,
if (ocp->Open(dsn, 10) < 1) // openReadOnly + noODBCdialog if (ocp->Open(dsn, 10) < 1) // openReadOnly + noODBCdialog
return NULL; return NULL;
if (table && !strchr(table, '%')) {
// We fix a MySQL limit because some data sources return 32767 // We fix a MySQL limit because some data sources return 32767
n = ocp->GetMaxValue(SQL_MAX_COLUMNS_IN_TABLE); n = ocp->GetMaxValue(SQL_MAX_COLUMNS_IN_TABLE);
maxres = (n) ? min(n, 4096) : 4096; maxres = (n) ? min(n, 4096) : 4096;
n = ocp->GetMaxValue(SQL_MAX_QUALIFIER_NAME_LEN); } else if (!maxres)
length[0] = (n) ? (n + 1) : 128; maxres = 20000;
n = ocp->GetMaxValue(SQL_MAX_USER_NAME_LEN);
length[1] = (n) ? (n + 1) : 128; // n = ocp->GetMaxValue(SQL_MAX_QUALIFIER_NAME_LEN);
n = ocp->GetMaxValue(SQL_MAX_TABLE_NAME_LEN); // length[0] = (n) ? (n + 1) : 0;
length[2] = (n) ? (n + 1) : 128; // n = ocp->GetMaxValue(SQL_MAX_USER_NAME_LEN);
// length[1] = (n) ? (n + 1) : 0;
// n = ocp->GetMaxValue(SQL_MAX_TABLE_NAME_LEN);
// length[2] = (n) ? (n + 1) : 0;
n = ocp->GetMaxValue(SQL_MAX_COLUMN_NAME_LEN); n = ocp->GetMaxValue(SQL_MAX_COLUMN_NAME_LEN);
length[3] = (n) ? (n + 1) : 128; length[3] = (n) ? (n + 1) : 128;
} else { // Info table } else { // Info table
...@@ -305,6 +326,8 @@ PQRYRES ODBCColumns(PGLOBAL g, char *dsn, char *table, ...@@ -305,6 +326,8 @@ PQRYRES ODBCColumns(PGLOBAL g, char *dsn, char *table,
length[1] = 128; length[1] = 128;
length[2] = 128; length[2] = 128;
length[3] = 128; length[3] = 128;
length[5] = 30;
length[11] = 255;
} // endif ocp } // endif ocp
if (trace) if (trace)
...@@ -317,13 +340,15 @@ PQRYRES ODBCColumns(PGLOBAL g, char *dsn, char *table, ...@@ -317,13 +340,15 @@ PQRYRES ODBCColumns(PGLOBAL g, char *dsn, char *table,
qrp = PlgAllocResult(g, ncol, maxres, IDS_COLUMNS, qrp = PlgAllocResult(g, ncol, maxres, IDS_COLUMNS,
buftyp, fldtyp, length, false, true); buftyp, fldtyp, length, false, true);
if (info) // Info table if (info || !qrp) // Info table
return qrp; return qrp;
if (trace) if (trace)
htrc("Getting col results ncol=%d\n", qrp->Nbcol); htrc("Getting col results ncol=%d\n", qrp->Nbcol);
cap = AllocCatInfo(g, CAT_COL, table, qrp); if (!(cap = AllocCatInfo(g, CAT_COL, db, table, qrp)))
return NULL;
cap->Pat = (PUCHAR)colpat; cap->Pat = (PUCHAR)colpat;
/************************************************************************/ /************************************************************************/
...@@ -331,7 +356,7 @@ PQRYRES ODBCColumns(PGLOBAL g, char *dsn, char *table, ...@@ -331,7 +356,7 @@ PQRYRES ODBCColumns(PGLOBAL g, char *dsn, char *table,
/************************************************************************/ /************************************************************************/
if ((n = ocp->GetCatInfo(cap)) >= 0) { if ((n = ocp->GetCatInfo(cap)) >= 0) {
qrp->Nblin = n; qrp->Nblin = n;
ResetNullValues(cap); // ResetNullValues(cap);
if (trace) if (trace)
htrc("Columns: NBCOL=%d NBLIN=%d\n", qrp->Nbcol, qrp->Nblin); htrc("Columns: NBCOL=%d NBLIN=%d\n", qrp->Nbcol, qrp->Nblin);
...@@ -385,7 +410,7 @@ PQRYRES MyODBCCols(PGLOBAL g, char *dsn, char *tab, bool info) ...@@ -385,7 +410,7 @@ PQRYRES MyODBCCols(PGLOBAL g, char *dsn, char *tab, bool info)
/**********************************************************************/ /**********************************************************************/
/* Get the information about the ODBC table columns. */ /* Get the information about the ODBC table columns. */
/**********************************************************************/ /**********************************************************************/
if ((qrp = ODBCColumns(g, ocp, dsn, tab, NULL)) && ocp) if ((qrp = ODBCColumns(g, ocp, dsn, NULL, tab, 0, NULL)) && ocp)
dsn = ocp->GetConnect(); // Complete connect string dsn = ocp->GetConnect(); // Complete connect string
/************************************************************************/ /************************************************************************/
...@@ -434,17 +459,16 @@ PQRYRES MyODBCCols(PGLOBAL g, char *dsn, char *tab, bool info) ...@@ -434,17 +459,16 @@ PQRYRES MyODBCCols(PGLOBAL g, char *dsn, char *tab, bool info)
#endif // 0 #endif // 0
/*************************************************************************/ /*************************************************************************/
/* ODBCDataSources: constructs the result blocks containing all ODBC */ /* ODBCDrivers: constructs the result blocks containing all ODBC */
/* data sources available on the local host. */ /* drivers available on the local host. */
/* Called with info=true to have result column names. */ /* Called with info=true to have result column names. */
/*************************************************************************/ /*************************************************************************/
PQRYRES ODBCDataSources(PGLOBAL g, bool info) PQRYRES ODBCDrivers(PGLOBAL g, int maxres, bool info)
{ {
static int buftyp[] = {TYPE_STRING, TYPE_STRING}; int buftyp[] = {TYPE_STRING, TYPE_STRING};
static XFLD fldtyp[] = {FLD_NAME, FLD_REM}; XFLD fldtyp[] = {FLD_NAME, FLD_REM};
static unsigned int length[] = {0, 256}; unsigned int length[] = {128, 256};
int n = 0, ncol = 2; int ncol = 2;
int maxres;
PQRYRES qrp; PQRYRES qrp;
ODBConn *ocp = NULL; ODBConn *ocp = NULL;
...@@ -453,47 +477,45 @@ PQRYRES ODBCDataSources(PGLOBAL g, bool info) ...@@ -453,47 +477,45 @@ PQRYRES ODBCDataSources(PGLOBAL g, bool info)
/************************************************************************/ /************************************************************************/
if (!info) { if (!info) {
ocp = new(g) ODBConn(g, NULL); ocp = new(g) ODBConn(g, NULL);
n = ocp->GetMaxValue(SQL_MAX_DSN_LENGTH);
length[0] = (n) ? (n + 1) : 256; if (!maxres)
maxres = 512; // Estimated max number of data sources maxres = 256; // Estimated max number of drivers
} else {
length[0] = 256; } else
maxres = 0; maxres = 0;
} // endif info
if (trace) if (trace)
htrc("ODBCDataSources: max=%d len=%d\n", maxres, length[0]); htrc("ODBCDrivers: max=%d len=%d\n", maxres, length[0]);
/************************************************************************/ /************************************************************************/
/* Allocate the structures used to refer to the result set. */ /* Allocate the structures used to refer to the result set. */
/************************************************************************/ /************************************************************************/
qrp = PlgAllocResult(g, ncol, maxres, IDS_DSRC, qrp = PlgAllocResult(g, ncol, maxres, IDS_DRIVER,
buftyp, fldtyp, length, false, true); buftyp, fldtyp, length, false, true);
/************************************************************************/ /************************************************************************/
/* Now get the results into blocks. */ /* Now get the results into blocks. */
/************************************************************************/ /************************************************************************/
if (!info && ocp->GetDataSources(qrp)) if (!info && qrp && ocp->GetDrivers(qrp))
qrp = NULL; qrp = NULL;
/************************************************************************/ /************************************************************************/
/* Return the result pointer for use by GetData routines. */ /* Return the result pointer for use by GetData routines. */
/************************************************************************/ /************************************************************************/
return qrp; return qrp;
} // end of ODBCDataSources } // end of ODBCDrivers
/*************************************************************************/ /*************************************************************************/
/* ODBCDrivers: constructs the result blocks containing all ODBC */ /* ODBCDataSources: constructs the result blocks containing all ODBC */
/* drivers available on the local host. */ /* data sources available on the local host. */
/* Called with info=true to have result column names. */ /* Called with info=true to have result column names. */
/*************************************************************************/ /*************************************************************************/
PQRYRES ODBCDrivers(PGLOBAL g, bool info) PQRYRES ODBCDataSources(PGLOBAL g, int maxres, bool info)
{ {
static int buftyp[] = {TYPE_STRING, TYPE_STRING}; int buftyp[] = {TYPE_STRING, TYPE_STRING};
static XFLD fldtyp[] = {FLD_NAME, FLD_REM}; XFLD fldtyp[] = {FLD_NAME, FLD_REM};
static unsigned int length[] = {128, 256}; unsigned int length[] = {0, 256};
int ncol = 2; int n = 0, ncol = 2;
int maxres;
PQRYRES qrp; PQRYRES qrp;
ODBConn *ocp = NULL; ODBConn *ocp = NULL;
...@@ -502,45 +524,51 @@ PQRYRES ODBCDrivers(PGLOBAL g, bool info) ...@@ -502,45 +524,51 @@ PQRYRES ODBCDrivers(PGLOBAL g, bool info)
/************************************************************************/ /************************************************************************/
if (!info) { if (!info) {
ocp = new(g) ODBConn(g, NULL); ocp = new(g) ODBConn(g, NULL);
maxres = 256; // Estimated max number of drivers n = ocp->GetMaxValue(SQL_MAX_DSN_LENGTH);
} else length[0] = (n) ? (n + 1) : 256;
if (!maxres)
maxres = 512; // Estimated max number of data sources
} else {
length[0] = 256;
maxres = 0; maxres = 0;
} // endif info
if (trace) if (trace)
htrc("ODBCDrivers: max=%d len=%d\n", maxres, length[0]); htrc("ODBCDataSources: max=%d len=%d\n", maxres, length[0]);
/************************************************************************/ /************************************************************************/
/* Allocate the structures used to refer to the result set. */ /* Allocate the structures used to refer to the result set. */
/************************************************************************/ /************************************************************************/
qrp = PlgAllocResult(g, ncol, maxres, IDS_DRIVER, qrp = PlgAllocResult(g, ncol, maxres, IDS_DSRC,
buftyp, fldtyp, length, false, true); buftyp, fldtyp, length, false, true);
/************************************************************************/ /************************************************************************/
/* Now get the results into blocks. */ /* Now get the results into blocks. */
/************************************************************************/ /************************************************************************/
if (!info && ocp->GetDrivers(qrp)) if (!info && qrp && ocp->GetDataSources(qrp))
qrp = NULL; qrp = NULL;
/************************************************************************/ /************************************************************************/
/* Return the result pointer for use by GetData routines. */ /* Return the result pointer for use by GetData routines. */
/************************************************************************/ /************************************************************************/
return qrp; return qrp;
} // end of ODBCDrivers } // end of ODBCDataSources
/***********************************************************************/ /**************************************************************************/
/* ODBCTables: constructs the result blocks containing all tables in */ /* ODBCTables: constructs the result blocks containing all tables in */
/* an ODBC database that will be retrieved by GetData commands. */ /* an ODBC database that will be retrieved by GetData commands. */
/* Note: The first two columns (Qualifier, Owner) are ignored. */ /**************************************************************************/
/***********************************************************************/ PQRYRES ODBCTables(PGLOBAL g, char *dsn, char *db, char *tabpat,
PQRYRES ODBCTables(PGLOBAL g, char *dsn, char *tabpat, bool info) int maxres, bool info)
{ {
static int buftyp[] = {TYPE_STRING, TYPE_STRING, TYPE_STRING, int buftyp[] = {TYPE_STRING, TYPE_STRING, TYPE_STRING,
TYPE_STRING, TYPE_STRING}; TYPE_STRING, TYPE_STRING};
static XFLD fldtyp[] = {FLD_QUALIF, FLD_OWNER, FLD_NAME, XFLD fldtyp[] = {FLD_QUALIF, FLD_OWNER, FLD_NAME,
FLD_TYPE, FLD_REM}; FLD_TYPE, FLD_REM};
static unsigned int length[] = {0, 0, 0, 16, 128}; unsigned int length[] = {0, 0, 0, 16, 0};
int n, ncol = 5; int n, ncol = 5;
int maxres;
PQRYRES qrp; PQRYRES qrp;
CATPARM *cap; CATPARM *cap;
ODBConn *ocp = NULL; ODBConn *ocp = NULL;
...@@ -557,11 +585,13 @@ PQRYRES ODBCTables(PGLOBAL g, char *dsn, char *tabpat, bool info) ...@@ -557,11 +585,13 @@ PQRYRES ODBCTables(PGLOBAL g, char *dsn, char *tabpat, bool info)
if (ocp->Open(dsn, 2) < 1) // 2 is openReadOnly if (ocp->Open(dsn, 2) < 1) // 2 is openReadOnly
return NULL; return NULL;
maxres = 16384; // This is completely arbitrary if (!maxres)
n = ocp->GetMaxValue(SQL_MAX_QUALIFIER_NAME_LEN); maxres = 10000; // This is completely arbitrary
length[0] = (n) ? (n + 1) : 128;
n = ocp->GetMaxValue(SQL_MAX_USER_NAME_LEN); // n = ocp->GetMaxValue(SQL_MAX_QUALIFIER_NAME_LEN);
length[1] = (n) ? (n + 1) : 128; // length[0] = (n) ? (n + 1) : 0;
// n = ocp->GetMaxValue(SQL_MAX_USER_NAME_LEN);
// length[1] = (n) ? (n + 1) : 0;
n = ocp->GetMaxValue(SQL_MAX_TABLE_NAME_LEN); n = ocp->GetMaxValue(SQL_MAX_TABLE_NAME_LEN);
length[2] = (n) ? (n + 1) : 128; length[2] = (n) ? (n + 1) : 128;
} else { } else {
...@@ -569,6 +599,7 @@ PQRYRES ODBCTables(PGLOBAL g, char *dsn, char *tabpat, bool info) ...@@ -569,6 +599,7 @@ PQRYRES ODBCTables(PGLOBAL g, char *dsn, char *tabpat, bool info)
length[0] = 128; length[0] = 128;
length[1] = 128; length[1] = 128;
length[2] = 128; length[2] = 128;
length[4] = 255;
} // endif info } // endif info
if (trace) if (trace)
...@@ -580,10 +611,12 @@ PQRYRES ODBCTables(PGLOBAL g, char *dsn, char *tabpat, bool info) ...@@ -580,10 +611,12 @@ PQRYRES ODBCTables(PGLOBAL g, char *dsn, char *tabpat, bool info)
qrp = PlgAllocResult(g, ncol, maxres, IDS_TABLES, buftyp, qrp = PlgAllocResult(g, ncol, maxres, IDS_TABLES, buftyp,
fldtyp, length, false, true); fldtyp, length, false, true);
if (info) if (info || !qrp)
return qrp; return qrp;
cap = AllocCatInfo(g, CAT_TAB, tabpat, qrp); if (!(cap = AllocCatInfo(g, CAT_TAB, db, tabpat, qrp)))
return NULL;
//cap->Pat = (PUCHAR)tabtyp; //cap->Pat = (PUCHAR)tabtyp;
if (trace) if (trace)
...@@ -594,7 +627,7 @@ PQRYRES ODBCTables(PGLOBAL g, char *dsn, char *tabpat, bool info) ...@@ -594,7 +627,7 @@ PQRYRES ODBCTables(PGLOBAL g, char *dsn, char *tabpat, bool info)
/************************************************************************/ /************************************************************************/
if ((n = ocp->GetCatInfo(cap)) >= 0) { if ((n = ocp->GetCatInfo(cap)) >= 0) {
qrp->Nblin = n; qrp->Nblin = n;
ResetNullValues(cap); // ResetNullValues(cap);
if (trace) if (trace)
htrc("Tables: NBCOL=%d NBLIN=%d\n", qrp->Nbcol, qrp->Nblin); htrc("Tables: NBCOL=%d NBLIN=%d\n", qrp->Nbcol, qrp->Nblin);
...@@ -667,14 +700,14 @@ PQRYRES ODBCPrimaryKeys(PGLOBAL g, ODBConn *op, char *dsn, char *table) ...@@ -667,14 +700,14 @@ PQRYRES ODBCPrimaryKeys(PGLOBAL g, ODBConn *op, char *dsn, char *table)
if (trace) if (trace)
htrc("Getting pkey results ncol=%d\n", qrp->Nbcol); htrc("Getting pkey results ncol=%d\n", qrp->Nbcol);
cap = AllocCatInfo(g, CAT_KEY, table, qrp); cap = AllocCatInfo(g, CAT_KEY, NULL, table, qrp);
/************************************************************************/ /************************************************************************/
/* Now get the results into blocks. */ /* Now get the results into blocks. */
/************************************************************************/ /************************************************************************/
if ((n = ocp->GetCatInfo(cap)) >= 0) { if ((n = ocp->GetCatInfo(cap)) >= 0) {
qrp->Nblin = n; qrp->Nblin = n;
ResetNullValues(cap); // ResetNullValues(cap);
if (trace) if (trace)
htrc("PrimaryKeys: NBCOL=%d NBLIN=%d\n", qrp->Nbcol, qrp->Nblin); htrc("PrimaryKeys: NBCOL=%d NBLIN=%d\n", qrp->Nbcol, qrp->Nblin);
...@@ -749,7 +782,7 @@ PQRYRES ODBCStatistics(PGLOBAL g, ODBConn *op, char *dsn, char *pat, ...@@ -749,7 +782,7 @@ PQRYRES ODBCStatistics(PGLOBAL g, ODBConn *op, char *dsn, char *pat,
if (trace) if (trace)
htrc("Getting stat results ncol=%d\n", qrp->Nbcol); htrc("Getting stat results ncol=%d\n", qrp->Nbcol);
cap = AllocCatInfo(g, CAT_STAT, pat, qrp); cap = AllocCatInfo(g, CAT_STAT, NULL, pat, qrp);
cap->Unique = (un < 0) ? SQL_INDEX_UNIQUE : (UWORD)un; cap->Unique = (un < 0) ? SQL_INDEX_UNIQUE : (UWORD)un;
cap->Accuracy = (acc < 0) ? SQL_QUICK : (UWORD)acc; cap->Accuracy = (acc < 0) ? SQL_QUICK : (UWORD)acc;
...@@ -758,7 +791,7 @@ PQRYRES ODBCStatistics(PGLOBAL g, ODBConn *op, char *dsn, char *pat, ...@@ -758,7 +791,7 @@ PQRYRES ODBCStatistics(PGLOBAL g, ODBConn *op, char *dsn, char *pat,
/************************************************************************/ /************************************************************************/
if ((n = ocp->GetCatInfo(cap)) >= 0) { if ((n = ocp->GetCatInfo(cap)) >= 0) {
qrp->Nblin = n; qrp->Nblin = n;
ResetNullValues(cap); // ResetNullValues(cap);
if (trace) if (trace)
htrc("Statistics: NBCOL=%d NBLIN=%d\n", qrp->Nbcol, qrp->Nblin); htrc("Statistics: NBCOL=%d NBLIN=%d\n", qrp->Nbcol, qrp->Nblin);
...@@ -1837,8 +1870,9 @@ PQRYRES ODBConn::GetMetaData(PGLOBAL g, char *dsn, char *src) ...@@ -1837,8 +1870,9 @@ PQRYRES ODBConn::GetMetaData(PGLOBAL g, char *dsn, char *src)
/************************************************************************/ /************************************************************************/
/* Allocate the structures used to refer to the result set. */ /* Allocate the structures used to refer to the result set. */
/************************************************************************/ /************************************************************************/
qrp = PlgAllocResult(g, qcol, ncol, IDS_COLUMNS + 3, if (!(qrp = PlgAllocResult(g, qcol, ncol, IDS_COLUMNS + 3,
buftyp, fldtyp, length, false, true); buftyp, fldtyp, length, false, true)))
return NULL;
// Some columns must be renamed // Some columns must be renamed
for (i = 0, crp = qrp->Colresp; crp; crp = crp->Next) for (i = 0, crp = qrp->Colresp; crp; crp = crp->Next)
...@@ -1987,35 +2021,39 @@ bool ODBConn::GetDrivers(PQRYRES qrp) ...@@ -1987,35 +2021,39 @@ bool ODBConn::GetDrivers(PQRYRES qrp)
} // end of GetDrivers } // end of GetDrivers
/** /***********************************************************************/
A helper class to split an optionally qualified table name into components. /* A helper class to split an optionally qualified table name into */
These formats are understood: /* components. */
"CatalogName.SchemaName.TableName" /* These formats are understood: */
"SchemaName.TableName" /* "CatalogName.SchemaName.TableName" */
"TableName" /* "SchemaName.TableName" */
*/ /* "TableName" */
/***********************************************************************/
class SQLQualifiedName class SQLQualifiedName
{ {
static const uint max_parts= 3; /* Catalog.Schema.Table */ static const uint max_parts= 3; // Catalog.Schema.Table
MYSQL_LEX_STRING m_part[max_parts]; MYSQL_LEX_STRING m_part[max_parts];
char m_buf[512]; char m_buf[512];
void lex_string_set(MYSQL_LEX_STRING *S, char *str, size_t length) void lex_string_set(MYSQL_LEX_STRING *S, char *str, size_t length)
{ {
S->str= str; S->str= str;
S->length= length; S->length= length;
} } // eend of lex_string_set
void lex_string_shorten_down(MYSQL_LEX_STRING *S, size_t offs) void lex_string_shorten_down(MYSQL_LEX_STRING *S, size_t offs)
{ {
DBUG_ASSERT(offs <= S->length); DBUG_ASSERT(offs <= S->length);
S->str+= offs; S->str+= offs;
S->length-= offs; S->length-= offs;
} } // end of lex_string_shorten_down
/*
Find the rightmost '.' delimiter and return the length /*********************************************************************/
of the qualifier, including the rightmost '.' delimier. /* Find the rightmost '.' delimiter and return the length */
For example, for the string {"a.b.c",5} it will return 4, /* of the qualifier, including the rightmost '.' delimier. */
which is the length of the qualifier "a.b." /* For example, for the string {"a.b.c",5} it will return 4, */
*/ /* which is the length of the qualifier "a.b." */
/*********************************************************************/
size_t lex_string_find_qualifier(MYSQL_LEX_STRING *S) size_t lex_string_find_qualifier(MYSQL_LEX_STRING *S)
{ {
size_t i; size_t i;
...@@ -2028,53 +2066,66 @@ class SQLQualifiedName ...@@ -2028,53 +2066,66 @@ class SQLQualifiedName
} }
} }
return 0; return 0;
} } // end of lex_string_find_qualifier
public: public:
/* /*********************************************************************/
Initialize to the given optionally qualified name. /* Initialize to the given optionally qualified name. */
NULL pointer in "name" is supported. /* NULL pointer in "name" is supported. */
*/ /* name qualifier has precedence over schema. */
SQLQualifiedName(const char *name) /*********************************************************************/
SQLQualifiedName(CATPARM *cap)
{ {
size_t len, i= 0; const char *name = (const char *)cap->Tab;
if (!name) char *db = (char *)cap->DB;
goto ret; size_t len, i;
/* Initialize the first (rightmost) part */
// Initialize the parts
for (i = 0 ; i < max_parts; i++)
lex_string_set(&m_part[i], NULL, 0);
if (name) {
// Initialize the first (rightmost) part
lex_string_set(&m_part[0], m_buf, lex_string_set(&m_part[0], m_buf,
strmake(m_buf, name, sizeof(m_buf) - 1) - m_buf); strmake(m_buf, name, sizeof(m_buf) - 1) - m_buf);
/* Initialize the other parts, if exist. */
for (i= 1; i < max_parts; i++) // Initialize the other parts, if exist.
{ for (i= 1; i < max_parts; i++) {
if (!(len= lex_string_find_qualifier(&m_part[i - 1]))) if (!(len= lex_string_find_qualifier(&m_part[i - 1])))
break; break;
lex_string_set(&m_part[i], m_part[i - 1].str, len - 1); lex_string_set(&m_part[i], m_part[i - 1].str, len - 1);
lex_string_shorten_down(&m_part[i - 1], len); lex_string_shorten_down(&m_part[i - 1], len);
} } // endfor i
ret:
/* Initialize the remaining parts */ } // endif name
for ( ; i < max_parts; i++)
lex_string_set(&m_part[i], NULL, 0); // If it was not specified, set schema as the passed db name
} if (db && !m_part[1].length)
lex_string_set(&m_part[1], db, strlen(db));
} // end of SQLQualifiedName
SQLCHAR *ptr(uint i) SQLCHAR *ptr(uint i)
{ {
DBUG_ASSERT(i < max_parts); DBUG_ASSERT(i < max_parts);
return (SQLCHAR *) (m_part[i].length ? m_part[i].str : NULL); return (SQLCHAR *) (m_part[i].length ? m_part[i].str : NULL);
} } // end of ptr
size_t length(uint i) size_t length(uint i)
{ {
DBUG_ASSERT(i < max_parts); DBUG_ASSERT(i < max_parts);
return m_part[i].length; return m_part[i].length;
} } // end of length
};
}; // end of class SQLQualifiedName
/***********************************************************************/ /***********************************************************************/
/* Allocate recset and call SQLTables, SQLColumns or SQLPrimaryKeys. */ /* Allocate recset and call SQLTables, SQLColumns or SQLPrimaryKeys. */
/***********************************************************************/ /***********************************************************************/
int ODBConn::GetCatInfo(CATPARM *cap) int ODBConn::GetCatInfo(CATPARM *cap)
{ {
#if defined(NEWMSG) || defined(XMSG)
PGLOBAL& g = m_G; PGLOBAL& g = m_G;
#endif // NEWMSG || XMSG
void *buffer; void *buffer;
int i, irc; int i, irc;
bool b; bool b;
...@@ -2082,6 +2133,7 @@ int ODBConn::GetCatInfo(CATPARM *cap) ...@@ -2082,6 +2133,7 @@ int ODBConn::GetCatInfo(CATPARM *cap)
UWORD n; UWORD n;
SWORD ncol, len, tp; SWORD ncol, len, tp;
SQLULEN crow; SQLULEN crow;
PQRYRES qrp = cap->Qrp;
PCOLRES crp; PCOLRES crp;
RETCODE rc; RETCODE rc;
HSTMT hstmt = NULL; HSTMT hstmt = NULL;
...@@ -2102,34 +2154,16 @@ int ODBConn::GetCatInfo(CATPARM *cap) ...@@ -2102,34 +2154,16 @@ int ODBConn::GetCatInfo(CATPARM *cap)
b = true; b = true;
if ((m_RowsetSize = cap->Qrp->Maxres) > 0) { // Currently m_Catver should be always 0 here
if (m_Catver) { assert(!m_Catver); // This may be temporary
// Attempt to set rowset size.
// In case of failure reset it to 0 to use Fetch.
if (m_Catver == 3) // ODBC Ver 3
{
SQLULEN tmp= m_RowsetSize;
rc = SQLSetStmtAttr(hstmt, SQL_ATTR_ROW_ARRAY_SIZE, &tmp, 0);
}
else
rc = SQLSetStmtOption(hstmt, SQL_ROWSET_SIZE, m_RowsetSize);
if (!Check(rc))
m_RowsetSize = 1; // don't attempt it again
// ThrowDBX(rc, hstmt); // Temporary
if (m_Catver == 3) { // ODBC Ver 3
rc = SQLSetStmtAttr(hstmt, SQL_ATTR_ROW_STATUS_PTR, cap->Status, 0);
rc = SQLSetStmtAttr(hstmt, SQL_ATTR_ROWS_FETCHED_PTR, &crow, 0);
} // endif m_Catver
} else // ORABUG if (qrp->Maxres > 0)
m_RowsetSize = 1; m_RowsetSize = 1;
else
} else
ThrowDBX("0-sized result"); ThrowDBX("0-sized result");
SQLQualifiedName name((const char *) cap->Tab); SQLQualifiedName name(cap);
// Now do call the proper ODBC API // Now do call the proper ODBC API
switch (cap->Id) { switch (cap->Id) {
case CAT_TAB: case CAT_TAB:
...@@ -2173,33 +2207,28 @@ int ODBConn::GetCatInfo(CATPARM *cap) ...@@ -2173,33 +2207,28 @@ int ODBConn::GetCatInfo(CATPARM *cap)
rc = SQLNumResultCols(hstmt, &ncol); rc = SQLNumResultCols(hstmt, &ncol);
// n because we no more ignore the first column // n because we no more ignore the first column
if ((n = (UWORD)cap->Qrp->Nbcol) > (UWORD)ncol) if ((n = (UWORD)qrp->Nbcol) > (UWORD)ncol)
ThrowDBX(MSG(COL_NUM_MISM)); ThrowDBX(MSG(COL_NUM_MISM));
if (m_RowsetSize == 1 && cap->Qrp->Maxres > 1) { // Unconditional to handle STRBLK's
pval = (PVAL *)PlugSubAlloc(m_G, NULL, n * sizeof(PVAL)); pval = (PVAL *)PlugSubAlloc(g, NULL, n * sizeof(PVAL));
vlen = (SQLLEN *)PlugSubAlloc(m_G, NULL, n * sizeof(SQLLEN *)); vlen = (SQLLEN *)PlugSubAlloc(g, NULL, n * sizeof(SQLLEN));
} // endif
// Now bind the column buffers // Now bind the column buffers
for (n = 0, crp = cap->Qrp->Colresp; crp; crp = crp->Next) { for (n = 0, crp = qrp->Colresp; crp; crp = crp->Next) {
if (pval) { if ((tp = GetSQLCType(crp->Type)) == SQL_TYPE_NULL) {
pval[n] = AllocateValue(m_G, crp->Kdata->GetType(), sprintf(g->Message, MSG(INV_COLUMN_TYPE), crp->Type, crp->Name);
crp->Kdata->GetVlen(), 0); ThrowDBX(g->Message);
buffer = pval[n]->GetTo_Val(); } // endif tp
vl = vlen + n;
} else {
buffer = crp->Kdata->GetValPointer();
vl = cap->Vlen[n];
} // endif pval
len = GetTypeSize(crp->Type, crp->Clen); if (!(len = GetTypeSize(crp->Type, crp->Length))) {
tp = GetSQLCType(crp->Type); len = 255; // for STRBLK's
((STRBLK*)crp->Kdata)->SetSorted(true);
} // endif len
if (tp == SQL_TYPE_NULL) { pval[n] = AllocateValue(g, crp->Type, len, 0);
sprintf(m_G->Message, MSG(INV_COLUMN_TYPE), crp->Type, crp->Name); buffer = pval[n]->GetTo_Val();
ThrowDBX(m_G->Message); vl = vlen + n;
} // endif tp
// n + 1 because column numbers begin with 1 // n + 1 because column numbers begin with 1
rc = SQLBindCol(hstmt, n + 1, tp, buffer, len, vl); rc = SQLBindCol(hstmt, n + 1, tp, buffer, len, vl);
...@@ -2213,41 +2242,61 @@ int ODBConn::GetCatInfo(CATPARM *cap) ...@@ -2213,41 +2242,61 @@ int ODBConn::GetCatInfo(CATPARM *cap)
fnc = "SQLFetch"; fnc = "SQLFetch";
// Now fetch the result // Now fetch the result
if (m_Catver != 3) { // Extended fetch cannot be used because of STRBLK's
if (m_RowsetSize > 1) { for (i = 0; i < qrp->Maxres; i++) {
fnc = "SQLExtendedFetch"; if ((rc = SQLFetch(hstmt)) == SQL_NO_DATA_FOUND)
rc = SQLExtendedFetch(hstmt, SQL_FETCH_NEXT, 1, &crow, cap->Status);
} else if (pval) {
for (n = 0; n < cap->Qrp->Maxres; n++) {
if ((rc = SQLFetch(hstmt)) != SQL_SUCCESS)
break; break;
else if (rc != SQL_SUCCESS) {
if (trace > 1 || (trace && rc != SQL_SUCCESS_WITH_INFO)) {
UCHAR msg[SQL_MAX_MESSAGE_LENGTH + 1];
UCHAR state[SQL_SQLSTATE_SIZE + 1];
RETCODE erc;
SDWORD native;
for (i = 0, crp = cap->Qrp->Colresp; crp; i++, crp = crp->Next) { htrc("SQLFetch: row %d rc=%d\n", i+1, rc);
crp->Kdata->SetValue(pval[i], n); erc = SQLError(m_henv, m_hdbc, hstmt, state, &native, msg,
cap->Vlen[i][n] = vlen[i]; SQL_MAX_MESSAGE_LENGTH - 1, &len);
} // endfor crp
if (rc != SQL_INVALID_HANDLE)
// Skip non-errors
for (n = 0; n < MAX_NUM_OF_MSG
&& (erc == SQL_SUCCESS || erc == SQL_SUCCESS_WITH_INFO)
&& strcmp((char*)state, "00000"); n++) {
htrc("%s: %s, Native=%d\n", state, msg, native);
erc = SQLError(m_henv, m_hdbc, hstmt, state, &native,
msg, SQL_MAX_MESSAGE_LENGTH - 1, &len);
} // endfor n } // endfor n
if ((crow = n) && rc == SQL_NO_DATA) } // endif trace
rc = SQL_SUCCESS;
} else { if (rc != SQL_SUCCESS_WITH_INFO)
rc = SQLFetch(hstmt); qrp->BadLines++;
crow = 1;
} // endif's
} else // ODBC Ver 3 } // endif rc
rc = SQLFetch(hstmt);
for (n = 0, crp = qrp->Colresp; crp; n++, crp = crp->Next) {
pval[n]->SetNull(vlen[n] == SQL_NULL_DATA);
crp->Kdata->SetValue(pval[n], i);
cap->Vlen[n][i] = vlen[n];
} // endfor crp
} // endfor i
if ((crow = i) && (rc == SQL_NO_DATA || rc == SQL_SUCCESS_WITH_INFO))
rc = SQL_SUCCESS;
if (rc == SQL_NO_DATA_FOUND) { if (rc == SQL_NO_DATA_FOUND) {
if (cap->Pat) if (cap->Pat)
sprintf(m_G->Message, MSG(NO_TABCOL_DATA), cap->Tab, cap->Pat); sprintf(g->Message, MSG(NO_TABCOL_DATA), cap->Tab, cap->Pat);
else else
sprintf(m_G->Message, MSG(NO_TAB_DATA), cap->Tab); sprintf(g->Message, MSG(NO_TAB_DATA), cap->Tab);
ThrowDBX(m_G->Message); ThrowDBX(g->Message);
} else if (rc != SQL_SUCCESS) } else if (rc == SQL_SUCCESS) {
if ((rc = SQLFetch(hstmt)) != SQL_NO_DATA_FOUND)
qrp->Truncated = true;
} else
ThrowDBX(rc, fnc, hstmt); ThrowDBX(rc, fnc, hstmt);
irc = (int)crow; irc = (int)crow;
...@@ -2256,7 +2305,7 @@ int ODBConn::GetCatInfo(CATPARM *cap) ...@@ -2256,7 +2305,7 @@ int ODBConn::GetCatInfo(CATPARM *cap)
for (int i = 0; i < MAX_NUM_OF_MSG && x->m_ErrMsg[i]; i++) for (int i = 0; i < MAX_NUM_OF_MSG && x->m_ErrMsg[i]; i++)
htrc(x->m_ErrMsg[i]); htrc(x->m_ErrMsg[i]);
strcpy(m_G->Message, x->GetErrorMessage(0)); strcpy(g->Message, x->GetErrorMessage(0));
irc = -1; irc = -1;
} // end try/catch } // end try/catch
......
...@@ -58,6 +58,7 @@ enum CATINFO {CAT_TAB = 1, /* SQLTables */ ...@@ -58,6 +58,7 @@ enum CATINFO {CAT_TAB = 1, /* SQLTables */
typedef struct tagCATPARM { typedef struct tagCATPARM {
CATINFO Id; // Id to indicate function CATINFO Id; // Id to indicate function
PQRYRES Qrp; // Result set pointer PQRYRES Qrp; // Result set pointer
PUCHAR DB; // Database (Schema)
PUCHAR Tab; // Table name or pattern PUCHAR Tab; // Table name or pattern
PUCHAR Pat; // Table type or column pattern PUCHAR Pat; // Table type or column pattern
SQLLEN* *Vlen; // To array of indicator values SQLLEN* *Vlen; // To array of indicator values
......
...@@ -574,6 +574,7 @@ DllExport PDBUSER PlgGetUser(PGLOBAL g); ...@@ -574,6 +574,7 @@ DllExport PDBUSER PlgGetUser(PGLOBAL g);
DllExport PCATLG PlgGetCatalog(PGLOBAL g, bool jump = true); DllExport PCATLG PlgGetCatalog(PGLOBAL g, bool jump = true);
DllExport bool PlgSetXdbPath(PGLOBAL g, PSZ, PSZ, char *, int, char *, int); DllExport bool PlgSetXdbPath(PGLOBAL g, PSZ, PSZ, char *, int, char *, int);
DllExport void PlgDBfree(MBLOCK&); DllExport void PlgDBfree(MBLOCK&);
DllExport void *PlgDBSubAlloc(PGLOBAL g, void *memp, size_t size);
//lExport PSZ GetIniString(PGLOBAL, void *, LPCSTR, LPCSTR, LPCSTR, LPCSTR); //lExport PSZ GetIniString(PGLOBAL, void *, LPCSTR, LPCSTR, LPCSTR, LPCSTR);
//lExport int GetIniSize(char *, char *, char *, char *); //lExport int GetIniSize(char *, char *, char *, char *);
//lExport bool WritePrivateProfileInt(LPCSTR, LPCSTR, int, LPCSTR); //lExport bool WritePrivateProfileInt(LPCSTR, LPCSTR, int, LPCSTR);
......
...@@ -1446,7 +1446,6 @@ void PlgDBfree(MBLOCK& mp) ...@@ -1446,7 +1446,6 @@ void PlgDBfree(MBLOCK& mp)
mp.Size = 0; mp.Size = 0;
} // end of PlgDBfree } // end of PlgDBfree
#if 0 // Not used yet
/***********************************************************************/ /***********************************************************************/
/* Program for sub-allocating one item in a storage area. */ /* Program for sub-allocating one item in a storage area. */
/* Note: This function is equivalent to PlugSubAlloc except that in */ /* Note: This function is equivalent to PlugSubAlloc except that in */
...@@ -1463,8 +1462,8 @@ void *PlgDBSubAlloc(PGLOBAL g, void *memp, size_t size) ...@@ -1463,8 +1462,8 @@ void *PlgDBSubAlloc(PGLOBAL g, void *memp, size_t size)
/*******************************************************************/ /*******************************************************************/
memp = g->Sarea; memp = g->Sarea;
size = ((size + 3) / 4) * 4; /* Round up size to multiple of 4 */ //size = ((size + 3) / 4) * 4; /* Round up size to multiple of 4 */
//size = ((size + 7) / 8) * 8; /* Round up size to multiple of 8 */ size = ((size + 7) / 8) * 8; /* Round up size to multiple of 8 */
pph = (PPOOLHEADER)memp; pph = (PPOOLHEADER)memp;
#if defined(DEBTRACE) #if defined(DEBTRACE)
...@@ -1473,34 +1472,9 @@ void *PlgDBSubAlloc(PGLOBAL g, void *memp, size_t size) ...@@ -1473,34 +1472,9 @@ void *PlgDBSubAlloc(PGLOBAL g, void *memp, size_t size)
#endif #endif
if ((uint)size > pph->FreeBlk) { /* Not enough memory left in pool */ if ((uint)size > pph->FreeBlk) { /* Not enough memory left in pool */
char *pname = NULL;
PACTIVITY ap;
if (memp == g->Sarea)
pname = "Work";
else if ((ap = g->Activityp)) {
if (memp == ap->LangRulep)
pname = "Rule";
else if (memp == ap->Nodep[0])
pname = "Dictionary";
else if (memp == ap->Nodep[1])
pname = "Vartok";
else if (memp == ap->Nodep[2])
pname = "Lexicon";
else if (memp == ap->User_Dictp)
pname = "User dictionary";
else if (ap->Aptr)
pname = "Application";
} // endif memp
if (pname)
sprintf(g->Message, sprintf(g->Message,
"Not enough memory in %s area for request of %d (used=%d free=%d)", "Not enough memory in Work area for request of %d (used=%d free=%d)",
pname, size, pph->To_Free, pph->FreeBlk); size, pph->To_Free, pph->FreeBlk);
else
sprintf(g->Message, MSG(SUBALLOC_ERROR),
memp, size, pph->To_Free, pph->FreeBlk);
#if defined(DEBTRACE) #if defined(DEBTRACE)
htrc("%s\n", g->Message); htrc("%s\n", g->Message);
...@@ -1521,7 +1495,6 @@ void *PlgDBSubAlloc(PGLOBAL g, void *memp, size_t size) ...@@ -1521,7 +1495,6 @@ void *PlgDBSubAlloc(PGLOBAL g, void *memp, size_t size)
#endif #endif
return (memp); return (memp);
} // end of PlgDBSubAlloc } // end of PlgDBSubAlloc
#endif // 0 Not used yet
/***********************************************************************/ /***********************************************************************/
/* PUTOUT: Plug DB object typing routine. */ /* PUTOUT: Plug DB object typing routine. */
......
...@@ -130,20 +130,20 @@ char *GetMsgid(int id) ...@@ -130,20 +130,20 @@ char *GetMsgid(int id)
case IDS_13: p = "%s: invalid connection key value %d"; break; case IDS_13: p = "%s: invalid connection key value %d"; break;
case IDS_14: p = "SafeDB: %s rc=%d"; break; case IDS_14: p = "SafeDB: %s rc=%d"; break;
case IDS_15: p = "Wrong communication Dll called for engine %s"; break; case IDS_15: p = "Wrong communication Dll called for engine %s"; break;
case IDS_TAB_01: p = "Table_Qualifier"; break; case IDS_TAB_01: p = "Table_Cat"; break;
case IDS_TAB_02: p = "Table_Owner"; break; case IDS_TAB_02: p = "Table_Schema"; break;
case IDS_TAB_03: p = "Table_Name"; break; case IDS_TAB_03: p = "Table_Name"; break;
case IDS_TAB_04: p = "Table_Type"; break; case IDS_TAB_04: p = "Table_Type"; break;
case IDS_TAB_05: p = "Remark"; break; case IDS_TAB_05: p = "Remark"; break;
case IDS_COL_01: p = "Table_Qualif"; break; case IDS_COL_01: p = "Table_Cat"; break;
case IDS_COL_02: p = "Table_Owner"; break; case IDS_COL_02: p = "Table_Schema"; break;
case IDS_COL_03: p = "Table_Name"; break; case IDS_COL_03: p = "Table_Name"; break;
case IDS_COL_04: p = "Column_Name"; break; case IDS_COL_04: p = "Column_Name"; break;
case IDS_COL_05: p = "Data_Type"; break; case IDS_COL_05: p = "Data_Type"; break;
case IDS_COL_06: p = "Type_Name"; break; case IDS_COL_06: p = "Type_Name"; break;
case IDS_COL_07: p = "Precision"; break; case IDS_COL_07: p = "Column_Size"; break;
case IDS_COL_08: p = "Length"; break; case IDS_COL_08: p = "Buffer_Length"; break;
case IDS_COL_09: p = "Scale"; break; case IDS_COL_09: p = "Decimal_Digits"; break;
case IDS_COL_10: p = "Radix"; break; case IDS_COL_10: p = "Radix"; break;
case IDS_COL_11: p = "Nullable"; break; case IDS_COL_11: p = "Nullable"; break;
case IDS_COL_12: p = "Remarks"; break; case IDS_COL_12: p = "Remarks"; break;
......
...@@ -340,11 +340,11 @@ PQRYRES CSVColumns(PGLOBAL g, const char *fn, char sep, char q, ...@@ -340,11 +340,11 @@ PQRYRES CSVColumns(PGLOBAL g, const char *fn, char sep, char q,
/*********************************************************************/ /*********************************************************************/
qrp = PlgAllocResult(g, ncol, imax, IDS_COLUMNS + 3, qrp = PlgAllocResult(g, ncol, imax, IDS_COLUMNS + 3,
buftyp, fldtyp, length, false, false); buftyp, fldtyp, length, false, false);
qrp->Nblin = imax; if (info || !qrp)
if (info)
return qrp; return qrp;
qrp->Nblin = imax;
/*********************************************************************/ /*********************************************************************/
/* Now get the results into blocks. */ /* Now get the results into blocks. */
/*********************************************************************/ /*********************************************************************/
......
...@@ -478,6 +478,16 @@ bool TDBCAT::Initialize(PGLOBAL g) ...@@ -478,6 +478,16 @@ bool TDBCAT::Initialize(PGLOBAL g)
if (!(Qrp = GetResult(g))) if (!(Qrp = GetResult(g)))
return true; return true;
if (Qrp->Truncated) {
sprintf(g->Message, "Result limited to %d lines", Qrp->Maxres);
PushWarning(g, this);
} // endif Truncated
if (Qrp->BadLines) {
sprintf(g->Message, "%d bad lines in result", Qrp->BadLines);
PushWarning(g, this);
} // endif Badlines
Init = true; Init = true;
return false; return false;
} // end of Initialize } // end of Initialize
...@@ -488,10 +498,11 @@ bool TDBCAT::Initialize(PGLOBAL g) ...@@ -488,10 +498,11 @@ bool TDBCAT::Initialize(PGLOBAL g)
int TDBCAT::GetMaxSize(PGLOBAL g) int TDBCAT::GetMaxSize(PGLOBAL g)
{ {
if (MaxSize < 0) { if (MaxSize < 0) {
if (Initialize(g)) // if (Initialize(g))
return -1; // return -1;
MaxSize = Qrp->Nblin; // MaxSize = Qrp->Nblin;
MaxSize = 10; // To make MariaDB happy
} // endif MaxSize } // endif MaxSize
return MaxSize; return MaxSize;
......
/************* Tabodbc C++ Program Source Code File (.CPP) *************/ /************* Tabodbc C++ Program Source Code File (.CPP) *************/
/* PROGRAM NAME: TABODBC */ /* PROGRAM NAME: TABODBC */
/* ------------- */ /* ------------- */
/* Version 2.6 */ /* Version 2.7 */
/* */ /* */
/* COPYRIGHT: */ /* COPYRIGHT: */
/* ---------- */ /* ---------- */
...@@ -90,8 +90,8 @@ extern int num_read, num_there, num_eq[2]; // Statistics ...@@ -90,8 +90,8 @@ extern int num_read, num_there, num_eq[2]; // Statistics
/***********************************************************************/ /***********************************************************************/
ODBCDEF::ODBCDEF(void) ODBCDEF::ODBCDEF(void)
{ {
Connect = Tabname = Tabowner = Tabqual = Srcdef = Qrystr = NULL; Connect = Tabname = Tabowner = Tabqual = Srcdef = Qchar = Qrystr = NULL;
Catver = Options = Quoted = 0; Catver = Options = Quoted = Maxerr = Maxres = 0;
Xsrc = false; Xsrc = false;
} // end of ODBCDEF constructor } // end of ODBCDEF constructor
...@@ -104,13 +104,15 @@ bool ODBCDEF::DefineAM(PGLOBAL g, LPCSTR am, int poff) ...@@ -104,13 +104,15 @@ bool ODBCDEF::DefineAM(PGLOBAL g, LPCSTR am, int poff)
Tabname = Cat->GetStringCatInfo(g, "Name", Tabname = Cat->GetStringCatInfo(g, "Name",
(Catfunc & (FNC_TABLE | FNC_COL)) ? NULL : Name); (Catfunc & (FNC_TABLE | FNC_COL)) ? NULL : Name);
Tabname = Cat->GetStringCatInfo(g, "Tabname", Tabname); Tabname = Cat->GetStringCatInfo(g, "Tabname", Tabname);
Tabowner = Cat->GetStringCatInfo(g, "Owner", ""); //Tabowner = Cat->GetStringCatInfo(g, "Owner", NULL);
Tabqual = Cat->GetStringCatInfo(g, "Qualifier", ""); Tabowner = Cat->GetStringCatInfo(g, "Dbname", NULL);
Tabqual = Cat->GetStringCatInfo(g, "Qualifier", NULL);
Srcdef = Cat->GetStringCatInfo(g, "Srcdef", NULL); Srcdef = Cat->GetStringCatInfo(g, "Srcdef", NULL);
Qrystr = Cat->GetStringCatInfo(g, "Query_String", "?"); Qrystr = Cat->GetStringCatInfo(g, "Query_String", "?");
Catver = Cat->GetIntCatInfo("Catver", 2); Catver = Cat->GetIntCatInfo("Catver", 2);
Xsrc = Cat->GetBoolCatInfo("Execsrc", FALSE); Xsrc = Cat->GetBoolCatInfo("Execsrc", FALSE);
Mxr = Cat->GetIntCatInfo("Maxerr", 0); Maxerr = Cat->GetIntCatInfo("Maxerr", 0);
Maxres = Cat->GetIntCatInfo("Maxres", 0);
Quoted = Cat->GetIntCatInfo("Quoted", 0); Quoted = Cat->GetIntCatInfo("Quoted", 0);
Options = ODBConn::noOdbcDialog; Options = ODBConn::noOdbcDialog;
Pseudo = 2; // FILID is Ok but not ROWID Pseudo = 2; // FILID is Ok but not ROWID
...@@ -1152,7 +1154,7 @@ TDBXDBC::TDBXDBC(PODEF tdp) : TDBODBC(tdp) ...@@ -1152,7 +1154,7 @@ TDBXDBC::TDBXDBC(PODEF tdp) : TDBODBC(tdp)
{ {
Cmdlist = NULL; Cmdlist = NULL;
Cmdcol = NULL; Cmdcol = NULL;
Mxr = tdp->Mxr; Mxr = tdp->Maxerr;
Nerr = 0; Nerr = 0;
} // end of TDBXDBC constructor } // end of TDBXDBC constructor
...@@ -1385,24 +1387,24 @@ void XSRCCOL::WriteColumn(PGLOBAL g) ...@@ -1385,24 +1387,24 @@ void XSRCCOL::WriteColumn(PGLOBAL g)
// Should never be called // Should never be called
} // end of WriteColumn } // end of WriteColumn
/* ---------------------------TDBSRC class --------------------------- */ /* ---------------------------TDBDRV class --------------------------- */
/***********************************************************************/ /***********************************************************************/
/* GetResult: Get the list of ODBC data sources. */ /* GetResult: Get the list of ODBC drivers. */
/***********************************************************************/ /***********************************************************************/
PQRYRES TDBSRC::GetResult(PGLOBAL g) PQRYRES TDBDRV::GetResult(PGLOBAL g)
{ {
return ODBCDataSources(g, false); return ODBCDrivers(g, Maxres, false);
} // end of GetResult } // end of GetResult
/* ---------------------------TDBDRV class --------------------------- */ /* ---------------------------TDBSRC class --------------------------- */
/***********************************************************************/ /***********************************************************************/
/* GetResult: Get the list of ODBC drivers. */ /* GetResult: Get the list of ODBC data sources. */
/***********************************************************************/ /***********************************************************************/
PQRYRES TDBDRV::GetResult(PGLOBAL g) PQRYRES TDBSRC::GetResult(PGLOBAL g)
{ {
return ODBCDrivers(g, false); return ODBCDataSources(g, Maxres, false);
} // end of GetResult } // end of GetResult
/* ---------------------------TDBOTB class --------------------------- */ /* ---------------------------TDBOTB class --------------------------- */
...@@ -1410,9 +1412,10 @@ PQRYRES TDBDRV::GetResult(PGLOBAL g) ...@@ -1410,9 +1412,10 @@ PQRYRES TDBDRV::GetResult(PGLOBAL g)
/***********************************************************************/ /***********************************************************************/
/* TDBOTB class constructor. */ /* TDBOTB class constructor. */
/***********************************************************************/ /***********************************************************************/
TDBOTB::TDBOTB(PODEF tdp) : TDBCAT(tdp) TDBOTB::TDBOTB(PODEF tdp) : TDBDRV(tdp)
{ {
Dsn = tdp->GetConnect(); Dsn = tdp->GetConnect();
Schema = tdp->GetTabowner();
Tab = tdp->GetTabname(); Tab = tdp->GetTabname();
} // end of TDBOTB constructor } // end of TDBOTB constructor
...@@ -1421,7 +1424,7 @@ TDBOTB::TDBOTB(PODEF tdp) : TDBCAT(tdp) ...@@ -1421,7 +1424,7 @@ TDBOTB::TDBOTB(PODEF tdp) : TDBCAT(tdp)
/***********************************************************************/ /***********************************************************************/
PQRYRES TDBOTB::GetResult(PGLOBAL g) PQRYRES TDBOTB::GetResult(PGLOBAL g)
{ {
return ODBCTables(g, Dsn, Tab, false); return ODBCTables(g, Dsn, Schema, Tab, Maxres, false);
} // end of GetResult } // end of GetResult
/* ---------------------------TDBOCL class --------------------------- */ /* ---------------------------TDBOCL class --------------------------- */
...@@ -1431,7 +1434,7 @@ PQRYRES TDBOTB::GetResult(PGLOBAL g) ...@@ -1431,7 +1434,7 @@ PQRYRES TDBOTB::GetResult(PGLOBAL g)
/***********************************************************************/ /***********************************************************************/
PQRYRES TDBOCL::GetResult(PGLOBAL g) PQRYRES TDBOCL::GetResult(PGLOBAL g)
{ {
return ODBCColumns(g, Dsn, Tab, NULL, false); return ODBCColumns(g, Dsn, Schema, Tab, NULL, Maxres, false);
} // end of GetResult } // end of GetResult
/* ------------------------ End of Tabodbc --------------------------- */ /* ------------------------ End of Tabodbc --------------------------- */
...@@ -23,6 +23,7 @@ typedef class TDBSRC *PTDBSRC; ...@@ -23,6 +23,7 @@ typedef class TDBSRC *PTDBSRC;
class DllExport ODBCDEF : public TABDEF { /* Logical table description */ class DllExport ODBCDEF : public TABDEF { /* Logical table description */
friend class TDBODBC; friend class TDBODBC;
friend class TDBXDBC; friend class TDBXDBC;
friend class TDBDRV;
public: public:
// Constructor // Constructor
ODBCDEF(void); ODBCDEF(void);
...@@ -54,7 +55,8 @@ class DllExport ODBCDEF : public TABDEF { /* Logical table description */ ...@@ -54,7 +55,8 @@ class DllExport ODBCDEF : public TABDEF { /* Logical table description */
int Catver; /* ODBC version for catalog functions */ int Catver; /* ODBC version for catalog functions */
int Options; /* Open connection options */ int Options; /* Open connection options */
int Quoted; /* Identifier quoting level */ int Quoted; /* Identifier quoting level */
int Mxr; /* Maxerr for an Exec table */ int Maxerr; /* Maxerr for an Exec table */
int Maxres; /* Maxres for a catalog table */
bool Xsrc; /* Execution type */ bool Xsrc; /* Execution type */
}; // end of ODBCDEF }; // end of ODBCDEF
...@@ -250,37 +252,40 @@ class XSRCCOL : public ODBCCOL { ...@@ -250,37 +252,40 @@ class XSRCCOL : public ODBCCOL {
}; // end of class XSRCCOL }; // end of class XSRCCOL
/***********************************************************************/ /***********************************************************************/
/* This is the class declaration for the Data Sources catalog table. */ /* This is the class declaration for the Drivers catalog table. */
/***********************************************************************/ /***********************************************************************/
class TDBSRC : public TDBCAT { class TDBDRV : public TDBCAT {
public: public:
// Constructor // Constructor
TDBSRC(PODEF tdp) : TDBCAT(tdp) {} TDBDRV(PODEF tdp) : TDBCAT(tdp) {Maxres = tdp->Maxres;}
protected: protected:
// Specific routines // Specific routines
virtual PQRYRES GetResult(PGLOBAL g); virtual PQRYRES GetResult(PGLOBAL g);
}; // end of class TDBSRC // Members
int Maxres; // Returned lines limit
}; // end of class TDBDRV
/***********************************************************************/ /***********************************************************************/
/* This is the class declaration for the Drivers catalog table. */ /* This is the class declaration for the Data Sources catalog table. */
/***********************************************************************/ /***********************************************************************/
class TDBDRV : public TDBCAT { class TDBSRC : public TDBDRV {
public: public:
// Constructor // Constructor
TDBDRV(PODEF tdp) : TDBCAT(tdp) {} TDBSRC(PODEF tdp) : TDBDRV(tdp) {}
protected: protected:
// Specific routines // Specific routines
virtual PQRYRES GetResult(PGLOBAL g); virtual PQRYRES GetResult(PGLOBAL g);
}; // end of class TDBDRV // No additional Members
}; // end of class TDBSRC
/***********************************************************************/ /***********************************************************************/
/* This is the class declaration for the tables catalog table. */ /* This is the class declaration for the tables catalog table. */
/***********************************************************************/ /***********************************************************************/
class TDBOTB : public TDBCAT { class TDBOTB : public TDBDRV {
public: public:
// Constructor // Constructor
TDBOTB(PODEF tdp); TDBOTB(PODEF tdp);
...@@ -291,6 +296,7 @@ class TDBOTB : public TDBCAT { ...@@ -291,6 +296,7 @@ class TDBOTB : public TDBCAT {
// Members // Members
char *Dsn; // Points to connection string char *Dsn; // Points to connection string
char *Schema; // Points to schema name or NULL
char *Tab; // Points to ODBC table name or pattern char *Tab; // Points to ODBC table name or pattern
}; // end of class TDBOTB }; // end of class TDBOTB
...@@ -306,7 +312,7 @@ class TDBOCL : public TDBOTB { ...@@ -306,7 +312,7 @@ class TDBOCL : public TDBOTB {
// Specific routines // Specific routines
virtual PQRYRES GetResult(PGLOBAL g); virtual PQRYRES GetResult(PGLOBAL g);
// Members // No additional Members
}; // end of class TDBOCL }; // end of class TDBOCL
#endif // !NODBC #endif // !NODBC
...@@ -158,8 +158,9 @@ PQRYRES TabColumns(PGLOBAL g, THD *thd, const char *db, ...@@ -158,8 +158,9 @@ PQRYRES TabColumns(PGLOBAL g, THD *thd, const char *db,
/**********************************************************************/ /**********************************************************************/
/* Allocate the structures used to refer to the result set. */ /* Allocate the structures used to refer to the result set. */
/**********************************************************************/ /**********************************************************************/
qrp = PlgAllocResult(g, ncol, n, IDS_COLUMNS + 3, if (!(qrp = PlgAllocResult(g, ncol, n, IDS_COLUMNS + 3,
buftyp, fldtyp, length, false, true); buftyp, fldtyp, length, false, true)))
return NULL;
// Some columns must be renamed // Some columns must be renamed
for (i = 0, crp = qrp->Colresp; crp; crp = crp->Next) for (i = 0, crp = qrp->Colresp; crp; crp = crp->Next)
......
...@@ -213,7 +213,7 @@ PQRYRES WMIColumns(PGLOBAL g, char *nsp, char *cls, bool info) ...@@ -213,7 +213,7 @@ PQRYRES WMIColumns(PGLOBAL g, char *nsp, char *cls, bool info)
qrp = PlgAllocResult(g, ncol, n, IDS_COLUMNS + 3, qrp = PlgAllocResult(g, ncol, n, IDS_COLUMNS + 3,
buftyp, fldtyp, length, false, true); buftyp, fldtyp, length, false, true);
if (info) if (info || !qrp)
return qrp; return qrp;
/*********************************************************************/ /*********************************************************************/
......
...@@ -95,8 +95,8 @@ bool user_connect::user_init() ...@@ -95,8 +95,8 @@ bool user_connect::user_init()
PDBUSER dup= NULL; PDBUSER dup= NULL;
// Areasize= 64M because of VEC tables. Should be parameterisable // Areasize= 64M because of VEC tables. Should be parameterisable
//g= PlugInit(NULL, 67108864); g= PlugInit(NULL, 67108864);
g= PlugInit(NULL, 134217728); // 128M because of embedded tests (???) //g= PlugInit(NULL, 134217728); // 128M was because of old embedded tests
// Check whether the initialization is complete // Check whether the initialization is complete
if (!g || !g->Sarea || PlugSubSet(g, g->Sarea, g->Sarea_Size) if (!g || !g->Sarea || PlugSubSet(g, g->Sarea, g->Sarea_Size)
......
...@@ -246,12 +246,12 @@ void TYPBLK<TYPE>::SetValue(PVAL valp, int n) ...@@ -246,12 +246,12 @@ void TYPBLK<TYPE>::SetValue(PVAL valp, int n)
ChkIndx(n); ChkIndx(n);
ChkTyp(valp); ChkTyp(valp);
if (!(b = valp->IsNull() && Nullable)) if (!(b = valp->IsNull()))
Typp[n] = GetTypedValue(valp); Typp[n] = GetTypedValue(valp);
else else
Reset(n); Reset(n);
SetNull(n, b); SetNull(n, b && Nullable);
} // end of SetValue } // end of SetValue
template <> template <>
...@@ -671,12 +671,12 @@ void CHRBLK::SetValue(PVAL valp, int n) ...@@ -671,12 +671,12 @@ void CHRBLK::SetValue(PVAL valp, int n)
ChkIndx(n); ChkIndx(n);
ChkTyp(valp); ChkTyp(valp);
if (!(b = valp->IsNull() && Nullable)) if (!(b = valp->IsNull()))
SetValue((PSZ)valp->GetCharValue(), n); SetValue((PSZ)valp->GetCharValue(), n);
else else
Reset(n); Reset(n);
SetNull(n, b); SetNull(n, b && Nullable);
} // end of SetValue } // end of SetValue
/***********************************************************************/ /***********************************************************************/
...@@ -887,6 +887,7 @@ STRBLK::STRBLK(PGLOBAL g, void *mp, int nval) ...@@ -887,6 +887,7 @@ STRBLK::STRBLK(PGLOBAL g, void *mp, int nval)
{ {
Global = g; Global = g;
Nullable = true; Nullable = true;
Sorted = false;
} // end of STRBLK constructor } // end of STRBLK constructor
/***********************************************************************/ /***********************************************************************/
...@@ -1026,8 +1027,12 @@ void STRBLK::SetValue(PVAL valp, int n) ...@@ -1026,8 +1027,12 @@ void STRBLK::SetValue(PVAL valp, int n)
void STRBLK::SetValue(PSZ p, int n) void STRBLK::SetValue(PSZ p, int n)
{ {
if (p) { if (p) {
if (!Sorted || !n || !Strp[n-1] || strcmp(p, Strp[n-1])) {
Strp[n] = (PSZ)PlugSubAlloc(Global, NULL, strlen(p) + 1); Strp[n] = (PSZ)PlugSubAlloc(Global, NULL, strlen(p) + 1);
strcpy(Strp[n], p); strcpy(Strp[n], p);
} else
Strp[n] = Strp[n-1];
} else } else
Strp[n] = NULL; Strp[n] = NULL;
...@@ -1041,9 +1046,14 @@ void STRBLK::SetValue(char *sp, uint len, int n) ...@@ -1041,9 +1046,14 @@ void STRBLK::SetValue(char *sp, uint len, int n)
PSZ p; PSZ p;
if (sp) { if (sp) {
if (!Sorted || !n || !Strp[n-1] || strlen(Strp[n-1]) != len ||
strncmp(sp, Strp[n-1], len)) {
p = (PSZ)PlugSubAlloc(Global, NULL, len + 1); p = (PSZ)PlugSubAlloc(Global, NULL, len + 1);
memcpy(p, sp, len); memcpy(p, sp, len);
p[len] = 0; p[len] = 0;
} else
Strp[n] = Strp[n-1];
} else } else
p = NULL; p = NULL;
......
...@@ -268,9 +268,13 @@ class STRBLK : public VALBLK { ...@@ -268,9 +268,13 @@ class STRBLK : public VALBLK {
virtual int Find(PVAL vp); virtual int Find(PVAL vp);
virtual int GetMaxLength(void); virtual int GetMaxLength(void);
// Specific
void SetSorted(bool b) {Sorted = b;}
protected: protected:
// Members // Members
PSZ* const &Strp; // Pointer to PSZ buffer PSZ* const &Strp; // Pointer to PSZ buffer
bool Sorted; // Values are (semi?) sorted
}; // end of class STRBLK }; // end of class STRBLK
/***********************************************************************/ /***********************************************************************/
......
...@@ -1129,7 +1129,8 @@ void TYPVAL<PSZ>::SetValue_psz(PSZ s) ...@@ -1129,7 +1129,8 @@ void TYPVAL<PSZ>::SetValue_psz(PSZ s)
/***********************************************************************/ /***********************************************************************/
void TYPVAL<PSZ>::SetValue_pvblk(PVBLK blk, int n) void TYPVAL<PSZ>::SetValue_pvblk(PVBLK blk, int n)
{ {
strncpy(Strp, blk->GetCharValue(n), Len); // STRBLK's can return a NULL pointer
SetValue_psz(blk->GetCharValue(n));
} // end of SetValue_pvblk } // end of SetValue_pvblk
/***********************************************************************/ /***********************************************************************/
......
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