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
#include "ha_ibmdb2i.h"
39
/* Helper function for records_in_range.
40
Input: Bitmap of used key parts.
41
Output: Number of used key parts. */
43
static inline int getKeyCntFromMap(key_part_map keypart_map)
48
keypart_map = keypart_map >> 1;
56
Given a starting key and an ending key, estimate the number of rows that
57
will exist between the two keys.
61
min_key Min key. Is NULL if no min range
62
max_key Max key. Is NULL if no max range
65
min_key.flag can have one of the following values:
66
HA_READ_KEY_EXACT Include the key in the range
67
HA_READ_AFTER_KEY Don't include key in range
69
max_key.flag can have one of the following values:
70
HA_READ_BEFORE_KEY Don't include key in range
71
HA_READ_AFTER_KEY Include all 'end_key' values in the range
74
HA_POS_ERROR Error or the storage engine cannot estimate the number of rows
75
1 There are no matching keys in the given range
76
n > 0 There are approximately n rows in the range
78
ha_rows ha_ibmdb2i::records_in_range(uint inx,
82
DBUG_ENTER("ha_ibmdb2i::records_in_range");
83
int rc = 0; // Return code
84
ha_rows rows = 0; // Row count returned to caller of this method
85
uint32 spcLen; // Length of space passed to DB2
86
uint32 keyCnt; // Number of fields in the key composite
87
uint32 literalCnt = 0; // Number of literals
88
uint32 boundsOff; // Offset from beginning of space to range bounds
89
uint32 litDefOff; // Offset from beginning of space to literal definitions
90
uint32 literalsOff; // Offset from beginning of space to literal values
91
uint32 cutoff = 0; // Early exit cutoff (currently not used)
92
uint64 recCnt; // Row count from DB2
93
uint16 rtnCode; // Return code from DB2
94
Bounds* boundsPtr; // Pointer to a pair of range bounds
95
Bound* boundPtr; // Pointer to a single (high or low) range bound
96
LitDef* litDefPtr; // Pointer to a literal definition
97
char* literalsPtr; // Pointer to the start of all literal values
98
char* literalPtr; // Pointer to the start of this literal value
99
char* tempPtr; // Temporary pointer
100
char* tempMinPtr; // Temporary pointer into min_key
101
int minKeyCnt = 0; // Number of fields in the min_key composite
102
int maxKeyCnt = 0; // Number of fields in the max_key composite
103
size_t tempLen = 0; // Temporary length
104
uint16 DB2FieldWidth = 0; // DB2 field width
105
uint32 workFieldLen = 0; // Length of workarea needed for CCSID conversions
106
bool overrideInclusion; // Indicator for inclusion/exclusion
107
char* endOfLiteralPtr; // Pointer to the end of this literal
108
char* endOfMinPtr; // Pointer to end of min_key
109
uint16 endByte = 0; // End byte of char or graphic literal (padding not included)
110
bool reuseLiteral; // Indicator that hi and lo bounds use same literal
111
char* minPtr = NULL; // Work pointer for traversing min_key
112
char* maxPtr = NULL; // Work pointer for traversing max_key
114
Handle the special case of 'x < null' anywhere in the key range. There are
115
no values less than null, but return 1 so that MySQL does not assume
116
the empty set for the query.
118
if (min_key != NULL && max_key != NULL &&
119
min_key->flag == HA_READ_AFTER_KEY && max_key->flag == HA_READ_BEFORE_KEY &&
120
min_key->length == max_key->length &&
121
(memcmp((uchar*)min_key->key,(uchar*)max_key->key,min_key->length)==0))
123
DBUG_PRINT("ha_ibmdb2i::records_in_range",("Estimate 1 row for key %d; special case: < null", inx));
124
DBUG_RETURN((ha_rows) 1 );
127
Determine the number of fields in the key composite.
132
minKeyCnt = getKeyCntFromMap(min_key->keypart_map);
133
minPtr = (char*)min_key->key;
137
maxKeyCnt = getKeyCntFromMap(max_key->keypart_map);
138
maxPtr = (char*)max_key->key;
140
keyCnt = maxKeyCnt >= minKeyCnt ? maxKeyCnt : minKeyCnt;
143
Handle the special case where MySQL does not pass either a min or max
144
key range. In this case, set the key count to 1 (knowing that there
145
is at least one key field) to flow through and create one bounds structure.
146
When both the min and max key ranges are nil, the bounds structure will
147
specify positive and negative infinity and DB2 will estimate the total
154
Allocate the space needed to pass range information to DB2. The
155
space must be large enough to store the following:
156
- one pair of bounds (high and low) per field in the key composite
157
- one literal definition per literal value
159
- work area for literal CCSID conversions
160
Since we don't know yet how many of these structures are needed,
161
allocate enough space for the maximum that we will possibly need.
162
The workarea for the literal conversion must be big enough to hold the
163
largest of the DB2 key fields.
165
KEY& curKey = table->key_info[inx];
167
for (int i = 0; i < keyCnt; i++)
170
db2Table->db2Field(curKey.key_part[i].field->field_index).getByteLengthInRecord();
171
if (DB2FieldWidth > workFieldLen)
172
workFieldLen = DB2FieldWidth; // Get length of largest DB2 field
173
tempLen = tempLen + DB2FieldWidth; // Tally the DB2 field lengths
175
spcLen = (sizeof(Bounds)*keyCnt) + (sizeof(LitDef)*keyCnt*2) + (tempLen*2) + workFieldLen;
177
ValidatedPointer<char> spcPtr(spcLen); // Pointer to space passed to DB2
178
memset(spcPtr, 0, spcLen); // Clear the allocated space
180
Set addressability to the various sections of the DB2 interface space.
182
boundsOff = 0; // Range bounds are at the start of the space
183
litDefOff = sizeof(Bounds) * keyCnt; // Literal defs follow all the range bounds
184
literalsOff = litDefOff + (sizeof(LitDef) * keyCnt * 2); // Literal values are last
185
boundsPtr = (Bounds_t*)(void*)spcPtr; // Address first bounds structure
186
tempPtr = (char*)((char*)spcPtr + litDefOff);
187
litDefPtr = (LitDef_t*)tempPtr; // Address first literal definition
188
tempPtr = (char*)((char*)spcPtr + literalsOff);
189
literalsPtr = (char*)tempPtr; // Address start of literal values
190
literalPtr = literalsPtr; // Address first literal value
192
For each key part, build the low (min) and high (max) DB2 range bounds.
193
If literals are specified in the MySQL range, build DB2 literal
194
definitions and store the literal values for access by DB2.
196
If no value is specified for a key part, assume infinity. Negative
197
infinity will cause processing to start at the first index entry.
198
Positive infinity will cause processing to end at the last index entry.
199
When infinity is specified in a bound, inclusion/exclusion and position
200
are ignored, and there is no literal definition or literal value for
203
If the keypart value is null, the null indicator is set in the range
204
bound and the other fields in the bound are ignored. When the bound is
205
null, only index entries with the null value will be included in the
206
estimate. If one bound is null, both bounds must be null. When the bound
207
is not null, the data offset and length must be set, and the literal
208
value stored for access by DB2.
210
for (int partsInUse = 0; partsInUse < keyCnt; ++partsInUse)
212
Field *field= curKey.key_part[partsInUse].field;
213
overrideInclusion = false;
214
reuseLiteral = false;
215
endOfLiteralPtr = NULL;
217
Build the low bound for the key range.
219
if ((partsInUse + 1) > minKeyCnt) // if no min_key info for this part
220
boundsPtr->LoBound.Infinity[0] = QMY_NEG_INFINITY; // select...where 3 between x and y
223
if ((curKey.key_part[partsInUse].null_bit) && (char*)minPtr[0])
225
if (max_key == NULL ||
226
((partsInUse + 1) > maxKeyCnt)) // select...where x='ab' and y=null and z != 'c'
227
boundsPtr->LoBound.Infinity[0] = QMY_NEG_INFINITY; // select...where x not null or
228
// select...where x > null
229
else // max_key is not null
231
if (min_key->flag == HA_READ_KEY_EXACT)
232
boundsPtr->LoBound.IsNull[0] = QMY_YES; // select...where x is null
235
if ((char*)maxPtr[0])
236
boundsPtr->LoBound.IsNull[0] = QMY_YES; // select...where a = null and b < 5 (max-before)
237
// select...where a='a' and b is null and c !='a' (max-after)
239
boundsPtr->LoBound.Infinity[0] = QMY_NEG_INFINITY; // select...where x < y
241
} // end min_key is null
243
else // min_key is not null
245
if (literalCnt) litDefPtr = litDefPtr + 1;
246
literalCnt = literalCnt + 1;
247
boundsPtr->LoBound.Position = literalCnt;
249
Determine inclusion or exclusion.
251
if (min_key->flag == HA_READ_KEY_EXACT || //select...where a like 'this%'
253
/* An example for the following conditions is 'select...where a = 5 and b > null'. */
256
(memcmp((uchar*)minPtr,(uchar*)maxPtr,
257
curKey.key_part[partsInUse].store_length)==0)))
260
if ((min_key->flag != HA_READ_KEY_EXACT) ||
262
(memcmp((uchar*)minPtr,(uchar*)maxPtr,
263
curKey.key_part[partsInUse].store_length)==0)))
264
overrideInclusion = true; // Need inclusion for both min and max
267
boundsPtr->LoBound.Embodiment[0] = QMY_EXCLUSION;
268
litDefPtr->FieldNbr = field->field_index + 1;
269
DB2Field& db2Field = db2Table->db2Field(field->field_index);
270
litDefPtr->DataType = db2Field.getType();
272
Convert the literal to DB2 format
274
if ((field->type() != MYSQL_TYPE_BIT) && // Don't do conversion on BIT data
275
(field->charset() != &my_charset_bin) && // Don't do conversion on BINARY data
276
(litDefPtr->DataType == QMY_CHAR ||
277
litDefPtr->DataType == QMY_VARCHAR ||
278
litDefPtr->DataType == QMY_GRAPHIC ||
279
litDefPtr->DataType == QMY_VARGRAPHIC))
281
// Most of the code is required by the considerable wrangling needed
282
// to prepare partial keys for use by DB2
283
// 1. UTF8 (CCSID 1208) data can be copied across unmodified if it is
284
// utf8_bin. Otherwise, we need to convert the min and max
285
// characters into the min and max characters employed
286
// by the DB2 sort sequence. This is complicated by the fact that
287
// the character widths are not always equal.
288
// 2. Likewise, UCS2 (CCSID 13488) data can be copied across unmodified
289
// if it is ucs2_bin or ucs2_general_ci. Otherwise, we need to
290
// convert the min and max characters into the min and max characters
291
// employed by the DB2 sort sequence.
292
// 3. All other data will use standard iconv conversions. If an
293
// unconvertible character is encountered, we assume it is the min
294
// char and fill the remainder of the DB2 key with 0s. This may not
295
// always be accurate, but it is probably sufficient for range
297
const char* keyData = minPtr+((curKey.key_part[partsInUse].null_bit)? 1 : 0);
298
char* db2Data = literalPtr;
299
uint16 outLen = db2Field.getByteLengthInRecord();
301
if (litDefPtr->DataType == QMY_VARCHAR ||
302
litDefPtr->DataType == QMY_VARGRAPHIC)
304
inLen = *(uint8*)keyData + ((*(uint8*)(keyData+1)) << 8);
306
outLen -= sizeof(uint16);
307
db2Data += sizeof(uint16);
311
inLen = field->max_display_length();
314
size_t convertedBytes = 0;
315
if (db2Field.getCCSID() == 1208)
317
DBUG_ASSERT(inLen <= outLen);
318
if (strcmp(field->charset()->name, "utf8_bin"))
320
const char* end = keyData+inLen;
321
const char* curKey = keyData;
322
char* curDB2 = db2Data;
323
uint32 min = field->charset()->min_sort_char;
324
while ((curKey < end) && (curDB2 < db2Data+outLen-3))
327
int len = field->charset()->cset->mb_wc(field->charset(),
329
(const uchar*)curKey,
333
DBUG_ASSERT(len <= 3);
336
case 3: *(curDB2+2) = *(curKey+2);
337
case 2: *(curDB2+1) = *(curKey+1);
338
case 1: *(curDB2) = *(curKey);
350
convertedBytes = curDB2 - db2Data;
354
memcpy(db2Data, keyData, inLen);
355
convertedBytes = inLen;
359
else if (db2Field.getCCSID() == 13488)
361
DBUG_ASSERT(inLen <= outLen);
362
if (strcmp(field->charset()->name, "ucs2_bin") &&
363
strcmp(field->charset()->name, "ucs2_general_ci"))
365
const char* end = keyData+inLen;
366
const uint16* curKey = (uint16*)keyData;
367
uint16* curDB2 = (uint16*)db2Data;
368
uint16 min = field->charset()->min_sort_char;
369
while (curKey < (uint16*)end)
381
memcpy(db2Data, keyData, inLen);
383
convertedBytes = inLen;
388
rc = convertFieldChars(toDB2,
397
if (rc == DB2I_ERR_ILL_CHAR)
399
// If an illegal character is encountered, we fill the remainder
400
// of the key with 0x00. This was implemented as a corollary to
401
// Bug#45012, though it should probably remain even after that
403
memset(db2Data+convertedBytes, 0x00, outLen-convertedBytes);
404
convertedBytes = outLen;
410
(litDefPtr->DataType == QMY_VARGRAPHIC ||
411
litDefPtr->DataType == QMY_VARCHAR))
413
*(uint16*)(db2Data-sizeof(uint16)) =
414
convertedBytes / (litDefPtr->DataType == QMY_VARGRAPHIC ? 2 : 1);
418
else // Non-character fields
420
rc = convertMySQLtoDB2(field,
423
(uchar*)minPtr+((curKey.key_part[partsInUse].null_bit)? 1 : 0));
427
litDefPtr->Offset = (uint32_t)(literalPtr - literalsPtr);
428
litDefPtr->Length = db2Field.getByteLengthInRecord();
429
literalPtr = literalPtr + litDefPtr->Length; // Bump pointer for next literal
431
/* If there is a max_key value for this field, and if the max_key value is
432
the same as the min_key value, then the low bound literal can be reused
433
for the high bound literal. This eliminates the overhead of copying and
434
converting the same value twice. */
435
if (max_key && ((partsInUse + 1) <= maxKeyCnt) &&
436
(memcmp((uchar*)minPtr,(uchar*)maxPtr,
437
curKey.key_part[partsInUse].store_length)==0 || endOfLiteralPtr))
439
minPtr += curKey.key_part[partsInUse].store_length;
442
Build the high bound for the key range.
444
if (max_key == NULL || ((partsInUse + 1) > maxKeyCnt))
445
boundsPtr->HiBound.Infinity[0] = QMY_POS_INFINITY;
448
if ((curKey.key_part[partsInUse].null_bit) && (char*)maxPtr[0])
451
boundsPtr->HiBound.Infinity[0] = QMY_POS_INFINITY;
453
boundsPtr->HiBound.IsNull[0] = QMY_YES; // select...where x is null
455
else // max_key field is not null
457
if (boundsPtr->LoBound.IsNull[0] == QMY_YES) // select where x < 10 or x is null
465
litDefPtr = litDefPtr + 1;
466
literalCnt = literalCnt + 1;
467
litDefPtr->FieldNbr = field->field_index + 1;
468
DB2Field& db2Field = db2Table->db2Field(field->field_index);
469
litDefPtr->DataType = db2Field.getType();
471
Convert the literal to DB2 format
473
if ((field->type() != MYSQL_TYPE_BIT) && // Don't do conversion on BIT data
474
(field->charset() != &my_charset_bin) && // Don't do conversion on BINARY data
475
(litDefPtr->DataType == QMY_CHAR ||
476
litDefPtr->DataType == QMY_VARCHAR ||
477
litDefPtr->DataType == QMY_GRAPHIC ||
478
litDefPtr->DataType == QMY_VARGRAPHIC))
480
// We need to handle char fields in a special way in order to account
481
// for partial keys. Refer to the note above for a description of the
483
char* keyData = maxPtr+((curKey.key_part[partsInUse].null_bit)? 1 : 0);
484
char* db2Data = literalPtr;
485
uint16 outLen = db2Field.getByteLengthInRecord();
487
if (litDefPtr->DataType == QMY_VARCHAR ||
488
litDefPtr->DataType == QMY_VARGRAPHIC)
490
inLen = *(uint8*)keyData + ((*(uint8*)(keyData+1)) << 8);
492
outLen -= sizeof(uint16);
493
db2Data += sizeof(uint16);
497
inLen = field->max_display_length();
500
size_t convertedBytes;
501
if (db2Field.getCCSID() == 1208)
503
if (strcmp(field->charset()->name, "utf8_bin"))
505
const char* end = keyData+inLen;
506
const char* curKey = keyData;
507
char* curDB2 = db2Data;
508
uint32 max = field->charset()->max_sort_char;
509
while (curKey < end && (curDB2 < db2Data+outLen-3))
512
int len = field->charset()->cset->mb_wc(field->charset(), &temp, (const uchar*)curKey, (const uchar*)end);
515
DBUG_ASSERT(len <= 3);
518
case 3: *(curDB2+2) = *(curKey+2);
519
case 2: *(curDB2+1) = *(curKey+1);
520
case 1: *(curDB2) = *(curKey);
532
convertedBytes = curDB2 - db2Data;
536
DBUG_ASSERT(inLen <= outLen);
537
memcpy(db2Data, keyData, inLen);
538
convertedBytes = inLen;
542
else if (db2Field.getCCSID() == 13488)
544
if (strcmp(field->charset()->name, "ucs2_bin") &&
545
strcmp(field->charset()->name, "ucs2_general_ci"))
547
char* end = keyData+inLen;
548
uint16* curKey = (uint16*)keyData;
549
uint16* curDB2 = (uint16*)db2Data;
550
uint16 max = field->charset()->max_sort_char;
551
while (curKey < (uint16*)end)
563
memcpy(db2Data, keyData, outLen);
569
size_t substituteChars = 0;
570
rc = convertFieldChars(toDB2,
580
if (rc == DB2I_ERR_ILL_CHAR)
582
// If an illegal character is encountered, we fill the remainder
583
// of the key with 0xFF. This was implemented to work around
584
// Bug#45012, though it should probably remain even after that
586
memset(db2Data+convertedBytes, 0xFF, outLen-convertedBytes);
589
else if ((substituteChars &&
590
(litDefPtr->DataType == QMY_VARCHAR ||
591
litDefPtr->DataType == QMY_CHAR)) ||
592
strcmp(field->charset()->name, "cp1251_bulgarian_ci") == 0)
594
// When iconv translates the max_sort_char with a substitute
595
// character, we have no way to know whether this affects
596
// the sort order of the key. Therefore, to be safe, when
597
// we know that substitute characters have been used in a
598
// single-byte string, we traverse the translated key
599
// in reverse, replacing substitue characters with 0xFF, which
600
// always sorts with the greatest weight in DB2 sort sequences.
601
// cp1251_bulgarian_ci is also handled this way because the
602
// max_sort_char is a control character which does not sort
603
// equivalently in DB2.
604
DBUG_ASSERT(inLen == outLen);
605
char* tmpKey = keyData + inLen - 1;
606
char* tmpDB2 = db2Data + outLen - 1;
607
while (*tmpKey == field->charset()->max_sort_char &&
618
(litDefPtr->DataType == QMY_VARGRAPHIC ||
619
litDefPtr->DataType == QMY_VARCHAR))
621
*(uint16*)(db2Data-sizeof(uint16)) =
622
outLen / (litDefPtr->DataType == QMY_VARGRAPHIC ? 2 : 1);
627
rc = convertMySQLtoDB2(field,
630
(uchar*)maxPtr+((curKey.key_part[partsInUse].null_bit)? 1 : 0));
633
litDefPtr->Offset = (uint32_t)(literalPtr - literalsPtr);
634
litDefPtr->Length = db2Field.getByteLengthInRecord();
635
literalPtr = literalPtr + litDefPtr->Length; // Bump pointer for next literal
637
boundsPtr->HiBound.Position = literalCnt;
638
if (max_key->flag == HA_READ_BEFORE_KEY && !overrideInclusion)
639
boundsPtr->HiBound.Embodiment[0] = QMY_EXCLUSION;
641
maxPtr += curKey.key_part[partsInUse].store_length;
644
Bump to the next field in the key composite.
647
if ((partsInUse+1) < keyCnt)
648
boundsPtr = boundsPtr + 1;
652
Call DB2 to estimate the number of rows in the key range.
656
rc = db2i_ileBridge::getBridgeForThread()->recordsInRange((indexHandles[inx] ? indexHandles[inx] : db2Table->indexFile(inx)->getMasterDefnHandle()),
664
(uint32_t)(literalPtr - (char*)spcPtr),
670
Set the row count and return.
671
Beware that if this method returns a zero row count, MySQL assumes the
672
result set for the query is zero; never return a zero row count.
674
if ((rc == 0) && (rtnCode == QMY_SUCCESS || rtnCode == QMY_EARLY_EXIT))
676
rows = recCnt ? (ha_rows)recCnt : 1;
679
rows = (rows > 0 ? rows : HA_POS_ERROR);
681
setIndexReadEstimate(inx, rows);
683
DBUG_PRINT("ha_ibmdb2i::recordsInRange",("Estimate %d rows for key %d", uint32(rows), inx));