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

Generated by: LCOV version 1.14