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

Generated by: LCOV version 1.14