1 /************************************************************************************ 2 Copyright (C) 2020 MariaDB Corporation AB 3 4 This library is free software; you can redistribute it and/or 5 modify it under the terms of the GNU Library General Public 6 License as published by the Free Software Foundation; either 7 version 2.1 of the License, or (at your option) any later version. 8 9 This library is distributed in the hope that it will be useful, 10 but WITHOUT ANY WARRANTY; without even the implied warranty of 11 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 12 Library General Public License for more details. 13 14 You should have received a copy of the GNU Library General Public 15 License along with this library; if not see <http://www.gnu.org/licenses> 16 or write to the Free Software Foundation, Inc., 17 51 Franklin St., Fifth Floor, Boston, MA 02110, USA 18 *************************************************************************************/ 19 20 /** 21 * "Internal" ODBC API functions - functions, that have to be called internally if API 22 * function needs to be executed 23 * 24 * Calling SQLFunction itself inside the connector on non-Windows platforms will result 25 * in the driver manager function instead of our own function. 26 */ 27 28 #include <ma_odbc.h> 29 30 31 /* {{{ MA_SQLAllocHandle */ 32 SQLRETURN MA_SQLAllocHandle(SQLSMALLINT HandleType, 33 SQLHANDLE InputHandle, 34 SQLHANDLE *OutputHandlePtr) 35 { 36 SQLRETURN ret= SQL_ERROR; 37 38 switch(HandleType) { 39 case SQL_HANDLE_DBC: 40 EnterCriticalSection(&((MADB_Env *)InputHandle)->cs); 41 MADB_CLEAR_ERROR(&((MADB_Env *)InputHandle)->Error); 42 if ((*OutputHandlePtr= (SQLHANDLE)MADB_DbcInit((MADB_Env *)InputHandle)) != NULL) 43 { 44 ret= SQL_SUCCESS; 45 } 46 LeaveCriticalSection(&((MADB_Env *)InputHandle)->cs); 47 break; 48 case SQL_HANDLE_DESC: 49 EnterCriticalSection(&((MADB_Dbc *)InputHandle)->cs); 50 MADB_CLEAR_ERROR(&((MADB_Dbc *)InputHandle)->Error); 51 if ((*OutputHandlePtr= (SQLHANDLE)MADB_DescInit((MADB_Dbc *)InputHandle, MADB_DESC_UNKNOWN, TRUE)) != NULL) 52 { 53 ret= SQL_SUCCESS; 54 } 55 LeaveCriticalSection(&((MADB_Dbc *)InputHandle)->cs); 56 break; 57 case SQL_HANDLE_ENV: 58 if ((*OutputHandlePtr= (SQLHANDLE)MADB_EnvInit()) != NULL) 59 { 60 ret= SQL_SUCCESS; 61 } 62 break; 63 case SQL_HANDLE_STMT: 64 { 65 MADB_Dbc *Connection= (MADB_Dbc *)InputHandle; 66 MDBUG_C_ENTER(InputHandle, "MA_SQLAllocHandle(Stmt)"); 67 MDBUG_C_DUMP(InputHandle, InputHandle, 0x); 68 MDBUG_C_DUMP(InputHandle, OutputHandlePtr, 0x); 69 70 MADB_CLEAR_ERROR(&Connection->Error); 71 72 if (!CheckConnection(Connection)) 73 { 74 MADB_SetError(&Connection->Error, MADB_ERR_08003, NULL, 0); 75 break; 76 } 77 78 ret= MADB_StmtInit(Connection, OutputHandlePtr); 79 MDBUG_C_DUMP(InputHandle, *OutputHandlePtr, 0x); 80 MDBUG_C_RETURN(InputHandle,ret, &Connection->Error); 81 } 82 break; 83 default: 84 /* todo: set error message */ 85 break; 86 } 87 return ret; 88 } 89 /* }}} */ 90 91 /* {{{ MA_SQLBindParameter */ 92 SQLRETURN MA_SQLBindParameter(SQLHSTMT StatementHandle, 93 SQLUSMALLINT ParameterNumber, 94 SQLSMALLINT InputOutputType, 95 SQLSMALLINT ValueType, 96 SQLSMALLINT ParameterType, 97 SQLULEN ColumnSize, 98 SQLSMALLINT DecimalDigits, 99 SQLPOINTER ParameterValuePtr, 100 SQLLEN BufferLength, 101 SQLLEN *StrLen_or_IndPtr) 102 { 103 MADB_Stmt *Stmt= (MADB_Stmt *)StatementHandle; 104 SQLRETURN ret; 105 106 if (!Stmt) 107 return SQL_INVALID_HANDLE; 108 109 MDBUG_C_ENTER(Stmt->Connection, "SQLBindParameter"); 110 MDBUG_C_DUMP(Stmt->Connection, Stmt, 0x); 111 MDBUG_C_DUMP(Stmt->Connection, ParameterNumber, u); 112 MDBUG_C_DUMP(Stmt->Connection, InputOutputType, d); 113 MDBUG_C_DUMP(Stmt->Connection, ValueType, d); 114 MDBUG_C_DUMP(Stmt->Connection, ParameterType, d); 115 MDBUG_C_DUMP(Stmt->Connection, ColumnSize, u); 116 MDBUG_C_DUMP(Stmt->Connection, DecimalDigits, d); 117 MDBUG_C_DUMP(Stmt->Connection, ParameterValuePtr, 0x); 118 MDBUG_C_DUMP(Stmt->Connection, BufferLength, d); 119 MDBUG_C_DUMP(Stmt->Connection, StrLen_or_IndPtr, 0x); 120 121 MADB_CHECK_STMT_HANDLE(Stmt,stmt); 122 ret= Stmt->Methods->BindParam(Stmt, ParameterNumber, InputOutputType, ValueType, ParameterType, ColumnSize, DecimalDigits, 123 ParameterValuePtr, BufferLength, StrLen_or_IndPtr); 124 125 MDBUG_C_RETURN(Stmt->Connection, ret, &Stmt->Error); 126 } 127 /* }}} */ 128 129 130 /* {{{ MA_SQLCancel */ 131 SQLRETURN MA_SQLCancel(SQLHSTMT StatementHandle) 132 { 133 MADB_Stmt *Stmt= (MADB_Stmt *)StatementHandle; 134 SQLRETURN ret= SQL_ERROR; 135 136 if (!Stmt) 137 return SQL_INVALID_HANDLE; 138 139 MADB_CLEAR_ERROR(&Stmt->Error); 140 141 MDBUG_C_ENTER(Stmt->Connection, "SQLCancel"); 142 MDBUG_C_DUMP(Stmt->Connection, Stmt, 0x); 143 144 if (TryEnterCriticalSection(&Stmt->Connection->cs)) 145 { 146 LeaveCriticalSection(&Stmt->Connection->cs); 147 ret= Stmt->Methods->StmtFree(Stmt, SQL_CLOSE); 148 149 MDBUG_C_RETURN(Stmt->Connection, ret, &Stmt->Error); 150 } else 151 { 152 MYSQL *MariaDb, *Kill=Stmt->Connection->mariadb; 153 154 char StmtStr[30]; 155 156 if (!(MariaDb= mysql_init(NULL))) 157 { 158 ret= SQL_ERROR; 159 goto end; 160 } 161 if (!(mysql_real_connect(MariaDb, Kill->host, Kill->user, Kill->passwd, 162 "", Kill->port, Kill->unix_socket, 0))) 163 { 164 mysql_close(MariaDb); 165 goto end; 166 } 167 168 _snprintf(StmtStr, 30, "KILL QUERY %ld", mysql_thread_id(Kill)); 169 if (mysql_query(MariaDb, StmtStr)) 170 { 171 mysql_close(MariaDb); 172 goto end; 173 } 174 mysql_close(MariaDb); 175 ret= SQL_SUCCESS; 176 } 177 end: 178 LeaveCriticalSection(&Stmt->Connection->cs); 179 180 MDBUG_C_RETURN(Stmt->Connection, ret, &Stmt->Error); 181 } 182 183 /* {{{ MA_SQLEndTran */ 184 SQLRETURN MA_SQLEndTran(SQLSMALLINT HandleType, 185 SQLHANDLE Handle, 186 SQLSMALLINT CompletionType) 187 { 188 SQLRETURN ret= SQL_SUCCESS; 189 switch (HandleType) { 190 case SQL_HANDLE_ENV: 191 { 192 MADB_Env *Env= (MADB_Env *)Handle; 193 MADB_List *List= Env->Dbcs; 194 195 for (List= Env->Dbcs; List; List= List->next) 196 ((MADB_Dbc *)List->data)->Methods->EndTran((MADB_Dbc *)List->data, CompletionType); 197 } 198 break; 199 case SQL_HANDLE_DBC: 200 { 201 MADB_Dbc *Dbc= (MADB_Dbc *)Handle; 202 if (!Dbc->mariadb) 203 MADB_SetError(&Dbc->Error, MADB_ERR_08002, NULL, 0); 204 else 205 Dbc->Methods->EndTran(Dbc, CompletionType); 206 ret= Dbc->Error.ReturnValue; 207 } 208 break; 209 default: 210 /* todo: Do we need to set an error ?! */ 211 break; 212 } 213 214 return ret; 215 } 216 /* }}} */ 217 218 /* {{{ MA_SQLGetDiagRecW */ 219 SQLRETURN SQL_API MA_SQLGetDiagRecW(SQLSMALLINT HandleType, 220 SQLHANDLE Handle, 221 SQLSMALLINT RecNumber, 222 SQLWCHAR *SQLState, 223 SQLINTEGER *NativeErrorPtr, 224 SQLWCHAR *MessageText, 225 SQLSMALLINT BufferLength, 226 SQLSMALLINT *TextLengthPtr) 227 { 228 if (!Handle) 229 return SQL_INVALID_HANDLE; 230 231 /* Maria ODBC driver doesn't support error lists, so only the first record can be retrieved */ 232 if (RecNumber != 1) 233 return SQL_NO_DATA_FOUND; 234 235 switch (HandleType) { 236 case SQL_HANDLE_DBC: 237 { 238 MADB_Dbc *Dbc= (MADB_Dbc *)Handle; 239 return MADB_GetDiagRec(&Dbc->Error, RecNumber, (void *)SQLState, NativeErrorPtr, 240 (void *)MessageText, BufferLength, TextLengthPtr, TRUE, 241 Dbc->Environment->OdbcVersion); 242 } 243 break; 244 case SQL_HANDLE_STMT: 245 { 246 MADB_Stmt *Stmt= (MADB_Stmt *)Handle; 247 return MADB_GetDiagRec(&Stmt->Error, RecNumber, (void *)SQLState, NativeErrorPtr, 248 (void *)MessageText, BufferLength, TextLengthPtr, TRUE, 249 Stmt->Connection->Environment->OdbcVersion); 250 } 251 break; 252 case SQL_HANDLE_DESC: 253 { 254 MADB_Desc *Desc= (MADB_Desc *)Handle; 255 return MADB_GetDiagRec(&Desc->Error, RecNumber, (void *)SQLState, NativeErrorPtr, 256 (void *)MessageText, BufferLength, TextLengthPtr, TRUE, 257 SQL_OV_ODBC3); 258 } 259 break; 260 case SQL_HANDLE_ENV: 261 { 262 MADB_Env *Env= (MADB_Env *)Handle; 263 return MADB_GetDiagRec(&Env->Error, RecNumber, (void *)SQLState, NativeErrorPtr, 264 (void *)MessageText, BufferLength, TextLengthPtr, TRUE, 265 Env->OdbcVersion); 266 } 267 default: 268 return SQL_ERROR; 269 break; 270 } 271 } 272 /* }}} */ 273 274 /* {{{ MA_SQLGetConnectAttr */ 275 SQLRETURN MA_SQLGetConnectAttr(SQLHDBC ConnectionHandle, 276 SQLINTEGER Attribute, 277 SQLPOINTER ValuePtr, 278 SQLINTEGER BufferLength, 279 SQLINTEGER *StringLengthPtr) 280 { 281 MADB_Dbc *Dbc= (MADB_Dbc *)ConnectionHandle; 282 SQLRETURN ret; 283 284 if (!Dbc) 285 return SQL_INVALID_HANDLE; 286 287 MDBUG_C_ENTER(Dbc, "SQLGetConnectAttr"); 288 MDBUG_C_DUMP(Dbc, Attribute, d); 289 MDBUG_C_DUMP(Dbc, ValuePtr, 0x); 290 MDBUG_C_DUMP(Dbc, BufferLength, d); 291 MDBUG_C_DUMP(Dbc, StringLengthPtr, 0x); 292 293 ret= Dbc->Methods->GetAttr(Dbc, Attribute, ValuePtr, BufferLength, StringLengthPtr, FALSE); 294 295 MDBUG_C_RETURN(Dbc, ret, &Dbc->Error); 296 } 297 /* }}} */ 298 299 /* {{{ SQLGetDiagRec */ 300 SQLRETURN MA_SQLGetDiagRec(SQLSMALLINT HandleType, 301 SQLHANDLE Handle, 302 SQLSMALLINT RecNumber, 303 SQLCHAR *SQLState, 304 SQLINTEGER *NativeErrorPtr, 305 SQLCHAR *MessageText, 306 SQLSMALLINT BufferLength, 307 SQLSMALLINT *TextLengthPtr) 308 { 309 SQLRETURN ret= SQL_ERROR; 310 311 if (!Handle) 312 MDBUG_RETURN(SQL_INVALID_HANDLE); 313 314 if (RecNumber < 1 || BufferLength < 0) 315 MDBUG_RETURN(SQL_ERROR); 316 317 /* Maria ODBC driver doesn't support error lists, so only the first record can be retrieved */ 318 if (RecNumber != 1) 319 MDBUG_RETURN(SQL_NO_DATA_FOUND); 320 321 switch (HandleType) { 322 case SQL_HANDLE_DBC: 323 { 324 MADB_Dbc *Dbc= (MADB_Dbc *)Handle; 325 326 MDBUG_C_ENTER(Dbc, "SQLGetDiagRec"); 327 MDBUG_C_DUMP(Dbc, HandleType, d); 328 MDBUG_C_DUMP(Dbc, Handle, 0x); 329 MDBUG_C_DUMP(Dbc, MessageText, 0x); 330 MDBUG_C_DUMP(Dbc, BufferLength, d); 331 MDBUG_C_DUMP(Dbc, TextLengthPtr, 0x); 332 333 ret= MADB_GetDiagRec(&Dbc->Error, RecNumber, (void *)SQLState, NativeErrorPtr, 334 (void *) MessageText, BufferLength, TextLengthPtr, FALSE, 335 Dbc->Environment->OdbcVersion); 336 } 337 break; 338 case SQL_HANDLE_STMT: 339 { 340 MADB_Stmt *Stmt= (MADB_Stmt *)Handle; 341 342 MDBUG_C_ENTER(Stmt->Connection, "SQLGetDiagRec"); 343 MDBUG_C_DUMP(Stmt->Connection, HandleType, d); 344 MDBUG_C_DUMP(Stmt->Connection, Handle, 0x); 345 MDBUG_C_DUMP(Stmt->Connection, MessageText, 0x); 346 MDBUG_C_DUMP(Stmt->Connection, BufferLength, d); 347 MDBUG_C_DUMP(Stmt->Connection, TextLengthPtr, 0x); 348 349 ret= MADB_GetDiagRec(&Stmt->Error, RecNumber, (void *)SQLState, NativeErrorPtr, 350 (void *)MessageText, BufferLength, TextLengthPtr, FALSE, 351 Stmt->Connection->Environment->OdbcVersion); 352 } 353 break; 354 case SQL_HANDLE_DESC: 355 { 356 MADB_Desc *Desc= (MADB_Desc *)Handle; 357 358 MDBUG_C_ENTER(Desc->Dbc, "SQLGetDiagRec"); 359 MDBUG_C_DUMP(Desc->Dbc, HandleType, d); 360 MDBUG_C_DUMP(Desc->Dbc, Handle, 0x); 361 MDBUG_C_DUMP(Desc->Dbc, MessageText, 0x); 362 MDBUG_C_DUMP(Desc->Dbc, BufferLength, d); 363 MDBUG_C_DUMP(Desc->Dbc, TextLengthPtr, 0x); 364 365 ret= MADB_GetDiagRec(&Desc->Error, RecNumber, (void *)SQLState, NativeErrorPtr, 366 (void *)MessageText, BufferLength, TextLengthPtr, FALSE, 367 SQL_OV_ODBC3); 368 } 369 break; 370 case SQL_HANDLE_ENV: 371 { 372 MADB_Env *Env= (MADB_Env *)Handle; 373 ret= MADB_GetDiagRec(&Env->Error, RecNumber, (void *)SQLState, NativeErrorPtr, 374 (void *)MessageText, BufferLength, TextLengthPtr, FALSE, 375 Env->OdbcVersion); 376 } 377 break; 378 } 379 380 MDBUG_RETURN(ret); 381 } 382 /* }}} */ 383 384 /* {{{ MA_SQLGetStmtAttr */ 385 SQLRETURN MA_SQLGetStmtAttr(SQLHSTMT StatementHandle, 386 SQLINTEGER Attribute, 387 SQLPOINTER ValuePtr, 388 SQLINTEGER BufferLength, 389 SQLINTEGER *StringLengthPtr) 390 { 391 MADB_Stmt *Stmt= (MADB_Stmt *)StatementHandle; 392 if (!Stmt) 393 return SQL_INVALID_HANDLE; 394 return Stmt->Methods->GetAttr(Stmt, Attribute, ValuePtr, BufferLength, StringLengthPtr); 395 } 396 /* }}} */ 397 398 /* {{{ SQLSetConnectAttr */ 399 SQLRETURN MA_SQLSetConnectAttr(SQLHDBC ConnectionHandle, 400 SQLINTEGER Attribute, 401 SQLPOINTER ValuePtr, 402 SQLINTEGER StringLength) 403 { 404 MADB_Dbc *Dbc= (MADB_Dbc *)ConnectionHandle; 405 SQLRETURN ret; 406 407 if (!Dbc) 408 return SQL_INVALID_HANDLE; 409 410 MDBUG_C_ENTER(Dbc, "SQLSetConnectAttr"); 411 MDBUG_C_DUMP(Dbc, Attribute, d); 412 MDBUG_C_DUMP(Dbc, ValuePtr, 0x); 413 MDBUG_C_DUMP(Dbc, StringLength, d); 414 415 ret= Dbc->Methods->SetAttr(Dbc, Attribute, ValuePtr, StringLength, FALSE); 416 417 MDBUG_C_RETURN(Dbc, ret, &Dbc->Error); 418 } 419 /* }}} */ 420 421 /* {{{ SQLSetStmtAttr */ 422 SQLRETURN MA_SQLSetStmtAttr(SQLHSTMT StatementHandle, 423 SQLINTEGER Attribute, 424 SQLPOINTER ValuePtr, 425 SQLINTEGER StringLength) 426 { 427 MADB_Stmt *Stmt= (MADB_Stmt *)StatementHandle; 428 SQLRETURN ret; 429 430 if (!Stmt) 431 return SQL_INVALID_HANDLE; 432 433 MDBUG_C_ENTER(Stmt->Connection, "SQLSetStmtAttr"); 434 MDBUG_C_DUMP(Stmt->Connection, Attribute, d); 435 MDBUG_C_DUMP(Stmt->Connection, ValuePtr, 0x); 436 MDBUG_C_DUMP(Stmt->Connection, StringLength, d); 437 438 ret= Stmt->Methods->SetAttr(Stmt, Attribute, ValuePtr, StringLength); 439 440 MDBUG_C_RETURN(Stmt->Connection, ret, &Stmt->Error); 441 } 442 /* }}} */ 443 444