LCOV - code coverage report
Current view: top level - clients/odbc/driver - SQLProcedures.c (source / functions) Hit Total Coverage
Test: coverage.info Lines: 41 79 51.9 %
Date: 2024-10-04 20:04:04 Functions: 1 1 100.0 %

          Line data    Source code
       1             : /*
       2             :  * SPDX-License-Identifier: MPL-2.0
       3             :  *
       4             :  * This Source Code Form is subject to the terms of the Mozilla Public
       5             :  * License, v. 2.0.  If a copy of the MPL was not distributed with this
       6             :  * file, You can obtain one at http://mozilla.org/MPL/2.0/.
       7             :  *
       8             :  * Copyright 2024 MonetDB Foundation;
       9             :  * Copyright August 2008 - 2023 MonetDB B.V.;
      10             :  * Copyright 1997 - July 2008 CWI.
      11             :  */
      12             : 
      13             : /*
      14             :  * This code was created by Peter Harvey (mostly during Christmas 98/99).
      15             :  * This code is LGPL. Please ensure that this message remains in future
      16             :  * distributions and uses of this code (that's about all I get out of it).
      17             :  * - Peter Harvey pharvey@codebydesign.com
      18             :  *
      19             :  * This file has been modified for the MonetDB project.  See the file
      20             :  * Copyright in this directory for more information.
      21             :  */
      22             : 
      23             : /**********************************************************************
      24             :  * SQLProcedures()
      25             :  * CLI Compliance: ODBC (Microsoft)
      26             :  *
      27             :  * Author: Martin van Dinther, Sjoerd Mullender
      28             :  * Date  : 30 aug 2002
      29             :  *
      30             :  **********************************************************************/
      31             : 
      32             : #include "ODBCGlobal.h"
      33             : #include "ODBCStmt.h"
      34             : #include "ODBCUtil.h"
      35             : 
      36             : 
      37             : static SQLRETURN
      38           4 : MNDBProcedures(ODBCStmt *stmt,
      39             :                const SQLCHAR *CatalogName,
      40             :                SQLSMALLINT NameLength1,
      41             :                const SQLCHAR *SchemaName,
      42             :                SQLSMALLINT NameLength2,
      43             :                const SQLCHAR *ProcName,
      44             :                SQLSMALLINT NameLength3)
      45             : {
      46           4 :         RETCODE rc;
      47             : 
      48             :         /* buffer for the constructed query to do meta data retrieval */
      49           4 :         char *query = NULL;
      50           4 :         size_t querylen;
      51           4 :         size_t pos = 0;
      52           4 :         char *sch = NULL, *pro = NULL;
      53             : 
      54             :         /* convert input string parameters to normal null terminated C strings */
      55           4 :         fixODBCstring(CatalogName, NameLength1, SQLSMALLINT,
      56             :                       addStmtError, stmt, return SQL_ERROR);
      57           4 :         fixODBCstring(SchemaName, NameLength2, SQLSMALLINT,
      58             :                       addStmtError, stmt, return SQL_ERROR);
      59           4 :         fixODBCstring(ProcName, NameLength3, SQLSMALLINT,
      60             :                       addStmtError, stmt, return SQL_ERROR);
      61             : 
      62             : #ifdef ODBCDEBUG
      63           4 :         ODBCLOG("\"%.*s\" \"%.*s\" \"%.*s\"\n",
      64             :                 (int) NameLength1, CatalogName ? (char *) CatalogName : "",
      65             :                 (int) NameLength2, SchemaName ? (char *) SchemaName : "",
      66             :                 (int) NameLength3, ProcName ? (char *) ProcName : "");
      67             : #endif
      68             : 
      69             :         /* SQLProcedures returns a table with the following columns:
      70             :            VARCHAR      PROCEDURE_CAT
      71             :            VARCHAR      PROCEDURE_SCHEM
      72             :            VARCHAR      PROCEDURE_NAME NOT NULL
      73             :            N/A          NUM_INPUT_PARAMS (Reserved for future use)
      74             :            N/A          NUM_OUTPUT_PARAMS (Reserved for future use)
      75             :            N/A          NUM_RESULT_SETS (Reserved for future use)
      76             :            VARCHAR      REMARKS
      77             :            SMALLINT     PROCEDURE_TYPE
      78             :            VARCHAR      SPECIFIC_NAME   (Note this is a MonetDB extension, needed to differentiate between overloaded procedure/function names)
      79             :                                         (similar to JDBC DatabaseMetaData methods getProcedures() and getFunctions())
      80             :          */
      81             : 
      82           4 :         if (stmt->Dbc->sql_attr_metadata_id == SQL_FALSE) {
      83           4 :                 if (NameLength2 > 0) {
      84           4 :                         sch = ODBCParsePV("s", "name",
      85             :                                           (const char *) SchemaName,
      86             :                                           (size_t) NameLength2,
      87             :                                           stmt->Dbc);
      88           4 :                         if (sch == NULL)
      89           0 :                                 goto nomem;
      90             :                 }
      91           4 :                 if (NameLength3 > 0) {
      92           8 :                         pro = ODBCParsePV("p", "name",
      93             :                                           (const char *) ProcName,
      94             :                                           (size_t) NameLength3,
      95           4 :                                           stmt->Dbc);
      96           4 :                         if (pro == NULL)
      97           0 :                                 goto nomem;
      98             :                 }
      99             :         } else {
     100           0 :                 if (NameLength2 > 0) {
     101           0 :                         sch = ODBCParseID("s", "name",
     102             :                                           (const char *) SchemaName,
     103             :                                           (size_t) NameLength2);
     104           0 :                         if (sch == NULL)
     105           0 :                                 goto nomem;
     106             :                 }
     107           0 :                 if (NameLength3 > 0) {
     108           0 :                         pro = ODBCParseID("p", "name",
     109             :                                           (const char *) ProcName,
     110             :                                           (size_t) NameLength3);
     111           0 :                         if (pro == NULL)
     112           0 :                                 goto nomem;
     113             :                 }
     114             :         }
     115             : 
     116           4 :         querylen = 1000 + (sch ? strlen(sch) : 0) + (pro ? strlen(pro) : 0);
     117           4 :         query = malloc(querylen);
     118           4 :         if (query == NULL)
     119           0 :                 goto nomem;
     120             : 
     121             : /* see sql/include/sql_catalog.h */
     122             : #define F_FUNC 1
     123             : #define F_PROC 2
     124             : #define F_UNION 5
     125           4 :         pos += snprintf(query + pos, querylen - pos,
     126             :                 "select cast(null as varchar(1)) as \"PROCEDURE_CAT\", "
     127             :                         "s.name as \"PROCEDURE_SCHEM\", "
     128             :                         "p.name as \"PROCEDURE_NAME\", "
     129             :                         "0 as \"NUM_INPUT_PARAMS\", "
     130             :                         "0 as \"NUM_OUTPUT_PARAMS\", "
     131             :                         "0 as \"NUM_RESULT_SETS\", "
     132             :                         "%s as \"REMARKS\", "
     133             :                         "cast(case when p.type = %d then %d else %d end as smallint) as \"PROCEDURE_TYPE\", "
     134             :                         /* Only the id value uniquely identifies a specific procedure.
     135             :                            Include it to be able to differentiate between multiple
     136             :                            overloaded procedures with the same name and schema */
     137             :                         "cast(p.id as varchar(10)) AS \"SPECIFIC_NAME\" "
     138             :                 "from sys.schemas as s, "
     139             :                      "sys.functions as p%s "
     140             :                 "where p.schema_id = s.id and "
     141             :                       "p.type in (%d, %d, %d)",
     142             :                 stmt->Dbc->has_comment ? "c.remark" : "cast(null as varchar(1))",
     143             :                 F_PROC, SQL_PT_PROCEDURE, SQL_PT_FUNCTION,
     144             :                 /* from clause: */
     145           4 :                 stmt->Dbc->has_comment ? " left outer join sys.comments c on c.id = p.id" : "",
     146             :                 /* where clause: */
     147             :                 F_FUNC, F_PROC, F_UNION);
     148           4 :         assert(pos < 900);
     149             : 
     150             :         /* Construct the selection condition query part */
     151           4 :         if (NameLength1 > 0 && CatalogName != NULL) {
     152             :                 /* filtering requested on catalog name */
     153           0 :                 if (strcmp((char *) CatalogName, msetting_string(stmt->Dbc->settings, MP_DATABASE)) != 0) {
     154             :                         /* catalog name does not match the database name, so return no rows */
     155           0 :                         pos += snprintf(query + pos, querylen - pos, " and 1=2");
     156             :                 }
     157             :         }
     158           4 :         if (sch) {
     159             :                 /* filtering requested on schema name */
     160           4 :                 pos += snprintf(query + pos, querylen - pos, " and %s", sch);
     161           4 :                 free(sch);
     162             :         }
     163           4 :         if (pro) {
     164             :                 /* filtering requested on procedure name */
     165           4 :                 pos += snprintf(query + pos, querylen - pos, " and %s", pro);
     166           4 :                 free(pro);
     167             :         }
     168             : 
     169             :         /* add the ordering (exclude procedure_cat as it is the same for all rows) */
     170           4 :         pos += strcpy_len(query + pos, " order by \"PROCEDURE_SCHEM\", \"PROCEDURE_NAME\", \"SPECIFIC_NAME\"", querylen - pos);
     171           4 :         assert(pos < querylen);
     172             : 
     173             :         /* debug: fprintf(stdout, "SQLProcedures query (pos: %zu, len: %zu):\n%s\n\n", pos, strlen(query), query); */
     174             : 
     175             :         /* query the MonetDB data dictionary tables */
     176           4 :         rc = MNDBExecDirect(stmt, (SQLCHAR *) query, (SQLINTEGER) pos);
     177             : 
     178           4 :         free(query);
     179             : 
     180           4 :         return rc;
     181             : 
     182           0 :   nomem:
     183             :         /* note that query must be NULL when we get here */
     184           0 :         if (sch)
     185           0 :                 free(sch);
     186           0 :         if (pro)
     187           0 :                 free(pro);
     188             :         /* Memory allocation error */
     189           0 :         addStmtError(stmt, "HY001", NULL, 0);
     190           0 :         return SQL_ERROR;
     191             : }
     192             : 
     193             : SQLRETURN SQL_API
     194             : SQLProcedures(SQLHSTMT StatementHandle,
     195             :               SQLCHAR *CatalogName,
     196             :               SQLSMALLINT NameLength1,
     197             :               SQLCHAR *SchemaName,
     198             :               SQLSMALLINT NameLength2,
     199             :               SQLCHAR *ProcName,
     200             :               SQLSMALLINT NameLength3)
     201             : {
     202           4 :         ODBCStmt *stmt = (ODBCStmt *) StatementHandle;
     203             : 
     204             : #ifdef ODBCDEBUG
     205           4 :         ODBCLOG("SQLProcedures %p ", StatementHandle);
     206             : #endif
     207             : 
     208           4 :         if (!isValidStmt(stmt))
     209             :                  return SQL_INVALID_HANDLE;
     210             : 
     211           4 :         clearStmtErrors(stmt);
     212             : 
     213           4 :         return MNDBProcedures(stmt,
     214             :                               CatalogName, NameLength1,
     215             :                               SchemaName, NameLength2,
     216             :                               ProcName, NameLength3);
     217             : }
     218             : 
     219             : SQLRETURN SQL_API
     220             : SQLProceduresA(SQLHSTMT StatementHandle,
     221             :                SQLCHAR *CatalogName,
     222             :                SQLSMALLINT NameLength1,
     223             :                SQLCHAR *SchemaName,
     224             :                SQLSMALLINT NameLength2,
     225             :                SQLCHAR *ProcName,
     226             :                SQLSMALLINT NameLength3)
     227             : {
     228           0 :         return SQLProcedures(StatementHandle,
     229             :                              CatalogName, NameLength1,
     230             :                              SchemaName, NameLength2,
     231             :                              ProcName, NameLength3);
     232             : }
     233             : 
     234             : SQLRETURN SQL_API
     235             : SQLProceduresW(SQLHSTMT StatementHandle,
     236             :                SQLWCHAR *CatalogName, SQLSMALLINT NameLength1,
     237             :                SQLWCHAR *SchemaName, SQLSMALLINT NameLength2,
     238             :                SQLWCHAR *ProcName, SQLSMALLINT NameLength3)
     239             : {
     240           0 :         ODBCStmt *stmt = (ODBCStmt *) StatementHandle;
     241           0 :         SQLRETURN rc = SQL_ERROR;
     242           0 :         SQLCHAR *catalog = NULL, *schema = NULL, *proc = NULL;
     243             : 
     244             : #ifdef ODBCDEBUG
     245           0 :         ODBCLOG("SQLProceduresW %p ", StatementHandle);
     246             : #endif
     247             : 
     248           0 :         if (!isValidStmt(stmt))
     249             :                  return SQL_INVALID_HANDLE;
     250             : 
     251           0 :         clearStmtErrors(stmt);
     252             : 
     253           0 :         fixWcharIn(CatalogName, NameLength1, SQLCHAR, catalog,
     254             :                    addStmtError, stmt, goto bailout);
     255           0 :         fixWcharIn(SchemaName, NameLength2, SQLCHAR, schema,
     256             :                    addStmtError, stmt, goto bailout);
     257           0 :         fixWcharIn(ProcName, NameLength3, SQLCHAR, proc,
     258             :                    addStmtError, stmt, goto bailout);
     259             : 
     260           0 :         rc = MNDBProcedures(stmt,
     261             :                             catalog, SQL_NTS,
     262             :                             schema, SQL_NTS,
     263             :                             proc, SQL_NTS);
     264             : 
     265           0 :       bailout:
     266           0 :         if (catalog)
     267           0 :                 free(catalog);
     268           0 :         if (schema)
     269           0 :                 free(schema);
     270           0 :         if (proc)
     271           0 :                 free(proc);
     272             : 
     273             :         return rc;
     274             : }

Generated by: LCOV version 1.14