Commit d1a80e6a authored by Jimmy Yang's avatar Jimmy Yang

Fix Bug #12885783 - BLOCK LOADING TABLE WITH LARGE COLLATION NUMBER

FROM 5.6 SERVER

rb://747 approved by Marko
parent 10e7b948
......@@ -25,6 +25,7 @@ Created 4/24/1996 Heikki Tuuri
#include "rem0cmp.h"
#include "srv0start.h"
#include "srv0srv.h"
#include "db0err.h"
/********************************************************************
Returns TRUE if index's i'th column's name is 'name' .*/
......@@ -329,7 +330,7 @@ dict_check_tablespaces_and_store_max_id(
/************************************************************************
Loads definitions for table columns. */
static
void
ulint
dict_load_columns(
/*==============*/
dict_table_t* table, /* in: table */
......@@ -350,6 +351,7 @@ dict_load_columns(
ulint col_len;
ulint i;
mtr_t mtr;
ulint err = DB_SUCCESS;
ut_ad(mutex_own(&(dict_sys->mutex)));
......@@ -397,6 +399,30 @@ dict_load_columns(
field = rec_get_nth_field_old(rec, 6, &len);
prtype = mach_read_from_4(field);
/* We can rely on dtype_get_charset_coll() to check
charset collation number exceed limit, since it comes
with a smaller mask. We have to do the check explicitly
here */
if (((prtype >> 16) & LARGE_CHAR_COLL_PRTYPE_MASK)
> MAX_CHAR_COLL_NUM) {
fprintf(stderr, "InnoDB: Error: load column"
" '%s' for table '%s' failed.\n"
"InnoDB: column '%s' has a charset"
" collation number of %lu, exceeds"
" maximum value %lu supported\n",
name, name, table->name,
(ulong) ((prtype >> 16)
& LARGE_CHAR_COLL_PRTYPE_MASK),
(ulong) MAX_CHAR_COLL_NUM);
err = DB_CORRUPTION;
/* If the force recovery flag is not set, it will
stop loading and exit */
if (!srv_force_recovery) {
goto func_exit;
}
}
if (dtype_get_charset_coll(prtype) == 0
&& dtype_is_string_type(mtype)) {
/* The table was created with < 4.1.2. */
......@@ -428,8 +454,11 @@ dict_load_columns(
btr_pcur_move_to_next_user_rec(&pcur, &mtr);
}
func_exit:
btr_pcur_close(&pcur);
mtr_commit(&mtr);
return(err);
}
/************************************************************************
......@@ -899,7 +928,12 @@ dict_load_table(
btr_pcur_close(&pcur);
mtr_commit(&mtr);
dict_load_columns(table, heap);
err = dict_load_columns(table, heap);
if (err != DB_SUCCESS && !srv_force_recovery) {
table = NULL;
goto func_exit;
}
dict_table_add_to_cache(table, heap);
......@@ -961,6 +995,8 @@ dict_load_table(
mutex_exit(&dict_foreign_err_mutex);
}
#endif /* 0 */
func_exit:
mem_heap_free(heap);
return(table);
......
......@@ -5336,13 +5336,14 @@ create_table_def(
charset_no = (ulint)field->charset()->number;
ut_a(charset_no < 256); /* in data0type.h we assume
that the number fits in one
byte */
/* in data0type.h we assume
that the number fits in one byte */
ut_a(charset_no <= MAX_CHAR_COLL_NUM);
}
ut_a(field->type() < 256); /* we assume in dtype_form_prtype()
that this fits in one byte */
/* we assume in dtype_form_prtype() that this fits in
one byte */
ut_a(field->type() <= MAX_CHAR_COLL_NUM);
col_len = field->pack_length();
/* The MySQL pack length contains 1 or 2 bytes length field
......
......@@ -149,6 +149,15 @@ SQL null*/
store the charset-collation number; one byte is left unused, though */
#define DATA_NEW_ORDER_NULL_TYPE_BUF_SIZE 6
/* We support 8 bits (up to 255) collation number until 5.6.3, in which
the collation number is extended to 32767 */
#define MAX_CHAR_COLL_NUM 255
/* Mask to get the large charset-collation number in PRTYPE
This is used to mainly block loading tables with large charset-collation
value with database from 5.6 */
#define LARGE_CHAR_COLL_PRTYPE_MASK 0xFFFFUL
/*************************************************************************
Gets the MySQL type code from a dtype. */
UNIV_INLINE
......
......@@ -272,7 +272,7 @@ dtype_new_store_for_order_and_null_size(
mach_write_to_2(buf + 2, len & 0xFFFFUL);
ut_ad(dtype_get_charset_coll(type->prtype) < 256);
ut_ad(dtype_get_charset_coll(type->prtype) <= MAX_CHAR_COLL_NUM);
mach_write_to_2(buf + 4, dtype_get_charset_coll(type->prtype));
if (type->prtype & DATA_NOT_NULL) {
......@@ -339,12 +339,10 @@ dtype_new_read_for_order_and_null_size(
type->len = mach_read_from_2(buf + 2);
mach_read_from_2(buf + 4);
charset_coll = mach_read_from_2(buf + 4) & 0x7fff;
if (dtype_is_string_type(type->mtype)) {
ut_a(charset_coll < 256);
ut_a(charset_coll <= MAX_CHAR_COLL_NUM);
if (charset_coll == 0) {
/* This insert buffer record was inserted with MySQL
......
2011-09-08 The InnoDB Team
* dict/dict0load.c, handler/ha_innodb.cc, include/data0type.h
include/data0type.ic:
Fix Bug##12885783 - BLOCK LOADING TABLE WITH LARGE COLLATION
NUMBER FROM 5.6 SERVER
2011-09-06 The InnoDB Team
* buf/buf0buddy.c:
......
......@@ -40,6 +40,7 @@ Created 4/24/1996 Heikki Tuuri
#include "rem0cmp.h"
#include "srv0start.h"
#include "srv0srv.h"
#include "db0err.h"
/****************************************************************//**
Compare the name of an index column.
......@@ -449,7 +450,7 @@ dict_check_tablespaces_and_store_max_id(
/********************************************************************//**
Loads definitions for table columns. */
static
void
enum db_err
dict_load_columns(
/*==============*/
dict_table_t* table, /*!< in: table */
......@@ -470,6 +471,7 @@ dict_load_columns(
ulint col_len;
ulint i;
mtr_t mtr;
enum db_err err = DB_SUCCESS;
ut_ad(mutex_own(&(dict_sys->mutex)));
......@@ -517,6 +519,30 @@ dict_load_columns(
field = rec_get_nth_field_old(rec, 6, &len);
prtype = mach_read_from_4(field);
/* We can rely on dtype_get_charset_coll() to check
charset collation number exceed limit, since it comes
with a smaller mask. We have to do the check explicitly
here */
if (((prtype >> 16) & LARGE_CHAR_COLL_PRTYPE_MASK)
> MAX_CHAR_COLL_NUM) {
fprintf(stderr, "InnoDB: Error: load column"
" '%s' for table '%s' failed.\n"
"InnoDB: column '%s' has a charset"
" collation number of %lu, exceeds"
" maximum value %lu supported\n",
name, name, table->name,
(ulong) ((prtype >> 16)
& LARGE_CHAR_COLL_PRTYPE_MASK),
(ulong) MAX_CHAR_COLL_NUM);
err = DB_CORRUPTION;
/* If the force recovery flag is not set, it will
stop loading and exit */
if (!srv_force_recovery) {
goto func_exit;
}
}
if (dtype_get_charset_coll(prtype) == 0
&& dtype_is_string_type(mtype)) {
/* The table was created with < 4.1.2. */
......@@ -548,8 +574,11 @@ dict_load_columns(
btr_pcur_move_to_next_user_rec(&pcur, &mtr);
}
func_exit:
btr_pcur_close(&pcur);
mtr_commit(&mtr);
return(err);
}
/********************************************************************//**
......@@ -1044,7 +1073,12 @@ dict_load_table(
btr_pcur_close(&pcur);
mtr_commit(&mtr);
dict_load_columns(table, heap);
err = dict_load_columns(table, heap);
if (err != DB_SUCCESS && !srv_force_recovery) {
table = NULL;
goto func_exit;
}
dict_table_add_to_cache(table, heap);
......@@ -1106,6 +1140,8 @@ dict_load_table(
mutex_exit(&dict_foreign_err_mutex);
}
#endif /* 0 */
func_exit:
mem_heap_free(heap);
return(table);
......
......@@ -6086,7 +6086,7 @@ create_table_def(
charset_no = (ulint)field->charset()->number;
if (UNIV_UNLIKELY(charset_no >= 256)) {
if (UNIV_UNLIKELY(charset_no > MAX_CHAR_COLL_NUM)) {
/* in data0type.h we assume that the
number fits in one byte in prtype */
push_warning_printf(
......@@ -6101,8 +6101,9 @@ create_table_def(
}
}
ut_a(field->type() < 256); /* we assume in dtype_form_prtype()
that this fits in one byte */
/* we assume in dtype_form_prtype() that this fits in
one byte */
ut_a(field->type() <= MAX_CHAR_COLL_NUM);
col_len = field->pack_length();
/* The MySQL pack length contains 1 or 2 bytes length field
......
......@@ -168,6 +168,15 @@ SQL null*/
store the charset-collation number; one byte is left unused, though */
#define DATA_NEW_ORDER_NULL_TYPE_BUF_SIZE 6
/* We support 8 bits (up to 255) collation number until 5.6.3, in which
the collation number is extended to 32767 */
#define MAX_CHAR_COLL_NUM 255
/* Mask to get the large charset-collation number in PRTYPE
This is used to mainly block loading tables with large charset-collation
value with database from 5.6 */
#define LARGE_CHAR_COLL_PRTYPE_MASK 0xFFFFUL
#ifndef UNIV_HOTBACKUP
/*********************************************************************//**
Gets the MySQL type code from a dtype.
......
......@@ -306,7 +306,7 @@ dtype_new_store_for_order_and_null_size(
mach_write_to_2(buf + 2, len & 0xFFFFUL);
ut_ad(dtype_get_charset_coll(type->prtype) < 256);
ut_ad(dtype_get_charset_coll(type->prtype) <= MAX_CHAR_COLL_NUM);
mach_write_to_2(buf + 4, dtype_get_charset_coll(type->prtype));
if (type->prtype & DATA_NOT_NULL) {
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment