LCOV - code coverage report
Current view: top level - clients/odbc/driver - ODBCStmt.c (source / functions) Hit Total Coverage
Test: coverage.info Lines: 58 66 87.9 %
Date: 2024-10-04 20:04:04 Functions: 5 5 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             :  * ODBCStmt.c
      25             :  *
      26             :  * Description:
      27             :  * This file contains the functions which operate on
      28             :  * ODBC statement structures/objects (see ODBCStmt.h).
      29             :  *
      30             :  * Author: Martin van Dinther, Sjoerd Mullender
      31             :  * Date  : 30 aug 2002
      32             :  *
      33             :  **********************************************/
      34             : 
      35             : #include "ODBCGlobal.h"
      36             : #include "ODBCStmt.h"
      37             : 
      38             : #define ODBC_STMT_MAGIC_NR  5461        /* for internal sanity check only */
      39             : 
      40             : 
      41             : /*
      42             :  * Creates a new allocated ODBCStmt object and initializes it.
      43             :  *
      44             :  * Precondition: none
      45             :  * Postcondition: returns a new ODBCStmt object
      46             :  */
      47             : ODBCStmt *
      48          19 : newODBCStmt(ODBCDbc *dbc)
      49             : {
      50          19 :         ODBCStmt *stmt = (ODBCStmt *) malloc(sizeof(ODBCStmt));
      51             : 
      52          19 :         assert(dbc);
      53          19 :         assert(dbc->mid);
      54             : 
      55          19 :         if (stmt == NULL) {
      56             :                 /* Memory allocation error */
      57           0 :                 addDbcError(dbc, "HY001", NULL, 0);
      58           0 :                 return NULL;
      59             :         }
      60             : 
      61          38 :         *stmt = (ODBCStmt) {
      62             :                 .Dbc = dbc,
      63             :                 .Error = NULL,
      64             :                 .RetrievedErrors = 0,
      65             : 
      66             :                 .State = INITED,
      67          19 :                 .hdl = mapi_new_handle(dbc->mid),
      68             :                 .currentRow = 0,
      69             :                 .startRow = 0,
      70             :                 .rowSetSize = 0,
      71             :                 .queryid = -1,
      72             :                 .nparams = 0,
      73             :                 .querytype = -1,
      74             :                 .rowcount = 0,
      75             : 
      76          19 :                 .qtimeout = dbc->qtimeout, /* inherit query timeout */
      77             : 
      78             :                 .cursorType = SQL_CURSOR_FORWARD_ONLY,
      79             :                 .cursorScrollable = SQL_NONSCROLLABLE,
      80             :                 .retrieveData = SQL_RD_ON,
      81             :                 .noScan = SQL_NOSCAN_OFF,
      82             : 
      83          19 :                 .AutoApplRowDescr = newODBCDesc(dbc),
      84          19 :                 .AutoApplParamDescr = newODBCDesc(dbc),
      85          19 :                 .ImplRowDescr = newODBCDesc(dbc),
      86          19 :                 .ImplParamDescr = newODBCDesc(dbc),
      87             : 
      88             :                 .Type = ODBC_STMT_MAGIC_NR,     /* set it valid */
      89             :         };
      90             : 
      91          19 :         if (stmt->hdl == NULL) {
      92             :                 /* Memory allocation error */
      93           0 :                 addDbcError(dbc, "HY001", NULL, 0);
      94           0 :                 destroyODBCStmt(stmt);
      95           0 :                 return NULL;
      96             :         }
      97          19 :         if (stmt->AutoApplRowDescr == NULL || stmt->AutoApplParamDescr == NULL ||
      98          19 :             stmt->ImplRowDescr == NULL || stmt->ImplParamDescr == NULL) {
      99           0 :                 destroyODBCStmt(stmt);
     100           0 :                 return NULL;
     101             :         }
     102             : 
     103          19 :         stmt->AutoApplRowDescr->sql_desc_alloc_type = SQL_DESC_ALLOC_AUTO;
     104          19 :         stmt->AutoApplParamDescr->sql_desc_alloc_type = SQL_DESC_ALLOC_AUTO;
     105          19 :         stmt->ImplRowDescr->sql_desc_alloc_type = SQL_DESC_ALLOC_AUTO;
     106          19 :         stmt->ImplParamDescr->sql_desc_alloc_type = SQL_DESC_ALLOC_AUTO;
     107          19 :         stmt->ImplRowDescr->Stmt = stmt;
     108          19 :         stmt->ImplParamDescr->Stmt = stmt;
     109          19 :         stmt->ApplRowDescr = stmt->AutoApplRowDescr;
     110          19 :         stmt->ApplParamDescr = stmt->AutoApplParamDescr;
     111             : 
     112             :         /* add this stmt to the administrative linked stmt list */
     113          19 :         stmt->next = dbc->FirstStmt,
     114          19 :         dbc->FirstStmt = stmt;
     115             : 
     116          19 :         return stmt;
     117             : }
     118             : 
     119             : 
     120             : /*
     121             :  * Check if the statement handle is valid.
     122             :  * Note: this function is used internally by the driver to assert legal
     123             :  * and save usage of the handle and prevent crashes as much as possible.
     124             :  *
     125             :  * Precondition: none
     126             :  * Postcondition: returns 1 if it is a valid statement handle,
     127             :  *      returns 0 if is invalid and thus an unusable handle.
     128             :  */
     129             : int
     130       13521 : isValidStmt(ODBCStmt *stmt)
     131             : {
     132             : #ifdef ODBCDEBUG
     133       13521 :         if (!(stmt &&stmt->Type == ODBC_STMT_MAGIC_NR))
     134           0 :                 ODBCLOG("stmt %p not a valid statement handle\n", stmt);
     135             : #endif
     136       13521 :         return stmt &&stmt->Type == ODBC_STMT_MAGIC_NR;
     137             : }
     138             : 
     139             : 
     140             : /*
     141             :  * Creates and adds an error msg object to the end of the error list of
     142             :  * this ODBCStmt struct.
     143             :  * When the errMsg is NULL and the SQLState is an ISO SQLState the
     144             :  * standard ISO message text for the SQLState is used as message.
     145             :  *
     146             :  * Precondition: stmt must be valid. SQLState and errMsg may be NULL.
     147             :  */
     148             : void
     149          62 : addStmtError(ODBCStmt *stmt, const char *SQLState, const char *errMsg, int nativeErrCode)
     150             : {
     151          62 :         ODBCError *error = NULL;
     152             : 
     153             : #ifdef ODBCDEBUG
     154          62 :         ODBCLOG("addStmtError %p %s %s %d\n", stmt, SQLState, errMsg ? errMsg : getStandardSQLStateMsg(SQLState), nativeErrCode);
     155             : #endif
     156          62 :         assert(isValidStmt(stmt));
     157             : 
     158          62 :         error = newODBCError(SQLState, errMsg, nativeErrCode);
     159          62 :         appendODBCError(&stmt->Error, error);
     160          62 : }
     161             : 
     162             : 
     163             : /*
     164             :  * Extracts an error object from the error list of this ODBCStmt struct.
     165             :  * The error object itself is removed from the error list.
     166             :  * The caller is now responsible for freeing the error object memory.
     167             :  *
     168             :  * Precondition: stmt and error must be valid
     169             :  * Postcondition: returns a ODBCError object or null when no error is available.
     170             :  */
     171             : ODBCError *
     172          55 : getStmtError(ODBCStmt *stmt)
     173             : {
     174          55 :         assert(isValidStmt(stmt));
     175          55 :         return stmt->Error;
     176             : }
     177             : 
     178             : 
     179             : 
     180             : /*
     181             :  * Destroys the ODBCStmt object including its own managed data.
     182             :  *
     183             :  * Precondition: stmt must be valid.
     184             :  * Postcondition: stmt is completely destroyed, stmt handle is invalid.
     185             :  */
     186             : void
     187          19 : destroyODBCStmt(ODBCStmt *stmt)
     188             : {
     189          19 :         ODBCStmt **stmtp;
     190             : 
     191          19 :         assert(isValidStmt(stmt));
     192             : 
     193             :         /* first set this object to invalid */
     194          19 :         stmt->Type = 0;
     195             : 
     196             :         /* remove this stmt from the dbc */
     197          19 :         assert(stmt->Dbc);
     198             : 
     199             :         /* search for stmt in linked list */
     200          19 :         stmtp = &stmt->Dbc->FirstStmt;
     201             : 
     202          20 :         while (*stmtp && *stmtp != stmt)
     203           1 :                 stmtp = &(*stmtp)->next;
     204             :         /* stmtp points to location in list where stmt is found, or
     205             :          * *stmtp is NULL in case it wasn't there (presumably not added
     206             :          * yet) */
     207             : 
     208          19 :         if (*stmtp) {
     209             :                 /* now remove it from the linked list */
     210          19 :                 *stmtp = stmt->next;
     211             :         }
     212             : 
     213             :         /* cleanup own managed data */
     214          19 :         deleteODBCErrorList(&stmt->Error);
     215             : 
     216          19 :         destroyODBCDesc(stmt->ImplParamDescr);
     217          19 :         destroyODBCDesc(stmt->ImplRowDescr);
     218          19 :         destroyODBCDesc(stmt->AutoApplParamDescr);
     219          19 :         destroyODBCDesc(stmt->AutoApplRowDescr);
     220             : 
     221          19 :         if (stmt->hdl)
     222          19 :                 mapi_close_handle(stmt->hdl);
     223             : 
     224          19 :         free(stmt);
     225          19 : }

Generated by: LCOV version 1.14