LCOV - code coverage report
Current view: top level - clients/odbc/driver - SQLForeignKeys.c (source / functions) Hit Total Coverage
Test: coverage.info Lines: 0 109 0.0 %
Date: 2021-10-13 02:24:04 Functions: 0 1 0.0 %

          Line data    Source code
       1             : /*
       2             :  * This Source Code Form is subject to the terms of the Mozilla Public
       3             :  * License, v. 2.0.  If a copy of the MPL was not distributed with this
       4             :  * file, You can obtain one at http://mozilla.org/MPL/2.0/.
       5             :  *
       6             :  * Copyright 1997 - July 2008 CWI, August 2008 - 2021 MonetDB B.V.
       7             :  */
       8             : 
       9             : /*
      10             :  * This code was created by Peter Harvey (mostly during Christmas 98/99).
      11             :  * This code is LGPL. Please ensure that this message remains in future
      12             :  * distributions and uses of this code (thats about all I get out of it).
      13             :  * - Peter Harvey pharvey@codebydesign.com
      14             :  *
      15             :  * This file has been modified for the MonetDB project.  See the file
      16             :  * Copyright in this directory for more information.
      17             :  */
      18             : 
      19             : /**********************************************************************
      20             :  * SQLForeignKeys()
      21             :  * CLI Compliance: ODBC (Microsoft)
      22             :  *
      23             :  * Author: Martin van Dinther, Sjoerd Mullender
      24             :  * Date  : 30 aug 2002
      25             :  *
      26             :  **********************************************************************/
      27             : 
      28             : #include "ODBCGlobal.h"
      29             : #include "ODBCStmt.h"
      30             : #include "ODBCUtil.h"
      31             : 
      32             : static SQLRETURN
      33           0 : MNDBForeignKeys(ODBCStmt *stmt,
      34             :                 const SQLCHAR *PKCatalogName,
      35             :                 SQLSMALLINT NameLength1,
      36             :                 const SQLCHAR *PKSchemaName,
      37             :                 SQLSMALLINT NameLength2,
      38             :                 const SQLCHAR *PKTableName,
      39             :                 SQLSMALLINT NameLength3,
      40             :                 const SQLCHAR *FKCatalogName,
      41             :                 SQLSMALLINT NameLength4,
      42             :                 const SQLCHAR *FKSchemaName,
      43             :                 SQLSMALLINT NameLength5,
      44             :                 const SQLCHAR *FKTableName,
      45             :                 SQLSMALLINT NameLength6)
      46             : {
      47             :         RETCODE rc;
      48             : 
      49             :         /* buffer for the constructed query to do meta data retrieval */
      50             :         char *query = NULL;
      51             :         size_t querylen;
      52             :         size_t pos = 0;
      53             :         char *psch = NULL, *ptab = NULL;
      54             :         char *fsch = NULL, *ftab = NULL;
      55             : 
      56             :         /* deal with SQL_NTS and SQL_NULL_DATA */
      57           0 :         fixODBCstring(PKCatalogName, NameLength1, SQLSMALLINT,
      58             :                       addStmtError, stmt, return SQL_ERROR);
      59           0 :         fixODBCstring(PKSchemaName, NameLength2, SQLSMALLINT,
      60             :                       addStmtError, stmt, return SQL_ERROR);
      61           0 :         fixODBCstring(PKTableName, NameLength3, SQLSMALLINT,
      62             :                       addStmtError, stmt, return SQL_ERROR);
      63           0 :         fixODBCstring(FKCatalogName, NameLength4, SQLSMALLINT,
      64             :                       addStmtError, stmt, return SQL_ERROR);
      65           0 :         fixODBCstring(FKSchemaName, NameLength5, SQLSMALLINT,
      66             :                       addStmtError, stmt, return SQL_ERROR);
      67           0 :         fixODBCstring(FKTableName, NameLength6, SQLSMALLINT,
      68             :                       addStmtError, stmt, return SQL_ERROR);
      69             : 
      70             : #ifdef ODCBDEBUG
      71             :         ODBCLOG("\"%.*s\" \"%.*s\" \"%.*s\" \"%.*s\" \"%.*s\" \"%.*s\"\n",
      72             :                 (int) NameLength1, PKCatalogName ? (char *) PKCatalogName : "",
      73             :                 (int) NameLength2, PKSchemaName ? (char *) PKSchemaName : "",
      74             :                 (int) NameLength3, PKTableName ? (char *) PKTableName : "",
      75             :                 (int) NameLength4, FKCatalogName ? (char *) FKCatalogName : "",
      76             :                 (int) NameLength5, FKSchemaName ? (char *) FKSchemaName : "",
      77             :                 (int) NameLength6, FKTableName ? (char *) FKTableName : "");
      78             : #endif
      79             :         /* dependent on the input parameter values we must add a
      80             :            variable selection condition dynamically */
      81             : 
      82           0 :         if (stmt->Dbc->sql_attr_metadata_id == SQL_FALSE) {
      83           0 :                 if (NameLength2 > 0) {
      84           0 :                         psch = ODBCParseOA("pks", "name",
      85             :                                            (const char *) PKSchemaName,
      86             :                                            (size_t) NameLength2);
      87           0 :                         if (psch == NULL)
      88           0 :                                 goto nomem;
      89             :                 }
      90           0 :                 if (NameLength3 > 0) {
      91           0 :                         ptab = ODBCParseOA("pkt", "name",
      92             :                                            (const char *) PKTableName,
      93             :                                            (size_t) NameLength3);
      94           0 :                         if (ptab == NULL)
      95           0 :                                 goto nomem;
      96             :                 }
      97           0 :                 if (NameLength5 > 0) {
      98           0 :                         fsch = ODBCParseOA("fks", "name",
      99             :                                            (const char *) FKSchemaName,
     100             :                                            (size_t) NameLength5);
     101           0 :                         if (fsch == NULL)
     102           0 :                                 goto nomem;
     103             :                 }
     104           0 :                 if (NameLength6 > 0) {
     105           0 :                         ftab = ODBCParseOA("fkt", "name",
     106             :                                            (const char *) FKTableName,
     107             :                                            (size_t) NameLength6);
     108           0 :                         if (ftab == NULL)
     109           0 :                                 goto nomem;
     110             :                 }
     111             :         } else {
     112           0 :                 if (NameLength2 > 0) {
     113           0 :                         psch = ODBCParseID("pks", "name",
     114             :                                            (const char *) PKSchemaName,
     115             :                                            (size_t) NameLength2);
     116           0 :                         if (psch == NULL)
     117           0 :                                 goto nomem;
     118             :                 }
     119           0 :                 if (NameLength3 > 0) {
     120           0 :                         ptab = ODBCParseID("pkt", "name",
     121             :                                            (const char *) PKTableName,
     122             :                                            (size_t) NameLength3);
     123           0 :                         if (ptab == NULL)
     124           0 :                                 goto nomem;
     125             :                 }
     126           0 :                 if (NameLength5 > 0) {
     127           0 :                         fsch = ODBCParseID("fks", "name",
     128             :                                            (const char *) FKSchemaName,
     129             :                                            (size_t) NameLength5);
     130           0 :                         if (fsch == NULL)
     131           0 :                                 goto nomem;
     132             :                 }
     133           0 :                 if (NameLength6 > 0) {
     134           0 :                         ftab = ODBCParseID("fkt", "name",
     135             :                                            (const char *) FKTableName,
     136             :                                            (size_t) NameLength6);
     137           0 :                         if (ftab == NULL)
     138           0 :                                 goto nomem;
     139             :                 }
     140             :         }
     141             : 
     142             :         /* first create a string buffer (1200 extra bytes is plenty:
     143             :            we actually need just over 1000) */
     144           0 :         querylen = 1200 + (2 * strlen(stmt->Dbc->dbname)) +
     145           0 :                 (psch ? strlen(psch) : 0) + (ptab ? strlen(ptab) : 0) +
     146           0 :                 (fsch ? strlen(fsch) : 0) + (ftab ? strlen(ftab) : 0);
     147           0 :         query = malloc(querylen);
     148           0 :         if (query == NULL)
     149           0 :                 goto nomem;
     150             : 
     151             :         /* SQLForeignKeys returns a table with the following columns:
     152             :            VARCHAR      pktable_cat
     153             :            VARCHAR      pktable_schem
     154             :            VARCHAR      pktable_name NOT NULL
     155             :            VARCHAR      pkcolumn_name NOT NULL
     156             :            VARCHAR      fktable_cat
     157             :            VARCHAR      fktable_schem
     158             :            VARCHAR      fktable_name NOT NULL
     159             :            VARCHAR      fkcolumn_name NOT NULL
     160             :            SMALLINT     key_seq NOT NULL
     161             :            SMALLINT     update_rule
     162             :            SMALLINT     delete_rule
     163             :            VARCHAR      fk_name
     164             :            VARCHAR      pk_name
     165             :            SMALLINT     deferrability
     166             :          */
     167             : 
     168           0 :         pos += snprintf(query + pos, querylen - pos,
     169             :                 "select '%s' as pktable_cat, "
     170             :                        "pks.name as pktable_schem, "
     171             :                        "pkt.name as pktable_name, "
     172             :                        "pkkc.name as pkcolumn_name, "
     173             :                        "'%s' as fktable_cat, "
     174             :                        "fks.name as fktable_schem, "
     175             :                        "fkt.name as fktable_name, "
     176             :                        "fkkc.name as fkcolumn_name, "
     177             :                        "cast(fkkc.nr + 1 as smallint) as key_seq, "
     178             :                        "cast(%d as smallint) as update_rule, "
     179             :                        "cast(%d as smallint) as delete_rule, "
     180             :                        "fkk.name as fk_name, "
     181             :                        "pkk.name as pk_name, "
     182             :                        "cast(%d as smallint) as deferrability "
     183             :                 "from sys.schemas fks, sys.tables fkt, "
     184             :                      "sys.objects fkkc, sys.keys as fkk, "
     185             :                      "sys.schemas pks, sys.tables pkt, "
     186             :                      "sys.objects pkkc, sys.keys as pkk "
     187             :                 "where fkt.id = fkk.table_id and "
     188             :                       "pkt.id = pkk.table_id and "
     189             :                       "fkk.id = fkkc.id and "
     190             :                       "pkk.id = pkkc.id and "
     191             :                       "fks.id = fkt.schema_id and "
     192             :                       "pks.id = pkt.schema_id and "
     193             :                       "fkk.rkey = pkk.id and "
     194             :                       "fkkc.nr = pkkc.nr",
     195             :                 stmt->Dbc->dbname,
     196             :                 stmt->Dbc->dbname,
     197             :                 SQL_NO_ACTION, SQL_NO_ACTION, SQL_NOT_DEFERRABLE);
     198           0 :         assert(pos < 1100);
     199             : 
     200             :         /* Construct the selection condition query part */
     201           0 :         if (NameLength1 > 0 && PKCatalogName != NULL) {
     202             :                 /* filtering requested on catalog name */
     203           0 :                 if (strcmp((char *) PKCatalogName, stmt->Dbc->dbname) != 0) {
     204             :                         /* catalog name does not match the database name, so return no rows */
     205           0 :                         pos += snprintf(query + pos, querylen - pos, " and 1=2");
     206             :                 }
     207             :         }
     208           0 :         if (psch) {
     209             :                 /* filtering requested on schema name */
     210           0 :                 pos += snprintf(query + pos, querylen - pos, " and %s", psch);
     211           0 :                 free(psch);
     212             :         }
     213           0 :         if (ptab) {
     214             :                 /* filtering requested on table name */
     215           0 :                 pos += snprintf(query + pos, querylen - pos, " and %s", ptab);
     216           0 :                 free(ptab);
     217             :         }
     218           0 :         if (NameLength4 > 0 && FKCatalogName != NULL) {
     219             :                 /* filtering requested on catalog name */
     220           0 :                 if (strcmp((char *) FKCatalogName, stmt->Dbc->dbname) != 0) {
     221             :                         /* catalog name does not match the database name, so return no rows */
     222           0 :                         pos += snprintf(query + pos, querylen - pos, " and 1=2");
     223             :                 }
     224             :         }
     225           0 :         if (fsch) {
     226             :                 /* filtering requested on schema name */
     227           0 :                 pos += snprintf(query + pos, querylen - pos, " and %s", fsch);
     228           0 :                 free(fsch);
     229             :         }
     230           0 :         if (ftab) {
     231             :                 /* filtering requested on table name */
     232           0 :                 pos += snprintf(query + pos, querylen - pos, " and %s", ftab);
     233           0 :                 free(ftab);
     234             :         }
     235             : 
     236             : /* TODO finish the FROM and WHERE clauses */
     237             : 
     238             :         /* add the ordering */
     239             :         /* if PKTableName != NULL, selection on primary key, order
     240             :            on FK output columns, else order on PK output columns */
     241           0 :         pos += snprintf(query + pos, querylen - pos,
     242             :                         " order by %stable_schem, %stable_name, key_seq",
     243             :                         PKTableName != NULL ? "fk" : "pk",
     244             :                         PKTableName != NULL ? "fk" : "pk");
     245             : 
     246             :         /* query the MonetDB data dictionary tables */
     247           0 :         rc = MNDBExecDirect(stmt, (SQLCHAR *) query, (SQLINTEGER) pos);
     248             : 
     249           0 :         free(query);
     250             : 
     251           0 :         return rc;
     252             : 
     253           0 :   nomem:
     254           0 :         if (psch)
     255           0 :                 free(psch);
     256           0 :         if (ptab)
     257           0 :                 free(ptab);
     258           0 :         if (fsch)
     259           0 :                 free(fsch);
     260           0 :         if (ftab)
     261           0 :                 free(ftab);
     262             :         if (query)
     263             :                 free(query);
     264             :         /* Memory allocation error */
     265           0 :         addStmtError(stmt, "HY001", NULL, 0);
     266           0 :         return SQL_ERROR;
     267             : }
     268             : 
     269             : SQLRETURN SQL_API
     270             : SQLForeignKeys(SQLHSTMT StatementHandle,
     271             :                SQLCHAR *PKCatalogName,
     272             :                SQLSMALLINT NameLength1,
     273             :                SQLCHAR *PKSchemaName,
     274             :                SQLSMALLINT NameLength2,
     275             :                SQLCHAR *PKTableName,
     276             :                SQLSMALLINT NameLength3,
     277             :                SQLCHAR *FKCatalogName,
     278             :                SQLSMALLINT NameLength4,
     279             :                SQLCHAR *FKSchemaName,
     280             :                SQLSMALLINT NameLength5,
     281             :                SQLCHAR *FKTableName,
     282             :                SQLSMALLINT NameLength6)
     283             : {
     284             :         ODBCStmt *stmt = (ODBCStmt *) StatementHandle;
     285             : 
     286             : #ifdef ODBCDEBUG
     287           0 :         ODBCLOG("SQLForeignKeys %p ", StatementHandle);
     288             : #endif
     289             : 
     290           0 :         if (!isValidStmt(stmt))
     291             :                  return SQL_INVALID_HANDLE;
     292             : 
     293           0 :         clearStmtErrors(stmt);
     294             : 
     295           0 :         return MNDBForeignKeys(stmt, PKCatalogName, NameLength1,
     296             :                                PKSchemaName, NameLength2,
     297             :                                PKTableName, NameLength3,
     298             :                                FKCatalogName, NameLength4,
     299             :                                FKSchemaName, NameLength5,
     300             :                                FKTableName, NameLength6);
     301             : }
     302             : 
     303             : SQLRETURN SQL_API
     304             : SQLForeignKeysA(SQLHSTMT StatementHandle,
     305             :                 SQLCHAR *PKCatalogName,
     306             :                 SQLSMALLINT NameLength1,
     307             :                 SQLCHAR *PKSchemaName,
     308             :                 SQLSMALLINT NameLength2,
     309             :                 SQLCHAR *PKTableName,
     310             :                 SQLSMALLINT NameLength3,
     311             :                 SQLCHAR *FKCatalogName,
     312             :                 SQLSMALLINT NameLength4,
     313             :                 SQLCHAR *FKSchemaName,
     314             :                 SQLSMALLINT NameLength5,
     315             :                 SQLCHAR *FKTableName,
     316             :                 SQLSMALLINT NameLength6)
     317             : {
     318           0 :         return SQLForeignKeys(StatementHandle, PKCatalogName, NameLength1,
     319             :                               PKSchemaName, NameLength2,
     320             :                               PKTableName, NameLength3,
     321             :                               FKCatalogName, NameLength4,
     322             :                               FKSchemaName, NameLength5,
     323             :                               FKTableName, NameLength6);
     324             : }
     325             : 
     326             : SQLRETURN SQL_API
     327             : SQLForeignKeysW(SQLHSTMT StatementHandle,
     328             :                 SQLWCHAR *PKCatalogName,
     329             :                 SQLSMALLINT NameLength1,
     330             :                 SQLWCHAR *PKSchemaName,
     331             :                 SQLSMALLINT NameLength2,
     332             :                 SQLWCHAR *PKTableName,
     333             :                 SQLSMALLINT NameLength3,
     334             :                 SQLWCHAR *FKCatalogName,
     335             :                 SQLSMALLINT NameLength4,
     336             :                 SQLWCHAR *FKSchemaName,
     337             :                 SQLSMALLINT NameLength5,
     338             :                 SQLWCHAR *FKTableName,
     339             :                 SQLSMALLINT NameLength6)
     340             : {
     341             :         ODBCStmt *stmt = (ODBCStmt *) StatementHandle;
     342             :         SQLCHAR *PKcatalog = NULL, *PKschema = NULL, *PKtable = NULL;
     343             :         SQLCHAR *FKcatalog = NULL, *FKschema = NULL, *FKtable = NULL;
     344             :         SQLRETURN rc = SQL_ERROR;
     345             : 
     346             : #ifdef ODBCDEBUG
     347           0 :         ODBCLOG("SQLForeignKeysW %p ", StatementHandle);
     348             : #endif
     349             : 
     350           0 :         if (!isValidStmt(stmt))
     351             :                  return SQL_INVALID_HANDLE;
     352             : 
     353           0 :         clearStmtErrors(stmt);
     354             : 
     355           0 :         fixWcharIn(PKCatalogName, NameLength1, SQLCHAR,
     356             :                    PKcatalog, addStmtError, stmt, goto bailout);
     357           0 :         fixWcharIn(PKSchemaName, NameLength2, SQLCHAR,
     358             :                    PKschema, addStmtError, stmt, goto bailout);
     359           0 :         fixWcharIn(PKTableName, NameLength3, SQLCHAR,
     360             :                    PKtable, addStmtError, stmt, goto bailout);
     361           0 :         fixWcharIn(FKCatalogName, NameLength4, SQLCHAR,
     362             :                    FKcatalog, addStmtError, stmt, goto bailout);
     363           0 :         fixWcharIn(FKSchemaName, NameLength5, SQLCHAR,
     364             :                    FKschema, addStmtError, stmt, goto bailout);
     365           0 :         fixWcharIn(FKTableName, NameLength6, SQLCHAR,
     366             :                    FKtable, addStmtError, stmt, goto bailout);
     367             : 
     368           0 :         rc = MNDBForeignKeys(stmt, PKcatalog, SQL_NTS, PKschema, SQL_NTS,
     369             :                              PKtable, SQL_NTS, FKcatalog, SQL_NTS,
     370             :                              FKschema, SQL_NTS, FKtable, SQL_NTS);
     371             : 
     372           0 :       bailout:
     373           0 :         if (PKcatalog)
     374           0 :                 free(PKcatalog);
     375           0 :         if (PKschema)
     376           0 :                 free(PKschema);
     377           0 :         if (PKtable)
     378           0 :                 free(PKtable);
     379           0 :         if (FKcatalog)
     380           0 :                 free(FKcatalog);
     381           0 :         if (FKschema)
     382           0 :                 free(FKschema);
     383           0 :         if (FKtable)
     384           0 :                 free(FKtable);
     385             : 
     386             :         return rc;
     387             : }

Generated by: LCOV version 1.14