summaryrefslogtreecommitdiff
path: root/storage
diff options
context:
space:
mode:
Diffstat (limited to 'storage')
-rw-r--r--storage/federated/ha_federated.cc42
-rw-r--r--storage/heap/ha_heap.cc8
-rw-r--r--storage/heap/ha_heap.h1
-rw-r--r--storage/ibmdb2i/db2i_charsetSupport.cc17
-rw-r--r--storage/ibmdb2i/db2i_collationSupport.cc14
-rw-r--r--storage/ibmdb2i/db2i_conversion.cc48
-rw-r--r--storage/ibmdb2i/db2i_misc.h16
-rw-r--r--storage/ibmdb2i/db2i_myconv.h1
-rw-r--r--storage/ibmdb2i/db2i_rir.cc401
-rw-r--r--storage/ibmdb2i/ha_ibmdb2i.cc193
-rw-r--r--storage/ibmdb2i/ha_ibmdb2i.h23
-rw-r--r--storage/innobase/Makefile.am5
-rw-r--r--storage/innobase/btr/btr0cur.c1
-rw-r--r--storage/innobase/fil/fil0fil.c6
-rw-r--r--storage/innobase/handler/ha_innodb.cc132
-rw-r--r--storage/innobase/include/fsp0fsp.h58
-rw-r--r--storage/innobase/include/fsp0types.h89
-rw-r--r--storage/innobase/include/mtr0log.ic24
-rw-r--r--storage/innobase/include/trx0rseg.ic1
-rw-r--r--storage/innobase/include/trx0sys.h6
-rw-r--r--storage/innobase/include/trx0sys.ic1
-rw-r--r--storage/innobase/row/row0mysql.c9
-rw-r--r--storage/innobase/trx/trx0purge.c1
-rw-r--r--storage/innobase/trx/trx0rec.c1
-rw-r--r--storage/innobase/trx/trx0sys.c14
-rw-r--r--storage/innobase/trx/trx0undo.c1
-rw-r--r--storage/myisam/ha_myisam.cc11
-rw-r--r--storage/myisam/ha_myisam.h1
-rw-r--r--storage/myisammrg/ha_myisammrg.cc3
-rw-r--r--storage/myisammrg/myrg_create.c2
-rw-r--r--storage/myisammrg/myrg_open.c20
31 files changed, 857 insertions, 293 deletions
diff --git a/storage/federated/ha_federated.cc b/storage/federated/ha_federated.cc
index 2fdf1bc7900..8deb8693960 100644
--- a/storage/federated/ha_federated.cc
+++ b/storage/federated/ha_federated.cc
@@ -2828,34 +2828,32 @@ int ha_federated::info(uint flag)
if (!(row= mysql_fetch_row(result)))
goto error;
- if (flag & (HA_STATUS_VARIABLE | HA_STATUS_CONST))
- {
- /*
- deleted is set in ha_federated::info
- */
- /*
- need to figure out what this means as far as federated is concerned,
- since we don't have a "file"
+ /*
+ deleted is set in ha_federated::info
+ */
+ /*
+ need to figure out what this means as far as federated is concerned,
+ since we don't have a "file"
- data_file_length = ?
- index_file_length = ?
- delete_length = ?
- */
- if (row[4] != NULL)
- stats.records= (ha_rows) my_strtoll10(row[4], (char**) 0,
+ data_file_length = ?
+ index_file_length = ?
+ delete_length = ?
+ */
+ if (row[4] != NULL)
+ stats.records= (ha_rows) my_strtoll10(row[4], (char**) 0,
&error);
- if (row[5] != NULL)
- stats.mean_rec_length= (ulong) my_strtoll10(row[5], (char**) 0, &error);
+ if (row[5] != NULL)
+ stats.mean_rec_length= (ulong) my_strtoll10(row[5], (char**) 0, &error);
- stats.data_file_length= stats.records * stats.mean_rec_length;
+ stats.data_file_length= stats.records * stats.mean_rec_length;
- if (row[12] != NULL)
- stats.update_time= (ulong) my_strtoll10(row[12], (char**) 0,
+ if (row[12] != NULL)
+ stats.update_time= (ulong) my_strtoll10(row[12], (char**) 0,
&error);
- if (row[13] != NULL)
- stats.check_time= (ulong) my_strtoll10(row[13], (char**) 0,
+ if (row[13] != NULL)
+ stats.check_time= (ulong) my_strtoll10(row[13], (char**) 0,
&error);
- }
+
/*
size of IO operations (This is based on a good guess, no high science
involved)
diff --git a/storage/heap/ha_heap.cc b/storage/heap/ha_heap.cc
index 19863d83874..fb7c13e4e41 100644
--- a/storage/heap/ha_heap.cc
+++ b/storage/heap/ha_heap.cc
@@ -419,6 +419,14 @@ int ha_heap::delete_all_rows()
return 0;
}
+
+int ha_heap::reset_auto_increment(ulonglong value)
+{
+ file->s->auto_increment= value;
+ return 0;
+}
+
+
int ha_heap::external_lock(THD *thd, int lock_type)
{
return 0; // No external locking
diff --git a/storage/heap/ha_heap.h b/storage/heap/ha_heap.h
index 5c5ad43658e..22722129f4c 100644
--- a/storage/heap/ha_heap.h
+++ b/storage/heap/ha_heap.h
@@ -98,6 +98,7 @@ public:
int reset();
int external_lock(THD *thd, int lock_type);
int delete_all_rows(void);
+ int reset_auto_increment(ulonglong value);
int disable_indexes(uint mode);
int enable_indexes(uint mode);
int indexes_are_disabled(void);
diff --git a/storage/ibmdb2i/db2i_charsetSupport.cc b/storage/ibmdb2i/db2i_charsetSupport.cc
index 1479776d71a..83bf1b9448b 100644
--- a/storage/ibmdb2i/db2i_charsetSupport.cc
+++ b/storage/ibmdb2i/db2i_charsetSupport.cc
@@ -245,11 +245,16 @@ static int32 getNewTextDesc(const int32 inType,
else if ((inType == Qlg_TypeAS400CCSID) && (outType == Qlg_TypeAix41))
{
// Override non-standard charsets
- if (unlikely(strcmp("1148", in) == 0))
+ if (strcmp("1148", in) == 0)
{
strcpy(out, "IBM-1148");
DBUG_RETURN(0);
}
+ else if (unlikely(strcmp("1153", in) == 0))
+ {
+ strcpy(out, "IBM-1153");
+ DBUG_RETURN(0);
+ }
}
char argBuf[sizeof(ArgList)+15];
@@ -379,6 +384,11 @@ static int32 convertTextDesc(const int32 inType, const int32 outType, const char
strcpy(outDesc,"IBM-1256");
DBUG_RETURN(0);
}
+ else if (strcmp("macce", inDescOverride) == 0)
+ {
+ strcpy(outDesc,"IBM-1282");
+ DBUG_RETURN(0);
+ }
}
else if (outType == Qlg_TypeAS400CCSID)
{
@@ -583,6 +593,11 @@ int32 getAssociatedCCSID(const uint16 inCcsid, const int inEncodingScheme, uint1
*outCcsid = 1148;
DBUG_RETURN(0);
}
+ else if ((inCcsid == 1250) && (inEncodingScheme == 0x1100))
+ {
+ *outCcsid = 1153;
+ DBUG_RETURN(0);
+ }
if (!ptrInited)
{
diff --git a/storage/ibmdb2i/db2i_collationSupport.cc b/storage/ibmdb2i/db2i_collationSupport.cc
index a41f211a689..65a17fd2452 100644
--- a/storage/ibmdb2i/db2i_collationSupport.cc
+++ b/storage/ibmdb2i/db2i_collationSupport.cc
@@ -44,7 +44,7 @@ OF SUCH DAMAGE.
between corresponding array slots but is incomplete without case-sensitivity
markers dynamically added to the mySqlSortSequence names.
*/
-#define MAX_COLLATION 89
+#define MAX_COLLATION 87
static const char* mySQLCollation[MAX_COLLATION] =
{
{"ascii_general"},
@@ -52,7 +52,6 @@ static const char* mySQLCollation[MAX_COLLATION] =
{"big5_chinese"},
{"big5"},
{"cp1250_croatian"},
- {"cp1250_czech"},
{"cp1250_general"},
{"cp1250_polish"},
{"cp1250"},
@@ -84,7 +83,6 @@ static const char* mySQLCollation[MAX_COLLATION] =
{"latin1_swedish"},
{"latin1"},
{"latin2_croatian"},
- {"latin2_czech"},
{"latin2_general"},
{"latin2_hungarian"},
{"latin2"},
@@ -146,7 +144,6 @@ static const char* mySqlSortSequence[MAX_COLLATION] =
{"QACHT04B0"},
{"QBCHT04B0"},
{"QALA20481"},
- {"QBLA20481"},
{"QCLA20481"},
{"QDLA20481"},
{"QELA20481"},
@@ -178,7 +175,6 @@ static const char* mySqlSortSequence[MAX_COLLATION] =
{"QELA1047C"},
{"QFLA1047C"},
{"QCLA20366"},
- {"QDLA20366"},
{"QELA20366"},
{"QFLA20366"},
{"QGLA20366"},
@@ -190,8 +186,8 @@ static const char* mySqlSortSequence[MAX_COLLATION] =
{"QDJPN04B0"},
{"QATHA0346"},
{"QBTHA0346"},
- {"ACS"},
- {"ADA"},
+ {"ACS_CZ"},
+ {"ADA_DK"},
{"AEO"},
{"AET"},
{"QAUCS04B0"},
@@ -211,8 +207,8 @@ static const char* mySqlSortSequence[MAX_COLLATION] =
{"*HEX"},
{"QEJPN04B0"},
{"QFJPN04B0"},
- {"ACS"},
- {"ADA"},
+ {"ACS_CZ"},
+ {"ADA_DK"},
{"AEO"},
{"AET"},
{"QAUCS04B0"},
diff --git a/storage/ibmdb2i/db2i_conversion.cc b/storage/ibmdb2i/db2i_conversion.cc
index bdb8085d937..9a85eb01c9b 100644
--- a/storage/ibmdb2i/db2i_conversion.cc
+++ b/storage/ibmdb2i/db2i_conversion.cc
@@ -137,7 +137,9 @@ int ha_ibmdb2i::convertFieldChars(enum_conversionDirection direction,
char* output,
size_t ilen,
size_t olen,
- size_t* outDataLen)
+ size_t* outDataLen,
+ bool tacitErrors,
+ size_t* substChars)
{
DBUG_PRINT("ha_ibmdb2i::convertFieldChars",("Direction: %d; length = %d", direction, ilen));
@@ -157,26 +159,26 @@ int ha_ibmdb2i::convertFieldChars(enum_conversionDirection direction,
size_t initOLen= olen;
size_t substitutedChars = 0;
int rc = iconv(conversion, (char**)&input, &ilen, &output, &olen, &substitutedChars );
+ if (outDataLen) *outDataLen = initOLen - olen;
+ if (substChars) *substChars = substitutedChars;
if (unlikely(rc < 0))
{
int er = errno;
if (er == EILSEQ)
{
- getErrTxt(DB2I_ERR_ILL_CHAR, table->field[fieldID]->field_name);
+ if (!tacitErrors) getErrTxt(DB2I_ERR_ILL_CHAR, table->field[fieldID]->field_name);
return (DB2I_ERR_ILL_CHAR);
}
else
{
- getErrTxt(DB2I_ERR_ICONV,er);
+ if (!tacitErrors) getErrTxt(DB2I_ERR_ICONV,er);
return (DB2I_ERR_ICONV);
}
}
- if (unlikely(substitutedChars))
+ if (unlikely(substitutedChars) && (!tacitErrors))
{
warning(ha_thd(), DB2I_ERR_SUB_CHARS, table->field[fieldID]->field_name);
}
-
- if (outDataLen) *outDataLen = initOLen - olen;
return (0);
}
@@ -555,12 +557,12 @@ int ha_ibmdb2i::getFieldTypeMapping(Field* field,
return 1;
if (fieldCharSet->mbmaxlen > 1)
{
- if (strncmp(fieldCharSet->name, "ucs2_", sizeof("ucs2_")) == 0 ) // UCS2
+ if (memcmp(fieldCharSet->name, "ucs2_", sizeof("ucs2_")-1) == 0 ) // UCS2
{
sprintf(stringBuildBuffer, "GRAPHIC(%d)", max(fieldLength / fieldCharSet->mbmaxlen, 1)); // Number of characters
db2Ccsid = 13488;
}
- else if (strncmp(fieldCharSet->name, "utf8_", sizeof("utf8_")) == 0 &&
+ else if (memcmp(fieldCharSet->name, "utf8_", sizeof("utf8_")-1) == 0 &&
strcmp(fieldCharSet->name, "utf8_general_ci") != 0)
{
sprintf(stringBuildBuffer, "CHAR(%d)", max(fieldLength, 1)); // Number of bytes
@@ -584,12 +586,12 @@ int ha_ibmdb2i::getFieldTypeMapping(Field* field,
{
if (fieldCharSet->mbmaxlen > 1)
{
- if (strncmp(fieldCharSet->name, "ucs2_", sizeof("ucs2_")) == 0 ) // UCS2
+ if (memcmp(fieldCharSet->name, "ucs2_", sizeof("ucs2_")-1) == 0 ) // UCS2
{
sprintf(stringBuildBuffer, "VARGRAPHIC(%d)", max(fieldLength / fieldCharSet->mbmaxlen, 1)); // Number of characters
db2Ccsid = 13488;
}
- else if (strncmp(fieldCharSet->name, "utf8_", sizeof("utf8_")) == 0 &&
+ else if (memcmp(fieldCharSet->name, "utf8_", sizeof("utf8_")-1) == 0 &&
strcmp(fieldCharSet->name, "utf8_general_ci") != 0)
{
sprintf(stringBuildBuffer, "VARCHAR(%d)", max(fieldLength, 1)); // Number of bytes
@@ -611,12 +613,12 @@ int ha_ibmdb2i::getFieldTypeMapping(Field* field,
{
if (fieldCharSet->mbmaxlen > 1)
{
- if (strncmp(fieldCharSet->name, "ucs2_", sizeof("ucs2_")) == 0 ) // UCS2
+ if (memcmp(fieldCharSet->name, "ucs2_", sizeof("ucs2_")-1) == 0 ) // UCS2
{
sprintf(stringBuildBuffer, "LONG VARGRAPHIC ");
db2Ccsid = 13488;
}
- else if (strncmp(fieldCharSet->name, "utf8_", sizeof("utf8_")) == 0 &&
+ else if (memcmp(fieldCharSet->name, "utf8_", sizeof("utf8_")-1) == 0 &&
strcmp(fieldCharSet->name, "utf8_general_ci") != 0)
{
sprintf(stringBuildBuffer, "LONG VARCHAR ");
@@ -639,12 +641,12 @@ int ha_ibmdb2i::getFieldTypeMapping(Field* field,
if (fieldCharSet->mbmaxlen > 1)
{
- if (strncmp(fieldCharSet->name, "ucs2_", sizeof("ucs2_")) == 0 ) // UCS2
+ if (memcmp(fieldCharSet->name, "ucs2_", sizeof("ucs2_")-1) == 0 ) // UCS2
{
sprintf(stringBuildBuffer, "DBCLOB(%d)", max(fieldLength / fieldCharSet->mbmaxlen, 1)); // Number of characters
db2Ccsid = 13488;
}
- else if (strncmp(fieldCharSet->name, "utf8_", sizeof("utf8_")) == 0 &&
+ else if (memcmp(fieldCharSet->name, "utf8_", sizeof("utf8_")-1) == 0 &&
strcmp(fieldCharSet->name, "utf8_general_ci") != 0)
{
sprintf(stringBuildBuffer, "CLOB(%d)", max(fieldLength, 1)); // Number of bytes
@@ -671,11 +673,15 @@ int ha_ibmdb2i::getFieldTypeMapping(Field* field,
return rtnCode;
}
- // Check whether there is a character conversion available.
- iconv_t temp;
- int32 rc = getConversion(toDB2, fieldCharSet, db2Ccsid, temp);
- if (unlikely(rc))
- return rc;
+ if (db2Ccsid != 1208 &&
+ db2Ccsid != 13488)
+ {
+ // Check whether there is a character conversion available.
+ iconv_t temp;
+ int32 rc = getConversion(toDB2, fieldCharSet, db2Ccsid, temp);
+ if (unlikely(rc))
+ return rc;
+ }
sprintf(stringBuildBuffer, " CCSID %d ", db2Ccsid);
mapping.append(stringBuildBuffer);
@@ -1085,7 +1091,7 @@ int32 ha_ibmdb2i::convertMySQLtoDB2(Field* field, const DB2Field& db2Field, char
if (bytesToStore)
memcpy(db2Buf, dataToStore, bytesToStore);
if (bytesToPad)
- wmemset((wchar_t*)(db2Buf + bytesToStore), 0x0020, bytesToPad/2);
+ memset16((db2Buf + bytesToStore), 0x0020, bytesToPad/2);
}
else
{
@@ -1108,7 +1114,7 @@ int32 ha_ibmdb2i::convertMySQLtoDB2(Field* field, const DB2Field& db2Field, char
bytesToStore = db2BytesToStore;
}
if (db2BytesToStore < maxDb2BytesToStore) // If need to pad
- wmemset((wchar_t*)(db2Buf + db2BytesToStore), 0x0020, (maxDb2BytesToStore - db2BytesToStore)/2);
+ memset16((db2Buf + db2BytesToStore), 0x0020, (maxDb2BytesToStore - db2BytesToStore)/2);
}
if (db2FieldType == QMY_VARGRAPHIC)
diff --git a/storage/ibmdb2i/db2i_misc.h b/storage/ibmdb2i/db2i_misc.h
index 9e20f01208b..f0b527aaad0 100644
--- a/storage/ibmdb2i/db2i_misc.h
+++ b/storage/ibmdb2i/db2i_misc.h
@@ -109,5 +109,21 @@ bool isOrdinaryIdentifier(const char* s)
}
return true;
}
+
+/**
+ Fill memory with a 16-bit word.
+ @param p Pointer to space to fill.
+ @param v Value to fill
+ @param l Length of space (in 16-bit words)
+*/
+void memset16(void* p, uint16 v, size_t l)
+{
+ uint16* p2=(uint16*)p;
+ while (l--)
+ {
+ *(p2++) = v;
+ }
+}
+
#endif
diff --git a/storage/ibmdb2i/db2i_myconv.h b/storage/ibmdb2i/db2i_myconv.h
index a9e87474505..98032748148 100644
--- a/storage/ibmdb2i/db2i_myconv.h
+++ b/storage/ibmdb2i/db2i_myconv.h
@@ -220,6 +220,7 @@ INTERN size_t myconv_dmap(myconv_t cd,
} else {
*pOut=dmapS2S[*pIn];
if (*pOut == 0x00) {
+ errno=EILSEQ; /* 116 */
*outBytesLeft-=(*inBytesLeft-inLen);
*inBytesLeft=inLen;
*outBuf=pOut;
diff --git a/storage/ibmdb2i/db2i_rir.cc b/storage/ibmdb2i/db2i_rir.cc
index a80a181c9ac..091c4d98383 100644
--- a/storage/ibmdb2i/db2i_rir.cc
+++ b/storage/ibmdb2i/db2i_rir.cc
@@ -51,7 +51,6 @@ static inline int getKeyCntFromMap(key_part_map keypart_map)
return (cnt);
}
-
/**
@brief
Given a starting key and an ending key, estimate the number of rows that
@@ -270,81 +269,163 @@ ha_rows ha_ibmdb2i::records_in_range(uint inx,
DB2Field& db2Field = db2Table->db2Field(field->field_index);
litDefPtr->DataType = db2Field.getType();
/*
- Convert the literal to DB2 format.
- */
- rc = convertMySQLtoDB2(field,
- db2Field,
- literalPtr,
- (uchar*)minPtr+((curKey.key_part[partsInUse].null_bit)? 1 : 0));
- if (rc != 0) break;
- litDefPtr->Offset = (uint32_t)(literalPtr - literalsPtr);
- litDefPtr->Length = db2Field.getByteLengthInRecord();
- tempLen = litDefPtr->Length;
- /*
- Do additional conversion of a character or graphic value.
- */
- CHARSET_INFO* fieldCharSet = field->charset();
+ Convert the literal to DB2 format
+ */
if ((field->type() != MYSQL_TYPE_BIT) && // Don't do conversion on BIT data
(field->charset() != &my_charset_bin) && // Don't do conversion on BINARY data
- (litDefPtr->DataType == QMY_CHAR || litDefPtr->DataType == QMY_VARCHAR ||
- litDefPtr->DataType == QMY_GRAPHIC || litDefPtr->DataType == QMY_VARGRAPHIC))
+ (litDefPtr->DataType == QMY_CHAR ||
+ litDefPtr->DataType == QMY_VARCHAR ||
+ litDefPtr->DataType == QMY_GRAPHIC ||
+ litDefPtr->DataType == QMY_VARGRAPHIC))
{
- if (litDefPtr->DataType == QMY_VARCHAR ||
- litDefPtr->DataType == QMY_VARGRAPHIC)
- tempPtr = literalPtr + sizeof(uint16);
- else
- tempPtr = literalPtr;
- /* The following code checks to determine if MySQL is passing a
- partial key. DB2 will accept a partial field value, but only
- in the last field position of the key composite (and only if
- there is no ICU sort sequence on the index). */
- tempMinPtr = (char*)minPtr+((curKey.key_part[partsInUse].null_bit)? 1 : 0);
- if (field->type() == MYSQL_TYPE_VARCHAR)
- {
- /* MySQL always stores key lengths as 2 bytes, little-endian. */
- tempLen = *(uint8*)tempMinPtr + ((*(uint8*)(tempMinPtr+1)) << 8);
- tempMinPtr = (char*)((char*)tempMinPtr + 2);
- }
- else
- tempLen = field->field_length;
-
- /* Determine if we are dealing with a partial key and if so, find the end of the partial key. */
- if (litDefPtr->DataType == QMY_CHAR || litDefPtr->DataType == QMY_VARCHAR )
- { /* Char or varchar. If UTF8, no conversion is done to DB2 graphic.) */
- endOfMinPtr = (char*)memchr(tempMinPtr,field->charset()->min_sort_char,tempLen);
- if (endOfMinPtr)
- endOfLiteralPtr = tempPtr + ((uint32_t)(endOfMinPtr - tempMinPtr));
- }
- else
- {
- if (strncmp(fieldCharSet->csname, "utf8", sizeof("utf8")) == 0)
- { /* The MySQL charset is UTF8 but we are converting to graphic on DB2. Divide number of UTF8 bytes
- by 3 to get the number of characters, then multiple by 2 for double-byte graphic.*/
- endOfMinPtr = (char*)memchr(tempMinPtr,field->charset()->min_sort_char,tempLen);
- if (endOfMinPtr)
- endOfLiteralPtr = tempPtr + (((uint32_t)((endOfMinPtr - tempMinPtr)) / 3) * 2);
- }
- else
- { /* The DB2 data type is graphic or vargraphic, and we are not converting from UTF8 to graphic. */
- endOfMinPtr = (char*)wmemchr((wchar_t*)tempMinPtr,field->charset()->min_sort_char,tempLen/2);
- if (endOfMinPtr)
- endOfLiteralPtr = tempPtr + (endOfMinPtr - tempMinPtr);
+ // Most of the code is required by the considerable wrangling needed
+ // to prepare partial keys for use by DB2
+ // 1. UTF8 (CCSID 1208) data can be copied across unmodified if it is
+ // utf8_bin. Otherwise, we need to convert the min and max
+ // characters into the min and max characters employed
+ // by the DB2 sort sequence. This is complicated by the fact that
+ // the character widths are not always equal.
+ // 2. Likewise, UCS2 (CCSID 13488) data can be copied across unmodified
+ // if it is ucs2_bin or ucs2_general_ci. Otherwise, we need to
+ // convert the min and max characters into the min and max characters
+ // employed by the DB2 sort sequence.
+ // 3. All other data will use standard iconv conversions. If an
+ // unconvertible character is encountered, we assume it is the min
+ // char and fill the remainder of the DB2 key with 0s. This may not
+ // always be accurate, but it is probably sufficient for range
+ // estimations.
+ const char* keyData = minPtr+((curKey.key_part[partsInUse].null_bit)? 1 : 0);
+ char* db2Data = literalPtr;
+ uint16 outLen = db2Field.getByteLengthInRecord();
+ uint16 inLen;
+ if (litDefPtr->DataType == QMY_VARCHAR ||
+ litDefPtr->DataType == QMY_VARGRAPHIC)
+ {
+ inLen = *(uint8*)keyData + ((*(uint8*)(keyData+1)) << 8);
+ keyData += 2;
+ outLen -= sizeof(uint16);
+ db2Data += sizeof(uint16);
+ }
+ else
+ {
+ inLen = field->max_display_length();
+ }
+
+ size_t convertedBytes = 0;
+ if (db2Field.getCCSID() == 1208)
+ {
+ DBUG_ASSERT(inLen <= outLen);
+ if (strcmp(field->charset()->name, "utf8_bin"))
+ {
+ const char* end = keyData+inLen;
+ const char* curKey = keyData;
+ char* curDB2 = db2Data;
+ uint32 min = field->charset()->min_sort_char;
+ while ((curKey < end) && (curDB2 < db2Data+outLen-3))
+ {
+ my_wc_t temp;
+ int len = field->charset()->cset->mb_wc(field->charset(),
+ &temp,
+ (const uchar*)curKey,
+ (const uchar*)end);
+ if (temp != min)
+ {
+ DBUG_ASSERT(len <= 3);
+ switch (len)
+ {
+ case 3: *(curDB2+2) = *(curKey+2);
+ case 2: *(curDB2+1) = *(curKey+1);
+ case 1: *(curDB2) = *(curKey);
+ }
+ curDB2 += len;
+ }
+ else
+ {
+ *(curDB2++) = 0xEF;
+ *(curDB2++) = 0xBF;
+ *(curDB2++) = 0xBF;
+ }
+ curKey += len;
+ }
+ convertedBytes = curDB2 - db2Data;
+ }
+ else
+ {
+ memcpy(db2Data, keyData, inLen);
+ convertedBytes = inLen;
+ }
+ rc = 0;
+ }
+ else if (db2Field.getCCSID() == 13488)
+ {
+ DBUG_ASSERT(inLen <= outLen);
+ if (strcmp(field->charset()->name, "ucs2_bin") &&
+ strcmp(field->charset()->name, "ucs2_general_ci"))
+ {
+ const char* end = keyData+inLen;
+ const uint16* curKey = (uint16*)keyData;
+ uint16* curDB2 = (uint16*)db2Data;
+ uint16 min = field->charset()->min_sort_char;
+ while (curKey < (uint16*)end)
+ {
+ if (*curKey != min)
+ *curDB2 = *curKey;
+ else
+ *curDB2 = 0xFFFF;
+ ++curKey;
+ ++curDB2;
}
- }
- /* Enforce here that a partial is only allowed on the last field position
- of the key composite */
- if (endOfLiteralPtr)
- {
- if ((partsInUse + 1) < minKeyCnt)
- {
- rc = HA_POS_ERROR;
- break;
- }
- endByte = endOfLiteralPtr - tempPtr;
- /* We're making an assumption that if MySQL gives us a partial key,
- the length of the partial is the same for both the min_key and max_key. */
- }
+ }
+ else
+ {
+ memcpy(db2Data, keyData, inLen);
+ }
+ convertedBytes = inLen;
+ rc = 0;
+ }
+ else
+ {
+ rc = convertFieldChars(toDB2,
+ field->field_index,
+ keyData,
+ db2Data,
+ inLen,
+ outLen,
+ &convertedBytes,
+ true);
+
+ if (rc == DB2I_ERR_ILL_CHAR)
+ {
+ // If an illegal character is encountered, we fill the remainder
+ // of the key with 0x00. This was implemented as a corollary to
+ // Bug#45012, though it should probably remain even after that
+ // bug is fixed.
+ memset(db2Data+convertedBytes, 0x00, outLen-convertedBytes);
+ convertedBytes = outLen;
+ rc = 0;
+ }
+ }
+
+ if (!rc &&
+ (litDefPtr->DataType == QMY_VARGRAPHIC ||
+ litDefPtr->DataType == QMY_VARCHAR))
+ {
+ *(uint16*)(db2Data-sizeof(uint16)) =
+ convertedBytes / (litDefPtr->DataType == QMY_VARGRAPHIC ? 2 : 1);
+ }
+
}
+ else // Non-character fields
+ {
+ rc = convertMySQLtoDB2(field,
+ db2Field,
+ literalPtr,
+ (uchar*)minPtr+((curKey.key_part[partsInUse].null_bit)? 1 : 0));
+ }
+
+ if (rc != 0) break;
+ litDefPtr->Offset = (uint32_t)(literalPtr - literalsPtr);
+ litDefPtr->Length = db2Field.getByteLengthInRecord();
literalPtr = literalPtr + litDefPtr->Length; // Bump pointer for next literal
}
/* If there is a max_key value for this field, and if the max_key value is
@@ -389,28 +470,168 @@ ha_rows ha_ibmdb2i::records_in_range(uint inx,
/*
Convert the literal to DB2 format
*/
- rc = convertMySQLtoDB2(field,
- db2Field,
- literalPtr,
- (uchar*)maxPtr+((curKey.key_part[partsInUse].null_bit)? 1 : 0));
+ if ((field->type() != MYSQL_TYPE_BIT) && // Don't do conversion on BIT data
+ (field->charset() != &my_charset_bin) && // Don't do conversion on BINARY data
+ (litDefPtr->DataType == QMY_CHAR ||
+ litDefPtr->DataType == QMY_VARCHAR ||
+ litDefPtr->DataType == QMY_GRAPHIC ||
+ litDefPtr->DataType == QMY_VARGRAPHIC))
+ {
+ // We need to handle char fields in a special way in order to account
+ // for partial keys. Refer to the note above for a description of the
+ // basic design.
+ char* keyData = maxPtr+((curKey.key_part[partsInUse].null_bit)? 1 : 0);
+ char* db2Data = literalPtr;
+ uint16 outLen = db2Field.getByteLengthInRecord();
+ uint16 inLen;
+ if (litDefPtr->DataType == QMY_VARCHAR ||
+ litDefPtr->DataType == QMY_VARGRAPHIC)
+ {
+ inLen = *(uint8*)keyData + ((*(uint8*)(keyData+1)) << 8);
+ keyData += 2;
+ outLen -= sizeof(uint16);
+ db2Data += sizeof(uint16);
+ }
+ else
+ {
+ inLen = field->max_display_length();
+ }
+
+ size_t convertedBytes;
+ if (db2Field.getCCSID() == 1208)
+ {
+ if (strcmp(field->charset()->name, "utf8_bin"))
+ {
+ const char* end = keyData+inLen;
+ const char* curKey = keyData;
+ char* curDB2 = db2Data;
+ uint32 max = field->charset()->max_sort_char;
+ while (curKey < end && (curDB2 < db2Data+outLen-3))
+ {
+ my_wc_t temp;
+ int len = field->charset()->cset->mb_wc(field->charset(), &temp, (const uchar*)curKey, (const uchar*)end);
+ if (temp != max)
+ {
+ DBUG_ASSERT(len <= 3);
+ switch (len)
+ {
+ case 3: *(curDB2+2) = *(curKey+2);
+ case 2: *(curDB2+1) = *(curKey+1);
+ case 1: *(curDB2) = *(curKey);
+ }
+ curDB2 += len;
+ }
+ else
+ {
+ *(curDB2++) = 0xE4;
+ *(curDB2++) = 0xB6;
+ *(curDB2++) = 0xBF;
+ }
+ curKey += len;
+ }
+ convertedBytes = curDB2 - db2Data;
+ }
+ else
+ {
+ DBUG_ASSERT(inLen <= outLen);
+ memcpy(db2Data, keyData, inLen);
+ convertedBytes = inLen;
+ }
+ rc = 0;
+ }
+ else if (db2Field.getCCSID() == 13488)
+ {
+ if (strcmp(field->charset()->name, "ucs2_bin") &&
+ strcmp(field->charset()->name, "ucs2_general_ci"))
+ {
+ char* end = keyData+inLen;
+ uint16* curKey = (uint16*)keyData;
+ uint16* curDB2 = (uint16*)db2Data;
+ uint16 max = field->charset()->max_sort_char;
+ while (curKey < (uint16*)end)
+ {
+ if (*curKey != max)
+ *curDB2 = *curKey;
+ else
+ *curDB2 = 0x4DBF;
+ ++curKey;
+ ++curDB2;
+ }
+ }
+ else
+ {
+ memcpy(db2Data, keyData, outLen);
+ }
+ rc = 0;
+ }
+ else
+ {
+ size_t substituteChars = 0;
+ rc = convertFieldChars(toDB2,
+ field->field_index,
+ keyData,
+ db2Data,
+ inLen,
+ outLen,
+ &convertedBytes,
+ true,
+ &substituteChars);
+
+ if (rc == DB2I_ERR_ILL_CHAR)
+ {
+ // If an illegal character is encountered, we fill the remainder
+ // of the key with 0xFF. This was implemented to work around
+ // Bug#45012, though it should probably remain even after that
+ // bug is fixed.
+ memset(db2Data+convertedBytes, 0xFF, outLen-convertedBytes);
+ rc = 0;
+ }
+ else if ((substituteChars &&
+ (litDefPtr->DataType == QMY_VARCHAR ||
+ litDefPtr->DataType == QMY_CHAR)) ||
+ strcmp(field->charset()->name, "cp1251_bulgarian_ci") == 0)
+ {
+ // When iconv translates the max_sort_char with a substitute
+ // character, we have no way to know whether this affects
+ // the sort order of the key. Therefore, to be safe, when
+ // we know that substitute characters have been used in a
+ // single-byte string, we traverse the translated key
+ // in reverse, replacing substitue characters with 0xFF, which
+ // always sorts with the greatest weight in DB2 sort sequences.
+ // cp1251_bulgarian_ci is also handled this way because the
+ // max_sort_char is a control character which does not sort
+ // equivalently in DB2.
+ DBUG_ASSERT(inLen == outLen);
+ char* tmpKey = keyData + inLen - 1;
+ char* tmpDB2 = db2Data + outLen - 1;
+ while (*tmpKey == field->charset()->max_sort_char &&
+ *tmpDB2 != 0xFF)
+ {
+ *tmpDB2 = 0xFF;
+ --tmpKey;
+ --tmpDB2;
+ }
+ }
+ }
+
+ if (!rc &&
+ (litDefPtr->DataType == QMY_VARGRAPHIC ||
+ litDefPtr->DataType == QMY_VARCHAR))
+ {
+ *(uint16*)(db2Data-sizeof(uint16)) =
+ outLen / (litDefPtr->DataType == QMY_VARGRAPHIC ? 2 : 1);
+ }
+ }
+ else
+ {
+ rc = convertMySQLtoDB2(field,
+ db2Field,
+ literalPtr,
+ (uchar*)maxPtr+((curKey.key_part[partsInUse].null_bit)? 1 : 0));
+ }
if (rc != 0) break;
litDefPtr->Offset = (uint32_t)(literalPtr - literalsPtr);
litDefPtr->Length = db2Field.getByteLengthInRecord();
- tempLen = litDefPtr->Length;
- /*
- Now convert a character or graphic value.
- */
- if ((field->type() != MYSQL_TYPE_BIT) &&
- (litDefPtr->DataType == QMY_CHAR || litDefPtr->DataType == QMY_VARCHAR ||
- litDefPtr->DataType == QMY_GRAPHIC || litDefPtr->DataType == QMY_VARGRAPHIC))
- {
- if (litDefPtr->DataType == QMY_VARCHAR || litDefPtr->DataType == QMY_VARGRAPHIC)
- {
- tempPtr = literalPtr + sizeof(uint16);
- }
- else
- tempPtr = literalPtr;
- }
literalPtr = literalPtr + litDefPtr->Length; // Bump pointer for next literal
}
boundsPtr->HiBound.Position = literalCnt;
diff --git a/storage/ibmdb2i/ha_ibmdb2i.cc b/storage/ibmdb2i/ha_ibmdb2i.cc
index 5cf9568be67..0fc2d1e83dc 100644
--- a/storage/ibmdb2i/ha_ibmdb2i.cc
+++ b/storage/ibmdb2i/ha_ibmdb2i.cc
@@ -2230,34 +2230,19 @@ int ha_ibmdb2i::create(const char *name, TABLE *table_arg,
}
}
- bool primaryHasStringField = false;
-
+ String fieldDefinition(128);
+
if (table_arg->s->primary_key != MAX_KEY && !isTemporary)
{
- KEY& curKey = table_arg->key_info[table_arg->s->primary_key];
- query.append(STRING_WITH_LEN(", PRIMARY KEY( "));
- for (int j = 0; j < curKey.key_parts; ++j)
- {
- if (j != 0)
- {
- query.append( STRING_WITH_LEN(" , ") );
- }
- Field* field = curKey.key_part[j].field;
- convertMySQLNameToDB2Name(field->field_name, colName, sizeof(colName));
- query.append(colName);
- enum_field_types type = field->real_type();
- if (type == MYSQL_TYPE_VARCHAR || type == MYSQL_TYPE_BLOB ||
- type == MYSQL_TYPE_STRING)
- {
- rc = updateAssociatedSortSequence(field->charset(),
- &fileSortSequenceType,
- fileSortSequence,
- fileSortSequenceLibrary);
- if (rc) DBUG_RETURN (rc);
- primaryHasStringField = true;
- }
- }
- query.append(STRING_WITH_LEN(" ) "));
+ query.append(STRING_WITH_LEN(", PRIMARY KEY "));
+ rc = buildIndexFieldList(fieldDefinition,
+ table_arg->key_info[table_arg->s->primary_key],
+ true,
+ &fileSortSequenceType,
+ fileSortSequence,
+ fileSortSequenceLibrary);
+ if (rc) DBUG_RETURN(rc);
+ query.append(fieldDefinition);
}
rc = buildDB2ConstraintString(thd->lex,
@@ -2283,6 +2268,19 @@ int ha_ibmdb2i::create(const char *name, TABLE *table_arg,
SqlStatementStream sqlStream(query.length());
sqlStream.addStatement(query,fileSortSequence,fileSortSequenceLibrary);
+ if (table_arg->s->primary_key != MAX_KEY &&
+ !isTemporary &&
+ (THDVAR(thd, create_index_option)==1) &&
+ (fileSortSequenceType != 'B') &&
+ (fileSortSequenceType != ' '))
+ {
+ rc = generateShadowIndex(sqlStream,
+ table_arg->key_info[table_arg->s->primary_key],
+ libName,
+ fileName,
+ fieldDefinition);
+ if (rc) DBUG_RETURN(rc);
+ }
for (uint i = 0; i < table_arg->s->keys; ++i)
{
if (i != table_arg->s->primary_key || isTemporary)
@@ -3012,61 +3010,126 @@ int32 ha_ibmdb2i::buildCreateIndexStatement(SqlStatementStream& sqlStream,
}
String fieldDefinition(128);
- fieldDefinition.length(0);
- fieldDefinition.append(STRING_WITH_LEN(" ( "));
+ rc = buildIndexFieldList(fieldDefinition,
+ key,
+ isPrimary,
+ &fileSortSequenceType,
+ fileSortSequence,
+ fileSortSequenceLibrary);
+
+ if (rc) DBUG_RETURN(rc);
+
+ query.append(fieldDefinition);
+
+ if ((THDVAR(ha_thd(), create_index_option)==1) &&
+ (fileSortSequenceType != 'B') &&
+ (fileSortSequenceType != ' '))
+ {
+ rc = generateShadowIndex(sqlStream,
+ key,
+ db2LibName,
+ db2FileName,
+ fieldDefinition);
+ if (rc) DBUG_RETURN(rc);
+ }
+
+ DBUG_PRINT("ha_ibmdb2i::buildCreateIndexStatement", ("Sent to DB2: %s",query.c_ptr_safe()));
+ sqlStream.addStatement(query,fileSortSequence,fileSortSequenceLibrary);
+
+ DBUG_RETURN(0);
+}
+
+/**
+ Generate the SQL syntax for the list of fields to be assigned to the
+ specified key. The corresponding sort sequence is also calculated.
+
+ @param[out] appendHere The string to receive the generated SQL
+ @param key The key to evaluate
+ @param isPrimary True if this is being generated on behalf of the primary key
+ @param[out] fileSortSequenceType The type of the associated sort sequence
+ @param[out] fileSortSequence The name of the associated sort sequence
+ @param[out] fileSortSequenceLibrary The library of the associated sort sequence
+
+ @return 0 if successful; error value otherwise
+*/
+int32 ha_ibmdb2i::buildIndexFieldList(String& appendHere,
+ const KEY& key,
+ bool isPrimary,
+ char* fileSortSequenceType,
+ char* fileSortSequence,
+ char* fileSortSequenceLibrary)
+{
+ DBUG_ENTER("ha_ibmdb2i::buildIndexFieldList");
+ appendHere.append(STRING_WITH_LEN(" ( "));
for (int j = 0; j < key.key_parts; ++j)
{
char colName[MAX_DB2_COLNAME_LENGTH+1];
if (j != 0)
{
- fieldDefinition.append(STRING_WITH_LEN(" , "));
+ appendHere.append(STRING_WITH_LEN(" , "));
}
- Field* field = key.key_part[j].field;
- convertMySQLNameToDB2Name(field->field_name, colName, sizeof(colName));
- fieldDefinition.append(colName);
+
+ KEY_PART_INFO& kpi = key.key_part[j];
+ Field* field = kpi.field;
+
+ convertMySQLNameToDB2Name(field->field_name,
+ colName,
+ sizeof(colName));
+ appendHere.append(colName);
+
+ int32 rc;
rc = updateAssociatedSortSequence(field->charset(),
- &fileSortSequenceType,
+ fileSortSequenceType,
fileSortSequence,
fileSortSequenceLibrary);
if (rc) DBUG_RETURN (rc);
}
- fieldDefinition.append(STRING_WITH_LEN(" ) "));
-
- query.append(fieldDefinition);
-
- if ((THDVAR(ha_thd(), create_index_option)==1) &&
- (fileSortSequenceType != 'B'))
- {
- String shadowQuery(256);
- shadowQuery.length(0);
-
- shadowQuery.append(STRING_WITH_LEN("CREATE INDEX "));
-
- shadowQuery.append(db2LibName);
- shadowQuery.append('.');
- if (db2i_table::appendQualifiedIndexFileName(key.name, db2FileName, shadowQuery, db2i_table::ASCII_SQL, typeHex))
- {
- getErrTxt(DB2I_ERR_INVALID_NAME,"index","*generated*");
- DBUG_RETURN(DB2I_ERR_INVALID_NAME );
- }
-
- shadowQuery.append(STRING_WITH_LEN(" ON "));
-
- shadowQuery.append(db2LibName);
- shadowQuery.append('.');
- shadowQuery.append(db2FileName);
- shadowQuery.append(fieldDefinition);
- DBUG_PRINT("ha_ibmdb2i::buildCreateIndexStatement", ("Sent to DB2: %s",shadowQuery.c_ptr_safe()));
- sqlStream.addStatement(shadowQuery,"*HEX","QSYS");
- }
- DBUG_PRINT("ha_ibmdb2i::buildCreateIndexStatement", ("Sent to DB2: %s",query.c_ptr_safe()));
- sqlStream.addStatement(query,fileSortSequence,fileSortSequenceLibrary);
-
+ appendHere.append(STRING_WITH_LEN(" ) "));
+
DBUG_RETURN(0);
}
+/**
+ Generate an SQL statement that defines a *HEX sorted index to implement
+ the ibmdb2i_create_index.
+
+ @param[out] stream The stream to append the generated statement to
+ @param key The key to evaluate
+ @param[out] libName The library containg the table
+ @param[out] fileName The DB2-compatible name of the table
+ @param[out] fieldDefinition The list of the fields in the index, in SQL syntax
+
+ @return 0 if successful; error value otherwise
+*/
+int32 ha_ibmdb2i::generateShadowIndex(SqlStatementStream& stream,
+ const KEY& key,
+ const char* libName,
+ const char* fileName,
+ const String& fieldDefinition)
+{
+ String shadowQuery(256);
+ shadowQuery.length(0);
+ shadowQuery.append(STRING_WITH_LEN("CREATE INDEX "));
+ shadowQuery.append(libName);
+ shadowQuery.append('.');
+ if (db2i_table::appendQualifiedIndexFileName(key.name, fileName, shadowQuery, db2i_table::ASCII_SQL, typeHex))
+ {
+ getErrTxt(DB2I_ERR_INVALID_NAME,"index","*generated*");
+ return DB2I_ERR_INVALID_NAME;
+ }
+ shadowQuery.append(STRING_WITH_LEN(" ON "));
+ shadowQuery.append(libName);
+ shadowQuery.append('.');
+ shadowQuery.append(fileName);
+ shadowQuery.append(fieldDefinition);
+ DBUG_PRINT("ha_ibmdb2i::generateShadowIndex", ("Sent to DB2: %s",shadowQuery.c_ptr_safe()));
+ stream.addStatement(shadowQuery,"*HEX","QSYS");
+ return 0;
+}
+
+
void ha_ibmdb2i::doInitialRead(char orientation,
uint32 rowsToBuffer,
ILEMemHandle key,
diff --git a/storage/ibmdb2i/ha_ibmdb2i.h b/storage/ibmdb2i/ha_ibmdb2i.h
index 2a8d65825bf..b2a43232f2d 100644
--- a/storage/ibmdb2i/ha_ibmdb2i.h
+++ b/storage/ibmdb2i/ha_ibmdb2i.h
@@ -383,7 +383,15 @@ private:
int32 prepareWriteBufferForLobs();
uint32 adjustLobBuffersForRead();
bool lobFieldsRequested();
- int convertFieldChars(enum_conversionDirection direction, uint16 fieldID, const char* input, char* output, size_t ilen, size_t olen, size_t* outDataLen);
+ int convertFieldChars(enum_conversionDirection direction,
+ uint16 fieldID,
+ const char* input,
+ char* output,
+ size_t ilen,
+ size_t olen,
+ size_t* outDataLen,
+ bool tacitErrors=FALSE,
+ size_t* substChars=NULL);
/**
Fast integer log2 function
@@ -522,6 +530,13 @@ private:
bool isPrimary,
const char* db2LibName,
const char* db2FileName);
+
+ int32 buildIndexFieldList(String& appendHere,
+ const KEY& key,
+ bool isPrimary,
+ char* fileSortSequenceType,
+ char* fileSortSequence,
+ char* fileSortSequenceLibrary);
// Specify NULL for data when using the data pointed to by field
int32 convertMySQLtoDB2(Field* field, const DB2Field& db2Field, char* db2Buf, const uchar* data = NULL);
@@ -798,4 +813,10 @@ private:
query.append(STRING_WITH_LEN(" RCDFMT "));
query.append(rcdfmt);
}
+
+ int32 generateShadowIndex(SqlStatementStream& stream,
+ const KEY& key,
+ const char* libName,
+ const char* fileName,
+ const String& fieldDefinition);
};
diff --git a/storage/innobase/Makefile.am b/storage/innobase/Makefile.am
index 7410bf7e591..3df9a6bf988 100644
--- a/storage/innobase/Makefile.am
+++ b/storage/innobase/Makefile.am
@@ -50,13 +50,14 @@ noinst_HEADERS= include/btr0btr.h include/btr0btr.ic \
include/eval0eval.h include/eval0eval.ic \
include/eval0proc.h include/eval0proc.ic \
include/fil0fil.h include/fsp0fsp.h \
- include/fsp0fsp.ic include/fut0fut.h \
+ include/fsp0fsp.ic include/fsp0types.h \
+ include/fut0fut.h \
include/fut0fut.ic include/fut0lst.h \
include/fut0lst.ic include/ha0ha.h \
include/ha0ha.ic include/hash0hash.h \
include/hash0hash.ic include/ibuf0ibuf.h \
include/ibuf0ibuf.ic include/ibuf0types.h \
- include/lock0iter.h \
+ include/lock0iter.h \
include/lock0lock.h include/lock0lock.ic \
include/lock0priv.h include/lock0priv.ic \
include/lock0types.h include/log0log.h \
diff --git a/storage/innobase/btr/btr0cur.c b/storage/innobase/btr/btr0cur.c
index 54acdf73db6..d2a2e4d2157 100644
--- a/storage/innobase/btr/btr0cur.c
+++ b/storage/innobase/btr/btr0cur.c
@@ -23,6 +23,7 @@ Created 10/16/1994 Heikki Tuuri
#include "btr0cur.ic"
#endif
+#include "mtr0log.h"
#include "page0page.h"
#include "rem0rec.h"
#include "rem0cmp.h"
diff --git a/storage/innobase/fil/fil0fil.c b/storage/innobase/fil/fil0fil.c
index c63d67cae60..42e5166c9e4 100644
--- a/storage/innobase/fil/fil0fil.c
+++ b/storage/innobase/fil/fil0fil.c
@@ -2745,7 +2745,7 @@ fil_open_single_table_tablespace(
"InnoDB: and MySQL removed the .ibd file for this.\n"
"InnoDB: Please refer to\n"
"InnoDB: http://dev.mysql.com/doc/refman/5.1/en/"
- "innodb-troubleshooting.html\n"
+ "innodb-troubleshooting-datadict.html\n"
"InnoDB: for how to resolve the issue.\n", stderr);
mem_free(filepath);
@@ -2786,7 +2786,7 @@ fil_open_single_table_tablespace(
" IMPORT TABLESPACE?\n"
"InnoDB: Please refer to\n"
"InnoDB: http://dev.mysql.com/doc/refman/5.1/en/"
- "innodb-troubleshooting.html\n"
+ "innodb-troubleshooting-datadict.html\n"
"InnoDB: for how to resolve the issue.\n",
(ulong) space_id, (ulong) id);
@@ -3477,7 +3477,7 @@ fil_space_for_table_exists_in_mem(
error_exit:
fputs("InnoDB: Please refer to\n"
"InnoDB: http://dev.mysql.com/doc/refman/5.1/en/"
- "innodb-troubleshooting.html\n"
+ "innodb-troubleshooting-datadict.html\n"
"InnoDB: for how to resolve the issue.\n", stderr);
mem_free(path);
diff --git a/storage/innobase/handler/ha_innodb.cc b/storage/innobase/handler/ha_innodb.cc
index f06b42cc654..0c937eee3c8 100644
--- a/storage/innobase/handler/ha_innodb.cc
+++ b/storage/innobase/handler/ha_innodb.cc
@@ -166,6 +166,20 @@ static handler *innobase_create_handler(handlerton *hton,
static const char innobase_hton_name[]= "InnoDB";
+/** @brief Initialize the default value of innodb_commit_concurrency.
+
+Once InnoDB is running, the innodb_commit_concurrency must not change
+from zero to nonzero. (Bug #42101)
+
+The initial default value is 0, and without this extra initialization,
+SET GLOBAL innodb_commit_concurrency=DEFAULT would set the parameter
+to 0, even if it was initially set to nonzero at the command line
+or configuration file. */
+static
+void
+innobase_commit_concurrency_init_default(void);
+/*==========================================*/
+
/*****************************************************************
Check for a valid value of innobase_commit_concurrency. */
static
@@ -1870,6 +1884,8 @@ innobase_init(
(char*)"latin1_swedish_ci"));
memcpy(srv_latin1_ordering, my_charset_latin1.sort_order, 256);
+ innobase_commit_concurrency_init_default();
+
/* Since we in this module access directly the fields of a trx
struct, and due to different headers and flags it might happen that
mutex_t has a different size in this module and in InnoDB
@@ -8256,6 +8272,97 @@ innobase_set_cursor_view(
}
+/***********************************************************************
+Check whether any of the given columns is being renamed in the table. */
+static
+bool
+column_is_being_renamed(
+/*====================*/
+ /* out: true if any of col_names is
+ being renamed in table */
+ TABLE* table, /* in: MySQL table */
+ uint n_cols, /* in: number of columns */
+ const char** col_names) /* in: names of the columns */
+{
+ uint j;
+ uint k;
+ Field* field;
+ const char* col_name;
+
+ for (j = 0; j < n_cols; j++) {
+ col_name = col_names[j];
+ for (k = 0; k < table->s->fields; k++) {
+ field = table->field[k];
+ if ((field->flags & FIELD_IS_RENAMED)
+ && innobase_strcasecmp(field->field_name,
+ col_name) == 0) {
+ return(true);
+ }
+ }
+ }
+
+ return(false);
+}
+
+/***********************************************************************
+Check whether a column in table "table" is being renamed and if this column
+is part of a foreign key, either part of another table, referencing this
+table or part of this table, referencing another table. */
+static
+bool
+foreign_key_column_is_being_renamed(
+/*================================*/
+ /* out: true if a column that
+ participates in a foreign key definition
+ is being renamed */
+ row_prebuilt_t* prebuilt, /* in: InnoDB prebuilt struct */
+ TABLE* table) /* in: MySQL table */
+{
+ dict_foreign_t* foreign;
+
+ /* check whether there are foreign keys at all */
+ if (UT_LIST_GET_LEN(prebuilt->table->foreign_list) == 0
+ && UT_LIST_GET_LEN(prebuilt->table->referenced_list) == 0) {
+ /* no foreign keys involved with prebuilt->table */
+
+ return(false);
+ }
+
+ row_mysql_lock_data_dictionary(prebuilt->trx);
+
+ /* Check whether any column in the foreign key constraints which refer
+ to this table is being renamed. */
+ for (foreign = UT_LIST_GET_FIRST(prebuilt->table->referenced_list);
+ foreign != NULL;
+ foreign = UT_LIST_GET_NEXT(referenced_list, foreign)) {
+
+ if (column_is_being_renamed(table, foreign->n_fields,
+ foreign->referenced_col_names)) {
+
+ row_mysql_unlock_data_dictionary(prebuilt->trx);
+ return(true);
+ }
+ }
+
+ /* Check whether any column in the foreign key constraints in the
+ table is being renamed. */
+ for (foreign = UT_LIST_GET_FIRST(prebuilt->table->foreign_list);
+ foreign != NULL;
+ foreign = UT_LIST_GET_NEXT(foreign_list, foreign)) {
+
+ if (column_is_being_renamed(table, foreign->n_fields,
+ foreign->foreign_col_names)) {
+
+ row_mysql_unlock_data_dictionary(prebuilt->trx);
+ return(true);
+ }
+ }
+
+ row_mysql_unlock_data_dictionary(prebuilt->trx);
+
+ return(false);
+}
+
bool ha_innobase::check_if_incompatible_data(
HA_CREATE_INFO* info,
uint table_changes)
@@ -8272,6 +8379,13 @@ bool ha_innobase::check_if_incompatible_data(
return COMPATIBLE_DATA_NO;
}
+ /* Check if a column participating in a foreign key is being renamed.
+ There is no mechanism for updating InnoDB foreign key definitions. */
+ if (foreign_key_column_is_being_renamed(prebuilt, table)) {
+
+ return COMPATIBLE_DATA_NO;
+ }
+
/* Check that row format didn't change */
if ((info->used_fields & HA_CREATE_USED_ROW_FORMAT) &&
get_row_type() != info->row_type) {
@@ -8559,3 +8673,21 @@ mysql_declare_plugin(innobase)
NULL /* reserved */
}
mysql_declare_plugin_end;
+
+/** @brief Initialize the default value of innodb_commit_concurrency.
+
+Once InnoDB is running, the innodb_commit_concurrency must not change
+from zero to nonzero. (Bug #42101)
+
+The initial default value is 0, and without this extra initialization,
+SET GLOBAL innodb_commit_concurrency=DEFAULT would set the parameter
+to 0, even if it was initially set to nonzero at the command line
+or configuration file. */
+static
+void
+innobase_commit_concurrency_init_default(void)
+/*==========================================*/
+{
+ MYSQL_SYSVAR_NAME(commit_concurrency).def_val
+ = innobase_commit_concurrency;
+}
diff --git a/storage/innobase/include/fsp0fsp.h b/storage/innobase/include/fsp0fsp.h
index 82e95a2e920..17bfbeec2c1 100644
--- a/storage/innobase/include/fsp0fsp.h
+++ b/storage/innobase/include/fsp0fsp.h
@@ -15,29 +15,7 @@ Created 12/18/1995 Heikki Tuuri
#include "fut0lst.h"
#include "ut0byte.h"
#include "page0types.h"
-
-/* If records are inserted in order, there are the following
-flags to tell this (their type is made byte for the compiler
-to warn if direction and hint parameters are switched in
-fseg_alloc_free_page): */
-#define FSP_UP ((byte)111) /* alphabetically upwards */
-#define FSP_DOWN ((byte)112) /* alphabetically downwards */
-#define FSP_NO_DIR ((byte)113) /* no order */
-
-/* File space extent size in pages */
-#define FSP_EXTENT_SIZE 64
-
-/* On a page of any file segment, data may be put starting from this offset: */
-#define FSEG_PAGE_DATA FIL_PAGE_DATA
-
-/* File segment header which points to the inode describing the file segment */
-typedef byte fseg_header_t;
-
-#define FSEG_HDR_SPACE 0 /* space id of the inode */
-#define FSEG_HDR_PAGE_NO 4 /* page number of the inode */
-#define FSEG_HDR_OFFSET 8 /* byte offset of the inode */
-
-#define FSEG_HEADER_SIZE 10
+#include "fsp0types.h"
/**************************************************************************
Initializes the file space system. */
@@ -350,40 +328,6 @@ fseg_print(
fseg_header_t* header, /* in: segment header */
mtr_t* mtr); /* in: mtr */
-/* Flags for fsp_reserve_free_extents */
-#define FSP_NORMAL 1000000
-#define FSP_UNDO 2000000
-#define FSP_CLEANING 3000000
-
-/* Number of pages described in a single descriptor page: currently each page
-description takes less than 1 byte; a descriptor page is repeated every
-this many file pages */
-#define XDES_DESCRIBED_PER_PAGE UNIV_PAGE_SIZE
-
-/* The space low address page map */
-/*--------------------------------------*/
- /* The following two pages are repeated
- every XDES_DESCRIBED_PER_PAGE pages in
- every tablespace. */
-#define FSP_XDES_OFFSET 0 /* extent descriptor */
-#define FSP_IBUF_BITMAP_OFFSET 1 /* insert buffer bitmap */
- /* The ibuf bitmap pages are the ones whose
- page number is the number above plus a
- multiple of XDES_DESCRIBED_PER_PAGE */
-
-#define FSP_FIRST_INODE_PAGE_NO 2 /* in every tablespace */
- /* The following pages exist
- in the system tablespace (space 0). */
-#define FSP_IBUF_HEADER_PAGE_NO 3 /* in tablespace 0 */
-#define FSP_IBUF_TREE_ROOT_PAGE_NO 4 /* in tablespace 0 */
- /* The ibuf tree root page number in
- tablespace 0; its fseg inode is on the page
- number FSP_FIRST_INODE_PAGE_NO */
-#define FSP_TRX_SYS_PAGE_NO 5 /* in tablespace 0 */
-#define FSP_FIRST_RSEG_PAGE_NO 6 /* in tablespace 0 */
-#define FSP_DICT_HDR_PAGE_NO 7 /* in tablespace 0 */
-/*--------------------------------------*/
-
#ifndef UNIV_NONINL
#include "fsp0fsp.ic"
#endif
diff --git a/storage/innobase/include/fsp0types.h b/storage/innobase/include/fsp0types.h
new file mode 100644
index 00000000000..6756d9d285c
--- /dev/null
+++ b/storage/innobase/include/fsp0types.h
@@ -0,0 +1,89 @@
+/*****************************************************************************
+
+Copyright (c) 1995, 2009, Innobase Oy. All Rights Reserved.
+
+This program is free software; you can redistribute it and/or modify it under
+the terms of the GNU General Public License as published by the Free Software
+Foundation; version 2 of the License.
+
+This program is distributed in the hope that it will be useful, but WITHOUT
+ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
+FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License along with
+this program; if not, write to the Free Software Foundation, Inc., 59 Temple
+Place, Suite 330, Boston, MA 02111-1307 USA
+
+*****************************************************************************/
+
+/******************************************************
+File space management types
+
+Created May 26, 2009 Vasil Dimov
+*******************************************************/
+
+#ifndef fsp0types_h
+#define fsp0types_h
+
+#include "univ.i"
+
+#include "fil0fil.h" /* for FIL_PAGE_DATA */
+
+/* If records are inserted in order, there are the following
+flags to tell this (their type is made byte for the compiler
+to warn if direction and hint parameters are switched in
+fseg_alloc_free_page): */
+#define FSP_UP ((byte)111) /* alphabetically upwards */
+#define FSP_DOWN ((byte)112) /* alphabetically downwards */
+#define FSP_NO_DIR ((byte)113) /* no order */
+
+/* File space extent size in pages */
+#define FSP_EXTENT_SIZE 64
+
+/* On a page of any file segment, data may be put starting from this offset: */
+#define FSEG_PAGE_DATA FIL_PAGE_DATA
+
+/* File segment header which points to the inode describing the file segment */
+typedef byte fseg_header_t;
+
+#define FSEG_HDR_SPACE 0 /* space id of the inode */
+#define FSEG_HDR_PAGE_NO 4 /* page number of the inode */
+#define FSEG_HDR_OFFSET 8 /* byte offset of the inode */
+
+#define FSEG_HEADER_SIZE 10
+
+/* Flags for fsp_reserve_free_extents */
+#define FSP_NORMAL 1000000
+#define FSP_UNDO 2000000
+#define FSP_CLEANING 3000000
+
+/* Number of pages described in a single descriptor page: currently each page
+description takes less than 1 byte; a descriptor page is repeated every
+this many file pages */
+#define XDES_DESCRIBED_PER_PAGE UNIV_PAGE_SIZE
+
+/* The space low address page map */
+/*--------------------------------------*/
+ /* The following two pages are repeated
+ every XDES_DESCRIBED_PER_PAGE pages in
+ every tablespace. */
+#define FSP_XDES_OFFSET 0 /* extent descriptor */
+#define FSP_IBUF_BITMAP_OFFSET 1 /* insert buffer bitmap */
+ /* The ibuf bitmap pages are the ones whose
+ page number is the number above plus a
+ multiple of XDES_DESCRIBED_PER_PAGE */
+
+#define FSP_FIRST_INODE_PAGE_NO 2 /* in every tablespace */
+ /* The following pages exist
+ in the system tablespace (space 0). */
+#define FSP_IBUF_HEADER_PAGE_NO 3 /* in tablespace 0 */
+#define FSP_IBUF_TREE_ROOT_PAGE_NO 4 /* in tablespace 0 */
+ /* The ibuf tree root page number in
+ tablespace 0; its fseg inode is on the page
+ number FSP_FIRST_INODE_PAGE_NO */
+#define FSP_TRX_SYS_PAGE_NO 5 /* in tablespace 0 */
+#define FSP_FIRST_RSEG_PAGE_NO 6 /* in tablespace 0 */
+#define FSP_DICT_HDR_PAGE_NO 7 /* in tablespace 0 */
+/*--------------------------------------*/
+
+#endif /* fsp0types_h */
diff --git a/storage/innobase/include/mtr0log.ic b/storage/innobase/include/mtr0log.ic
index 5b1d1ed34d9..1626f1e77e5 100644
--- a/storage/innobase/include/mtr0log.ic
+++ b/storage/innobase/include/mtr0log.ic
@@ -9,6 +9,8 @@ Created 12/7/1995 Heikki Tuuri
#include "mach0data.h"
#include "ut0lst.h"
#include "buf0buf.h"
+#include "fsp0types.h"
+#include "trx0sys.h"
/************************************************************
Opens a buffer to mlog. It must be closed with mlog_close. */
@@ -174,6 +176,28 @@ mlog_write_initial_log_record_fast(
space = buf_block_get_space(block);
offset = buf_block_get_page_no(block);
+ /* check whether the page is in the doublewrite buffer;
+ the doublewrite buffer is located in pages
+ FSP_EXTENT_SIZE, ..., 3 * FSP_EXTENT_SIZE - 1 in the
+ system tablespace */
+ if (space == TRX_SYS_SPACE
+ && offset >= FSP_EXTENT_SIZE && offset < 3 * FSP_EXTENT_SIZE) {
+ if (trx_doublewrite_buf_is_being_created) {
+ /* Do nothing: we only come to this branch in an
+ InnoDB database creation. We do not redo log
+ anything for the doublewrite buffer pages. */
+ return(log_ptr);
+ } else {
+ fprintf(stderr,
+ "Error: trying to redo log a record of type "
+ "%d on page %lu of space %lu in the "
+ "doublewrite buffer, continuing anyway.\n"
+ "Please post a bug report to "
+ "bugs.mysql.com.\n",
+ type, offset, space);
+ }
+ }
+
mach_write_to_1(log_ptr, type);
log_ptr++;
log_ptr += mach_write_compressed(log_ptr, space);
diff --git a/storage/innobase/include/trx0rseg.ic b/storage/innobase/include/trx0rseg.ic
index eb1893587a6..577cd0dee7b 100644
--- a/storage/innobase/include/trx0rseg.ic
+++ b/storage/innobase/include/trx0rseg.ic
@@ -7,6 +7,7 @@ Created 3/26/1996 Heikki Tuuri
*******************************************************/
#include "srv0srv.h"
+#include "mtr0log.h"
/**********************************************************************
Gets a rollback segment header. */
diff --git a/storage/innobase/include/trx0sys.h b/storage/innobase/include/trx0sys.h
index a8da5cd51a3..bad3c9d570c 100644
--- a/storage/innobase/include/trx0sys.h
+++ b/storage/innobase/include/trx0sys.h
@@ -13,15 +13,12 @@ Created 3/26/1996 Heikki Tuuri
#include "trx0types.h"
#include "mtr0mtr.h"
-#include "mtr0log.h"
#include "ut0byte.h"
#include "mem0mem.h"
#include "sync0sync.h"
#include "ut0lst.h"
#include "buf0buf.h"
#include "fil0fil.h"
-#include "fut0lst.h"
-#include "fsp0fsp.h"
#include "read0types.h"
/* In a MySQL replication slave, in crash recovery we store the master log
@@ -45,6 +42,8 @@ extern trx_sys_t* trx_sys;
/* Doublewrite system */
extern trx_doublewrite_t* trx_doublewrite;
+/* Set to TRUE when the doublewrite buffer is being created */
+extern ibool trx_doublewrite_buf_is_being_created;
extern ibool trx_doublewrite_must_reset_space_ids;
extern ibool trx_sys_multiple_tablespace_format;
@@ -302,6 +301,7 @@ trx_sys_print_mysql_master_log_pos(void);
/* Space id and page no where the trx system file copy resides */
#define TRX_SYS_SPACE 0 /* the SYSTEM tablespace */
+#include "fsp0fsp.h"
#define TRX_SYS_PAGE_NO FSP_TRX_SYS_PAGE_NO
/* The offset of the transaction system header on the page */
diff --git a/storage/innobase/include/trx0sys.ic b/storage/innobase/include/trx0sys.ic
index 86b71df08d6..55bcc12a414 100644
--- a/storage/innobase/include/trx0sys.ic
+++ b/storage/innobase/include/trx0sys.ic
@@ -9,6 +9,7 @@ Created 3/26/1996 Heikki Tuuri
#include "srv0srv.h"
#include "trx0trx.h"
#include "data0type.h"
+#include "mtr0log.h"
/* The typedef for rseg slot in the file copy */
typedef byte trx_sysf_rseg_t;
diff --git a/storage/innobase/row/row0mysql.c b/storage/innobase/row/row0mysql.c
index 2d9ed4fc944..6ec466cf995 100644
--- a/storage/innobase/row/row0mysql.c
+++ b/storage/innobase/row/row0mysql.c
@@ -1529,9 +1529,14 @@ row_unlock_for_mysql(
index = btr_pcur_get_btr_cur(clust_pcur)->index;
}
+ if (UNIV_UNLIKELY(!(index->type & DICT_CLUSTERED))) {
+ /* This is not a clustered index record. We
+ do not know how to unlock the record. */
+ goto no_unlock;
+ }
+
/* If the record has been modified by this
transaction, do not unlock it. */
- ut_a(index->type & DICT_CLUSTERED);
if (index->trx_id_offset) {
rec_trx_id = trx_read_trx_id(rec
@@ -1568,7 +1573,7 @@ row_unlock_for_mysql(
prebuilt->select_lock_type);
}
}
-
+no_unlock:
mtr_commit(&mtr);
}
diff --git a/storage/innobase/trx/trx0purge.c b/storage/innobase/trx/trx0purge.c
index f0e85ef1604..f0f300d918e 100644
--- a/storage/innobase/trx/trx0purge.c
+++ b/storage/innobase/trx/trx0purge.c
@@ -14,6 +14,7 @@ Created 3/26/1996 Heikki Tuuri
#include "fsp0fsp.h"
#include "mach0data.h"
+#include "mtr0log.h"
#include "trx0rseg.h"
#include "trx0trx.h"
#include "trx0roll.h"
diff --git a/storage/innobase/trx/trx0rec.c b/storage/innobase/trx/trx0rec.c
index 50f8b011463..38ad53fcfb0 100644
--- a/storage/innobase/trx/trx0rec.c
+++ b/storage/innobase/trx/trx0rec.c
@@ -23,6 +23,7 @@ Created 3/26/1996 Heikki Tuuri
#include "que0que.h"
#include "trx0purge.h"
#include "row0row.h"
+#include "mtr0log.h"
/*=========== UNDO LOG RECORD CREATION AND DECODING ====================*/
diff --git a/storage/innobase/trx/trx0sys.c b/storage/innobase/trx/trx0sys.c
index 40348dd4199..19c5159e15f 100644
--- a/storage/innobase/trx/trx0sys.c
+++ b/storage/innobase/trx/trx0sys.c
@@ -13,7 +13,7 @@ Created 3/26/1996 Heikki Tuuri
#endif
#include "fsp0fsp.h"
-#include "mtr0mtr.h"
+#include "mtr0log.h"
#include "trx0trx.h"
#include "trx0rseg.h"
#include "trx0undo.h"
@@ -25,6 +25,7 @@ Created 3/26/1996 Heikki Tuuri
/* The transaction system */
trx_sys_t* trx_sys = NULL;
trx_doublewrite_t* trx_doublewrite = NULL;
+ibool trx_doublewrite_buf_is_being_created = FALSE;
/* The following is set to TRUE when we are upgrading from the old format data
files to the new >= 4.1.x format multiple tablespaces format data files */
@@ -180,6 +181,7 @@ trx_sys_create_doublewrite_buf(void)
start_again:
mtr_start(&mtr);
+ trx_doublewrite_buf_is_being_created = TRUE;
page = buf_page_get(TRX_SYS_SPACE, TRX_SYS_PAGE_NO, RW_X_LATCH, &mtr);
#ifdef UNIV_SYNC_DEBUG
@@ -196,6 +198,7 @@ start_again:
trx_doublewrite_init(doublewrite);
mtr_commit(&mtr);
+ trx_doublewrite_buf_is_being_created = FALSE;
} else {
fprintf(stderr,
"InnoDB: Doublewrite buffer not found:"
@@ -274,14 +277,8 @@ start_again:
buf_page_dbg_add_level(new_page, SYNC_NO_ORDER_CHECK);
#endif /* UNIV_SYNC_DEBUG */
- /* Make a dummy change to the page to ensure it will
- be written to disk in a flush */
-
- mlog_write_ulint(new_page + FIL_PAGE_DATA,
- TRX_SYS_DOUBLEWRITE_MAGIC_N,
- MLOG_4BYTES, &mtr);
-
if (i == FSP_EXTENT_SIZE / 2) {
+ ut_a(page_no == FSP_EXTENT_SIZE);
mlog_write_ulint(doublewrite
+ TRX_SYS_DOUBLEWRITE_BLOCK1,
page_no, MLOG_4BYTES, &mtr);
@@ -291,6 +288,7 @@ start_again:
page_no, MLOG_4BYTES, &mtr);
} else if (i == FSP_EXTENT_SIZE / 2
+ TRX_SYS_DOUBLEWRITE_BLOCK_SIZE) {
+ ut_a(page_no == 2 * FSP_EXTENT_SIZE);
mlog_write_ulint(doublewrite
+ TRX_SYS_DOUBLEWRITE_BLOCK2,
page_no, MLOG_4BYTES, &mtr);
diff --git a/storage/innobase/trx/trx0undo.c b/storage/innobase/trx/trx0undo.c
index b31580d0ce0..deb6c85e6e3 100644
--- a/storage/innobase/trx/trx0undo.c
+++ b/storage/innobase/trx/trx0undo.c
@@ -14,6 +14,7 @@ Created 3/26/1996 Heikki Tuuri
#include "fsp0fsp.h"
#include "mach0data.h"
+#include "mtr0log.h"
#include "trx0rseg.h"
#include "trx0trx.h"
#include "srv0srv.h"
diff --git a/storage/myisam/ha_myisam.cc b/storage/myisam/ha_myisam.cc
index cf290e2018a..d0e5f5a5c88 100644
--- a/storage/myisam/ha_myisam.cc
+++ b/storage/myisam/ha_myisam.cc
@@ -95,7 +95,7 @@ static void mi_check_print_msg(MI_CHECK *param, const char* msg_type,
if (!thd->vio_ok())
{
- sql_print_error(msgbuf);
+ sql_print_error("%s", msgbuf);
return;
}
@@ -1112,6 +1112,9 @@ int ha_myisam::repair(THD *thd, MI_CHECK &param, bool do_optimize)
param.out_flag= 0;
strmov(fixed_name,file->filename);
+ // Release latches since this can take a long time
+ ha_release_temporary_latches(thd);
+
// Don't lock tables if we have used LOCK TABLE
if (!thd->locked_tables &&
mi_lock_database(file, table->s->tmp_table ? F_EXTRA_LCK : F_WRLCK))
@@ -1867,6 +1870,12 @@ int ha_myisam::delete_all_rows()
return mi_delete_all_rows(file);
}
+int ha_myisam::reset_auto_increment(ulonglong value)
+{
+ file->s->state.auto_increment= value;
+ return 0;
+}
+
int ha_myisam::delete_table(const char *name)
{
return mi_delete_table(name);
diff --git a/storage/myisam/ha_myisam.h b/storage/myisam/ha_myisam.h
index ca44ae9ad87..55a5eac92de 100644
--- a/storage/myisam/ha_myisam.h
+++ b/storage/myisam/ha_myisam.h
@@ -101,6 +101,7 @@ class ha_myisam: public handler
int reset(void);
int external_lock(THD *thd, int lock_type);
int delete_all_rows(void);
+ int reset_auto_increment(ulonglong value);
int disable_indexes(uint mode);
int enable_indexes(uint mode);
int indexes_are_disabled(void);
diff --git a/storage/myisammrg/ha_myisammrg.cc b/storage/myisammrg/ha_myisammrg.cc
index 1e82983b97c..19510d0eae1 100644
--- a/storage/myisammrg/ha_myisammrg.cc
+++ b/storage/myisammrg/ha_myisammrg.cc
@@ -545,7 +545,8 @@ int ha_myisammrg::attach_children(void)
if (myrg_attach_children(this->file, this->test_if_locked |
current_thd->open_options,
- myisammrg_attach_children_callback, this))
+ myisammrg_attach_children_callback, this,
+ (my_bool *) &need_compat_check))
{
DBUG_PRINT("error", ("my_errno %d", my_errno));
DBUG_RETURN(my_errno ? my_errno : -1);
diff --git a/storage/myisammrg/myrg_create.c b/storage/myisammrg/myrg_create.c
index df81b730bfd..eaed470daec 100644
--- a/storage/myisammrg/myrg_create.c
+++ b/storage/myisammrg/myrg_create.c
@@ -46,7 +46,7 @@ int myrg_create(const char *name, const char **table_names,
fn_same(buff,name,4);
*(end=strend(buff))='\n';
end[1]=0;
- if (my_write(file,(char*) buff,(uint) (end-buff+1),
+ if (my_write(file,(uchar*) buff,(uint) (end-buff+1),
MYF(MY_WME | MY_NABP)))
goto err;
}
diff --git a/storage/myisammrg/myrg_open.c b/storage/myisammrg/myrg_open.c
index 14ba2853b22..01420f47a0c 100644
--- a/storage/myisammrg/myrg_open.c
+++ b/storage/myisammrg/myrg_open.c
@@ -365,11 +365,14 @@ MYRG_INFO *myrg_parent_open(const char *parent_name,
The callback returns the MyISAM table handle of the child table.
Check table definition match.
- @param[in] m_info MERGE parent table structure
- @param[in] handle_locking if contains HA_OPEN_FOR_REPAIR, warn about
- incompatible child tables, but continue
- @param[in] callback function to call for each child table
- @param[in] callback_param data pointer to give to the callback
+ @param[in] m_info MERGE parent table structure
+ @param[in] handle_locking if contains HA_OPEN_FOR_REPAIR, warn about
+ incompatible child tables, but continue
+ @param[in] callback function to call for each child table
+ @param[in] callback_param data pointer to give to the callback
+ @param[in] need_compat_check pointer to ha_myisammrg::need_compat_check
+ (we need this one to decide if previously
+ allocated buffers can be reused).
@return status
@retval 0 OK
@@ -382,7 +385,7 @@ MYRG_INFO *myrg_parent_open(const char *parent_name,
int myrg_attach_children(MYRG_INFO *m_info, int handle_locking,
MI_INFO *(*callback)(void*),
- void *callback_param)
+ void *callback_param, my_bool *need_compat_check)
{
ulonglong file_offset;
MI_INFO *myisam;
@@ -423,6 +426,11 @@ int myrg_attach_children(MYRG_INFO *m_info, int handle_locking,
m_info->reclength= myisam->s->base.reclength;
min_keys= myisam->s->base.keys;
key_parts= myisam->s->base.key_parts;
+ if (*need_compat_check && m_info->rec_per_key_part)
+ {
+ my_free((char *) m_info->rec_per_key_part, MYF(0));
+ m_info->rec_per_key_part= NULL;
+ }
if (!m_info->rec_per_key_part)
{
if(!(m_info->rec_per_key_part= (ulong*)