Changeset: 28dc6e7ba84e for MonetDB
URL: https://dev.monetdb.org/hg/MonetDB/rev/28dc6e7ba84e
Modified Files:
        clients/odbc/ChangeLog
        clients/odbc/driver/SQLForeignKeys.c
        clients/odbc/samples/metadata.c
Branch: default
Log Message:

For SQLForeignKeys() corrected the output of columns UPDATE_RULE and 
DELETE_RULE. These columns used to always return 3 (= SQL_NO_ACTION) but now 
they will report the action codes as specified in the FOREIGN KEY CONSTRAINT.
Added multiple simple and complex pkey and fkey tests to odbc metadata test 
program.


diffs (292 lines):

diff --git a/clients/odbc/ChangeLog b/clients/odbc/ChangeLog
--- a/clients/odbc/ChangeLog
+++ b/clients/odbc/ChangeLog
@@ -1,6 +1,12 @@
 # ChangeLog file for odbc
 # This file is updated with Maddlog
 
+* Thu Jun  9 2022 Martin van Dinther <[email protected]>
+- For SQLForeignKeys() corrected the output of columns UPDATE_RULE and
+  DELETE_RULE. These columns used to always return 3 (= SQL_NO_ACTION)
+  but now they will report the action codes as specified in the FOREIGN KEY
+  CONSTRAINT construction.
+
 * Thu Jun  2 2022 Martin van Dinther <[email protected]>
 - Fixed issue in function SQLProcedureColumns(). When the argument ColumnName
   was not empty it generated an invalid SQL query which failed with error:
diff --git a/clients/odbc/driver/SQLForeignKeys.c 
b/clients/odbc/driver/SQLForeignKeys.c
--- a/clients/odbc/driver/SQLForeignKeys.c
+++ b/clients/odbc/driver/SQLForeignKeys.c
@@ -139,9 +139,9 @@ MNDBForeignKeys(ODBCStmt *stmt,
                }
        }
 
-       /* first create a string buffer (1200 extra bytes is plenty:
-          we actually need just over 1000) */
-       querylen = 1200 + (2 * strlen(stmt->Dbc->dbname)) +
+       /* first create a string buffer (1300 extra bytes is plenty:
+          we actually need just over 1100) */
+       querylen = 1300 + (2 * strlen(stmt->Dbc->dbname)) +
                (psch ? strlen(psch) : 0) + (ptab ? strlen(ptab) : 0) +
                (fsch ? strlen(fsch) : 0) + (ftab ? strlen(ftab) : 0);
        query = malloc(querylen);
@@ -167,35 +167,44 @@ MNDBForeignKeys(ODBCStmt *stmt,
 
        pos += snprintf(query + pos, querylen - pos,
                "select '%s' as \"PKTABLE_CAT\", "
-                      "pks.name as \"PKTABLE_SCHEM\", "
-                      "pkt.name as \"PKTABLE_NAME\", "
-                      "pkkc.name as \"PKCOLUMN_NAME\", "
-                      "'%s' as \"FKTABLE_CAT\", "
-                      "fks.name as \"FKTABLE_SCHEM\", "
-                      "fkt.name as \"FKTABLE_NAME\", "
-                      "fkkc.name as \"FKCOLUMN_NAME\", "
-                      "cast(fkkc.nr + 1 as smallint) as \"KEY_SEQ\", "
-                      "cast(%d as smallint) as \"UPDATE_RULE\", "
-                      "cast(%d as smallint) as \"DELETE_RULE\", "
-                      "fkk.name as \"FK_NAME\", "
-                      "pkk.name as \"PK_NAME\", "
-                      "cast(%d as smallint) as \"DEFERRABILITY\" "
-               "from sys.schemas fks, sys.tables fkt, "
-                    "sys.objects fkkc, sys.keys as fkk, "
-                    "sys.schemas pks, sys.tables pkt, "
-                    "sys.objects pkkc, sys.keys as pkk "
-               "where fkt.id = fkk.table_id and "
-                     "pkt.id = pkk.table_id and "
+                       "pks.name as \"PKTABLE_SCHEM\", "
+                       "pkt.name as \"PKTABLE_NAME\", "
+                       "pkkc.name as \"PKCOLUMN_NAME\", "
+                       "'%s' as \"FKTABLE_CAT\", "
+                       "fks.name as \"FKTABLE_SCHEM\", "
+                       "fkt.name as \"FKTABLE_NAME\", "
+                       "fkkc.name as \"FKCOLUMN_NAME\", "
+                       "cast(fkkc.nr + 1 as smallint) as \"KEY_SEQ\", "
+                       /* logic for "action" value interpretation pulled from 
clients/mapiclient/dump.c dump_foreign_keys() */
+                       /* for "action" code values meaning see table: 
sys.fkey_actions */
+                       "cast(CASE ((fkk.\"action\" >> 8) & 255)"
+                       " WHEN 0 THEN %d WHEN 1 THEN %d WHEN 2 THEN %d"
+                       " WHEN 3 THEN %d WHEN 4 THEN %d ELSE %d END"
+                       " AS smallint) as \"UPDATE_RULE\", "
+                       "cast(CASE (fkk.\"action\" & 255)"
+                       " WHEN 0 THEN %d WHEN 1 THEN %d WHEN 2 THEN %d"
+                       " WHEN 3 THEN %d WHEN 4 THEN %d ELSE %d END"
+                       " AS smallint) as \"DELETE_RULE\", "
+                       "fkk.name as \"FK_NAME\", "
+                       "pkk.name as \"PK_NAME\", "
+                       "cast(%d as smallint) as \"DEFERRABILITY\" "
+               "from sys.keys as fkk, sys.objects fkkc, sys.tables fkt, 
sys.schemas fks, "
+                    "sys.keys as pkk, sys.objects pkkc, sys.tables pkt, 
sys.schemas pks "
+               "where fkk.rkey > 0 and "       /* exclude invalid rkey 
references, such as -1 first */
+                     "fkk.rkey = pkk.id and "
                      "fkk.id = fkkc.id and "
                      "pkk.id = pkkc.id and "
+                     "fkkc.nr = pkkc.nr and "
+                     "fkt.id = fkk.table_id and "
+                     "pkt.id = pkk.table_id and "
                      "fks.id = fkt.schema_id and "
-                     "pks.id = pkt.schema_id and "
-                     "fkk.rkey = pkk.id and "
-                     "fkkc.nr = pkkc.nr",
+                     "pks.id = pkt.schema_id",
                stmt->Dbc->dbname,
                stmt->Dbc->dbname,
-               SQL_NO_ACTION, SQL_NO_ACTION, SQL_NOT_DEFERRABLE);
-       assert(pos < 1100);
+               SQL_NO_ACTION, SQL_CASCADE, SQL_RESTRICT, SQL_SET_NULL, 
SQL_SET_DEFAULT, SQL_NO_ACTION,
+               SQL_NO_ACTION, SQL_CASCADE, SQL_RESTRICT, SQL_SET_NULL, 
SQL_SET_DEFAULT, SQL_NO_ACTION,
+               SQL_NOT_DEFERRABLE);
+       assert(pos < 1200);
 
        /* Construct the selection condition query part */
        if (NameLength1 > 0 && PKCatalogName != NULL) {
@@ -233,16 +242,19 @@ MNDBForeignKeys(ODBCStmt *stmt,
                free(ftab);
        }
 
-/* TODO finish the FROM and WHERE clauses */
-
        /* add the ordering */
        /* if PKTableName != NULL, selection on primary key, order
           on FK output columns, else order on PK output columns */
+       /* MvD: added additional ordering on FK_NAME or PK_NAME to get proper 
ordering
+          for multiple multi-column fks to the same multi-column pk from one 
table */
        pos += snprintf(query + pos, querylen - pos,
-                       " order by \"%sTABLE_SCHEM\", \"%sTABLE_NAME\", 
\"KEY_SEQ\"",
+                       " order by \"%sTABLE_SCHEM\", \"%sTABLE_NAME\", 
\"%s_NAME\", \"KEY_SEQ\"",
+                       PKTableName != NULL ? "FK" : "PK",
                        PKTableName != NULL ? "FK" : "PK",
                        PKTableName != NULL ? "FK" : "PK");
 
+       /* debug: fprintf(stdout, "SQLForeignKeys SQL (%zu):\n%s\n\n", pos, 
query); */
+
        /* query the MonetDB data dictionary tables */
        rc = MNDBExecDirect(stmt, (SQLCHAR *) query, (SQLINTEGER) pos);
 
@@ -348,7 +360,7 @@ SQLForeignKeysW(SQLHSTMT StatementHandle
 #endif
 
        if (!isValidStmt(stmt))
-                return SQL_INVALID_HANDLE;
+               return SQL_INVALID_HANDLE;
 
        clearStmtErrors(stmt);
 
diff --git a/clients/odbc/samples/metadata.c b/clients/odbc/samples/metadata.c
--- a/clients/odbc/samples/metadata.c
+++ b/clients/odbc/samples/metadata.c
@@ -196,6 +196,15 @@ main(int argc, char **argv)
                "CREATE TABLE odbctst.nopk_twoucs (id2 INT NOT NULL UNIQUE, 
name2 VARCHAR(99) UNIQUE);\n"
                "CREATE LOCAL TEMP TABLE tmp.tmp_nopk_twoucs (id2 INT NOT NULL 
UNIQUE, name2 VARCHAR(99) UNIQUE);\n"
                "CREATE GLOBAL TEMP TABLE tmp.glbl_nopk_twoucs (id2 INT NOT 
NULL UNIQUE, name2 VARCHAR(99) UNIQUE);\n"
+               /* next 3 tables copied from example in 
https://docs.microsoft.com/en-us/sql/odbc/reference/syntax/sqlforeignkeys-function?view=sql-server-ver15
 */
+               "CREATE TABLE \"CUSTOMERS\" (\"CUSTID\" INT PRIMARY KEY, 
\"NAME\" VARCHAR(60) NOT NULL, \"ADDRESS\" VARCHAR(90), \"PHONE\" 
VARCHAR(20));\n"
+               "CREATE TABLE \"ORDERS\" (\"ORDERID\" INT PRIMARY KEY, 
\"CUSTID\" INT NOT NULL REFERENCES \"CUSTOMERS\" (\"CUSTID\"), \"OPENDATE\" 
DATE NOT NULL, \"SALESPERSON\" VARCHAR(60), \"STATUS\" VARCHAR(10) NOT NULL);\n"
+               "CREATE TABLE \"LINES\" (\"ORDERID\" INT NOT NULL REFERENCES 
\"ORDERS\" (\"ORDERID\"), \"LINES\" INT, PRIMARY KEY (\"ORDERID\", \"LINES\"), 
\"PARTID\" INT NOT NULL, \"QUANTITY\" DECIMAL(9,3) NOT NULL);\n"
+               /* also test situation where one table has multiple fks to the 
same multi column pk */
+               "CREATE TABLE odbctst.pk2c (pkc1 INT, pkc2 VARCHAR(99), name1 
VARCHAR(99) UNIQUE, PRIMARY KEY (pkc2, pkc1));\n"
+               "CREATE TABLE odbctst.fk2c (fkc1 INT NOT NULL PRIMARY KEY, fkc2 
VARCHAR(99), fkc3 INT"
+               ", FOREIGN KEY (fkc2, fkc1) REFERENCES odbctst.pk2c (pkc2, 
pkc1) ON UPDATE CASCADE ON DELETE RESTRICT"
+               ", FOREIGN KEY (fkc2, fkc3) REFERENCES odbctst.pk2c (pkc2, 
pkc1) ON UPDATE SET NULL ON DELETE NO ACTION);\n"
                , SQL_NTS);
        check(ret, SQL_HANDLE_DBC, dbc, "SQLExecDirect (create tables script)");
 
@@ -266,7 +275,12 @@ main(int argc, char **argv)
        compareResult(stmt, ret, "SQLTables (odbctst, %)",
                "Resultset with 5 columns\n"
                "TABLE_CAT      TABLE_SCHEM     TABLE_NAME      TABLE_TYPE      
REMARKS\n"
+               "mTests_sql_odbc_samples        odbctst CUSTOMERS       TABLE   
NULL\n"
+               "mTests_sql_odbc_samples        odbctst LINES   TABLE   NULL\n"
+               "mTests_sql_odbc_samples        odbctst ORDERS  TABLE   NULL\n"
+               "mTests_sql_odbc_samples        odbctst fk2c    TABLE   NULL\n"
                "mTests_sql_odbc_samples        odbctst nopk_twoucs     TABLE   
NULL\n"
+               "mTests_sql_odbc_samples        odbctst pk2c    TABLE   NULL\n"
                "mTests_sql_odbc_samples        odbctst pk_uc   TABLE   
NULL\n");
 
        // All user tables and views
@@ -280,10 +294,15 @@ main(int argc, char **argv)
                "mTests_sql_odbc_samples        tmp     glbl_pk_uc      GLOBAL 
TEMPORARY TABLE  NULL\n"
                "mTests_sql_odbc_samples        tmp     tmp_nopk_twoucs LOCAL 
TEMPORARY TABLE   NULL\n"
                "mTests_sql_odbc_samples        tmp     tmp_pk_uc       LOCAL 
TEMPORARY TABLE   NULL\n"
+               "mTests_sql_odbc_samples        odbctst CUSTOMERS       TABLE   
NULL\n"
+               "mTests_sql_odbc_samples        odbctst LINES   TABLE   NULL\n"
+               "mTests_sql_odbc_samples        odbctst ORDERS  TABLE   NULL\n"
+               "mTests_sql_odbc_samples        odbctst fk2c    TABLE   NULL\n"
                "mTests_sql_odbc_samples        odbctst nopk_twoucs     TABLE   
NULL\n"
+               "mTests_sql_odbc_samples        odbctst pk2c    TABLE   NULL\n"
                "mTests_sql_odbc_samples        odbctst pk_uc   TABLE   
NULL\n");
 
-       // All columns of the odbctst tables
+       // All columns of odbctst tables containg 'pk' in their name
        ret = SQLColumns(stmt, (SQLCHAR*)"", SQL_NTS,
                        (SQLCHAR*)"odbctst", SQL_NTS, (SQLCHAR*)"%pk%", SQL_NTS,
                        (SQLCHAR*)"%", SQL_NTS);
@@ -292,6 +311,9 @@ main(int argc, char **argv)
                "TABLE_CAT      TABLE_SCHEM     TABLE_NAME      COLUMN_NAME     
DATA_TYPE       TYPE_NAME       COLUMN_SIZE     BUFFER_LENGTH   DECIMAL_DIGITS  
NUM_PREC_RADIX  NULLABLE        REMARKS COLUMN_DEF      SQL_DATA_TYPE   
SQL_DATETIME_SUB        CHAR_OCTET_LENGTH       ORDINAL_POSITION        
IS_NULLABLE\n"
                "mTests_sql_odbc_samples        odbctst nopk_twoucs     id2     
4       INTEGER 32      11      0       2       0       NULL    NULL    4       
NULL    NULL    1       NO\n"
                "mTests_sql_odbc_samples        odbctst nopk_twoucs     name2   
-9      VARCHAR 99      198     NULL    NULL    1       NULL    NULL    -9      
NULL    198     2       YES\n"
+               "mTests_sql_odbc_samples        odbctst pk2c    pkc1    4       
INTEGER 32      11      0       2       0       NULL    NULL    4       NULL    
NULL    1       NO\n"
+               "mTests_sql_odbc_samples        odbctst pk2c    pkc2    -9      
VARCHAR 99      198     NULL    NULL    0       NULL    NULL    -9      NULL    
198     2       NO\n"
+               "mTests_sql_odbc_samples        odbctst pk2c    name1   -9      
VARCHAR 99      198     NULL    NULL    1       NULL    NULL    -9      NULL    
198     3       YES\n"
                "mTests_sql_odbc_samples        odbctst pk_uc   id1     4       
INTEGER 32      11      0       2       0       NULL    NULL    4       NULL    
NULL    1       NO\n"
                "mTests_sql_odbc_samples        odbctst pk_uc   name1   -9      
VARCHAR 99      198     NULL    NULL    1       NULL    NULL    -9      NULL    
198     2       YES\n");
 
@@ -579,16 +601,71 @@ main(int argc, char **argv)
                "mTests_sql_odbc_samples        tmp     glbl_nopk_twoucs        
1       NULL    glbl_nopk_twoucs_i      2       1       id2     NULL    NULL    
NULL    NULL\n"
                "mTests_sql_odbc_samples        tmp     glbl_nopk_twoucs        
1       NULL    glbl_nopk_twoucs_i      2       2       name2   NULL    NULL    
NULL    NULL\n");
 
+       // odbctst.CUSTOMERS, odbctst.ORDERS and odbctst.LINES
+       /* next tests are copied from code examples on 
https://docs.microsoft.com/en-us/sql/odbc/reference/syntax/sqlforeignkeys-function?view=sql-server-ver15
 */
+       ret = SQLPrimaryKeys(stmt, NULL, 0, NULL, 0, (SQLCHAR*)"ORDERS", 
SQL_NTS);
+       compareResult(stmt, ret, "SQLPrimaryKeys (NULL, ORDERS)",
+               "Resultset with 6 columns\n"
+               "TABLE_CAT      TABLE_SCHEM     TABLE_NAME      COLUMN_NAME     
KEY_SEQ PK_NAME\n"
+               "mTests_sql_odbc_samples        odbctst ORDERS  ORDERID 1       
ORDERS_ORDERID_pkey\n");
 
-       // TODO add tables with fk constraints and procedures such that below 
calls also return data rows
+       ret = SQLForeignKeys(stmt, NULL, 0, NULL, 0, (SQLCHAR*)"ORDERS", 
SQL_NTS, NULL, 0, NULL, 0, NULL, 0);
+       compareResult(stmt, ret, "SQLForeignKeys (NULL, ORDERS, NULL, NULL)",
+               "Resultset with 14 columns\n"
+               "PKTABLE_CAT    PKTABLE_SCHEM   PKTABLE_NAME    PKCOLUMN_NAME   
FKTABLE_CAT     FKTABLE_SCHEM   FKTABLE_NAME    FKCOLUMN_NAME   KEY_SEQ 
UPDATE_RULE     DELETE_RULE     FK_NAME PK_NAME DEFERRABILITY\n"
+               "mTests_sql_odbc_samples        odbctst ORDERS  ORDERID 
mTests_sql_odbc_samples odbctst LINES   ORDERID 1       1       1       
LINES_ORDERID_fkey      ORDERS_ORDERID_pkey     7\n");
+
+       ret = SQLForeignKeys(stmt, NULL, 0, NULL, 0, NULL, 0, NULL, 0, NULL, 0, 
(SQLCHAR*)"ORDERS", SQL_NTS);
+       compareResult(stmt, ret, "SQLForeignKeys (NULL, NULL, NULL, ORDERS)",
+               "Resultset with 14 columns\n"
+               "PKTABLE_CAT    PKTABLE_SCHEM   PKTABLE_NAME    PKCOLUMN_NAME   
FKTABLE_CAT     FKTABLE_SCHEM   FKTABLE_NAME    FKCOLUMN_NAME   KEY_SEQ 
UPDATE_RULE     DELETE_RULE     FK_NAME PK_NAME DEFERRABILITY\n"
+               "mTests_sql_odbc_samples        odbctst CUSTOMERS       CUSTID  
mTests_sql_odbc_samples odbctst ORDERS  CUSTID  1       1       1       
ORDERS_CUSTID_fkey      CUSTOMERS_CUSTID_pkey   7\n");
+
+       // odbctst.pk2c and odbctst.fk2c (tests multi-column pks and multiple 
multi-column fks from one table */
+       ret = SQLPrimaryKeys(stmt, NULL, 0, (SQLCHAR*)"odbctst", SQL_NTS, 
(SQLCHAR*)"pk2c", SQL_NTS);
+       compareResult(stmt, ret, "SQLPrimaryKeys (odbctst, pk2c)",
+               "Resultset with 6 columns\n"
+               "TABLE_CAT      TABLE_SCHEM     TABLE_NAME      COLUMN_NAME     
KEY_SEQ PK_NAME\n"
+               "mTests_sql_odbc_samples        odbctst pk2c    pkc2    1       
pk2c_pkc2_pkc1_pkey\n"
+               "mTests_sql_odbc_samples        odbctst pk2c    pkc1    2       
pk2c_pkc2_pkc1_pkey\n");
+
        ret = SQLForeignKeys(stmt, (SQLCHAR*)"", SQL_NTS,
-                       (SQLCHAR*)"odbctst", SQL_NTS, (SQLCHAR*)"totbl", 
SQL_NTS,
+                       (SQLCHAR*)"odbctst", SQL_NTS, (SQLCHAR*)"pk2c", SQL_NTS,
                        (SQLCHAR*)"", SQL_NTS,
-                       (SQLCHAR*)"odbctst", SQL_NTS, (SQLCHAR*)"fromtbl", 
SQL_NTS);
-       compareResult(stmt, ret, "SQLForeignKeys (odbctst, totbl, odbctst, 
fromtbl)",
+                       (SQLCHAR*)"", SQL_NTS, (SQLCHAR*)"", SQL_NTS);
+       compareResult(stmt, ret, "SQLForeignKeys (odbctst, pk2c, , )",
+               "Resultset with 14 columns\n"
+               "PKTABLE_CAT    PKTABLE_SCHEM   PKTABLE_NAME    PKCOLUMN_NAME   
FKTABLE_CAT     FKTABLE_SCHEM   FKTABLE_NAME    FKCOLUMN_NAME   KEY_SEQ 
UPDATE_RULE     DELETE_RULE     FK_NAME PK_NAME DEFERRABILITY\n"
+               "mTests_sql_odbc_samples        odbctst pk2c    pkc2    
mTests_sql_odbc_samples odbctst fk2c    fkc2    1       0       1       
fk2c_fkc2_fkc1_fkey     pk2c_pkc2_pkc1_pkey     7\n"
+               "mTests_sql_odbc_samples        odbctst pk2c    pkc1    
mTests_sql_odbc_samples odbctst fk2c    fkc1    2       0       1       
fk2c_fkc2_fkc1_fkey     pk2c_pkc2_pkc1_pkey     7\n"
+               "mTests_sql_odbc_samples        odbctst pk2c    pkc2    
mTests_sql_odbc_samples odbctst fk2c    fkc2    1       2       3       
fk2c_fkc2_fkc3_fkey     pk2c_pkc2_pkc1_pkey     7\n"
+               "mTests_sql_odbc_samples        odbctst pk2c    pkc1    
mTests_sql_odbc_samples odbctst fk2c    fkc3    2       2       3       
fk2c_fkc2_fkc3_fkey     pk2c_pkc2_pkc1_pkey     7\n");
+
+       ret = SQLForeignKeys(stmt, (SQLCHAR*)"", SQL_NTS,
+                       (SQLCHAR*)"", SQL_NTS, (SQLCHAR*)"", SQL_NTS,
+                       (SQLCHAR*)"", SQL_NTS,
+                       (SQLCHAR*)"odbctst", SQL_NTS, (SQLCHAR*)"fk2c", 
SQL_NTS);
+       compareResult(stmt, ret, "SQLForeignKeys (, , odbctst, fk2c)",
                "Resultset with 14 columns\n"
-               "PKTABLE_CAT    PKTABLE_SCHEM   PKTABLE_NAME    PKCOLUMN_NAME   
FKTABLE_CAT     FKTABLE_SCHEM   FKTABLE_NAME    FKCOLUMN_NAME   KEY_SEQ 
UPDATE_RULE     DELETE_RULE     FK_NAME PK_NAME DEFERRABILITY\n");
+               "PKTABLE_CAT    PKTABLE_SCHEM   PKTABLE_NAME    PKCOLUMN_NAME   
FKTABLE_CAT     FKTABLE_SCHEM   FKTABLE_NAME    FKCOLUMN_NAME   KEY_SEQ 
UPDATE_RULE     DELETE_RULE     FK_NAME PK_NAME DEFERRABILITY\n"
+               "mTests_sql_odbc_samples        odbctst pk2c    pkc2    
mTests_sql_odbc_samples odbctst fk2c    fkc2    1       0       1       
fk2c_fkc2_fkc1_fkey     pk2c_pkc2_pkc1_pkey     7\n"
+               "mTests_sql_odbc_samples        odbctst pk2c    pkc1    
mTests_sql_odbc_samples odbctst fk2c    fkc1    2       0       1       
fk2c_fkc2_fkc1_fkey     pk2c_pkc2_pkc1_pkey     7\n"
+               "mTests_sql_odbc_samples        odbctst pk2c    pkc2    
mTests_sql_odbc_samples odbctst fk2c    fkc2    1       2       3       
fk2c_fkc2_fkc3_fkey     pk2c_pkc2_pkc1_pkey     7\n"
+               "mTests_sql_odbc_samples        odbctst pk2c    pkc1    
mTests_sql_odbc_samples odbctst fk2c    fkc3    2       2       3       
fk2c_fkc2_fkc3_fkey     pk2c_pkc2_pkc1_pkey     7\n");
 
+       ret = SQLForeignKeys(stmt, (SQLCHAR*)"", SQL_NTS,
+                       (SQLCHAR*)"odbctst", SQL_NTS, (SQLCHAR*)"pk2c", SQL_NTS,
+                       (SQLCHAR*)"", SQL_NTS,
+                       (SQLCHAR*)"odbctst", SQL_NTS, (SQLCHAR*)"fk2c", 
SQL_NTS);
+       compareResult(stmt, ret, "SQLForeignKeys (odbctst, pk2c, odbctst, 
fk2c)",
+               "Resultset with 14 columns\n"
+               "PKTABLE_CAT    PKTABLE_SCHEM   PKTABLE_NAME    PKCOLUMN_NAME   
FKTABLE_CAT     FKTABLE_SCHEM   FKTABLE_NAME    FKCOLUMN_NAME   KEY_SEQ 
UPDATE_RULE     DELETE_RULE     FK_NAME PK_NAME DEFERRABILITY\n"
+               "mTests_sql_odbc_samples        odbctst pk2c    pkc2    
mTests_sql_odbc_samples odbctst fk2c    fkc2    1       0       1       
fk2c_fkc2_fkc1_fkey     pk2c_pkc2_pkc1_pkey     7\n"
+               "mTests_sql_odbc_samples        odbctst pk2c    pkc1    
mTests_sql_odbc_samples odbctst fk2c    fkc1    2       0       1       
fk2c_fkc2_fkc1_fkey     pk2c_pkc2_pkc1_pkey     7\n"
+               "mTests_sql_odbc_samples        odbctst pk2c    pkc2    
mTests_sql_odbc_samples odbctst fk2c    fkc2    1       2       3       
fk2c_fkc2_fkc3_fkey     pk2c_pkc2_pkc1_pkey     7\n"
+               "mTests_sql_odbc_samples        odbctst pk2c    pkc1    
mTests_sql_odbc_samples odbctst fk2c    fkc3    2       2       3       
fk2c_fkc2_fkc3_fkey     pk2c_pkc2_pkc1_pkey     7\n");
+
+       // TODO add tables with procedures such that below calls also return 
data rows
        ret = SQLProcedures(stmt, (SQLCHAR*)"", SQL_NTS,
                        (SQLCHAR*)"odbctst", SQL_NTS, (SQLCHAR*)"myproc", 
SQL_NTS);
        compareResult(stmt, ret, "SQLProcedures (odbctst, myproc)",
@@ -620,9 +697,22 @@ main(int argc, char **argv)
                "DROP TABLE odbctst.nopk_twoucs;\n"
                "DROP TABLE tmp.tmp_nopk_twoucs;\n"
                "DROP TABLE tmp.glbl_nopk_twoucs;\n"
+               "DROP TABLE odbctst.\"LINES\";\n"
+               "DROP TABLE odbctst.\"ORDERS\";\n"
+               "DROP TABLE odbctst.\"CUSTOMERS\";\n"
+               "DROP TABLE odbctst.fk2c;\n"
+               "DROP TABLE odbctst.pk2c;\n"
                , SQL_NTS);
        check(ret, SQL_HANDLE_DBC, dbc, "SQLExecDirect (drop tables script)");
 
+       // All tables in schema odbctst should be empty now, else we missed 
some DROP statements
+       ret = SQLTables(stmt, NULL, 0,
+                       (SQLCHAR*)"odbctst", SQL_NTS, (SQLCHAR*)"%", SQL_NTS,
+                       NULL, 0);
+       compareResult(stmt, ret, "SQLTables (odbctst, %, NULL)",
+               "Resultset with 5 columns\n"
+               "TABLE_CAT      TABLE_SCHEM     TABLE_NAME      TABLE_TYPE      
REMARKS\n");
+
        ret = SQLExecDirect(stmt, (SQLCHAR *)
                "SET SCHEMA sys;\n"
                "DROP SCHEMA odbctst;\n"
_______________________________________________
checkin-list mailing list -- [email protected]
To unsubscribe send an email to [email protected]

Reply via email to