1 /************************************************************************************ 2 Copyright (C) 2013,2016 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 #ifndef _ma_odbc_h_ 20 #define _ma_odbc_h_ 21 22 #include <ma_odbc_version.h> 23 24 #ifdef _WIN32 25 # include "ma_platform_win32.h" 26 #else 27 # include "ma_platform_posix.h" 28 #endif 29 30 #include <stdlib.h> 31 32 #include <mysql.h> 33 34 #include <ma_legacy_helpers.h> 35 36 #include <sql.h> 37 #include <sqlext.h> 38 #include <odbcinst.h> 39 40 #include <errmsg.h> 41 #include <string.h> 42 #include <stdio.h> 43 #include <math.h> 44 #include <stddef.h> 45 #include <assert.h> 46 #include <time.h> 47 48 49 typedef struct st_ma_odbc_connection MADB_Dbc; 50 typedef struct st_ma_odbc_stmt MADB_Stmt; 51 52 typedef struct st_ma_odbc_error 53 { 54 char SqlState[SQL_SQLSTATE_SIZE + 1]; 55 char SqlStateV2[SQLSTATE_LENGTH + 1]; 56 char SqlErrorMsg[SQL_MAX_MESSAGE_LENGTH + 1]; 57 SQLRETURN ReturnValue; 58 } MADB_ERROR; 59 60 typedef struct 61 { 62 size_t PrefixLen; 63 MADB_ERROR *ErrRecord; 64 SQLINTEGER NativeError; 65 /* Order number of last requested error record */ 66 unsigned int ErrorNum; 67 char SqlState[SQLSTATE_LENGTH + 1]; 68 SQLRETURN ReturnValue; 69 char SqlErrorMsg[SQL_MAX_MESSAGE_LENGTH + 1]; 70 } MADB_Error; 71 72 typedef struct 73 { 74 SQLUINTEGER TargetType; 75 SQLPOINTER TargetValuePtr; 76 SQLLEN BufferLength; 77 SQLLEN Utf8BufferLength; 78 SQLLEN *StrLen_or_Ind; 79 void *InternalBuffer; /* used for conversion */ 80 } MADB_ColBind; 81 82 typedef struct 83 { 84 SQLSMALLINT InputOutputType; 85 SQLSMALLINT ValueType; 86 SQLSMALLINT ParameterType; 87 SQLULEN ColumnSize; 88 SQLSMALLINT DecimalDigits; 89 SQLPOINTER ParameterValuePtr; 90 SQLLEN BufferLength; 91 SQLLEN *StrLen_or_IndPtr; 92 void *InternalBuffer; /* used for conversion */ 93 } MADB_ParmBind; 94 95 typedef struct 96 { 97 /* Header */ 98 SQLSMALLINT AllocType; 99 SQLULEN ArraySize; 100 SQLUSMALLINT *ArrayStatusPtr; 101 SQLULEN *BindOffsetPtr; 102 SQLULEN BindType; 103 SQLSMALLINT Count; 104 /* TODO: In IPD this is SQLUINTEGER* field */ 105 SQLULEN *RowsProcessedPtr; 106 /* Header end */ 107 } MADB_Header; 108 109 typedef struct 110 { 111 SQLUINTEGER BindSize; /* size of each structure if using * Row-wise Binding */ 112 SQLUSMALLINT *RowOperationPtr; 113 SQLULEN *RowOffsetPtr; 114 MADB_ColBind *ColumnBind; 115 MYSQL_BIND *Bind; 116 SQLSMALLINT Allocated; 117 } MADB_Ard; 118 119 typedef struct 120 { 121 SQLLEN ParamsetSize; 122 SQLUINTEGER ParamBindType; 123 SQLUSMALLINT *ParamOperationPtr; 124 SQLULEN *ParamOffsetPtr; 125 MADB_ParmBind *ParamBind; 126 MYSQL_BIND *Bind; 127 SQLSMALLINT Allocated; 128 SQLLEN Dummy; /* dummy item to fit APD to ARD */ 129 } MADB_Apd; 130 131 typedef struct 132 { 133 MADB_Stmt *stmt; 134 SQLULEN *RowsFetched; 135 SQLUSMALLINT *RowStatusArray; 136 SQLUINTEGER FieldCount; 137 SQLSMALLINT Allocated; 138 MYSQL_FIELD *Fields; 139 } MADB_Ird; 140 141 typedef struct 142 { 143 MADB_Header Header; 144 #if (ODBCVER >= 0x0300) 145 SQLUINTEGER *ParamProcessedPtr; 146 #else 147 SQLULEN *ParamProcessedPtr; /* SQLParamOptions */ 148 #endif /* ODBCVER */ 149 SQLUSMALLINT *ParamStatusPtr; 150 SQLSMALLINT Allocated; 151 MADB_ParmBind *Parameters; 152 } MADB_Ipd; 153 154 typedef struct { 155 SQLINTEGER AutoUniqueValue; 156 char *BaseCatalogName; 157 char *BaseColumnName; 158 char *BaseTableName; 159 SQLINTEGER CaseSensitive; 160 char *CatalogName; 161 char *ColumnName; 162 SQLSMALLINT ConciseType; 163 SQLPOINTER DataPtr; 164 SQLSMALLINT DateTimeIntervalCode; 165 SQLINTEGER DateTimeIntervalPrecision; 166 SQLINTEGER DescLength; 167 SQLLEN DisplaySize; 168 SQLSMALLINT FixedPrecScale; 169 SQLLEN *IndicatorPtr; 170 char *Label; 171 SQLULEN Length; 172 char *LiteralPrefix; 173 char *LiteralSuffix; 174 char *LocalTypeName; 175 SQLSMALLINT Nullable; 176 SQLINTEGER NumPrecRadix; 177 SQLLEN OctetLength; 178 SQLLEN *OctetLengthPtr; 179 SQLSMALLINT ParameterType; 180 SQLSMALLINT Precision; 181 SQLSMALLINT RowVer; 182 SQLSMALLINT Scale; 183 char *SchemaName; 184 SQLSMALLINT Searchable; 185 char *TableName; 186 SQLSMALLINT Type; 187 char *TypeName; 188 SQLSMALLINT Unnamed; 189 SQLSMALLINT Unsigned; 190 SQLSMALLINT Updateable; 191 unsigned long InternalLength; /* This to be used in the MYSQL_BIND. Thus is the type */ 192 char *InternalBuffer; /* used for internal conversion */ 193 char *DefaultValue; 194 char *DaeData; 195 SQLULEN DaeDataLength; /* Doesn't seem to be used anywhere */ 196 my_bool PutData; 197 my_bool inUse; 198 my_bool TruncError; 199 } MADB_DescRecord; 200 201 typedef struct 202 { 203 MADB_Header Header; 204 SQLINTEGER DescType; /* SQL_ATTR_APP_ROW_DESC or SQL_ATTR_APP_PARAM_DESC */ 205 my_bool AppType; /* Allocated by Application ? */ 206 MADB_DynArray Records; 207 MADB_DynArray Stmts; 208 MADB_Error Error; 209 MADB_Dbc * Dbc; /* Disconnect must automatically free allocated descriptors. Thus 210 descriptor has to know the connection it is allocated on */ 211 MADB_List ListItem; /* To store in the dbc */ 212 union { 213 MADB_Ard Ard; 214 MADB_Apd Apd; 215 MADB_Ipd Ipd; 216 MADB_Ird Ird; 217 } Fields; 218 } MADB_Desc; 219 220 struct st_ma_desc_fldid 221 { 222 SQLSMALLINT FieldIdentifier; 223 SQLSMALLINT Access[4]; 224 }; 225 226 struct st_ma_stmt_methods; 227 228 typedef struct 229 { 230 SQLLEN MaxRows; 231 SQLLEN MaxLength; 232 SQLLEN KeysetSize; 233 SQLUINTEGER CursorType; 234 SQLUINTEGER ScrollConcurrency; 235 SQLUINTEGER RetrieveData; 236 SQLUINTEGER UseBookmarks; 237 void* BookmarkPtr; 238 SQLLEN BookmarkLength; 239 SQLSMALLINT BookmarkType; 240 SQLULEN MetadataId; 241 SQLULEN SimulateCursor; 242 } MADB_StmtOptions; 243 244 /* TODO: To check is it 0 or 1 based? not quite clear from its usage */ 245 typedef struct 246 { 247 char *Name; 248 SQLLEN Position; 249 SQLLEN RowsetSize; 250 MYSQL_ROW_OFFSET Next; 251 } MADB_Cursor; 252 253 enum MADB_DaeType {MADB_DAE_NORMAL=0, MADB_DAE_ADD=1, MADB_DAE_UPDATE=2, MADB_DAE_DELETE=3}; 254 255 #define RESET_DAE_STATUS(Stmt_Hndl) (Stmt_Hndl)->Status=0; (Stmt_Hndl)->PutParam= -1 256 #define MARK_DAE_DONE(Stmt_Hndl) (Stmt_Hndl)->Status=0; (Stmt_Hndl)->PutParam= (Stmt_Hndl)->ParamCount 257 258 #define PARAM_IS_DAE(Len_Ptr) ((Len_Ptr) && (*(Len_Ptr) == SQL_DATA_AT_EXEC || *(Len_Ptr) <= SQL_LEN_DATA_AT_EXEC_OFFSET)) 259 #define DAE_DONE(Stmt_Hndl) ((Stmt_Hndl)->PutParam >= (Stmt_Hndl)->ParamCount) 260 261 enum MADB_StmtState {MADB_SS_INITED= 0, MADB_SS_EMULATED= 1, MADB_SS_PREPARED= 2, MADB_SS_EXECUTED= 3, MADB_SS_OUTPARAMSFETCHED= 4}; 262 263 #define STMT_WAS_PREPARED(Stmt_Hndl) (Stmt_Hndl->State >= MADB_SS_EMULATED) 264 #define RESET_STMT_STATE(Stmt_Hndl) Stmt_Hndl->State= STMT_WAS_PREPARED(Stmt_Hndl) ?\ 265 (Stmt_Hndl->State == MADB_SS_EMULATED ? MADB_SS_EMULATED : MADB_SS_PREPARED) :\ 266 MADB_SS_INITED 267 268 /* Struct used to define column type when driver has to fix it (in catalog functions + SQLGetTypeInfo) */ 269 typedef struct 270 { 271 SQLSMALLINT SqlType; 272 my_bool Unsigned; 273 SQLSMALLINT Nullable; 274 SQLLEN OctetLength; 275 276 } MADB_ShortTypeInfo; 277 278 typedef struct 279 { 280 unsigned int ArraySize; 281 my_bool HasRowsToSkip; 282 283 } MADB_BulkOperationInfo; 284 285 /* Stmt struct needs definitions from my_parse.h */ 286 #include <ma_parse.h> 287 288 #define STMT_STRING(STMT) (STMT)->Query.Original 289 290 struct st_ma_odbc_stmt 291 { 292 MADB_Dbc *Connection; 293 struct st_ma_stmt_methods *Methods; 294 MADB_StmtOptions Options; 295 MADB_Error Error; 296 MADB_Cursor Cursor; 297 MYSQL_STMT *stmt; 298 MYSQL_RES *metadata; 299 MADB_List ListItem; 300 MADB_QUERY Query; 301 SQLSMALLINT ParamCount; 302 enum MADB_DaeType DataExecutionType; 303 MYSQL_RES *DefaultsResult; 304 int ArrayOffset; 305 SQLSETPOSIROW DaeRowNumber; 306 int Status; 307 MADB_DescRecord *PutDataRec; 308 MADB_Stmt *DaeStmt; 309 MADB_Stmt *PositionedCursor; 310 my_bool PositionedCommand; 311 enum MADB_StmtState State; 312 MYSQL_STMT **MultiStmts; 313 unsigned int MultiStmtNr; 314 unsigned int MultiStmtMaxParam; 315 SQLLEN LastRowFetched; 316 MYSQL_BIND *result; 317 MYSQL_BIND *params; 318 int PutParam; 319 my_bool RebindParams; 320 my_bool bind_done; 321 long long AffectedRows; 322 unsigned long *CharOffset; 323 unsigned long *Lengths; 324 char *TableName; 325 char *CatalogName; 326 MADB_ShortTypeInfo *ColsTypeFixArr; 327 MADB_BulkOperationInfo Bulk; 328 /* Application Descriptors */ 329 MADB_Desc *Apd; 330 MADB_Desc *Ard; 331 MADB_Desc *Ird; 332 MADB_Desc *Ipd; 333 /* Internal Descriptors */ 334 MADB_Desc *IApd; 335 MADB_Desc *IArd; 336 MADB_Desc *IIrd; 337 MADB_Desc *IIpd; 338 }; 339 340 enum MADB_AppType{ 341 ATypeGeneral= 0, 342 ATypeMSAccess= 1 343 }; 344 345 typedef struct st_ma_odbc_environment { 346 MADB_Error Error; 347 CRITICAL_SECTION cs; 348 MADB_List *Dbcs; 349 SQLWCHAR *TraceFile; 350 SQLUINTEGER Trace; 351 SQLINTEGER OdbcVersion; 352 SQLINTEGER OutputNTS; 353 enum MADB_AppType AppType; 354 } MADB_Env; 355 356 //const size_t sizeOfT = sizeof(MADB_Env); 357 358 #include <ma_dsn.h> 359 360 361 typedef struct st_client_charset 362 { 363 unsigned int CodePage; 364 MARIADB_CHARSET_INFO *cs_info; 365 } Client_Charset; 366 367 struct st_ma_odbc_connection 368 { 369 MADB_Error Error; 370 CRITICAL_SECTION cs; /* mutex for mariadb handle, i.e. for server communications */ 371 CRITICAL_SECTION ListsCs; /* for operations with lists */ 372 MADB_List ListItem; 373 Client_Charset Charset; 374 MYSQL *mariadb; /* handle to a mariadb connection */ 375 MADB_Env *Environment; /* global environment */ 376 MADB_Dsn *Dsn; 377 struct st_ma_connection_methods *Methods; 378 379 Client_Charset *ConnOrSrcCharset; /* "Source" here stands for which charset Windows DM was using as source, when converted to unicode. 380 We have to use same charset to recode from unicode to get same string as application sent it. 381 For Unicode application that is the same as "Charset", or in case of ANSI on Windows - defaulst system codepage */ 382 char *CurrentSchema; /* Used to store current schema if the seesion tracking is possible */ 383 MADB_List *Stmts; 384 MADB_List *Descrs; 385 /* Attributes */ 386 char *CatalogName; 387 HWND QuietMode; 388 char *TraceFile; 389 390 SQLULEN AsyncEnable; 391 SQLPOINTER EnlistInDtc; 392 SQLULEN OdbcCursors; 393 unsigned long Options; 394 SQLUINTEGER AutoIpd; 395 SQLUINTEGER AutoCommit; 396 SQLUINTEGER ConnectionDead; 397 SQLUINTEGER ConnectionTimeout; 398 SQLUINTEGER ReadTimeout; 399 SQLUINTEGER WriteTimeout; 400 SQLUINTEGER PacketSize; 401 SQLINTEGER AccessMode; 402 SQLINTEGER IsolationLevel; /* tx_isolation */ 403 SQLUINTEGER Trace; 404 SQLUINTEGER LoginTimeout; 405 SQLUINTEGER MetadataId; 406 SQLINTEGER TxnIsolation; 407 SQLINTEGER CursorCount; 408 char ServerCapabilities; 409 my_bool IsAnsi; 410 my_bool IsMySQL; 411 }; 412 413 typedef BOOL (__stdcall *PromptDSN)(HWND hwnd, MADB_Dsn *Dsn); 414 415 typedef struct 416 { 417 void *LibraryHandle; 418 PromptDSN Call; 419 } MADB_Prompt; 420 421 #define MADB_PROMPT_NOT_SUPPORTED 1 422 #define MADB_PROMPT_COULDNT_LOAD 2 423 int DSNPrompt_Lookup(MADB_Prompt *prompt, const char *SetupLibName); 424 425 int DSNPrompt_Free (MADB_Prompt *prompt); 426 427 int InitClientCharset (Client_Charset *cc, const char *name); 428 void CopyClientCharset (Client_Charset *Src, Client_Charset *Dst); 429 void CloseClientCharset(Client_Charset *cc); 430 431 /* Default precision of SQL_NUMERIC */ 432 #define MADB_DEFAULT_PRECISION 38 433 #define MADB_MAX_SCALE MADB_DEFAULT_PRECISION 434 #define BINARY_CHARSETNR 63 435 /* Inexistent param id */ 436 #define MADB_NOPARAM -1 437 /* Macros to guard communications with the server. 438 TODO: make it(locking) optional depending on designated connection string option */ 439 #define LOCK_MARIADB(Dbc) EnterCriticalSection(&(Dbc)->cs) 440 #define UNLOCK_MARIADB(Dbc) LeaveCriticalSection(&(Dbc)->cs) 441 442 /* Enabling tracing */ 443 #define MAODBC_DEBUG 1 444 /* Macro checks return of the suplied SQLRETURN function call, checks if it is succeeded, and in case of error pushes error up */ 445 #define RETURN_ERROR_OR_CONTINUE(sqlreturn_func_call) {\ 446 SQLRETURN rc= (sqlreturn_func_call);\ 447 if (!SQL_SUCCEEDED(rc)) return rc;\ 448 } while(0) 449 450 #define iOdbc() (sizeof(SQLWCHAR)==4) 451 452 #include <ma_error.h> 453 #include <ma_info.h> 454 #include <ma_environment.h> 455 #include <ma_connection.h> 456 #include <ma_debug.h> 457 #include <ma_desc.h> 458 #include <ma_statement.h> 459 #include <ma_string.h> 460 #include <ma_result.h> 461 #include <ma_driver.h> 462 #include <ma_helper.h> 463 #include <ma_server.h> 464 #include <ma_typeconv.h> 465 #include <ma_bulk.h> 466 467 #include "ma_api_internal.h" 468 469 SQLRETURN MADB_GetBookmark(MADB_Stmt *StatementHandle, 470 SQLSMALLINT TargetType, 471 SQLPOINTER TargetValuePtr, 472 SQLLEN BufferLength, 473 SQLLEN *StrLen_or_IndPtr); 474 475 SQLRETURN MADB_StmtColAttr(MADB_Stmt *Stmt, SQLUSMALLINT ColumnNumber, SQLUSMALLINT FieldIdentifier, SQLPOINTER CharacterAttributePtr, 476 SQLSMALLINT BufferLength, SQLSMALLINT *StringLengthPtr, SQLLEN *NumericAttributePtr, my_bool IsWchar); 477 478 SQLRETURN MADB_StmtColAttr(MADB_Stmt *Stmt, SQLUSMALLINT ColumnNumber, SQLUSMALLINT FieldIdentifier, SQLPOINTER CharacterAttributePtr, 479 SQLSMALLINT BufferLength, SQLSMALLINT *StringLengthPtr, SQLLEN *NumericAttributePtr, my_bool IsWchar); 480 #endif /* _ma_odbc_h_ */ 481