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 : * ODBCDbc.c 25 : * 26 : * Description: 27 : * This file contains the functions which operate on 28 : * ODBC connection structures/objects (see ODBCDbc.h). 29 : * 30 : * Author: Martin van Dinther, Sjoerd Mullender 31 : * Date : 30 aug 2002 32 : * 33 : **********************************************/ 34 : 35 : #include "ODBCGlobal.h" 36 : #include "ODBCDbc.h" 37 : #include "ODBCAttrs.h" 38 : 39 : #define ODBC_DBC_MAGIC_NR 1365 /* for internal sanity check only */ 40 : 41 : static const char* 42 0 : odbc_parm_localizer(const void *data, mparm parm) 43 : { 44 0 : (void)data; 45 0 : for (int i = 0; i < attr_setting_count; i++) { 46 0 : const struct attr_setting *entry = &attr_settings[i]; 47 0 : if (entry->parm == parm) 48 0 : return entry->name; 49 : } 50 : return NULL; 51 : } 52 : 53 : /* 54 : * Creates a new allocated ODBCDbc object and initializes it. 55 : * 56 : * Precondition: none 57 : * Postcondition: returns a new ODBCDbc object 58 : */ 59 : ODBCDbc * 60 41 : newODBCDbc(ODBCEnv *env) 61 : { 62 41 : ODBCDbc *dbc; 63 41 : msettings *settings; 64 : 65 41 : assert(env); 66 : 67 41 : dbc = (ODBCDbc *) malloc(sizeof(ODBCDbc)); 68 41 : settings = msettings_create(); 69 : 70 41 : if (dbc == NULL || settings == NULL) { 71 0 : free(dbc); 72 0 : msettings_destroy(settings); 73 : /* Memory allocation error */ 74 0 : addEnvError(env, "HY001", NULL, 0); 75 0 : return NULL; 76 : } 77 : 78 41 : msettings_set_localizer(settings, odbc_parm_localizer, NULL); 79 : 80 41 : *dbc = (ODBCDbc) { 81 : .Env = env, 82 : .settings = settings, 83 : .sql_attr_metadata_id = SQL_FALSE, 84 : /* add this dbc to start of the administrative linked dbc list */ 85 41 : .next = env->FirstDbc, 86 : .Type = ODBC_DBC_MAGIC_NR, /* set it valid */ 87 : .setting_touched = { 0 }, 88 : }; 89 41 : env->FirstDbc = dbc; 90 41 : return dbc; 91 : } 92 : 93 : 94 : /* 95 : * Check if the connection handle is valid. 96 : * Note: this function is used internally by the driver to assert legal 97 : * and save usage of the handle and prevent crashes as much as possible. 98 : * 99 : * Precondition: none 100 : * Postcondition: returns 1 if it is a valid connection handle, 101 : * returns 0 if is invalid and thus an unusable handle. 102 : */ 103 : int 104 469 : isValidDbc(ODBCDbc *dbc) 105 : { 106 : #ifdef ODBCDEBUG 107 469 : if (!(dbc && dbc->Type == ODBC_DBC_MAGIC_NR)) 108 0 : ODBCLOG("dbc %p: not a valid connection handle\n", dbc); 109 : #endif 110 469 : return dbc && dbc->Type == ODBC_DBC_MAGIC_NR; 111 : } 112 : 113 : 114 : 115 : /* 116 : * Creates and adds an error msg object to the end of the error list of 117 : * this ODBCDbc struct. 118 : * When the errMsg is NULL and the SQLState is an ISO SQLState the 119 : * standard ISO message text for the SQLState is used as message. 120 : * 121 : * Precondition: dbc must be valid. SQLState and errMsg may be NULL. 122 : */ 123 : void 124 21 : addDbcError(ODBCDbc *dbc, const char *SQLState, const char *errMsg, int nativeErrCode) 125 : { 126 21 : ODBCError *error = NULL; 127 : 128 : #ifdef ODBCDEBUG 129 21 : ODBCLOG("addDbcError %p %s %s %d\n", dbc, SQLState, errMsg ? errMsg : getStandardSQLStateMsg(SQLState), nativeErrCode); 130 : #endif 131 21 : assert(isValidDbc(dbc)); 132 : 133 21 : error = newODBCError(SQLState, errMsg, nativeErrCode); 134 21 : appendODBCError(&dbc->Error, error); 135 21 : } 136 : 137 : 138 : /* 139 : * Extracts an error object from the error list of this ODBCDbc struct. 140 : * The error object itself is removed from the error list. 141 : * The caller is now responsible for freeing the error object memory. 142 : * 143 : * Precondition: dbc and error must be valid 144 : * Postcondition: returns a ODBCError object or null when no error is available. 145 : */ 146 : ODBCError * 147 34 : getDbcError(ODBCDbc *dbc) 148 : { 149 34 : assert(isValidDbc(dbc)); 150 34 : return dbc->Error; 151 : } 152 : 153 : 154 : /* 155 : * Destroys the ODBCDbc object including its own managed data. 156 : * 157 : * Precondition: dbc must be valid, inactive (not connected) and 158 : * no ODBCStmt (or ODBCDesc) objects may refer to this dbc. 159 : * Postcondition: dbc is completely destroyed, dbc handle is become invalid. 160 : */ 161 : void 162 39 : destroyODBCDbc(ODBCDbc *dbc) 163 : { 164 39 : assert(isValidDbc(dbc)); 165 39 : assert(!dbc->Connected); 166 39 : assert(dbc->FirstStmt == NULL); 167 : 168 : /* first set this object to invalid */ 169 39 : dbc->Type = 0; 170 : 171 : /* remove this dbc from the env */ 172 39 : assert(dbc->Env); 173 39 : assert(dbc->Env->FirstDbc); 174 : { 175 : /* search for this dbc in the list */ 176 : ODBCDbc *tmp_dbc = (ODBCDbc *) dbc->Env->FirstDbc; 177 : ODBCDbc *prv_dbc = NULL; 178 : 179 39 : while ((tmp_dbc != NULL) && (tmp_dbc != dbc)) { 180 0 : prv_dbc = tmp_dbc; 181 0 : tmp_dbc = tmp_dbc->next; 182 : } 183 : 184 39 : assert(tmp_dbc == dbc); /* we must have found it */ 185 : 186 : /* now remove it from the linked list */ 187 39 : if (prv_dbc != NULL) { 188 0 : prv_dbc->next = dbc->next; 189 : } else { 190 39 : dbc->Env->FirstDbc = dbc->next; 191 : } 192 : } 193 : 194 : /* cleanup own managed data */ 195 39 : deleteODBCErrorList(&dbc->Error); 196 39 : msettings_destroy(dbc->settings); 197 39 : free(dbc->dsn); 198 : 199 39 : free(dbc); 200 39 : }