LCOV - code coverage report
Current view: top level - clients/odbc/driver - SQLPrepare.c (source / functions) Hit Total Coverage
Test: coverage.info Lines: 120 162 74.1 %
Date: 2021-10-13 02:24:04 Functions: 2 2 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             :  * SQLPrepare
      21             :  * CLI Compliance: ISO 92
      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             : 
      33             : void
      34           9 : ODBCResetStmt(ODBCStmt *stmt)
      35             : {
      36           9 :         MNDBFreeStmt(stmt, SQL_CLOSE);
      37           9 :         setODBCDescRecCount(stmt->ImplParamDescr, 0);
      38             : 
      39           9 :         if (stmt->queryid >= 0)
      40           2 :                 mapi_release_id(stmt->Dbc->mid, stmt->queryid);
      41           9 :         stmt->queryid = -1;
      42           9 :         stmt->nparams = 0;
      43           9 :         stmt->State = INITED;
      44           9 : }
      45             : 
      46             : SQLRETURN
      47           3 : MNDBPrepare(ODBCStmt *stmt,
      48             :             const SQLCHAR *StatementText,
      49             :             SQLINTEGER TextLength)
      50             : {
      51             :         char *query, *s;
      52             :         MapiMsg ret;
      53             :         MapiHdl hdl;
      54             :         int nrows;
      55             :         int ncols;
      56             :         ODBCDescRec *prec, *rrec; /* param and row descriptors */
      57             :         ODBCDescRec *rec;
      58             :         int i;
      59             : 
      60           3 :         hdl = stmt->hdl;
      61             : 
      62           3 :         if (stmt->State >= EXECUTED1 ||
      63           0 :             (stmt->State == EXECUTED0 && mapi_more_results(hdl))) {
      64             :                 /* Invalid cursor state */
      65           0 :                 addStmtError(stmt, "24000", NULL, 0);
      66           0 :                 return SQL_ERROR;
      67             :         }
      68             : 
      69             :         /* check input parameter */
      70           3 :         if (StatementText == NULL) {
      71             :                 /* Invalid use of null pointer */
      72           0 :                 addStmtError(stmt, "HY009", NULL, 0);
      73           0 :                 return SQL_ERROR;
      74             :         }
      75             : 
      76           3 :         fixODBCstring(StatementText, TextLength, SQLINTEGER, addStmtError, stmt, return SQL_ERROR);
      77           3 :         query = ODBCTranslateSQL(stmt->Dbc, StatementText, (size_t) TextLength,
      78             :                                  stmt->noScan);
      79           3 :         if (query == NULL) {
      80             :                 /* Memory allocation error */
      81           0 :                 addStmtError(stmt, "HY001", NULL, 0);
      82           0 :                 return SQL_ERROR;
      83             :         }
      84             : #ifdef ODBCDEBUG
      85           3 :         ODBCLOG("SQLPrepare: \"%s\"\n", query);
      86             : #endif
      87           3 :         size_t querylen = strlen(query) + 9;
      88           3 :         s = malloc(querylen);
      89           3 :         if (s == NULL) {
      90           0 :                 free(query);
      91             :                 /* Memory allocation error */
      92           0 :                 addStmtError(stmt, "HY001", NULL, 0);
      93           0 :                 return SQL_ERROR;
      94             :         }
      95           3 :         strconcat_len(s, querylen, "prepare ", query, NULL);
      96           3 :         free(query);
      97             : 
      98           3 :         ODBCResetStmt(stmt);
      99             : 
     100           3 :         ret = mapi_query_handle(hdl, s);
     101           3 :         free(s);
     102             :         s = NULL;
     103           3 :         if (ret != MOK) {
     104             :                 const char *e, *m;
     105             : 
     106             :                 /* XXX more fine-grained control required */
     107             :                 /* Syntax error or access violation */
     108           0 :                 if ((m = mapi_result_error(hdl)) == NULL)
     109           0 :                         m = mapi_error_str(stmt->Dbc->mid);
     110           0 :                 if (m && (e = mapi_result_errorcode(hdl)) != NULL)
     111           0 :                         addStmtError(stmt, e, m, 0);
     112             :                 else
     113           0 :                         addStmtError(stmt, "42000", m, 0);
     114           0 :                 return SQL_ERROR;
     115             :         }
     116           3 :         if (mapi_rows_affected(hdl) > ((int64_t) 1 << 16)) {
     117             :                 /* arbitrarily limit the number of parameters */
     118             :                 /* Memory allocation error */
     119           0 :                 addStmtError(stmt, "HY001", 0, 0);
     120           0 :                 return SQL_ERROR;
     121             :         }
     122           3 :         nrows = (int) mapi_rows_affected(hdl);
     123           3 :         ncols = mapi_get_field_count(hdl);
     124             :         /* these two will be adjusted later */
     125           3 :         setODBCDescRecCount(stmt->ImplParamDescr, nrows);
     126           3 :         setODBCDescRecCount(stmt->ImplRowDescr, nrows);
     127           3 :         prec = stmt->ImplParamDescr->descRec + 1;
     128           3 :         rrec = stmt->ImplRowDescr->descRec + 1;
     129           3 :         stmt->nparams = 0;
     130          18 :         for (i = 0; i < nrows; i++) {
     131             :                 struct sql_types *tp;
     132             :                 int concise_type;
     133             :                 int length, scale;
     134             : 
     135          15 :                 if (mapi_fetch_row(hdl) == 0) {
     136             :                         /* Memory allocation error (or maybe something else) */
     137           0 :                         addStmtError(stmt, "HY001", 0, 0);
     138           0 :                         return SQL_ERROR;
     139             :                 }
     140          30 :                 if (ncols == 3 ||
     141          15 :                     (s = mapi_fetch_field(hdl, 5)) == NULL) {
     142             :                         /* either old prepare (i.e. old server) or no
     143             :                          * column name: either way, this describes a
     144             :                          * parameter */
     145           5 :                         stmt->nparams++;
     146           5 :                         rec = prec++;
     147           5 :                         rec->sql_desc_nullable = SQL_NULLABLE;
     148           5 :                         rec->sql_desc_searchable = SQL_UNSEARCHABLE;
     149           5 :                         rec->sql_desc_unnamed = SQL_UNNAMED;
     150           5 :                         rec->sql_desc_label = NULL;
     151           5 :                         rec->sql_desc_name = NULL;
     152           5 :                         rec->sql_desc_schema_name = NULL;
     153           5 :                         rec->sql_desc_table_name = NULL;
     154           5 :                         rec->sql_desc_base_table_name = NULL;
     155           5 :                         rec->sql_desc_base_column_name = NULL;
     156           5 :                         rec->sql_desc_parameter_type = SQL_PARAM_INPUT;
     157             :                 } else {
     158          10 :                         rec = rrec++;
     159          10 :                         rec->sql_desc_nullable = SQL_NULLABLE_UNKNOWN;
     160          10 :                         rec->sql_desc_searchable = SQL_PRED_SEARCHABLE;
     161          10 :                         rec->sql_desc_unnamed = SQL_NAMED;
     162          10 :                         rec->sql_desc_label = (SQLCHAR *) strdup(s);
     163          10 :                         rec->sql_desc_name = (SQLCHAR *) strdup(s);
     164          10 :                         s = mapi_fetch_field(hdl, 3); /* schema name */
     165          10 :                         rec->sql_desc_schema_name = s && *s ? (SQLCHAR *) strdup(s) : NULL;
     166          10 :                         s = mapi_fetch_field(hdl, 4); /* table name */
     167          10 :                         rec->sql_desc_table_name = s && *s ? (SQLCHAR *) strdup(s) : NULL;
     168          10 :                         if (rec->sql_desc_schema_name) {
     169             :                                 /* base table name and base column
     170             :                                  * name exist if there is a schema
     171             :                                  * name; the extra check is for static
     172             :                                  * code analyzers and robustness */
     173           0 :                                 rec->sql_desc_base_table_name = rec->sql_desc_table_name ? (SQLCHAR *) strdup((char *) rec->sql_desc_table_name) : NULL;
     174           0 :                                 rec->sql_desc_base_column_name = (SQLCHAR *) strdup((char *) rec->sql_desc_name);
     175             :                         } else {
     176          10 :                                 rec->sql_desc_base_table_name = NULL;
     177          10 :                                 rec->sql_desc_base_column_name = NULL;
     178             :                         }
     179          10 :                         rec->sql_desc_parameter_type = 0;
     180             :                 }
     181             : 
     182          15 :                 s = mapi_fetch_field(hdl, 0); /* type */
     183          15 :                 if (!stmt->Dbc->allow_hugeint && strcmp(s, "hugeint") == 0)
     184             :                         s = "bigint";
     185          15 :                 rec->sql_desc_type_name = (SQLCHAR *) strdup(s);
     186          15 :                 concise_type = ODBCConciseType(s);
     187             : 
     188          15 :                 s = mapi_fetch_field(hdl, 1); /* digits */
     189             :                 length = atoi(s);
     190             : 
     191          15 :                 s = mapi_fetch_field(hdl, 2); /* scale */
     192             :                 scale = atoi(s);
     193             : 
     194             :                 /* for interval types, length and scale are used
     195             :                  * differently */
     196          15 :                 if (concise_type == SQL_INTERVAL_MONTH) {
     197           0 :                         switch (length) {
     198             :                         case 1:
     199             :                                 concise_type = SQL_INTERVAL_YEAR;
     200             :                                 break;
     201             :                         case 2:
     202             :                                 concise_type = SQL_INTERVAL_YEAR_TO_MONTH;
     203             :                                 break;
     204             :                         case 3:
     205             :                                 concise_type = SQL_INTERVAL_MONTH;
     206             :                                 break;
     207             :                         default:
     208           0 :                                 assert(0);
     209             :                         }
     210           0 :                         rec->sql_desc_scale = 0;
     211           0 :                         rec->sql_desc_length = 0;
     212          15 :                 } else if (concise_type == SQL_INTERVAL_SECOND) {
     213           0 :                         switch (length) {
     214             :                         case 4:
     215             :                                 concise_type = SQL_INTERVAL_DAY;
     216             :                                 break;
     217             :                         case 5:
     218             :                                 concise_type = SQL_INTERVAL_DAY_TO_HOUR;
     219             :                                 break;
     220             :                         case 6:
     221             :                                 concise_type = SQL_INTERVAL_DAY_TO_MINUTE;
     222             :                                 break;
     223             :                         case 7:
     224             :                                 concise_type = SQL_INTERVAL_DAY_TO_SECOND;
     225             :                                 break;
     226             :                         case 8:
     227             :                                 concise_type = SQL_INTERVAL_HOUR;
     228             :                                 break;
     229             :                         case 9:
     230             :                                 concise_type = SQL_INTERVAL_HOUR_TO_MINUTE;
     231             :                                 break;
     232             :                         case 10:
     233             :                                 concise_type = SQL_INTERVAL_HOUR_TO_SECOND;
     234             :                                 break;
     235             :                         case 11:
     236             :                                 concise_type = SQL_INTERVAL_MINUTE;
     237             :                                 break;
     238             :                         case 12:
     239             :                                 concise_type = SQL_INTERVAL_MINUTE_TO_SECOND;
     240             :                                 break;
     241             :                         case 13:
     242             :                                 concise_type = SQL_INTERVAL_SECOND;
     243             :                                 break;
     244             :                         default:
     245           0 :                                 assert(0);
     246             :                         }
     247           0 :                         rec->sql_desc_scale = 0;
     248           0 :                         rec->sql_desc_length = 0;
     249             :                 } else {
     250          15 :                         rec->sql_desc_scale = scale;
     251          15 :                         rec->sql_desc_length = length;
     252             :                 }
     253             : 
     254         237 :                 for (tp = ODBC_sql_types; tp->concise_type; tp++)
     255         237 :                         if (concise_type == tp->concise_type)
     256             :                                 break;
     257          15 :                 rec->sql_desc_concise_type = tp->concise_type;
     258          15 :                 rec->sql_desc_type = tp->type;
     259          15 :                 rec->sql_desc_datetime_interval_code = tp->code;
     260          15 :                 if (tp->precision != UNAFFECTED)
     261           9 :                         rec->sql_desc_precision = tp->precision;
     262          15 :                 if (tp->datetime_interval_precision != UNAFFECTED)
     263           0 :                         rec->sql_desc_datetime_interval_precision = tp->datetime_interval_precision;
     264          15 :                 rec->sql_desc_fixed_prec_scale = tp->fixed;
     265          15 :                 rec->sql_desc_num_prec_radix = tp->radix;
     266          15 :                 rec->sql_desc_unsigned = tp->radix == 0 ? SQL_TRUE : SQL_FALSE;
     267             : 
     268          15 :                 if (rec->sql_desc_concise_type == SQL_CHAR ||
     269          15 :                     rec->sql_desc_concise_type == SQL_VARCHAR ||
     270          15 :                     rec->sql_desc_concise_type == SQL_LONGVARCHAR ||
     271          15 :                     rec->sql_desc_concise_type == SQL_WCHAR ||
     272          12 :                     rec->sql_desc_concise_type == SQL_WVARCHAR ||
     273             :                     rec->sql_desc_concise_type == SQL_WLONGVARCHAR)
     274           3 :                         rec->sql_desc_case_sensitive = SQL_TRUE;
     275             :                 else
     276          12 :                         rec->sql_desc_case_sensitive = SQL_FALSE;
     277             : 
     278          15 :                 rec->sql_desc_local_type_name = NULL;
     279          15 :                 rec->sql_desc_rowver = SQL_FALSE;
     280          15 :                 rec->sql_desc_catalog_name = stmt->Dbc->dbname ? (SQLCHAR *) strdup(stmt->Dbc->dbname) : NULL;
     281             : 
     282             :                 /* unused fields */
     283          15 :                 rec->sql_desc_auto_unique_value = SQL_FALSE;
     284          15 :                 rec->sql_desc_data_ptr = NULL;
     285          15 :                 rec->sql_desc_display_size = 0;
     286          15 :                 rec->sql_desc_indicator_ptr = NULL;
     287          15 :                 rec->sql_desc_literal_prefix = NULL;
     288          15 :                 rec->sql_desc_literal_suffix = NULL;
     289          15 :                 rec->sql_desc_octet_length_ptr = NULL;
     290          15 :                 rec->sql_desc_schema_name = NULL;
     291          15 :                 rec->sql_desc_updatable = SQL_ATTR_READONLY;
     292             : 
     293             :                 /* this must come after other fields have been
     294             :                  * initialized */
     295          15 :                 rec->sql_desc_length = ODBCLength(rec, SQL_DESC_LENGTH);
     296          15 :                 rec->sql_desc_display_size = ODBCLength(rec, SQL_DESC_DISPLAY_SIZE);
     297          15 :                 rec->sql_desc_octet_length = ODBCLength(rec, SQL_DESC_OCTET_LENGTH);
     298          15 :                 if (rec->sql_desc_length == 0) {
     299           0 :                         rec->sql_desc_length = SQL_NO_TOTAL;
     300           0 :                         rec->sql_desc_display_size = SQL_NO_TOTAL;
     301           0 :                         rec->sql_desc_octet_length = SQL_NO_TOTAL;
     302             :                 }
     303             :         }
     304             : 
     305           3 :         assert(prec - stmt->ImplParamDescr->descRec == stmt->nparams + 1);
     306           3 :         assert(rrec - stmt->ImplRowDescr->descRec == nrows - stmt->nparams + 1);
     307           3 :         setODBCDescRecCount(stmt->ImplParamDescr, stmt->nparams);
     308           3 :         setODBCDescRecCount(stmt->ImplRowDescr, nrows - stmt->nparams);
     309             : 
     310             :         /* update the internal state */
     311           3 :         stmt->queryid = mapi_get_tableid(hdl);
     312           3 :         if (stmt->ImplRowDescr->sql_desc_count == 0)
     313           1 :                 stmt->State = PREPARED0; /* no columns: no result set */
     314             :         else
     315           2 :                 stmt->State = PREPARED1;
     316             : 
     317             :         return SQL_SUCCESS;
     318             : }
     319             : 
     320             : SQLRETURN SQL_API
     321             : SQLPrepare(SQLHSTMT StatementHandle,
     322             :            SQLCHAR *StatementText,
     323             :            SQLINTEGER TextLength)
     324             : {
     325             : #ifdef ODBCDEBUG
     326           3 :         ODBCLOG("SQLPrepare %p\n", StatementHandle);
     327             : #endif
     328             : 
     329           3 :         if (!isValidStmt((ODBCStmt *) StatementHandle))
     330             :                 return SQL_INVALID_HANDLE;
     331             : 
     332           3 :         clearStmtErrors((ODBCStmt *) StatementHandle);
     333             : 
     334           3 :         return MNDBPrepare((ODBCStmt *) StatementHandle,
     335             :                            StatementText,
     336             :                            TextLength);
     337             : }
     338             : 
     339             : SQLRETURN SQL_API
     340             : SQLPrepareA(SQLHSTMT StatementHandle,
     341             :             SQLCHAR *StatementText,
     342             :             SQLINTEGER TextLength)
     343             : {
     344           0 :         return SQLPrepare(StatementHandle, StatementText, TextLength);
     345             : }
     346             : 
     347             : SQLRETURN SQL_API
     348             : SQLPrepareW(SQLHSTMT StatementHandle,
     349             :             SQLWCHAR *StatementText,
     350             :             SQLINTEGER TextLength)
     351             : {
     352             :         ODBCStmt *stmt = (ODBCStmt *) StatementHandle;
     353             :         SQLCHAR *sql;
     354             :         SQLRETURN rc;
     355             : 
     356             : #ifdef ODBCDEBUG
     357           0 :         ODBCLOG("SQLPrepareW %p\n", StatementHandle);
     358             : #endif
     359             : 
     360           0 :         if (!isValidStmt(stmt))
     361             :                  return SQL_INVALID_HANDLE;
     362             : 
     363           0 :         clearStmtErrors(stmt);
     364             : 
     365           0 :         fixWcharIn(StatementText, TextLength, SQLCHAR, sql,
     366             :                    addStmtError, stmt, return SQL_ERROR);
     367             : 
     368           0 :         rc = MNDBPrepare(stmt, sql, SQL_NTS);
     369             : 
     370           0 :         if (sql)
     371           0 :                 free(sql);
     372             : 
     373             :         return rc;
     374             : }

Generated by: LCOV version 1.14