LCOV - code coverage report
Current view: top level - clients/odbc/driver - SQLExecute.c (source / functions) Hit Total Coverage
Test: coverage.info Lines: 197 284 69.4 %
Date: 2024-04-26 00:35:57 Functions: 3 4 75.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 (thats 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             :  * SQLExecute()
      25             :  * CLI Compliance: ISO 92
      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             : #include <limits.h>
      36             : 
      37             : static struct msql_types {
      38             :         char *name;
      39             :         int concise_type;
      40             : } msql_types[] = {
      41             :         {"bigint", SQL_BIGINT},
      42             :         {"blob", SQL_LONGVARBINARY},
      43             :         {"boolean", SQL_BIT},
      44             :         {"char", SQL_WCHAR},
      45             :         {"clob", SQL_WLONGVARCHAR},
      46             :         {"date", SQL_TYPE_DATE},
      47             :         {"day_interval", SQL_INTERVAL_SECOND},
      48             :         {"decimal", SQL_DECIMAL},
      49             :         {"double", SQL_DOUBLE},
      50             :         {"hugeint", SQL_HUGEINT},
      51             :         /* {"inet", SQL_WCHAR}, */
      52             :         {"int", SQL_INTEGER},
      53             :         /* {"json", SQL_WVARCHAR}, */
      54             :         {"month_interval", SQL_INTERVAL_MONTH},
      55             :         {"oid", SQL_BIGINT},
      56             :         {"real", SQL_REAL},
      57             :         {"sec_interval", SQL_INTERVAL_SECOND},
      58             :         {"smallint", SQL_SMALLINT},
      59             :         {"table", 0},
      60             :         {"time", SQL_TYPE_TIME},
      61             :         {"timetz", SQL_TYPE_TIME},
      62             :         {"timestamp", SQL_TYPE_TIMESTAMP},
      63             :         {"timestamptz", SQL_TYPE_TIMESTAMP},
      64             :         {"tinyint", SQL_TINYINT},
      65             :         /* {"url", SQL_WVARCHAR}, */
      66             :         {"uuid", SQL_GUID},
      67             :         {"varchar", SQL_WVARCHAR},
      68             :         {0, 0},                 /* sentinel */
      69             : };
      70             : 
      71             : int
      72         944 : ODBCConciseType(const char *name)
      73             : {
      74         944 :         struct msql_types *p;
      75             : 
      76       18432 :         for (p = msql_types; p->name; p++)
      77       18432 :                 if (strcmp(p->name, name) == 0)
      78         944 :                         return p->concise_type;
      79             :         return 0;
      80             : }
      81             : 
      82             : #ifdef ODBCDEBUG
      83             : static char *
      84           0 : translatequerytype(int querytype)
      85             : {
      86           0 :         switch (querytype) {
      87             :         case Q_PARSE:
      88             :                 return "Q_PARSE";
      89           0 :         case Q_TABLE:
      90           0 :                 return "Q_TABLE";
      91           0 :         case Q_UPDATE:
      92           0 :                 return "Q_UPDATE";
      93           0 :         case Q_SCHEMA:
      94           0 :                 return "Q_SCHEMA";
      95           0 :         case Q_TRANS:
      96           0 :                 return "Q_TRANS";
      97           0 :         case Q_PREPARE:
      98           0 :                 return "Q_PREPARE";
      99           0 :         case Q_BLOCK:
     100           0 :                 return "Q_BLOCK";
     101           0 :         default:
     102           0 :                 return "unknown";
     103             :         }
     104             : }
     105             : #endif
     106             : 
     107             : SQLRETURN
     108        2106 : ODBCInitResult(ODBCStmt *stmt)
     109             : {
     110        2106 :         int i = 0;
     111        2106 :         int nrCols;
     112        2106 :         ODBCDescRec *rec;
     113        2106 :         MapiHdl hdl;
     114        2106 :         const char *errstr;
     115             : 
     116        2106 :         hdl = stmt->hdl;
     117             : 
     118             :         /* initialize the Result meta data values */
     119        2106 :         stmt->currentRow = 0;
     120        2106 :         stmt->startRow = 0;
     121        2106 :         stmt->rowSetSize = 0;
     122        2106 :         stmt->retrieved = 0;
     123        2106 :         stmt->currentCol = 0;
     124             : 
     125        2158 :       repeat:
     126        2158 :         errstr = mapi_result_error(hdl);
     127        2158 :         if (errstr) {
     128           0 :                 const char *sqlstate;
     129             : 
     130           0 :                 if ((sqlstate = mapi_result_errorcode(hdl)) != NULL)
     131           0 :                         addStmtError(stmt, sqlstate, errstr, 0);
     132             :                 else {
     133             :                         /* Syntax error or access violation */
     134           0 :                         addStmtError(stmt, "42000", errstr, 0);
     135             :                 }
     136           0 :                 return SQL_ERROR;
     137             :         }
     138        2158 :         nrCols = mapi_get_field_count(hdl);
     139        2158 :         stmt->querytype = mapi_get_querytype(hdl);
     140             : #if SIZEOF_SIZE_T == SIZEOF_INT
     141             :         if (mapi_rows_affected(hdl) >= (int64_t) 1 << (sizeof(int) * CHAR_BIT)) {
     142             :                 /* General error */
     143             :                 addStmtError(stmt, "HY000", "Too many rows to handle", 0);
     144             :                 return SQL_ERROR;
     145             :         }
     146             : #endif
     147        2158 :         stmt->rowcount = (SQLULEN) mapi_rows_affected(hdl);
     148             : 
     149             : #ifdef ODBCDEBUG
     150        2158 :         ODBCLOG("ODBCInitResult: querytype %s, rowcount %lu\n",
     151             :                 translatequerytype(stmt->querytype),
     152             :                 (unsigned long) stmt->rowcount);
     153             : #endif
     154             : 
     155        2158 :         switch (stmt->querytype) {
     156          94 :         case Q_TABLE:   /* Q_TABLE */
     157             :                 /* result set generating query */
     158          94 :                 assert(nrCols > 0);
     159          94 :                 stmt->State = EXECUTED1;
     160          94 :                 break;
     161        2000 :         case Q_UPDATE:          /* Q_UPDATE */
     162             :                 /* result count generating query */
     163        2000 :                 assert(nrCols == 0);
     164        2000 :                 stmt->State = EXECUTED0;
     165        2000 :                 break;
     166          64 :         default:
     167             :                 /* resultless query */
     168          64 :                 if (mapi_result_error(hdl) == NULL && mapi_next_result(hdl) == 1)
     169          52 :                         goto repeat;
     170          12 :                 stmt->State = EXECUTED0;
     171          12 :                 stmt->rowcount = 0;
     172          12 :                 nrCols = 0;
     173          12 :                 break;
     174             :         }
     175             : 
     176             : #if 0
     177             :         /* XXX is this correct? */
     178             :         assert(stmt->ImplRowDescr == NULL ||
     179             :                stmt->ImplRowDescr->sql_desc_count == nrCols ||
     180             :                stmt->ImplRowDescr->sql_desc_count == 0);
     181             : #endif
     182        2106 :         setODBCDescRecCount(stmt->ImplRowDescr, nrCols);
     183             : 
     184        2106 :         if (nrCols == 0)
     185             :                 return SQL_SUCCESS;
     186          94 :         if (stmt->ImplRowDescr->descRec == NULL) {
     187           0 :                 stmt->State = stmt->queryid >= 0 ? (stmt->State == EXECUTED0 ? PREPARED0 : PREPARED1) : INITED;
     188             : 
     189             :                 /* Memory allocation error */
     190           0 :                 addStmtError(stmt, "HY001", NULL, 0);
     191           0 :                 return SQL_ERROR;
     192             :         }
     193             : 
     194          94 :         rec = stmt->ImplRowDescr->descRec + 1;
     195             : 
     196        1011 :         for (i = 0; i < nrCols; i++) {
     197         917 :                 struct sql_types *tp;
     198         917 :                 int concise_type;
     199         917 :                 char *s;
     200             : 
     201         917 :                 rec->sql_desc_auto_unique_value = SQL_FALSE;
     202         917 :                 rec->sql_desc_nullable = SQL_NULLABLE_UNKNOWN;
     203         917 :                 rec->sql_desc_rowver = SQL_FALSE;
     204         917 :                 rec->sql_desc_searchable = SQL_PRED_SEARCHABLE;
     205         917 :                 rec->sql_desc_updatable = SQL_ATTR_READONLY;
     206             : 
     207         917 :                 s = mapi_get_name(hdl, i);
     208             :                 /* HACK to compensate for generated column names */
     209         917 :                 if (s == NULL || strcmp(s, "single_value") == 0)
     210           0 :                         s = "";
     211         917 :                 if (*s) {
     212         917 :                         rec->sql_desc_unnamed = SQL_NAMED;
     213         917 :                         if (rec->sql_desc_label)
     214          22 :                                 free(rec->sql_desc_label);
     215         917 :                         rec->sql_desc_label = (SQLCHAR *) strdup(s);
     216         917 :                         if (rec->sql_desc_label == NULL)
     217           0 :                                 goto nomem;
     218         917 :                         if (rec->sql_desc_name)
     219          22 :                                 free(rec->sql_desc_name);
     220         917 :                         rec->sql_desc_name = (SQLCHAR *) strdup(s);
     221         917 :                         if (rec->sql_desc_name == NULL)
     222           0 :                                 goto nomem;
     223             :                 } else {
     224           0 :                         rec->sql_desc_unnamed = SQL_UNNAMED;
     225           0 :                         rec->sql_desc_label = NULL;
     226           0 :                         rec->sql_desc_name = NULL;
     227             :                 }
     228         917 :                 if (rec->sql_desc_base_column_name)
     229           2 :                         free(rec->sql_desc_base_column_name);
     230         917 :                 rec->sql_desc_base_column_name = NULL; /* see below */
     231             : 
     232         917 :                 s = mapi_get_type(hdl, i);
     233         917 :                 if (s == NULL)  /* shouldn't happen */
     234           0 :                         s = "";
     235         917 :                 if (!stmt->Dbc->allow_hugeint && strcmp(s, "hugeint") == 0)
     236         917 :                         s = "bigint";
     237         917 :                 if (rec->sql_desc_type_name)
     238          22 :                         free(rec->sql_desc_type_name);
     239         917 :                 rec->sql_desc_type_name = (SQLCHAR *) strdup(s);
     240         917 :                 if (rec->sql_desc_type_name == NULL)
     241           0 :                         goto nomem;
     242         917 :                 concise_type = ODBCConciseType(s);
     243         917 :                 if (concise_type == SQL_INTERVAL_MONTH) {
     244           0 :                         switch (mapi_get_digits(hdl, i)) {
     245             :                         case 1:
     246             :                                 concise_type = SQL_INTERVAL_YEAR;
     247             :                                 break;
     248             :                         case 2:
     249             :                                 concise_type = SQL_INTERVAL_YEAR_TO_MONTH;
     250             :                                 break;
     251             :                         case 3:
     252             :                                 concise_type = SQL_INTERVAL_MONTH;
     253             :                                 break;
     254             :                         default:
     255           0 :                                 assert(0);
     256             :                         }
     257         917 :                 } else if (concise_type == SQL_INTERVAL_SECOND) {
     258           0 :                         switch (mapi_get_digits(hdl, i)) {
     259             :                         case 4:
     260             :                                 concise_type = SQL_INTERVAL_DAY;
     261             :                                 break;
     262             :                         case 5:
     263             :                                 concise_type = SQL_INTERVAL_DAY_TO_HOUR;
     264             :                                 break;
     265             :                         case 6:
     266             :                                 concise_type = SQL_INTERVAL_DAY_TO_MINUTE;
     267             :                                 break;
     268             :                         case 7:
     269             :                                 concise_type = SQL_INTERVAL_DAY_TO_SECOND;
     270             :                                 break;
     271             :                         case 8:
     272             :                                 concise_type = SQL_INTERVAL_HOUR;
     273             :                                 break;
     274             :                         case 9:
     275             :                                 concise_type = SQL_INTERVAL_HOUR_TO_MINUTE;
     276             :                                 break;
     277             :                         case 10:
     278             :                                 concise_type = SQL_INTERVAL_HOUR_TO_SECOND;
     279             :                                 break;
     280             :                         case 11:
     281             :                                 concise_type = SQL_INTERVAL_MINUTE;
     282             :                                 break;
     283             :                         case 12:
     284             :                                 concise_type = SQL_INTERVAL_MINUTE_TO_SECOND;
     285             :                                 break;
     286             :                         case 13:
     287             :                                 concise_type = SQL_INTERVAL_SECOND;
     288             :                                 break;
     289             :                         default:
     290           0 :                                 assert(0);
     291             :                         }
     292             :                 }
     293        7051 :                 for (tp = ODBC_sql_types; tp->concise_type; tp++)
     294        7051 :                         if (concise_type == tp->concise_type)
     295             :                                 break;
     296         917 :                 rec->sql_desc_concise_type = tp->concise_type;
     297         917 :                 rec->sql_desc_type = tp->type;
     298         917 :                 rec->sql_desc_datetime_interval_code = tp->code;
     299         917 :                 switch (concise_type) {
     300           2 :                 case SQL_DECIMAL:
     301             :                 case SQL_NUMERIC:
     302           2 :                         rec->sql_desc_precision = mapi_get_digits(hdl, i);
     303           2 :                         rec->sql_desc_scale = mapi_get_scale(hdl, i);
     304           2 :                         break;
     305         915 :                 default:
     306         915 :                         if (tp->precision != UNAFFECTED)
     307           6 :                                 rec->sql_desc_precision = tp->precision;
     308         915 :                         if (tp->scale != UNAFFECTED)
     309           0 :                                 rec->sql_desc_scale = tp->scale;
     310             :                         break;
     311             :                 }
     312         917 :                 if (tp->datetime_interval_precision != UNAFFECTED)
     313           0 :                         rec->sql_desc_datetime_interval_precision = tp->datetime_interval_precision;
     314         917 :                 rec->sql_desc_fixed_prec_scale = tp->fixed;
     315         917 :                 rec->sql_desc_num_prec_radix = tp->radix;
     316         917 :                 rec->sql_desc_unsigned = tp->radix == 0 ? SQL_TRUE : SQL_FALSE;
     317             : 
     318         917 :                 if (rec->sql_desc_concise_type == SQL_CHAR ||
     319             :                     rec->sql_desc_concise_type == SQL_VARCHAR ||
     320             :                     rec->sql_desc_concise_type == SQL_LONGVARCHAR ||
     321             :                     rec->sql_desc_concise_type == SQL_WCHAR ||
     322             :                     rec->sql_desc_concise_type == SQL_WVARCHAR ||
     323             :                     rec->sql_desc_concise_type == SQL_WLONGVARCHAR)
     324         528 :                         rec->sql_desc_case_sensitive = SQL_TRUE;
     325             :                 else
     326         389 :                         rec->sql_desc_case_sensitive = SQL_FALSE;
     327             : 
     328         917 :                 s = mapi_get_table(hdl, i);
     329         917 :                 if (s) {
     330         917 :                         char *p = strchr(s, '.');
     331         917 :                         if (rec->sql_desc_table_name)
     332          22 :                                 free(rec->sql_desc_table_name);
     333         917 :                         if (p) {
     334         917 :                                 if (rec->sql_desc_schema_name)
     335           2 :                                         free(rec->sql_desc_schema_name);
     336         917 :                                 rec->sql_desc_schema_name = (SQLCHAR *) dupODBCstring((SQLCHAR *) s, p - s);
     337         917 :                                 if (rec->sql_desc_schema_name == NULL)
     338           0 :                                         goto nomem;
     339         917 :                                 rec->sql_desc_table_name = (SQLCHAR *) strdup(p + 1);
     340         917 :                                 if (rec->sql_desc_table_name == NULL)
     341           0 :                                         goto nomem;
     342         917 :                                 if (p != s) {
     343             :                                         /* base table name and base
     344             :                                          * column name exist if there
     345             :                                          * is a schema name */
     346          92 :                                         if (rec->sql_desc_base_table_name)
     347           0 :                                                 free(rec->sql_desc_base_table_name);
     348          92 :                                         rec->sql_desc_base_table_name = (SQLCHAR *) strdup(p + 1);
     349          92 :                                         if (rec->sql_desc_base_table_name == NULL)
     350           0 :                                                 goto nomem;
     351          92 :                                         if (rec->sql_desc_name) {
     352          92 :                                                 rec->sql_desc_base_column_name = (SQLCHAR *) strdup((char *) rec->sql_desc_name);
     353          92 :                                                 if (rec->sql_desc_base_column_name == NULL)
     354           0 :                                                         goto nomem;
     355             :                                         }
     356             :                                 }
     357             :                         } else {
     358           0 :                                 rec->sql_desc_table_name = (SQLCHAR *) strdup(s);
     359           0 :                                 if (rec->sql_desc_table_name == NULL)
     360           0 :                                         goto nomem;
     361             :                         }
     362             :                 }
     363             : 
     364         917 :                 if (rec->sql_desc_type != SQL_INTERVAL &&
     365         917 :                     (rec->sql_desc_length = mapi_get_digits(hdl, i)) == 0)
     366          22 :                         rec->sql_desc_length = mapi_get_len(hdl, i);
     367             : 
     368         917 :                 rec->sql_desc_local_type_name = NULL;
     369         917 :                 rec->sql_desc_catalog_name = NULL;
     370         917 :                 rec->sql_desc_literal_prefix = NULL;
     371         917 :                 rec->sql_desc_literal_suffix = NULL;
     372             : 
     373             :                 /* unused fields */
     374         917 :                 rec->sql_desc_data_ptr = NULL;
     375         917 :                 rec->sql_desc_indicator_ptr = NULL;
     376         917 :                 rec->sql_desc_octet_length_ptr = NULL;
     377         917 :                 rec->sql_desc_parameter_type = 0;
     378             : 
     379             :                 /* this must come after other fields have been
     380             :                  * initialized */
     381         917 :                 if (rec->sql_desc_concise_type == SQL_CHAR ||
     382             :                     rec->sql_desc_concise_type == SQL_VARCHAR ||
     383             :                     rec->sql_desc_concise_type == SQL_LONGVARCHAR ||
     384             :                     rec->sql_desc_concise_type == SQL_WCHAR ||
     385             :                     rec->sql_desc_concise_type == SQL_WVARCHAR ||
     386             :                     rec->sql_desc_concise_type == SQL_WLONGVARCHAR) {
     387             :                         /* for strings, get the display size from what
     388             :                          * the server told us the size is for this
     389             :                          * column, and derive the octet length from
     390             :                          * that */
     391         528 :                         rec->sql_desc_display_size = mapi_get_len(hdl, i);
     392         528 :                         rec->sql_desc_octet_length = 4 * rec->sql_desc_display_size;
     393             : 
     394             :                         /* For large varchar column definitions conditionally
     395             :                          * change type to SQL_WLONGVARCHAR when mapToLongVarchar is set (e.g. to 4000)
     396             :                          * This is a workaround for MS SQL Server linked server
     397             :                          * which can not handle large varchars (ref: SUPPORT-747) */
     398         528 :                         if (rec->sql_desc_concise_type == SQL_WVARCHAR
     399         513 :                          && stmt->Dbc->mapToLongVarchar > 0
     400           0 :                          && rec->sql_desc_length > (SQLULEN) stmt->Dbc->mapToLongVarchar)
     401           0 :                                 rec->sql_desc_concise_type = SQL_WLONGVARCHAR;
     402             :                 } else {
     403         389 :                         rec->sql_desc_length = ODBCLength(rec, SQL_DESC_LENGTH);
     404         389 :                         rec->sql_desc_display_size = ODBCLength(rec, SQL_DESC_DISPLAY_SIZE);
     405         389 :                         rec->sql_desc_octet_length = ODBCLength(rec, SQL_DESC_OCTET_LENGTH);
     406             :                 }
     407         917 :                 if (rec->sql_desc_length == 0) {
     408           5 :                         rec->sql_desc_length = SQL_NO_TOTAL;
     409           5 :                         rec->sql_desc_display_size = SQL_NO_TOTAL;
     410           5 :                         rec->sql_desc_octet_length = SQL_NO_TOTAL;
     411             :                 }
     412             : 
     413         917 :                 rec++;
     414             :         }
     415             : 
     416          94 :         return stmt->Error ? SQL_SUCCESS_WITH_INFO : SQL_SUCCESS;
     417             : 
     418           0 :   nomem:
     419             :         /* Memory allocation error */
     420           0 :         addStmtError(stmt, "HY001", NULL, 0);
     421           0 :         return SQL_ERROR;
     422             : }
     423             : 
     424             : SQLRETURN
     425        2004 : MNDBExecute(ODBCStmt *stmt)
     426             : {
     427        2004 :         MapiHdl hdl;
     428        2004 :         MapiMsg msg;
     429        2004 :         char *query;
     430        2004 :         const char *errstr;
     431        2004 :         char *sep;
     432        2004 :         size_t querylen;
     433        2004 :         size_t querypos;
     434        2004 :         int i;
     435        2004 :         ODBCDesc *desc;
     436        2004 :         SQLLEN offset;
     437             : 
     438             :         /* check statement cursor state, query should be prepared */
     439        2004 :         if (stmt->State == INITED ||
     440        1999 :             (stmt->State >= EXECUTED0 && stmt->queryid < 0)) {
     441             :                 /* Function sequence error */
     442           0 :                 addStmtError(stmt, "HY010", NULL, 0);
     443           0 :                 return SQL_ERROR;
     444             :         }
     445        2004 :         if (stmt->State >= EXECUTED1 ||
     446        1999 :             (stmt->State == EXECUTED0 && mapi_more_results(stmt->hdl))) {
     447             :                 /* Invalid cursor state */
     448           0 :                 addStmtError(stmt, "24000", NULL, 0);
     449           0 :                 return SQL_ERROR;
     450             :         }
     451             : 
     452        2004 :         assert(stmt->Dbc);
     453        2004 :         assert(stmt->Dbc->mid);
     454        2004 :         hdl = stmt->hdl;
     455             : 
     456        2004 :         assert(hdl);
     457             : 
     458        2004 :         desc = stmt->ApplParamDescr;
     459             : 
     460        2004 :         if (desc->sql_desc_count < stmt->nparams ||
     461        2004 :             stmt->ImplParamDescr->sql_desc_count < stmt->nparams) {
     462             :                 /* COUNT field incorrect */
     463           0 :                 addStmtError(stmt, "07002", NULL, 0);
     464           0 :                 return SQL_ERROR;
     465             :         }
     466             : 
     467        2004 :         querylen = 1024;
     468        2004 :         query = malloc(querylen); /* XXX allocate space for parameters */
     469        2004 :         if (query == NULL) {
     470             :                 /* Memory allocation error */
     471           0 :                 addStmtError(stmt, "HY001", NULL, 0);
     472           0 :                 return SQL_ERROR;
     473             :         }
     474        2004 :         if (stmt->qtimeout != stmt->Dbc->qtimeout) {
     475           0 :                 snprintf(query, querylen, "call sys.%s(%" PRIu64 ")",
     476           0 :                          (stmt->Dbc->major == 11 && stmt->Dbc->minor >= 37)
     477             :                          ? "setquerytimeout" : "settimeout",
     478             :                          (uint64_t) stmt->qtimeout);
     479           0 :                 if (mapi_query_handle(hdl, query) == MOK)
     480           0 :                         stmt->Dbc->qtimeout = stmt->qtimeout;
     481             :         }
     482        2004 :         querypos = snprintf(query, querylen, "execute %d (", stmt->queryid);
     483             :         /* XXX fill in parameter values */
     484        2004 :         if (desc->sql_desc_bind_offset_ptr)
     485           0 :                 offset = *desc->sql_desc_bind_offset_ptr;
     486             :         else
     487             :                 offset = 0;
     488        2004 :         sep = "";
     489       12008 :         for (i = 1; i <= stmt->nparams; i++) {
     490       10004 :                 if (ODBCStore(stmt, i, offset, 0, &query, &querypos, &querylen, sep) == SQL_ERROR) {
     491           0 :                         if (query)
     492           0 :                                 free(query);
     493           0 :                         return SQL_ERROR;
     494             :                 }
     495       10004 :                 sep = ",";
     496             :         }
     497        2004 :         if (querypos + 1 >= querylen) {
     498           0 :                 char *q = realloc(query, querylen += 10);
     499           0 :                 if (q == NULL) {
     500           0 :                         free(query);
     501           0 :                         addStmtError(stmt, "HY001", NULL, 0);
     502           0 :                         return SQL_ERROR;
     503             :                 }
     504           0 :                 query = q;
     505             :         }
     506        2004 :         query[querypos++] = ')';
     507        2004 :         query[querypos] = 0;
     508             : 
     509             : #ifdef ODBCDEBUG
     510        2004 :         ODBCLOG("SQLExecute %p %s\n", stmt, query);
     511             : #endif
     512             : 
     513             :         /* Have the server execute the query */
     514        2004 :         if (stmt->next == NULL && stmt->Dbc->FirstStmt == stmt &&
     515        2003 :             stmt->cursorType == SQL_CURSOR_FORWARD_ONLY) {
     516             :                 /* we're the only Stmt handle, and we're only going forward */
     517        2003 :                 if (stmt->Dbc->cachelimit != 10000)
     518           3 :                         mapi_cache_limit(stmt->Dbc->mid, 10000);
     519        2003 :                 stmt->Dbc->cachelimit = 10000;
     520             :         } else {
     521           1 :                 if (stmt->Dbc->cachelimit != 100)
     522           1 :                         mapi_cache_limit(stmt->Dbc->mid, 100);
     523           1 :                 stmt->Dbc->cachelimit = 100;
     524             :         }
     525        2004 :         msg = mapi_query_handle(hdl, query);
     526        2004 :         free(query);
     527        2004 :         switch (msg) {
     528             :         case MOK:
     529        2004 :                 break;
     530           0 :         case MTIMEOUT:
     531             :                 /* Timeout expired / Communication link failure */
     532           0 :                 addStmtError(stmt, stmt->Dbc->sql_attr_connection_timeout ? "HYT00" : "08S01", mapi_error_str(stmt->Dbc->mid), 0);
     533           0 :                 return SQL_ERROR;
     534           0 :         default:
     535           0 :                 errstr = mapi_result_error(hdl);
     536           0 :                 if (errstr == NULL)
     537           0 :                         errstr = mapi_error_str(stmt->Dbc->mid);
     538           0 :                 if (errstr) {
     539           0 :                         const char *sqlstate;
     540             : 
     541           0 :                         if ((sqlstate = mapi_result_errorcode(hdl)) != NULL) {
     542           0 :                                 addStmtError(stmt, sqlstate, errstr, 0);
     543           0 :                                 return SQL_ERROR;
     544             :                         }
     545             :                 }
     546             :                 /* General error */
     547           0 :                 addStmtError(stmt, "HY000", errstr, 0);
     548           0 :                 return SQL_ERROR;
     549             :         }
     550             : 
     551             :         /* now get the result data and store it to our internal data structure */
     552             : 
     553        2004 :         return ODBCInitResult(stmt);
     554             : }
     555             : 
     556             : SQLRETURN SQL_API
     557             : SQLExecute(SQLHSTMT StatementHandle)
     558             : {
     559             : #ifdef ODBCDEBUG
     560        2004 :         ODBCLOG("SQLExecute %p\n", StatementHandle);
     561             : #endif
     562             : 
     563        2004 :         if (!isValidStmt((ODBCStmt *) StatementHandle))
     564             :                 return SQL_INVALID_HANDLE;
     565             : 
     566        2004 :         clearStmtErrors((ODBCStmt *) StatementHandle);
     567             : 
     568        2004 :         return MNDBExecute((ODBCStmt *) StatementHandle);
     569             : }

Generated by: LCOV version 1.14