diff options
25 files changed, 449 insertions, 386 deletions
diff --git a/storage/connect/filamdbf.cpp b/storage/connect/filamdbf.cpp index 02404a7c1f5..c7f389b3ac5 100644 --- a/storage/connect/filamdbf.cpp +++ b/storage/connect/filamdbf.cpp @@ -228,7 +228,7 @@ PQRYRES DBFColumns(PGLOBAL g, const char *fn, BOOL info) qrp = PlgAllocResult(g, ncol, fields, IDS_COLUMNS + 3, buftyp, fldtyp, length, true, false); - if (info) + if (info || !qrp) return qrp; if (trace) { diff --git a/storage/connect/ha_connect.cc b/storage/connect/ha_connect.cc index c10c5f4e81d..470d9ae766b 100644 --- a/storage/connect/ha_connect.cc +++ b/storage/connect/ha_connect.cc @@ -165,7 +165,7 @@ extern "C" char nmfile[]; extern "C" char pdebug[]; extern "C" { - char version[]= "Version 1.01.0010 November 30, 2013"; + char version[]= "Version 1.01.0011 December 15, 2013"; #if defined(XMSG) char msglang[]; // Default message language @@ -3873,11 +3873,11 @@ static int connect_assisted_discovery(handlerton *hton, THD* thd, const char *fncn= "?"; const char *user, *fn, *db, *host, *pwd, *sep, *tbl, *src; const char *col, *ocl, *rnk, *pic, *fcl; - char *tab, *dsn; + char *tab, *dsn, *shm; #if defined(WIN32) char *nsp= NULL, *cls= NULL; #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; uint tm, fnc= FNC_NO, supfnc= (FNC_NO | FNC_COL); bool bif, ok= false, dbf= false; @@ -3933,7 +3933,8 @@ static int connect_assisted_discovery(handlerton *hton, THD* thd, cls= GetListOption(g, "class", topt->oplist); #endif // WIN32 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) cop= atoi(GetListOption(g, "checkdsn", topt->oplist, "0")); #endif // PROMPT_OK @@ -3942,7 +3943,7 @@ static int connect_assisted_discovery(handlerton *hton, THD* thd, user= "root"; } // endif option_list - if (!db) + if (!(shm= (char*)db)) db= table_s->db.str; // Default value // Check table type @@ -4137,17 +4138,17 @@ static int connect_assisted_discovery(handlerton *hton, THD* thd, qrp= ODBCSrcCols(g, dsn, (char*)src); src= NULL; // for next tests } else - qrp= ODBCColumns(g, dsn, (char *) tab, NULL, fnc == FNC_COL); + qrp= ODBCColumns(g, dsn, shm, tab, NULL, mxr, fnc == FNC_COL); break; case FNC_TABLE: - qrp= ODBCTables(g, dsn, (char *) tab, true); + qrp= ODBCTables(g, dsn, shm, tab, mxr, true); break; case FNC_DSN: - qrp= ODBCDataSources(g, true); + qrp= ODBCDataSources(g, mxr, true); break; case FNC_DRIVER: - qrp= ODBCDrivers(g, true); + qrp= ODBCDrivers(g, mxr, true); break; default: sprintf(g->Message, "invalid catfunc %s", fncn); @@ -4163,7 +4164,7 @@ static int connect_assisted_discovery(handlerton *hton, THD* thd, break; #endif // MYSQL_SUPPORT 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; #if defined(WIN32) case TAB_WMI: @@ -4813,7 +4814,7 @@ maria_declare_plugin(connect) &connect_storage_engine, "CONNECT", "Olivier Bertrand", - "Direct access to external data, including many file formats", + "Management of External Data (SQL/MED), including many file formats", PLUGIN_LICENSE_GPL, connect_init_func, /* Plugin Init */ connect_done_func, /* Plugin Deinit */ @@ -4821,6 +4822,6 @@ maria_declare_plugin(connect) NULL, /* status variables */ NULL, /* system variables */ "0.1", /* string version */ - MariaDB_PLUGIN_MATURITY_ALPHA /* maturity */ + MariaDB_PLUGIN_MATURITY_BETA /* maturity */ } maria_declare_plugin_end; diff --git a/storage/connect/myconn.cpp b/storage/connect/myconn.cpp index d2a130e103f..ae4c21e5397 100644 --- a/storage/connect/myconn.cpp +++ b/storage/connect/myconn.cpp @@ -119,8 +119,9 @@ PQRYRES MyColumns(PGLOBAL g, const char *host, const char *db, /**********************************************************************/ /* Allocate the structures used to refer to the result set. */ /**********************************************************************/ - qrp = PlgAllocResult(g, ncol, n, IDS_COLUMNS + 3, - buftyp, fldtyp, length, false, true); + if (!(qrp = PlgAllocResult(g, ncol, n, IDS_COLUMNS + 3, + buftyp, fldtyp, length, false, true))) + return NULL; // Some columns must be renamed for (i = 0, crp = qrp->Colresp; crp; crp = crp->Next) diff --git a/storage/connect/mysql-test/connect/r/odbc.result b/storage/connect/mysql-test/connect/r/odbc.result index d602a77754b..8e1951f0b68 100644 --- a/storage/connect/mysql-test/connect/r/odbc.result +++ b/storage/connect/mysql-test/connect/r/odbc.result @@ -20,28 +20,28 @@ CREATE TABLE t1 ENGINE=CONNECT TABLE_TYPE=ODBC CATFUNC=Tables CONNECTION='Not im SHOW CREATE TABLE t1; Table Create Table t1 CREATE TABLE `t1` ( - `Table_Qualifier` char(128) NOT NULL, - `Table_Owner` char(128) NOT NULL, + `Table_Cat` char(128) NOT NULL, + `Table_Schema` char(128) NOT NULL, `Table_Name` char(128) 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' DROP TABLE t1; CREATE TABLE t1 ENGINE=CONNECT TABLE_TYPE=ODBC CATFUNC=Columns CONNECTION='Not important'; SHOW CREATE TABLE t1; Table Create Table t1 CREATE TABLE `t1` ( - `Table_Qualif` char(128) NOT NULL, - `Table_Owner` char(128) NOT NULL, + `Table_Cat` char(128) NOT NULL, + `Table_Schema` char(128) NOT NULL, `Table_Name` char(128) NOT NULL, `Column_Name` char(128) NOT NULL, `Data_Type` smallint(6) NOT NULL, - `Type_Name` char(20) NOT NULL, - `Precision` int(10) NOT NULL, - `Length` int(10) NOT NULL, - `Scale` smallint(6) NOT NULL, + `Type_Name` char(30) NOT NULL, + `Column_Size` int(10) NOT NULL, + `Buffer_Length` int(10) NOT NULL, + `Decimal_Digits` smallint(6) NOT NULL, `Radix` 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' DROP TABLE t1; diff --git a/storage/connect/mysql-test/connect/r/odbc_postgresql.result b/storage/connect/mysql-test/connect/r/odbc_postgresql.result index 7bef3fbc571..68ce03cb382 100644 --- a/storage/connect/mysql-test/connect/r/odbc_postgresql.result +++ b/storage/connect/mysql-test/connect/r/odbc_postgresql.result @@ -10,8 +10,8 @@ SET NAMES utf8; # All tables in all schemas 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; -Table_Qualifier Table_Owner Table_Name Table_Type Remark +SELECT * FROM t1 ORDER BY Table_Schema, Table_Name; +Table_Cat Table_Schema Table_Name Table_Type Remark mtr public t1 TABLE mtr public t2 TABLE mtr public v1 VIEW @@ -21,8 +21,8 @@ mtr schema1 v1 VIEW DROP TABLE t1; # All tables in all schemas 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; -Table_Qualifier Table_Owner Table_Name Table_Type Remark +SELECT * FROM t1 ORDER BY Table_Schema, Table_Name; +Table_Cat Table_Schema Table_Name Table_Type Remark mtr public t1 TABLE mtr public t2 TABLE mtr public v1 VIEW @@ -32,8 +32,8 @@ mtr schema1 v1 VIEW DROP TABLE t1; # All tables in all schemas 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; -Table_Qualifier Table_Owner Table_Name Table_Type Remark +SELECT * FROM t1 ORDER BY Table_Schema, Table_Name; +Table_Cat Table_Schema Table_Name Table_Type Remark mtr public t1 TABLE mtr public t2 TABLE mtr public v1 VIEW @@ -43,48 +43,48 @@ mtr schema1 v1 VIEW DROP TABLE t1; # 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='%'; -SELECT * FROM t1 ORDER BY Table_Owner, Table_Name; -Table_Qualifier Table_Owner Table_Name Table_Type Remark +SELECT * FROM t1 ORDER BY Table_Schema, Table_Name; +Table_Cat Table_Schema Table_Name Table_Type Remark mtr public t1 TABLE mtr public t2 TABLE mtr public v1 VIEW DROP TABLE t1; # 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'; -SELECT * FROM t1 ORDER BY Table_Owner, Table_Name; -Table_Qualifier Table_Owner Table_Name Table_Type Remark +SELECT * FROM t1 ORDER BY Table_Schema, Table_Name; +Table_Cat Table_Schema Table_Name Table_Type Remark mtr public t1 TABLE mtr schema1 t1 TABLE DROP TABLE t1; # 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'; -SELECT * FROM t1 ORDER BY Table_Owner, Table_Name; -Table_Qualifier Table_Owner Table_Name Table_Type Remark +SELECT * FROM t1 ORDER BY Table_Schema, Table_Name; +Table_Cat Table_Schema Table_Name Table_Type Remark mtr public t1 TABLE mtr schema1 t1 TABLE DROP TABLE t1; # 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'; -SELECT * FROM t1 ORDER BY Table_Owner, Table_Name; -Table_Qualifier Table_Owner Table_Name Table_Type Remark +SELECT * FROM t1 ORDER BY Table_Schema, Table_Name; +Table_Cat Table_Schema Table_Name Table_Type Remark mtr public t1 TABLE DROP TABLE t1; # 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'; -SELECT * FROM t1 ORDER BY Table_Owner, Table_Name; -Table_Qualifier Table_Owner Table_Name Table_Type Remark +SELECT * FROM t1 ORDER BY Table_Schema, Table_Name; +Table_Cat Table_Schema Table_Name Table_Type Remark mtr public t1 TABLE DROP TABLE t1; # 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'; -SELECT * FROM t1 ORDER BY Table_Owner, Table_Name; -Table_Qualifier Table_Owner Table_Name Table_Type Remark +SELECT * FROM t1 ORDER BY Table_Schema, Table_Name; +Table_Cat Table_Schema Table_Name Table_Type Remark mtr schema1 t1 TABLE DROP TABLE t1; # 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'; -SELECT * FROM t1 ORDER BY Table_Owner, Table_Name; -Table_Qualifier Table_Owner Table_Name Table_Type Remark +SELECT * FROM t1 ORDER BY Table_Schema, Table_Name; +Table_Cat Table_Schema Table_Name Table_Type Remark mtr public t1 TABLE mtr schema1 t1 TABLE DROP TABLE t1; @@ -94,8 +94,8 @@ DROP TABLE t1; # 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; -SELECT * FROM t1 WHERE Table_Owner IN ('public','schema1') ORDER BY Table_Owner, Table_Name; -Table_Qualif Table_Owner Table_Name Column_Name Data_Type Type_Name Precision Length Scale Radix Nullable Remarks +SELECT * FROM t1 WHERE Table_Schema IN ('public','schema1') ORDER BY Table_Schema, Table_Name; +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 t2 a 4 int4 10 4 0 10 0 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 DROP TABLE t1; # 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='%.%.%'; -SELECT * FROM t1 WHERE Table_Owner IN ('public','schema1') ORDER BY Table_Owner, Table_Name; -Table_Qualif Table_Owner Table_Name Column_Name Data_Type Type_Name Precision Length Scale Radix Nullable Remarks +SELECT * FROM t1 WHERE Table_Schema IN ('public','schema1') ORDER BY Table_Schema, Table_Name; +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 t2 a 4 int4 10 4 0 10 0 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 DROP TABLE t1; # 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'; -SELECT * FROM t1 ORDER BY Table_Owner, Table_Name; -Table_Qualif Table_Owner Table_Name Column_Name Data_Type Type_Name Precision Length Scale Radix Nullable Remarks +SELECT * FROM t1 ORDER BY Table_Schema, Table_Name; +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 schema1 t1 a 1 bpchar 10 60 0 0 0 DROP TABLE t1; # 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'; -SELECT * FROM t1 ORDER BY Table_Owner, Table_Name; -Table_Qualif Table_Owner Table_Name Column_Name Data_Type Type_Name Precision Length Scale Radix Nullable Remarks +SELECT * FROM t1 ORDER BY Table_Schema, Table_Name; +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 DROP TABLE t1; # 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'; -SELECT * FROM t1 ORDER BY Table_Owner, Table_Name; -Table_Qualif Table_Owner Table_Name Column_Name Data_Type Type_Name Precision Length Scale Radix Nullable Remarks +SELECT * FROM t1 ORDER BY Table_Schema, Table_Name; +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 DROP TABLE t1; # 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'; -SELECT * FROM t1 ORDER BY Table_Owner, Table_Name; -Table_Qualif Table_Owner Table_Name Column_Name Data_Type Type_Name Precision Length Scale Radix Nullable Remarks +SELECT * FROM t1 ORDER BY Table_Schema, Table_Name; +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 schema1 t1 a 1 bpchar 10 60 0 0 0 DROP TABLE t1; diff --git a/storage/connect/mysql-test/connect/r/odbc_sqlite3.result b/storage/connect/mysql-test/connect/r/odbc_sqlite3.result index 13fa2b3e799..24de417792d 100644 --- a/storage/connect/mysql-test/connect/r/odbc_sqlite3.result +++ b/storage/connect/mysql-test/connect/r/odbc_sqlite3.result @@ -43,17 +43,17 @@ DROP VIEW v1; 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; 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 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; SELECT * FROM t1; -Table_Qualifier Table_Owner Table_Name Table_Type Remark +Table_Cat Table_Schema Table_Name Table_Type Remark t1 TABLE 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; 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 b 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 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; 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 t001 TABLE t002 TABLE diff --git a/storage/connect/mysql-test/connect/r/odbc_xls.result b/storage/connect/mysql-test/connect/r/odbc_xls.result index a0b26fe3569..8c560ef013a 100644 --- a/storage/connect/mysql-test/connect/r/odbc_xls.result +++ b/storage/connect/mysql-test/connect/r/odbc_xls.result @@ -15,12 +15,12 @@ Menseau Eric NULL 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;; 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 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;; 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 Fonction 12 VARCHAR 255 510 0 0 1 DROP TABLE t1; diff --git a/storage/connect/mysql-test/connect/r/xml.result b/storage/connect/mysql-test/connect/r/xml.result index e952cc3a635..e412e44a9ba 100644 --- a/storage/connect/mysql-test/connect/r/xml.result +++ b/storage/connect/mysql-test/connect/r/xml.result @@ -413,7 +413,7 @@ DROP TABLE t1; SET @a=LOAD_FILE('MYSQLD_DATADIR/test/t1.xml'); SELECT CAST(@a AS CHAR CHARACTER SET latin1); CAST(@a AS CHAR CHARACTER SET latin1) <?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> <line> <node>ÀÁÂÃ</node> diff --git a/storage/connect/mysql-test/connect/t/odbc_postgresql.test b/storage/connect/mysql-test/connect/t/odbc_postgresql.test index b80135e6167..f634b34323f 100644 --- a/storage/connect/mysql-test/connect/t/odbc_postgresql.test +++ b/storage/connect/mysql-test/connect/t/odbc_postgresql.test @@ -22,7 +22,7 @@ # #[ConnectEnginePostgresql] #Description=PostgreSQL DSN for ConnectSE -#Driver=PostgreSQL +#Driver=PostgreSQL (should the path to the driver so file) #Database=mtr #Servername=localhost #Port=5432 @@ -36,52 +36,52 @@ SET NAMES utf8; --echo --echo # All tables in all schemas 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; --echo # All tables in all schemas 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; --echo # All tables in all schemas 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; --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='%'; -SELECT * FROM t1 ORDER BY Table_Owner, Table_Name; +SELECT * FROM t1 ORDER BY Table_Schema, Table_Name; DROP TABLE t1; --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'; -SELECT * FROM t1 ORDER BY Table_Owner, Table_Name; +SELECT * FROM t1 ORDER BY Table_Schema, Table_Name; DROP TABLE t1; --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'; -SELECT * FROM t1 ORDER BY Table_Owner, Table_Name; +SELECT * FROM t1 ORDER BY Table_Schema, Table_Name; DROP TABLE t1; --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'; -SELECT * FROM t1 ORDER BY Table_Owner, Table_Name; +SELECT * FROM t1 ORDER BY Table_Schema, Table_Name; DROP TABLE t1; --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'; -SELECT * FROM t1 ORDER BY Table_Owner, Table_Name; +SELECT * FROM t1 ORDER BY Table_Schema, Table_Name; DROP TABLE t1; --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'; -SELECT * FROM t1 ORDER BY Table_Owner, Table_Name; +SELECT * FROM t1 ORDER BY Table_Schema, Table_Name; DROP TABLE t1; --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'; -SELECT * FROM t1 ORDER BY Table_Owner, Table_Name; +SELECT * FROM t1 ORDER BY Table_Schema, Table_Name; DROP TABLE t1; --echo # @@ -92,37 +92,37 @@ DROP TABLE t1; # # For some reasons SQLColumn (unlike SQLTables) include columns of system # 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" 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; --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='%.%.%'; -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; --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'; -SELECT * FROM t1 ORDER BY Table_Owner, Table_Name; +SELECT * FROM t1 ORDER BY Table_Schema, Table_Name; DROP TABLE t1; --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'; -SELECT * FROM t1 ORDER BY Table_Owner, Table_Name; +SELECT * FROM t1 ORDER BY Table_Schema, Table_Name; DROP TABLE t1; --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'; -SELECT * FROM t1 ORDER BY Table_Owner, Table_Name; +SELECT * FROM t1 ORDER BY Table_Schema, Table_Name; DROP TABLE t1; --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'; -SELECT * FROM t1 ORDER BY Table_Owner, Table_Name; +SELECT * FROM t1 ORDER BY Table_Schema, Table_Name; DROP TABLE t1; diff --git a/storage/connect/odbccat.h b/storage/connect/odbccat.h index 1c89334f5a9..9cc14695977 100644 --- a/storage/connect/odbccat.h +++ b/storage/connect/odbccat.h @@ -4,9 +4,10 @@ #if defined(PROMPT_OK) char *ODBCCheckConnection(PGLOBAL g, char *dsn, int cop); #endif // PROMPT_OK -PQRYRES ODBCDataSources(PGLOBAL g, bool info); -PQRYRES ODBCColumns(PGLOBAL g, char *dsn, char *table, - char *colpat, bool info); +PQRYRES ODBCDataSources(PGLOBAL g, int maxres, bool info); +PQRYRES ODBCColumns(PGLOBAL g, char *dsn, char *db, char *table, + char *colpat, int maxres, bool info); PQRYRES ODBCSrcCols(PGLOBAL g, char *dsn, char *src); -PQRYRES ODBCTables(PGLOBAL g, char *dsn, char *tabpat, bool info); -PQRYRES ODBCDrivers(PGLOBAL g, bool info); +PQRYRES ODBCTables(PGLOBAL g, char *dsn, char *db, char *tabpat, + int maxres, bool info); +PQRYRES ODBCDrivers(PGLOBAL g, int maxres, bool info); diff --git a/storage/connect/odbconn.cpp b/storage/connect/odbconn.cpp index 9c287af8b7d..caf3a18f2ce 100644 --- a/storage/connect/odbconn.cpp +++ b/storage/connect/odbconn.cpp @@ -1,5 +1,5 @@ /************ 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 */ /* */ @@ -211,7 +211,8 @@ char *ODBCCheckConnection(PGLOBAL g, char *dsn, int cop) /***********************************************************************/ /* 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; CATPARM *cap; @@ -219,12 +220,26 @@ static CATPARM *AllocCatInfo(PGLOBAL g, CATINFO fid, char *tab, PQRYRES qrp) #if defined(_DEBUG) assert(qrp); #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; n = (size_t)qrp->Nbcol; cap = (CATPARM *)PlugSubAlloc(g, NULL, sizeof(CATPARM)); memset(cap, 0, sizeof(CATPARM)); cap->Id = fid; cap->Qrp = qrp; + cap->DB = (PUCHAR)db; cap->Tab = (PUCHAR)tab; cap->Vlen = (SQLLEN* *)PlugSubAlloc(g, NULL, n * sizeof(SQLLEN *)); @@ -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->Status = (UWORD *)PlugSubAlloc(g, NULL, m * sizeof(UWORD)); + + fin: + g->jump_level--; return cap; } // end of AllocCatInfo +#if 0 /***********************************************************************/ /* Check for nulls and reset them to Null (?) values. */ /***********************************************************************/ @@ -256,25 +275,23 @@ static void ResetNullValues(CATPARM *cap) crp->Kdata->Reset(n); } // end of ResetNullValues +#endif /***********************************************************************/ /* ODBCColumns: constructs the result blocks containing all columns */ /* of an ODBC table that will be retrieved by GetData commands. */ /***********************************************************************/ -PQRYRES ODBCColumns(PGLOBAL g, char *dsn, char *table, - char *colpat, bool info) +PQRYRES ODBCColumns(PGLOBAL g, char *dsn, char *db, char *table, + char *colpat, int maxres, bool info) { - static int buftyp[] = {TYPE_STRING, TYPE_STRING, TYPE_STRING, - TYPE_STRING, TYPE_SHORT, TYPE_STRING, - TYPE_INT, TYPE_INT, TYPE_SHORT, - TYPE_SHORT, TYPE_SHORT, TYPE_STRING}; - static XFLD fldtyp[] = {FLD_QUALIF, FLD_OWNER, FLD_TABNAME, - FLD_NAME, FLD_TYPE, FLD_TYPENAME, - FLD_PREC, FLD_LENGTH, FLD_SCALE, - FLD_RADIX, FLD_NULL, FLD_REM}; - static unsigned int length[] = {0, 0, 0, 0, 6, 20, 10, 10, 6, 6, 6, 128}; + int buftyp[] = {TYPE_STRING, TYPE_STRING, TYPE_STRING, TYPE_STRING, + TYPE_SHORT, TYPE_STRING, TYPE_INT, TYPE_INT, + TYPE_SHORT, TYPE_SHORT, TYPE_SHORT, TYPE_STRING}; + XFLD fldtyp[] = {FLD_QUALIF, FLD_OWNER, FLD_TABNAME, FLD_NAME, + FLD_TYPE, FLD_TYPENAME, FLD_PREC, FLD_LENGTH, + FLD_SCALE, FLD_RADIX, FLD_NULL, FLD_REM}; + unsigned int length[] = {0, 0, 0, 0, 6, 0, 10, 10, 6, 6, 6, 0}; int n, ncol = 12; - int maxres; PQRYRES qrp; CATPARM *cap; ODBConn *ocp = NULL; @@ -288,15 +305,19 @@ PQRYRES ODBCColumns(PGLOBAL g, char *dsn, char *table, if (ocp->Open(dsn, 10) < 1) // openReadOnly + noODBCdialog return NULL; - // We fix a MySQL limit because some data sources return 32767 - n = ocp->GetMaxValue(SQL_MAX_COLUMNS_IN_TABLE); - maxres = (n) ? min(n, 4096) : 4096; - n = ocp->GetMaxValue(SQL_MAX_QUALIFIER_NAME_LEN); - length[0] = (n) ? (n + 1) : 128; - n = ocp->GetMaxValue(SQL_MAX_USER_NAME_LEN); - length[1] = (n) ? (n + 1) : 128; - n = ocp->GetMaxValue(SQL_MAX_TABLE_NAME_LEN); - length[2] = (n) ? (n + 1) : 128; + if (table && !strchr(table, '%')) { + // We fix a MySQL limit because some data sources return 32767 + n = ocp->GetMaxValue(SQL_MAX_COLUMNS_IN_TABLE); + maxres = (n) ? min(n, 4096) : 4096; + } else if (!maxres) + maxres = 20000; + +// n = ocp->GetMaxValue(SQL_MAX_QUALIFIER_NAME_LEN); +// 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); +// length[2] = (n) ? (n + 1) : 0; n = ocp->GetMaxValue(SQL_MAX_COLUMN_NAME_LEN); length[3] = (n) ? (n + 1) : 128; } else { // Info table @@ -305,6 +326,8 @@ PQRYRES ODBCColumns(PGLOBAL g, char *dsn, char *table, length[1] = 128; length[2] = 128; length[3] = 128; + length[5] = 30; + length[11] = 255; } // endif ocp if (trace) @@ -317,13 +340,15 @@ PQRYRES ODBCColumns(PGLOBAL g, char *dsn, char *table, qrp = PlgAllocResult(g, ncol, maxres, IDS_COLUMNS, buftyp, fldtyp, length, false, true); - if (info) // Info table + if (info || !qrp) // Info table return qrp; if (trace) 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; /************************************************************************/ @@ -331,7 +356,7 @@ PQRYRES ODBCColumns(PGLOBAL g, char *dsn, char *table, /************************************************************************/ if ((n = ocp->GetCatInfo(cap)) >= 0) { qrp->Nblin = n; - ResetNullValues(cap); +// ResetNullValues(cap); if (trace) 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) /**********************************************************************/ /* 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 /************************************************************************/ @@ -434,17 +459,16 @@ PQRYRES MyODBCCols(PGLOBAL g, char *dsn, char *tab, bool info) #endif // 0 /*************************************************************************/ -/* ODBCDataSources: constructs the result blocks containing all ODBC */ -/* data sources available on the local host. */ +/* ODBCDrivers: constructs the result blocks containing all ODBC */ +/* drivers available on the local host. */ /* 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}; - static XFLD fldtyp[] = {FLD_NAME, FLD_REM}; - static unsigned int length[] = {0, 256}; - int n = 0, ncol = 2; - int maxres; + int buftyp[] = {TYPE_STRING, TYPE_STRING}; + XFLD fldtyp[] = {FLD_NAME, FLD_REM}; + unsigned int length[] = {128, 256}; + int ncol = 2; PQRYRES qrp; ODBConn *ocp = NULL; @@ -453,47 +477,45 @@ PQRYRES ODBCDataSources(PGLOBAL g, bool info) /************************************************************************/ if (!info) { ocp = new(g) ODBConn(g, NULL); - n = ocp->GetMaxValue(SQL_MAX_DSN_LENGTH); - length[0] = (n) ? (n + 1) : 256; - maxres = 512; // Estimated max number of data sources - } else { - length[0] = 256; + + if (!maxres) + maxres = 256; // Estimated max number of drivers + + } else maxres = 0; - } // endif info 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. */ /************************************************************************/ - qrp = PlgAllocResult(g, ncol, maxres, IDS_DSRC, + qrp = PlgAllocResult(g, ncol, maxres, IDS_DRIVER, buftyp, fldtyp, length, false, true); /************************************************************************/ /* Now get the results into blocks. */ /************************************************************************/ - if (!info && ocp->GetDataSources(qrp)) + if (!info && qrp && ocp->GetDrivers(qrp)) qrp = NULL; /************************************************************************/ /* Return the result pointer for use by GetData routines. */ /************************************************************************/ return qrp; - } // end of ODBCDataSources + } // end of ODBCDrivers /*************************************************************************/ -/* ODBCDrivers: constructs the result blocks containing all ODBC */ -/* drivers available on the local host. */ +/* ODBCDataSources: constructs the result blocks containing all ODBC */ +/* data sources available on the local host. */ /* 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}; - static XFLD fldtyp[] = {FLD_NAME, FLD_REM}; - static unsigned int length[] = {128, 256}; - int ncol = 2; - int maxres; + int buftyp[] = {TYPE_STRING, TYPE_STRING}; + XFLD fldtyp[] = {FLD_NAME, FLD_REM}; + unsigned int length[] = {0, 256}; + int n = 0, ncol = 2; PQRYRES qrp; ODBConn *ocp = NULL; @@ -502,45 +524,51 @@ PQRYRES ODBCDrivers(PGLOBAL g, bool info) /************************************************************************/ if (!info) { ocp = new(g) ODBConn(g, NULL); - maxres = 256; // Estimated max number of drivers - } else + n = ocp->GetMaxValue(SQL_MAX_DSN_LENGTH); + length[0] = (n) ? (n + 1) : 256; + + if (!maxres) + maxres = 512; // Estimated max number of data sources + + } else { + length[0] = 256; maxres = 0; + } // endif info 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. */ /************************************************************************/ - qrp = PlgAllocResult(g, ncol, maxres, IDS_DRIVER, + qrp = PlgAllocResult(g, ncol, maxres, IDS_DSRC, buftyp, fldtyp, length, false, true); /************************************************************************/ /* Now get the results into blocks. */ /************************************************************************/ - if (!info && ocp->GetDrivers(qrp)) + if (!info && qrp && ocp->GetDataSources(qrp)) qrp = NULL; /************************************************************************/ /* Return the result pointer for use by GetData routines. */ /************************************************************************/ return qrp; - } // end of ODBCDrivers + } // end of ODBCDataSources -/***********************************************************************/ -/* ODBCTables: constructs the result blocks containing all tables in */ -/* 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 *tabpat, bool info) +/**************************************************************************/ +/* ODBCTables: constructs the result blocks containing all tables in */ +/* an ODBC database that will be retrieved by GetData commands. */ +/**************************************************************************/ +PQRYRES ODBCTables(PGLOBAL g, char *dsn, char *db, char *tabpat, + int maxres, bool info) { - static int buftyp[] = {TYPE_STRING, TYPE_STRING, TYPE_STRING, - TYPE_STRING, TYPE_STRING}; - static XFLD fldtyp[] = {FLD_QUALIF, FLD_OWNER, FLD_NAME, - FLD_TYPE, FLD_REM}; - static unsigned int length[] = {0, 0, 0, 16, 128}; + int buftyp[] = {TYPE_STRING, TYPE_STRING, TYPE_STRING, + TYPE_STRING, TYPE_STRING}; + XFLD fldtyp[] = {FLD_QUALIF, FLD_OWNER, FLD_NAME, + FLD_TYPE, FLD_REM}; + unsigned int length[] = {0, 0, 0, 16, 0}; int n, ncol = 5; - int maxres; PQRYRES qrp; CATPARM *cap; ODBConn *ocp = NULL; @@ -557,11 +585,13 @@ PQRYRES ODBCTables(PGLOBAL g, char *dsn, char *tabpat, bool info) if (ocp->Open(dsn, 2) < 1) // 2 is openReadOnly return NULL; - maxres = 16384; // This is completely arbitrary - n = ocp->GetMaxValue(SQL_MAX_QUALIFIER_NAME_LEN); - length[0] = (n) ? (n + 1) : 128; - n = ocp->GetMaxValue(SQL_MAX_USER_NAME_LEN); - length[1] = (n) ? (n + 1) : 128; + if (!maxres) + maxres = 10000; // This is completely arbitrary + +// n = ocp->GetMaxValue(SQL_MAX_QUALIFIER_NAME_LEN); +// 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); length[2] = (n) ? (n + 1) : 128; } else { @@ -569,6 +599,7 @@ PQRYRES ODBCTables(PGLOBAL g, char *dsn, char *tabpat, bool info) length[0] = 128; length[1] = 128; length[2] = 128; + length[4] = 255; } // endif info if (trace) @@ -580,10 +611,12 @@ PQRYRES ODBCTables(PGLOBAL g, char *dsn, char *tabpat, bool info) qrp = PlgAllocResult(g, ncol, maxres, IDS_TABLES, buftyp, fldtyp, length, false, true); - if (info) + if (info || !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; if (trace) @@ -594,7 +627,7 @@ PQRYRES ODBCTables(PGLOBAL g, char *dsn, char *tabpat, bool info) /************************************************************************/ if ((n = ocp->GetCatInfo(cap)) >= 0) { qrp->Nblin = n; - ResetNullValues(cap); +// ResetNullValues(cap); if (trace) 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) if (trace) 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. */ /************************************************************************/ if ((n = ocp->GetCatInfo(cap)) >= 0) { qrp->Nblin = n; - ResetNullValues(cap); +// ResetNullValues(cap); if (trace) 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, if (trace) 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->Accuracy = (acc < 0) ? SQL_QUICK : (UWORD)acc; @@ -758,7 +791,7 @@ PQRYRES ODBCStatistics(PGLOBAL g, ODBConn *op, char *dsn, char *pat, /************************************************************************/ if ((n = ocp->GetCatInfo(cap)) >= 0) { qrp->Nblin = n; - ResetNullValues(cap); +// ResetNullValues(cap); if (trace) htrc("Statistics: NBCOL=%d NBLIN=%d\n", qrp->Nbcol, qrp->Nblin); @@ -1837,8 +1870,9 @@ PQRYRES ODBConn::GetMetaData(PGLOBAL g, char *dsn, char *src) /************************************************************************/ /* Allocate the structures used to refer to the result set. */ /************************************************************************/ - qrp = PlgAllocResult(g, qcol, ncol, IDS_COLUMNS + 3, - buftyp, fldtyp, length, false, true); + if (!(qrp = PlgAllocResult(g, qcol, ncol, IDS_COLUMNS + 3, + buftyp, fldtyp, length, false, true))) + return NULL; // Some columns must be renamed for (i = 0, crp = qrp->Colresp; crp; crp = crp->Next) @@ -1987,35 +2021,39 @@ bool ODBConn::GetDrivers(PQRYRES qrp) } // end of GetDrivers -/** - A helper class to split an optionally qualified table name into components. - These formats are understood: - "CatalogName.SchemaName.TableName" - "SchemaName.TableName" - "TableName" -*/ +/***********************************************************************/ +/* A helper class to split an optionally qualified table name into */ +/* components. */ +/* These formats are understood: */ +/* "CatalogName.SchemaName.TableName" */ +/* "SchemaName.TableName" */ +/* "TableName" */ +/***********************************************************************/ 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]; char m_buf[512]; + void lex_string_set(MYSQL_LEX_STRING *S, char *str, size_t length) { S->str= str; S->length= length; - } + } // eend of lex_string_set + void lex_string_shorten_down(MYSQL_LEX_STRING *S, size_t offs) { DBUG_ASSERT(offs <= S->length); S->str+= offs; S->length-= offs; - } - /* - Find the rightmost '.' delimiter and return the length - of the qualifier, including the rightmost '.' delimier. - For example, for the string {"a.b.c",5} it will return 4, - which is the length of the qualifier "a.b." - */ + } // end of lex_string_shorten_down + + /*********************************************************************/ + /* Find the rightmost '.' delimiter and return the length */ + /* of the qualifier, including the rightmost '.' delimier. */ + /* 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 i; @@ -2028,53 +2066,66 @@ class SQLQualifiedName } } return 0; - } + } // end of lex_string_find_qualifier + public: - /* - Initialize to the given optionally qualified name. - NULL pointer in "name" is supported. - */ - SQLQualifiedName(const char *name) + /*********************************************************************/ + /* Initialize to the given optionally qualified name. */ + /* NULL pointer in "name" is supported. */ + /* name qualifier has precedence over schema. */ + /*********************************************************************/ + SQLQualifiedName(CATPARM *cap) { - size_t len, i= 0; - if (!name) - goto ret; - /* Initialize the first (rightmost) part */ - lex_string_set(&m_part[0], 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++) - { - if (!(len= lex_string_find_qualifier(&m_part[i - 1]))) - break; - lex_string_set(&m_part[i], m_part[i - 1].str, len - 1); - lex_string_shorten_down(&m_part[i - 1], len); - } -ret: - /* Initialize the remaining parts */ - for ( ; i < max_parts; i++) + const char *name = (const char *)cap->Tab; + char *db = (char *)cap->DB; + size_t len, i; + + // 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, + strmake(m_buf, name, sizeof(m_buf) - 1) - m_buf); + + // Initialize the other parts, if exist. + for (i= 1; i < max_parts; i++) { + if (!(len= lex_string_find_qualifier(&m_part[i - 1]))) + break; + + lex_string_set(&m_part[i], m_part[i - 1].str, len - 1); + lex_string_shorten_down(&m_part[i - 1], len); + } // endfor i + + } // endif name + + // 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) { DBUG_ASSERT(i < max_parts); return (SQLCHAR *) (m_part[i].length ? m_part[i].str : NULL); - } + } // end of ptr + size_t length(uint i) { DBUG_ASSERT(i < max_parts); return m_part[i].length; - } -}; + } // end of length + +}; // end of class SQLQualifiedName /***********************************************************************/ /* Allocate recset and call SQLTables, SQLColumns or SQLPrimaryKeys. */ /***********************************************************************/ int ODBConn::GetCatInfo(CATPARM *cap) { -#if defined(NEWMSG) || defined(XMSG) PGLOBAL& g = m_G; -#endif // NEWMSG || XMSG void *buffer; int i, irc; bool b; @@ -2082,6 +2133,7 @@ int ODBConn::GetCatInfo(CATPARM *cap) UWORD n; SWORD ncol, len, tp; SQLULEN crow; + PQRYRES qrp = cap->Qrp; PCOLRES crp; RETCODE rc; HSTMT hstmt = NULL; @@ -2102,34 +2154,16 @@ int ODBConn::GetCatInfo(CATPARM *cap) b = true; - if ((m_RowsetSize = cap->Qrp->Maxres) > 0) { - if (m_Catver) { - // 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); + // Currently m_Catver should be always 0 here + assert(!m_Catver); // This may be temporary - 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 - m_RowsetSize = 1; - - } else + if (qrp->Maxres > 0) + m_RowsetSize = 1; + else ThrowDBX("0-sized result"); - SQLQualifiedName name((const char *) cap->Tab); + SQLQualifiedName name(cap); + // Now do call the proper ODBC API switch (cap->Id) { case CAT_TAB: @@ -2173,34 +2207,29 @@ int ODBConn::GetCatInfo(CATPARM *cap) rc = SQLNumResultCols(hstmt, &ncol); // 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)); - if (m_RowsetSize == 1 && cap->Qrp->Maxres > 1) { - pval = (PVAL *)PlugSubAlloc(m_G, NULL, n * sizeof(PVAL)); - vlen = (SQLLEN *)PlugSubAlloc(m_G, NULL, n * sizeof(SQLLEN *)); - } // endif + // Unconditional to handle STRBLK's + pval = (PVAL *)PlugSubAlloc(g, NULL, n * sizeof(PVAL)); + vlen = (SQLLEN *)PlugSubAlloc(g, NULL, n * sizeof(SQLLEN)); // Now bind the column buffers - for (n = 0, crp = cap->Qrp->Colresp; crp; crp = crp->Next) { - if (pval) { - pval[n] = AllocateValue(m_G, crp->Kdata->GetType(), - crp->Kdata->GetVlen(), 0); - buffer = pval[n]->GetTo_Val(); - vl = vlen + n; - } else { - buffer = crp->Kdata->GetValPointer(); - vl = cap->Vlen[n]; - } // endif pval - - len = GetTypeSize(crp->Type, crp->Clen); - tp = GetSQLCType(crp->Type); - - if (tp == SQL_TYPE_NULL) { - sprintf(m_G->Message, MSG(INV_COLUMN_TYPE), crp->Type, crp->Name); - ThrowDBX(m_G->Message); + for (n = 0, crp = qrp->Colresp; crp; crp = crp->Next) { + if ((tp = GetSQLCType(crp->Type)) == SQL_TYPE_NULL) { + sprintf(g->Message, MSG(INV_COLUMN_TYPE), crp->Type, crp->Name); + ThrowDBX(g->Message); } // endif tp + if (!(len = GetTypeSize(crp->Type, crp->Length))) { + len = 255; // for STRBLK's + ((STRBLK*)crp->Kdata)->SetSorted(true); + } // endif len + + pval[n] = AllocateValue(g, crp->Type, len, 0); + buffer = pval[n]->GetTo_Val(); + vl = vlen + n; + // n + 1 because column numbers begin with 1 rc = SQLBindCol(hstmt, n + 1, tp, buffer, len, vl); @@ -2213,41 +2242,61 @@ int ODBConn::GetCatInfo(CATPARM *cap) fnc = "SQLFetch"; // Now fetch the result - if (m_Catver != 3) { - if (m_RowsetSize > 1) { - fnc = "SQLExtendedFetch"; - 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; - - for (i = 0, crp = cap->Qrp->Colresp; crp; i++, crp = crp->Next) { - crp->Kdata->SetValue(pval[i], n); - cap->Vlen[i][n] = vlen[i]; - } // endfor crp - - } // endfor n - - if ((crow = n) && rc == SQL_NO_DATA) - rc = SQL_SUCCESS; + // Extended fetch cannot be used because of STRBLK's + for (i = 0; i < qrp->Maxres; i++) { + if ((rc = SQLFetch(hstmt)) == SQL_NO_DATA_FOUND) + 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; + + htrc("SQLFetch: row %d rc=%d\n", i+1, rc); + erc = SQLError(m_henv, m_hdbc, hstmt, state, &native, msg, + SQL_MAX_MESSAGE_LENGTH - 1, &len); + + 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 + + } // endif trace + + if (rc != SQL_SUCCESS_WITH_INFO) + qrp->BadLines++; + + } // endif rc + + 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 - } else { - rc = SQLFetch(hstmt); - crow = 1; - } // endif's + } // endfor i - } else // ODBC Ver 3 - rc = SQLFetch(hstmt); + if ((crow = i) && (rc == SQL_NO_DATA || rc == SQL_SUCCESS_WITH_INFO)) + rc = SQL_SUCCESS; if (rc == SQL_NO_DATA_FOUND) { 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 - sprintf(m_G->Message, MSG(NO_TAB_DATA), cap->Tab); + sprintf(g->Message, MSG(NO_TAB_DATA), cap->Tab); + + ThrowDBX(g->Message); + } else if (rc == SQL_SUCCESS) { + if ((rc = SQLFetch(hstmt)) != SQL_NO_DATA_FOUND) + qrp->Truncated = true; - ThrowDBX(m_G->Message); - } else if (rc != SQL_SUCCESS) + } else ThrowDBX(rc, fnc, hstmt); irc = (int)crow; @@ -2256,7 +2305,7 @@ int ODBConn::GetCatInfo(CATPARM *cap) for (int i = 0; i < MAX_NUM_OF_MSG && x->m_ErrMsg[i]; i++) htrc(x->m_ErrMsg[i]); - strcpy(m_G->Message, x->GetErrorMessage(0)); + strcpy(g->Message, x->GetErrorMessage(0)); irc = -1; } // end try/catch diff --git a/storage/connect/odbconn.h b/storage/connect/odbconn.h index 9b8f2d100f4..90d116cb1ad 100644 --- a/storage/connect/odbconn.h +++ b/storage/connect/odbconn.h @@ -58,12 +58,13 @@ enum CATINFO {CAT_TAB = 1, /* SQLTables */ typedef struct tagCATPARM { CATINFO Id; // Id to indicate function PQRYRES Qrp; // Result set pointer - PUCHAR Tab; // Table name or pattern - PUCHAR Pat; // Table type or column pattern + PUCHAR DB; // Database (Schema) + PUCHAR Tab; // Table name or pattern + PUCHAR Pat; // Table type or column pattern SQLLEN* *Vlen; // To array of indicator values UWORD *Status; // To status block // For SQLStatistics - UWORD Unique; // Index type + UWORD Unique; // Index type UWORD Accuracy; // For Cardinality and Pages // For SQLSpecialColumns UWORD ColType; diff --git a/storage/connect/plgdbsem.h b/storage/connect/plgdbsem.h index 9e9d84d4a28..9c906906dd0 100644 --- a/storage/connect/plgdbsem.h +++ b/storage/connect/plgdbsem.h @@ -574,6 +574,7 @@ DllExport PDBUSER PlgGetUser(PGLOBAL g); DllExport PCATLG PlgGetCatalog(PGLOBAL g, bool jump = true); DllExport bool PlgSetXdbPath(PGLOBAL g, PSZ, PSZ, char *, int, char *, int); DllExport void PlgDBfree(MBLOCK&); +DllExport void *PlgDBSubAlloc(PGLOBAL g, void *memp, size_t size); //lExport PSZ GetIniString(PGLOBAL, void *, LPCSTR, LPCSTR, LPCSTR, LPCSTR); //lExport int GetIniSize(char *, char *, char *, char *); //lExport bool WritePrivateProfileInt(LPCSTR, LPCSTR, int, LPCSTR); diff --git a/storage/connect/plgdbutl.cpp b/storage/connect/plgdbutl.cpp index 486128948ce..ce4639a75d4 100644 --- a/storage/connect/plgdbutl.cpp +++ b/storage/connect/plgdbutl.cpp @@ -1446,7 +1446,6 @@ void PlgDBfree(MBLOCK& mp) mp.Size = 0; } // end of PlgDBfree -#if 0 // Not used yet /***********************************************************************/ /* Program for sub-allocating one item in a storage area. */ /* Note: This function is equivalent to PlugSubAlloc except that in */ @@ -1463,8 +1462,8 @@ void *PlgDBSubAlloc(PGLOBAL g, void *memp, size_t size) /*******************************************************************/ memp = g->Sarea; - 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 + 3) / 4) * 4; /* Round up size to multiple of 4 */ + size = ((size + 7) / 8) * 8; /* Round up size to multiple of 8 */ pph = (PPOOLHEADER)memp; #if defined(DEBTRACE) @@ -1473,34 +1472,9 @@ void *PlgDBSubAlloc(PGLOBAL g, void *memp, size_t size) #endif 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, - "Not enough memory in %s area for request of %d (used=%d free=%d)", - pname, size, pph->To_Free, pph->FreeBlk); - else - sprintf(g->Message, MSG(SUBALLOC_ERROR), - memp, size, pph->To_Free, pph->FreeBlk); + sprintf(g->Message, + "Not enough memory in Work area for request of %d (used=%d free=%d)", + size, pph->To_Free, pph->FreeBlk); #if defined(DEBTRACE) htrc("%s\n", g->Message); @@ -1521,7 +1495,6 @@ void *PlgDBSubAlloc(PGLOBAL g, void *memp, size_t size) #endif return (memp); } // end of PlgDBSubAlloc -#endif // 0 Not used yet /***********************************************************************/ /* PUTOUT: Plug DB object typing routine. */ diff --git a/storage/connect/rcmsg.c b/storage/connect/rcmsg.c index 0c63fd55242..25dd4df7a92 100644 --- a/storage/connect/rcmsg.c +++ b/storage/connect/rcmsg.c @@ -130,20 +130,20 @@ char *GetMsgid(int id) case IDS_13: p = "%s: invalid connection key value %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_TAB_01: p = "Table_Qualifier"; break; - case IDS_TAB_02: p = "Table_Owner"; break; + case IDS_TAB_01: p = "Table_Cat"; break; + case IDS_TAB_02: p = "Table_Schema"; break; case IDS_TAB_03: p = "Table_Name"; break; case IDS_TAB_04: p = "Table_Type"; break; case IDS_TAB_05: p = "Remark"; break; - case IDS_COL_01: p = "Table_Qualif"; break; - case IDS_COL_02: p = "Table_Owner"; break; + case IDS_COL_01: p = "Table_Cat"; break; + case IDS_COL_02: p = "Table_Schema"; break; case IDS_COL_03: p = "Table_Name"; break; case IDS_COL_04: p = "Column_Name"; break; case IDS_COL_05: p = "Data_Type"; break; case IDS_COL_06: p = "Type_Name"; break; - case IDS_COL_07: p = "Precision"; break; - case IDS_COL_08: p = "Length"; break; - case IDS_COL_09: p = "Scale"; break; + case IDS_COL_07: p = "Column_Size"; break; + case IDS_COL_08: p = "Buffer_Length"; break; + case IDS_COL_09: p = "Decimal_Digits"; break; case IDS_COL_10: p = "Radix"; break; case IDS_COL_11: p = "Nullable"; break; case IDS_COL_12: p = "Remarks"; break; diff --git a/storage/connect/tabfmt.cpp b/storage/connect/tabfmt.cpp index 1955597bb76..95ea232d798 100644 --- a/storage/connect/tabfmt.cpp +++ b/storage/connect/tabfmt.cpp @@ -340,11 +340,11 @@ PQRYRES CSVColumns(PGLOBAL g, const char *fn, char sep, char q, /*********************************************************************/ qrp = PlgAllocResult(g, ncol, imax, IDS_COLUMNS + 3, buftyp, fldtyp, length, false, false); - qrp->Nblin = imax; - - if (info) + if (info || !qrp) return qrp; + qrp->Nblin = imax; + /*********************************************************************/ /* Now get the results into blocks. */ /*********************************************************************/ diff --git a/storage/connect/table.cpp b/storage/connect/table.cpp index 2d6a6d8dc64..efe203e8e75 100644 --- a/storage/connect/table.cpp +++ b/storage/connect/table.cpp @@ -478,6 +478,16 @@ bool TDBCAT::Initialize(PGLOBAL g) if (!(Qrp = GetResult(g))) 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; return false; } // end of Initialize @@ -488,10 +498,11 @@ bool TDBCAT::Initialize(PGLOBAL g) int TDBCAT::GetMaxSize(PGLOBAL g) { if (MaxSize < 0) { - if (Initialize(g)) - return -1; +// if (Initialize(g)) +// return -1; - MaxSize = Qrp->Nblin; +// MaxSize = Qrp->Nblin; + MaxSize = 10; // To make MariaDB happy } // endif MaxSize return MaxSize; diff --git a/storage/connect/tabodbc.cpp b/storage/connect/tabodbc.cpp index 164049b5267..9d705d7e757 100644 --- a/storage/connect/tabodbc.cpp +++ b/storage/connect/tabodbc.cpp @@ -1,7 +1,7 @@ /************* Tabodbc C++ Program Source Code File (.CPP) *************/ /* PROGRAM NAME: TABODBC */ /* ------------- */ -/* Version 2.6 */ +/* Version 2.7 */ /* */ /* COPYRIGHT: */ /* ---------- */ @@ -90,8 +90,8 @@ extern int num_read, num_there, num_eq[2]; // Statistics /***********************************************************************/ ODBCDEF::ODBCDEF(void) { - Connect = Tabname = Tabowner = Tabqual = Srcdef = Qrystr = NULL; - Catver = Options = Quoted = 0; + Connect = Tabname = Tabowner = Tabqual = Srcdef = Qchar = Qrystr = NULL; + Catver = Options = Quoted = Maxerr = Maxres = 0; Xsrc = false; } // end of ODBCDEF constructor @@ -104,13 +104,15 @@ bool ODBCDEF::DefineAM(PGLOBAL g, LPCSTR am, int poff) Tabname = Cat->GetStringCatInfo(g, "Name", (Catfunc & (FNC_TABLE | FNC_COL)) ? NULL : Name); Tabname = Cat->GetStringCatInfo(g, "Tabname", Tabname); - Tabowner = Cat->GetStringCatInfo(g, "Owner", ""); - Tabqual = Cat->GetStringCatInfo(g, "Qualifier", ""); +//Tabowner = Cat->GetStringCatInfo(g, "Owner", NULL); + Tabowner = Cat->GetStringCatInfo(g, "Dbname", NULL); + Tabqual = Cat->GetStringCatInfo(g, "Qualifier", NULL); Srcdef = Cat->GetStringCatInfo(g, "Srcdef", NULL); Qrystr = Cat->GetStringCatInfo(g, "Query_String", "?"); Catver = Cat->GetIntCatInfo("Catver", 2); 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); Options = ODBConn::noOdbcDialog; Pseudo = 2; // FILID is Ok but not ROWID @@ -1152,7 +1154,7 @@ TDBXDBC::TDBXDBC(PODEF tdp) : TDBODBC(tdp) { Cmdlist = NULL; Cmdcol = NULL; - Mxr = tdp->Mxr; + Mxr = tdp->Maxerr; Nerr = 0; } // end of TDBXDBC constructor @@ -1385,24 +1387,24 @@ void XSRCCOL::WriteColumn(PGLOBAL g) // Should never be called } // 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 -/* ---------------------------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 /* ---------------------------TDBOTB class --------------------------- */ @@ -1410,9 +1412,10 @@ PQRYRES TDBDRV::GetResult(PGLOBAL g) /***********************************************************************/ /* 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(); } // end of TDBOTB constructor @@ -1421,7 +1424,7 @@ TDBOTB::TDBOTB(PODEF tdp) : TDBCAT(tdp) /***********************************************************************/ PQRYRES TDBOTB::GetResult(PGLOBAL g) { - return ODBCTables(g, Dsn, Tab, false); + return ODBCTables(g, Dsn, Schema, Tab, Maxres, false); } // end of GetResult /* ---------------------------TDBOCL class --------------------------- */ @@ -1431,7 +1434,7 @@ PQRYRES TDBOTB::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 Tabodbc --------------------------- */ diff --git a/storage/connect/tabodbc.h b/storage/connect/tabodbc.h index 10c7207b954..a55e0c1f5b2 100644 --- a/storage/connect/tabodbc.h +++ b/storage/connect/tabodbc.h @@ -23,6 +23,7 @@ typedef class TDBSRC *PTDBSRC; class DllExport ODBCDEF : public TABDEF { /* Logical table description */ friend class TDBODBC; friend class TDBXDBC; + friend class TDBDRV; public: // Constructor ODBCDEF(void); @@ -54,7 +55,8 @@ class DllExport ODBCDEF : public TABDEF { /* Logical table description */ int Catver; /* ODBC version for catalog functions */ int Options; /* Open connection options */ 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 */ }; // end of ODBCDEF @@ -250,37 +252,40 @@ class XSRCCOL : public ODBCCOL { }; // 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: // Constructor - TDBSRC(PODEF tdp) : TDBCAT(tdp) {} + TDBDRV(PODEF tdp) : TDBCAT(tdp) {Maxres = tdp->Maxres;} protected: // Specific routines 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: // Constructor - TDBDRV(PODEF tdp) : TDBCAT(tdp) {} + TDBSRC(PODEF tdp) : TDBDRV(tdp) {} protected: // Specific routines 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. */ /***********************************************************************/ -class TDBOTB : public TDBCAT { +class TDBOTB : public TDBDRV { public: // Constructor TDBOTB(PODEF tdp); @@ -291,6 +296,7 @@ class TDBOTB : public TDBCAT { // Members char *Dsn; // Points to connection string + char *Schema; // Points to schema name or NULL char *Tab; // Points to ODBC table name or pattern }; // end of class TDBOTB @@ -306,7 +312,7 @@ class TDBOCL : public TDBOTB { // Specific routines virtual PQRYRES GetResult(PGLOBAL g); - // Members + // No additional Members }; // end of class TDBOCL #endif // !NODBC diff --git a/storage/connect/tabutil.cpp b/storage/connect/tabutil.cpp index 507f0832dfc..48b6d008a31 100644 --- a/storage/connect/tabutil.cpp +++ b/storage/connect/tabutil.cpp @@ -158,8 +158,9 @@ PQRYRES TabColumns(PGLOBAL g, THD *thd, const char *db, /**********************************************************************/ /* Allocate the structures used to refer to the result set. */ /**********************************************************************/ - qrp = PlgAllocResult(g, ncol, n, IDS_COLUMNS + 3, - buftyp, fldtyp, length, false, true); + if (!(qrp = PlgAllocResult(g, ncol, n, IDS_COLUMNS + 3, + buftyp, fldtyp, length, false, true))) + return NULL; // Some columns must be renamed for (i = 0, crp = qrp->Colresp; crp; crp = crp->Next) diff --git a/storage/connect/tabwmi.cpp b/storage/connect/tabwmi.cpp index 5fb349fa5c0..6d3d1609430 100644 --- a/storage/connect/tabwmi.cpp +++ b/storage/connect/tabwmi.cpp @@ -213,7 +213,7 @@ PQRYRES WMIColumns(PGLOBAL g, char *nsp, char *cls, bool info) qrp = PlgAllocResult(g, ncol, n, IDS_COLUMNS + 3, buftyp, fldtyp, length, false, true); - if (info) + if (info || !qrp) return qrp; /*********************************************************************/ diff --git a/storage/connect/user_connect.cc b/storage/connect/user_connect.cc index 394655f66d7..877f612fc0a 100644 --- a/storage/connect/user_connect.cc +++ b/storage/connect/user_connect.cc @@ -95,8 +95,8 @@ bool user_connect::user_init() PDBUSER dup= NULL; // Areasize= 64M because of VEC tables. Should be parameterisable -//g= PlugInit(NULL, 67108864); - g= PlugInit(NULL, 134217728); // 128M because of embedded tests (???) + g= PlugInit(NULL, 67108864); +//g= PlugInit(NULL, 134217728); // 128M was because of old embedded tests // Check whether the initialization is complete if (!g || !g->Sarea || PlugSubSet(g, g->Sarea, g->Sarea_Size) diff --git a/storage/connect/valblk.cpp b/storage/connect/valblk.cpp index afaff491249..59f5cdef586 100644 --- a/storage/connect/valblk.cpp +++ b/storage/connect/valblk.cpp @@ -246,12 +246,12 @@ void TYPBLK<TYPE>::SetValue(PVAL valp, int n) ChkIndx(n); ChkTyp(valp); - if (!(b = valp->IsNull() && Nullable)) + if (!(b = valp->IsNull())) Typp[n] = GetTypedValue(valp); else Reset(n); - SetNull(n, b); + SetNull(n, b && Nullable); } // end of SetValue template <> @@ -671,12 +671,12 @@ void CHRBLK::SetValue(PVAL valp, int n) ChkIndx(n); ChkTyp(valp); - if (!(b = valp->IsNull() && Nullable)) + if (!(b = valp->IsNull())) SetValue((PSZ)valp->GetCharValue(), n); else Reset(n); - SetNull(n, b); + SetNull(n, b && Nullable); } // end of SetValue /***********************************************************************/ @@ -887,6 +887,7 @@ STRBLK::STRBLK(PGLOBAL g, void *mp, int nval) { Global = g; Nullable = true; + Sorted = false; } // end of STRBLK constructor /***********************************************************************/ @@ -1026,8 +1027,12 @@ void STRBLK::SetValue(PVAL valp, int n) void STRBLK::SetValue(PSZ p, int n) { if (p) { - Strp[n] = (PSZ)PlugSubAlloc(Global, NULL, strlen(p) + 1); - strcpy(Strp[n], p); + if (!Sorted || !n || !Strp[n-1] || strcmp(p, Strp[n-1])) { + Strp[n] = (PSZ)PlugSubAlloc(Global, NULL, strlen(p) + 1); + strcpy(Strp[n], p); + } else + Strp[n] = Strp[n-1]; + } else Strp[n] = NULL; @@ -1041,9 +1046,14 @@ void STRBLK::SetValue(char *sp, uint len, int n) PSZ p; if (sp) { - p = (PSZ)PlugSubAlloc(Global, NULL, len + 1); - memcpy(p, sp, len); - p[len] = 0; + if (!Sorted || !n || !Strp[n-1] || strlen(Strp[n-1]) != len || + strncmp(sp, Strp[n-1], len)) { + p = (PSZ)PlugSubAlloc(Global, NULL, len + 1); + memcpy(p, sp, len); + p[len] = 0; + } else + Strp[n] = Strp[n-1]; + } else p = NULL; diff --git a/storage/connect/valblk.h b/storage/connect/valblk.h index a3669cabd37..debeb0669b0 100644 --- a/storage/connect/valblk.h +++ b/storage/connect/valblk.h @@ -268,9 +268,13 @@ class STRBLK : public VALBLK { virtual int Find(PVAL vp); virtual int GetMaxLength(void); + // Specific + void SetSorted(bool b) {Sorted = b;} + protected: // Members PSZ* const &Strp; // Pointer to PSZ buffer + bool Sorted; // Values are (semi?) sorted }; // end of class STRBLK /***********************************************************************/ diff --git a/storage/connect/value.cpp b/storage/connect/value.cpp index 2522fa178cd..8857608015e 100644 --- a/storage/connect/value.cpp +++ b/storage/connect/value.cpp @@ -1129,7 +1129,8 @@ void TYPVAL<PSZ>::SetValue_psz(PSZ s) /***********************************************************************/ 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 /***********************************************************************/ |