2
Licensed Materials - Property of IBM
3
DB2 Storage Engine Enablement
4
Copyright IBM Corporation 2007,2008
7
Redistribution and use in source and binary forms, with or without modification,
8
are permitted provided that the following conditions are met:
9
(a) Redistributions of source code must retain this list of conditions, the
10
copyright notice in section {d} below, and the disclaimer following this
12
(b) Redistributions in binary form must reproduce this list of conditions, the
13
copyright notice in section (d) below, and the disclaimer following this
14
list of conditions, in the documentation and/or other materials provided
15
with the distribution.
16
(c) The name of IBM may not be used to endorse or promote products derived from
17
this software without specific prior written permission.
18
(d) The text of the required copyright notice is:
19
Licensed Materials - Property of IBM
20
DB2 Storage Engine Enablement
21
Copyright IBM Corporation 2007,2008
24
THIS SOFTWARE IS PROVIDED BY IBM CORPORATION "AS IS" AND ANY EXPRESS OR IMPLIED
25
WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
26
MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT
27
SHALL IBM CORPORATION BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
28
EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT
29
OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
30
INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
31
CONTRACT, STRICT LIABILITY, OR TORT INCLUDING NEGLIGENCE OR OTHERWISE) ARISING
32
IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY
37
#ifndef DB2I_ILEBRIDGE_H
38
#define DB2I_ILEBRIDGE_H
40
#include "db2i_global.h"
41
#include "mysql_priv.h"
42
#include "as400_types.h"
43
#include "as400_protos.h"
45
#include "db2i_errors.h"
47
typedef uint64_t FILE_HANDLE;
48
typedef my_thread_id CONNECTION_HANDLE;
49
const char SAVEPOINT_NAME[] = {0xD4,0xE2,0xD7,0xC9,0xD5,0xE3,0xC5,0xD9,0xD5,0x0};
50
const uint32 TACIT_ERRORS_SIZE=2;
52
enum db2i_InfoRequestSpec
64
extern handlerton *ibmdb2i_hton;
67
const uint32 db2i_ileBridge_MAX_INPARM_SIZE = 512;
68
const uint32 db2i_ileBridge_MAX_OUTPARM_SIZE = 512;
70
extern pthread_key(IleParms*, THR_ILEPARMS);
73
char inParms[db2i_ileBridge_MAX_INPARM_SIZE];
74
char outParms[db2i_ileBridge_MAX_OUTPARM_SIZE];
80
Implements a connection-based interface to the QMY_* APIs
82
@details Each client connection that touches an IBMDB2I table has a "bridge"
83
associated with it. This bridge is constructed on first use and provides a
84
more C-like interface to the APIs. As well, it is reponsible for tracking
85
connection scoped information such as statement transaction state and error
86
message text. The bridge is destroyed when the connection ends.
92
funcRegisterParameterSpaces,
99
static db2i_ileBridge* globalBridge;
104
static void takedown();
107
Obtain a pointer to the bridge for the current connection.
109
If a MySQL client connection is on the stack, we get the associated brideg.
110
Otherwise, we use the globalBridge.
112
static db2i_ileBridge* getBridgeForThread()
114
THD* thd = current_thd;
116
return getBridgeForThread(thd);
122
Obtain a pointer to the bridge for the specified connection.
124
If a bridge exists already, we return it immediately. Otherwise, prepare
125
a new bridge for the connection.
127
static db2i_ileBridge* getBridgeForThread(const THD* thd)
129
void* thdData = *thd_ha_data(thd, ibmdb2i_hton);
130
if (likely(thdData != NULL))
131
return (db2i_ileBridge*)(thdData);
133
db2i_ileBridge* newBridge = createNewBridge(thd->thread_id);
134
*thd_ha_data(thd, ibmdb2i_hton) = (void*)newBridge;
138
static void destroyBridgeForThread(const THD* thd);
139
static void registerPtr(const void* ptr, ILEMemHandle* receiver);
140
static void unregisterPtr(ILEMemHandle handle);
141
int32 allocateFileDefn(ILEMemHandle definitionSpace,
142
ILEMemHandle handleSpace,
144
const char* schemaName,
145
uint16 schemaNameLength,
146
ILEMemHandle formatSpace,
147
uint32 formatSpaceLen);
148
int32 allocateFileInstance(FILE_HANDLE defnHandle,
149
ILEMemHandle inuseSpace,
150
FILE_HANDLE* instance);
151
int32 deallocateFile(FILE_HANDLE fileHandle,
152
bool postDropTable=FALSE);
153
int32 read(FILE_HANDLE rfileHandle,
158
bool asyncRead = FALSE,
159
ILEMemHandle rrn = 0,
160
ILEMemHandle key = 0,
164
int32 readByRRN(FILE_HANDLE rfileHandle,
169
int32 writeRows(FILE_HANDLE rfileHandle,
176
uint32* dupKeyNameLen,
177
uint32* outIdIncrement);
178
uint32 execSQL(const char* statement,
179
uint32 statementCount,
181
bool autoCreateSchema = FALSE,
182
bool dropSchema = FALSE,
183
bool noCommit = FALSE,
184
FILE_HANDLE fileHandle = 0);
185
int32 prepOpen(const char* statement,
186
FILE_HANDLE* rfileHandle,
188
int32 deleteRow(FILE_HANDLE rfileHandle,
190
int32 updateRow(FILE_HANDLE rfileHandle,
195
uint32* dupKeyNameLen);
196
int32 commitmentControl(uint8 function);
197
int32 savepoint(uint8 function,
198
const char* savepointName);
199
int32 recordsInRange(FILE_HANDLE rfileHandle,
205
uint32 inLiteralsOff,
211
int32 rrlslck(FILE_HANDLE rfileHandle,
213
int32 lockObj(FILE_HANDLE rfileHandle,
218
int32 constraints(FILE_HANDLE rfileHandle,
223
int32 optimizeTable(FILE_HANDLE rfileHandle);
224
static int32 initILE(const char* aspName,
225
uint16* traceCtlPtr);
226
int32 initFileForIO(FILE_HANDLE rfileHandle,
230
uint16* inRecNullOffset,
232
uint16* outRecNullOffset);
233
int32 readInterrupt(FILE_HANDLE fileHandle);
234
static int32 exitILE();
236
int32 objectOverride(FILE_HANDLE rfileHandle,
238
uint32 recordWidth = 0);
240
int32 retrieveTableInfo(FILE_HANDLE rfileHandle,
241
uint16 dataRequested,
242
ha_statistics& stats,
243
ILEMemHandle inSpc = NULL);
245
int32 retrieveIndexInfo(FILE_HANDLE rfileHandle,
248
int32 closeConnection(CONNECTION_HANDLE conn);
249
int32 quiesceFileInstance(FILE_HANDLE rfileHandle);
252
Mark the beginning of a "statement transaction"
254
@detail MySQL "statement transactions" (see sql/handler.cc) are implemented
255
as DB2 savepoints having a predefined name.
257
@return 0 if successful; error otherwise
261
DBUG_ENTER("db2i_ileBridge::beginStmtTx");
267
DBUG_RETURN(savepoint(QMY_SET_SAVEPOINT, SAVEPOINT_NAME));
271
Commit a "statement transaction"
273
@return 0 if successful; error otherwise
275
uint32 commitStmtTx()
277
DBUG_ENTER("db2i_ileBridge::commitStmtTx");
278
DBUG_ASSERT(stmtTxActive);
279
stmtTxActive = false;
280
DBUG_RETURN(savepoint(QMY_RELEASE_SAVEPOINT, SAVEPOINT_NAME));
284
Roll back a "statement transaction"
286
@return 0 if successful; error otherwise
288
uint32 rollbackStmtTx()
290
DBUG_ENTER("db2i_ileBridge::rollbackStmtTx");
291
DBUG_ASSERT(stmtTxActive);
292
stmtTxActive = false;
293
DBUG_RETURN(savepoint(QMY_ROLLBACK_SAVEPOINT, SAVEPOINT_NAME));
298
Provide storage for generating error messages.
300
This storage must persist until the error message is retrieved from the
301
handler instance. It is for this reason that we associate it with the bridge.
303
@return Pointer to heap storage of MYSQL_ERRMSG_SIZE bytes
305
char* getErrorStorage()
309
connErrText = (char*)my_malloc(MYSQL_ERRMSG_SIZE, MYF(MY_WME));
310
if (connErrText) connErrText[0] = 0;
317
Free storage for generating error messages.
319
void freeErrorStorage()
321
if (likely(connErrText))
323
my_free(connErrText, MYF(0));
330
Store a file handle for later retrieval.
332
If deallocateFile encounters a lock when trying to perform its operation,
333
the file remains allocated but must be deallocated later. This function
334
provides a way for the connection to "remember" that this deallocation is
337
@param newname The name of the file to be added
338
@param newhandle The handle associated with newname
341
void preserveHandle(const char* newname, FILE_HANDLE newhandle, IBMDB2I_SHARE* share)
343
pendingLockedHandles.add(newname, newhandle, share);
347
Retrieve a file handle stored by preserveHandle().
349
@param name The name of the file to be retrieved.
351
@return The handle associated with name
353
FILE_HANDLE findAndRemovePreservedHandle(const char* name, IBMDB2I_SHARE** share)
355
FILE_HANDLE hdl = pendingLockedHandles.findAndRemove(name, share);
360
Indicate which error messages should be suppressed on the next API call
362
These functions are useful for ensuring that the provided error numbers
363
are returned if a failure occurs but do not cause a spurious error message
366
@return A pointer to this instance
368
db2i_ileBridge* expectErrors(int32 er1)
374
db2i_ileBridge* expectErrors(int32 er1, int32 er2)
382
Obtain the IBM i system message that accompanied the last API failure.
384
@return A pointer to the 7 character message ID.
386
static const char* getErrorMsgID()
388
return ((Qmy_Error_output_t*)parms()->outParms)->MsgId;
392
Convert an API error code into the equivalent MySQL error code (if any)
394
@param rc The QMYSE API error code
396
@return If an equivalent exists, the MySQL error code; else rc
398
static int32 translateErrorCode(int32 rc)
405
case QMY_ERR_KEY_NOT_FOUND:
406
return HA_ERR_KEY_NOT_FOUND;
407
case QMY_ERR_DUP_KEY:
408
return HA_ERR_FOUND_DUPP_KEY;
409
case QMY_ERR_END_OF_FILE:
410
return HA_ERR_END_OF_FILE;
411
case QMY_ERR_LOCK_TIMEOUT:
412
return HA_ERR_LOCK_WAIT_TIMEOUT;
413
case QMY_ERR_CST_VIOLATION:
414
return HA_ERR_NO_REFERENCED_ROW;
415
case QMY_ERR_TABLE_NOT_FOUND:
416
return HA_ERR_NO_SUCH_TABLE;
417
case QMY_ERR_NON_UNIQUE_KEY:
421
if (memcmp(getErrorMsgID(), DB2I_CPF503A, 7) == 0)
422
return HA_ERR_ROW_IS_REFERENCED;
423
if (memcmp(getErrorMsgID(), DB2I_SQL0538, 7) == 0)
424
return HA_ERR_CANNOT_ADD_FOREIGN;
432
static db2i_ileBridge* createNewBridge(CONNECTION_HANDLE connID);
433
static void destroyBridge(db2i_ileBridge* bridge);
434
static int registerParmSpace(char* in, char* out);
438
static _ILEpointer *functionSymbols; ///< Array of ILE function pointers
439
CONNECTION_HANDLE cachedConnectionID; ///< The associated connection
440
bool stmtTxActive; ///< Inside statement transaction
441
char *connErrText; ///< Storage for error message
442
int32 tacitErrors[TACIT_ERRORS_SIZE]; ///< List of errors to be suppressed
444
static IleParms* initParmsForThread();
447
Get space for passing parameters to the QMY_* APIs
449
@details A fixed-length parameter passing space is associated with each
450
pthread. This space is allocated and registered by initParmsForThread()
451
the first time a pthread works with a bridge. The space is cached away
452
and remains available until the pthread ends. It became necessary to
453
disassociate the parameter space from the bridge in order to support
454
future enhancements to MySQL that sever the one-to-one relationship between
455
pthreads and user connections. The QMY_* APIs scope a registered parameter
456
space to the thread that executes the register operation.
458
static IleParms* parms()
460
IleParms* p = my_pthread_getspecific_ptr(IleParms*, THR_ILEPARMS);
464
return initParmsForThread();
467
class PreservedHandleList
469
friend db2i_ileBridge* db2i_ileBridge::createNewBridge(CONNECTION_HANDLE);
471
void add(const char* newname, FILE_HANDLE newhandle, IBMDB2I_SHARE* share);
472
FILE_HANDLE findAndRemove(const char* fileName, IBMDB2I_SHARE** share);
475
struct NameHandlePair
477
char name[FN_REFLEN];
479
IBMDB2I_SHARE* share;
480
NameHandlePair* next;
482
} pendingLockedHandles;
486
bool cachedStateIsCoherent()
488
return (current_thd->thread_id == cachedConnectionID);
491
friend void db2i_ileBridge::unregisterPtr(ILEMemHandle);
492
friend void db2i_ileBridge::registerPtr(const void*, ILEMemHandle*);
493
static uint32 registeredPtrs;