LCOV - code coverage report
Current view: top level - clients/odbc/driver - SQLColumns.c (source / functions) Hit Total Coverage
Test: coverage.info Lines: 34 90 37.8 %
Date: 2021-10-13 02:24:04 Functions: 1 1 100.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             :  * SQLColumns()
      21             :  * CLI Compliance: X/Open
      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             : #include "ODBCQueries.h"
      32             : 
      33             : #define NCOLUMNS        18
      34             : 
      35             : static SQLRETURN
      36           1 : MNDBColumns(ODBCStmt *stmt,
      37             :             const SQLCHAR *CatalogName,
      38             :             SQLSMALLINT NameLength1,
      39             :             const SQLCHAR *SchemaName,
      40             :             SQLSMALLINT NameLength2,
      41             :             const SQLCHAR *TableName,
      42             :             SQLSMALLINT NameLength3,
      43             :             const SQLCHAR *ColumnName,
      44             :             SQLSMALLINT NameLength4)
      45             : {
      46             :         RETCODE rc;
      47             : 
      48             :         /* buffer for the constructed query to do meta data retrieval */
      49             :         char *query = NULL;
      50             :         size_t querylen;
      51             :         size_t pos = 0;
      52             :         char *sch = NULL, *tab = NULL, *col = NULL;
      53             : 
      54             :         /* null pointers not allowed if arguments are identifiers */
      55           1 :         if (stmt->Dbc->sql_attr_metadata_id == SQL_TRUE &&
      56           0 :             (SchemaName == NULL || TableName == NULL || ColumnName == NULL)) {
      57           0 :                 addStmtError(stmt, "HY090", NULL, 0);
      58           0 :                 return SQL_ERROR;
      59             :         }
      60             : 
      61           1 :         fixODBCstring(CatalogName, NameLength1, SQLSMALLINT,
      62             :                       addStmtError, stmt, return SQL_ERROR);
      63           1 :         fixODBCstring(SchemaName, NameLength2, SQLSMALLINT,
      64             :                       addStmtError, stmt, return SQL_ERROR);
      65           1 :         fixODBCstring(TableName, NameLength3, SQLSMALLINT,
      66             :                       addStmtError, stmt, return SQL_ERROR);
      67           1 :         fixODBCstring(ColumnName, NameLength4, SQLSMALLINT,
      68             :                       addStmtError, stmt, return SQL_ERROR);
      69             : 
      70             : #ifdef ODBCDEBUG
      71           1 :         ODBCLOG(" \"%.*s\" \"%.*s\" \"%.*s\" \"%.*s\"\n",
      72             :                 (int) NameLength1, CatalogName ? (char *) CatalogName : "",
      73             :                 (int) NameLength2, SchemaName ? (char *) SchemaName : "",
      74             :                 (int) NameLength3, TableName ? (char *) TableName : "",
      75             :                 (int) NameLength4, ColumnName ? (char *) ColumnName : "");
      76             : #endif
      77             : 
      78           1 :         if (stmt->Dbc->sql_attr_metadata_id == SQL_FALSE) {
      79           1 :                 if (NameLength2 > 0) {
      80           0 :                         sch = ODBCParsePV("s", "name",
      81             :                                           (const char *) SchemaName,
      82             :                                           (size_t) NameLength2);
      83           0 :                         if (sch == NULL)
      84           0 :                                 goto nomem;
      85             :                 }
      86           1 :                 if (NameLength3 > 0) {
      87           1 :                         tab = ODBCParsePV("t", "name",
      88             :                                           (const char *) TableName,
      89             :                                           (size_t) NameLength3);
      90           1 :                         if (tab == NULL)
      91           0 :                                 goto nomem;
      92             :                 }
      93           1 :                 if (NameLength4 > 0) {
      94           0 :                         col = ODBCParsePV("c", "name",
      95             :                                           (const char *) ColumnName,
      96             :                                           (size_t) NameLength4);
      97           0 :                         if (col == NULL)
      98           0 :                                 goto nomem;
      99             :                 }
     100             :         } else {
     101           0 :                 if (NameLength2 > 0) {
     102           0 :                         sch = ODBCParseID("s", "name",
     103             :                                           (const char *) SchemaName,
     104             :                                           (size_t) NameLength2);
     105           0 :                         if (sch == NULL)
     106           0 :                                 goto nomem;
     107             :                 }
     108           0 :                 if (NameLength3 > 0) {
     109           0 :                         tab = ODBCParseID("t", "name",
     110             :                                           (const char *) TableName,
     111             :                                           (size_t) NameLength3);
     112           0 :                         if (tab == NULL)
     113           0 :                                 goto nomem;
     114             :                 }
     115           0 :                 if (NameLength4 > 0) {
     116           0 :                         col = ODBCParseID("c", "name",
     117             :                                           (const char *) ColumnName,
     118             :                                           (size_t) NameLength4);
     119           0 :                         if (col == NULL)
     120           0 :                                 goto nomem;
     121             :                 }
     122             :         }
     123             : 
     124             :         /* construct the query now */
     125           1 :         querylen = 6500 + strlen(stmt->Dbc->dbname) + (sch ? strlen(sch) : 0) +
     126           1 :                 (tab ? strlen(tab) : 0) + (col ? strlen(col) : 0);
     127           1 :         query = malloc(querylen);
     128           1 :         if (query == NULL)
     129           0 :                 goto nomem;
     130             : 
     131             :         /* SQLColumns returns a table with the following columns:
     132             :            VARCHAR      table_cat
     133             :            VARCHAR      table_schem
     134             :            VARCHAR      table_name NOT NULL
     135             :            VARCHAR      column_name NOT NULL
     136             :            SMALLINT     data_type NOT NULL
     137             :            VARCHAR      type_name NOT NULL
     138             :            INTEGER      column_size
     139             :            INTEGER      buffer_length
     140             :            SMALLINT     decimal_digits
     141             :            SMALLINT     num_prec_radix
     142             :            SMALLINT     nullable NOT NULL
     143             :            VARCHAR      remarks
     144             :            VARCHAR      column_def
     145             :            SMALLINT     sql_data_type NOT NULL
     146             :            SMALLINT     sql_datetime_sub
     147             :            INTEGER      char_octet_length
     148             :            INTEGER      ordinal_position NOT NULL
     149             :            VARCHAR      is_nullable
     150             :          */
     151             : 
     152           1 :         pos += snprintf(query + pos, querylen - pos,
     153             :                 "select '%s' as table_cat, "
     154             :                        "s.name as table_schem, "
     155             :                        "t.name as table_name, "
     156             :                        "c.name as column_name, "
     157             :                 DATA_TYPE(c) ", "
     158             :                 TYPE_NAME(c) ", "
     159             :                 COLUMN_SIZE(c) ", "
     160             :                 BUFFER_LENGTH(c) ", "
     161             :                 DECIMAL_DIGITS(c) ", "
     162             :                 NUM_PREC_RADIX(c) ", "
     163             :                        "case c.\"null\" "
     164             :                             "when true then cast(%d as smallint) "
     165             :                             "when false then cast(%d as smallint) "
     166             :                        "end as nullable, "
     167             :                        "%s as remarks, "
     168             :                        "c.\"default\" as column_def, "
     169             :                 SQL_DATA_TYPE(c) ", "
     170             :                 SQL_DATETIME_SUB(c) ", "
     171             :                 CHAR_OCTET_LENGTH(c) ", "
     172             :                        "cast(c.number + 1 as integer) as ordinal_position, "
     173             :                        "case c.\"null\" "
     174             :                             "when true then cast('YES' as varchar(3)) "
     175             :                             "when false then cast('NO' as varchar(3)) "
     176             :                        "end as is_nullable "
     177             :                  "from sys.schemas s, "
     178             :                       "sys.tables t, "
     179             :                       "sys.columns c%s "
     180             :                  "where s.id = t.schema_id and "
     181             :                        "t.id = c.table_id",
     182             :                 stmt->Dbc->dbname,
     183             : #ifdef DATA_TYPE_ARGS
     184             :                 DATA_TYPE_ARGS,
     185             : #endif
     186             : #ifdef TYPE_NAME_ARGS
     187             :                 TYPE_NAME_ARGS,
     188             : #endif
     189             : #ifdef COLUMN_SIZE_ARGS
     190             :                 COLUMN_SIZE_ARGS,
     191             : #endif
     192             : #ifdef BUFFER_LENGTH_ARGS
     193             :                 BUFFER_LENGTH_ARGS,
     194             : #endif
     195             : #ifdef DECIMAL_DIGITS_ARGS
     196             :                 DECIMAL_DIGITS_ARGS,
     197             : #endif
     198             : #ifdef NUM_PREC_RADIX_ARGS
     199             :                 NUM_PREC_RADIX_ARGS,
     200             : #endif
     201             :                 /* nullable: */
     202             :                 SQL_NULLABLE, SQL_NO_NULLS,
     203             :                 /* remarks: */
     204             :                 stmt->Dbc->has_comment ? "com.remark" : "cast(null as varchar(1))",
     205             : #ifdef SQL_DATA_TYPE_ARGS
     206             :                 SQL_DATA_TYPE_ARGS,
     207             : #endif
     208             : #ifdef SQL_DATETIME_SUB_ARGS
     209             :                 SQL_DATETIME_SUB_ARGS,
     210             : #endif
     211             : #ifdef CHAR_OCTET_LENGTH_ARGS
     212             :                 CHAR_OCTET_LENGTH_ARGS,
     213             : #endif
     214             :                 /* from clause: */
     215           1 :                 stmt->Dbc->has_comment ? " left outer join sys.comments com on com.id = c.id" : "");
     216           1 :         assert(pos < 6300);
     217             : 
     218             :         /* depending on the input parameter values we must add a
     219             :            variable selection condition dynamically */
     220             : 
     221             :         /* Construct the selection condition query part */
     222           1 :         if (NameLength1 > 0 && CatalogName != NULL) {
     223             :                 /* filtering requested on catalog name */
     224           0 :                 if (strcmp((char *) CatalogName, stmt->Dbc->dbname) != 0) {
     225             :                         /* catalog name does not match the database name, so return no rows */
     226           0 :                         pos += snprintf(query + pos, querylen - pos, " and 1=2");
     227             :                 }
     228             :         }
     229           1 :         if (sch) {
     230             :                 /* filtering requested on schema name */
     231           0 :                 pos += snprintf(query + pos, querylen - pos, " and %s", sch);
     232           0 :                 free(sch);
     233             :         }
     234           1 :         if (tab) {
     235             :                 /* filtering requested on table name */
     236           1 :                 pos += snprintf(query + pos, querylen - pos, " and %s", tab);
     237           1 :                 free(tab);
     238             :         }
     239           1 :         if (col) {
     240             :                 /* filtering requested on column name */
     241           0 :                 pos += snprintf(query + pos, querylen - pos, " and %s", col);
     242           0 :                 free(col);
     243             :         }
     244             : 
     245             :         /* add the ordering (exclude table_cat as it is the same for all rows) */
     246           1 :         pos += strcpy_len(query + pos, " order by table_schem, table_name, ordinal_position", querylen - pos);
     247             : 
     248             :         /* query the MonetDB data dictionary tables */
     249           1 :         rc = MNDBExecDirect(stmt, (SQLCHAR *) query, (SQLINTEGER) pos);
     250             : 
     251           1 :         free(query);
     252             : 
     253           1 :         return rc;
     254             : 
     255           0 :   nomem:
     256             :         /* note that query must be NULL when we get here */
     257           0 :         if (sch)
     258           0 :                 free(sch);
     259           0 :         if (tab)
     260           0 :                 free(tab);
     261           0 :         if (col)
     262           0 :                 free(col);
     263             :         /* Memory allocation error */
     264           0 :         addStmtError(stmt, "HY001", NULL, 0);
     265           0 :         return SQL_ERROR;
     266             : }
     267             : 
     268             : SQLRETURN SQL_API
     269             : SQLColumns(SQLHSTMT StatementHandle,
     270             :            SQLCHAR *CatalogName,
     271             :            SQLSMALLINT NameLength1,
     272             :            SQLCHAR *SchemaName,
     273             :            SQLSMALLINT NameLength2,
     274             :            SQLCHAR *TableName,
     275             :            SQLSMALLINT NameLength3,
     276             :            SQLCHAR *ColumnName,
     277             :            SQLSMALLINT NameLength4)
     278             : {
     279             :         ODBCStmt *stmt = (ODBCStmt *) StatementHandle;
     280             : 
     281             : #ifdef ODBCDEBUG
     282           1 :         ODBCLOG("SQLColumns %p", StatementHandle);
     283             : #endif
     284             : 
     285           1 :         if (!isValidStmt(stmt))
     286             :                  return SQL_INVALID_HANDLE;
     287             : 
     288           1 :         clearStmtErrors(stmt);
     289             : 
     290           1 :         return MNDBColumns(stmt,
     291             :                            CatalogName, NameLength1,
     292             :                            SchemaName, NameLength2,
     293             :                            TableName, NameLength3,
     294             :                            ColumnName, NameLength4);
     295             : }
     296             : 
     297             : SQLRETURN SQL_API
     298             : SQLColumnsA(SQLHSTMT StatementHandle,
     299             :             SQLCHAR *CatalogName,
     300             :             SQLSMALLINT NameLength1,
     301             :             SQLCHAR *SchemaName,
     302             :             SQLSMALLINT NameLength2,
     303             :             SQLCHAR *TableName,
     304             :             SQLSMALLINT NameLength3,
     305             :             SQLCHAR *ColumnName,
     306             :             SQLSMALLINT NameLength4)
     307             : {
     308           0 :         return SQLColumns(StatementHandle,
     309             :                           CatalogName, NameLength1,
     310             :                           SchemaName, NameLength2,
     311             :                           TableName, NameLength3,
     312             :                           ColumnName, NameLength4);
     313             : }
     314             : 
     315             : SQLRETURN SQL_API
     316             : SQLColumnsW(SQLHSTMT StatementHandle,
     317             :             SQLWCHAR *CatalogName,
     318             :             SQLSMALLINT NameLength1,
     319             :             SQLWCHAR *SchemaName,
     320             :             SQLSMALLINT NameLength2,
     321             :             SQLWCHAR *TableName,
     322             :             SQLSMALLINT NameLength3,
     323             :             SQLWCHAR *ColumnName,
     324             :             SQLSMALLINT NameLength4)
     325             : {
     326             :         ODBCStmt *stmt = (ODBCStmt *) StatementHandle;
     327             :         SQLCHAR *catalog = NULL, *schema = NULL, *table = NULL, *column = NULL;
     328             :         SQLRETURN rc = SQL_ERROR;
     329             : 
     330             : #ifdef ODBCDEBUG
     331           0 :         ODBCLOG("SQLColumnsW %p", StatementHandle);
     332             : #endif
     333             : 
     334           0 :         if (!isValidStmt(stmt))
     335             :                  return SQL_INVALID_HANDLE;
     336             : 
     337           0 :         clearStmtErrors(stmt);
     338             : 
     339           0 :         fixWcharIn(CatalogName, NameLength1, SQLCHAR, catalog,
     340             :                    addStmtError, stmt, goto bailout);
     341           0 :         fixWcharIn(SchemaName, NameLength2, SQLCHAR, schema,
     342             :                    addStmtError, stmt, goto bailout);
     343           0 :         fixWcharIn(TableName, NameLength3, SQLCHAR, table,
     344             :                    addStmtError, stmt, goto bailout);
     345           0 :         fixWcharIn(ColumnName, NameLength4, SQLCHAR, column,
     346             :                    addStmtError, stmt, goto bailout);
     347             : 
     348           0 :         rc = MNDBColumns(stmt,
     349             :                          catalog, SQL_NTS,
     350             :                          schema, SQL_NTS,
     351             :                          table, SQL_NTS,
     352             :                          column, SQL_NTS);
     353             : 
     354           0 :       bailout:
     355           0 :         if (catalog)
     356           0 :                 free(catalog);
     357           0 :         if (schema)
     358           0 :                 free(schema);
     359           0 :         if (table)
     360           0 :                 free(table);
     361           0 :         if (column)
     362           0 :                 free(column);
     363             :         return rc;
     364             : }

Generated by: LCOV version 1.14