mirror of
https://github.com/MariaDB/server.git
synced 2025-07-29 05:21:33 +03:00
MDEV-30805 SIGSEGV in my_convert and UBSAN: member access within null pointer of type 'const struct MY_CHARSET_HANDLER' in my_convert
Type_handler::partition_field_append_value() erroneously passed the address of my_collation_contextually_typed_binary to conversion functions copy_and_convert() and my_convert(). This happened because generate_partition_syntax_for_frm() was called from mysql_create_frm_image() in the stage when the fields in List<Create_field> can still contain unresolved contextual collations, like "binary" in the reported crash scenario: ALTER TABLE t CHANGE COLUMN a a CHAR BINARY; Fix: 1. Splitting mysql_prepare_create_table() into two parts: - mysql_prepare_create_table_stage1() interates through List<Create_field> and calls Create_field::prepare_stage1(), which performs basic attribute initialization, including context collation resolution. - mysql_prepare_create_table_finalize() - the rest of the old mysql_prepare_create_table() code. 2. Changing mysql_create_frm_image(): It now calls: - mysql_prepare_create_table_stage1() in the very beginning, before the partition related code. - mysql_prepare_create_table_finalize() in the end, instead of the old mysql_prepare_create_table() call 3. Adding mysql_prepare_create_table() as a wrapper for two calls: mysql_prepare_create_table_stage1() || mysql_prepare_create_table_finalize() so the code stays unchanged in the other places where mysql_prepare_create_table() was used. 4. Changing prototype for Type_handler::Column_definition_prepare_stage1() Removing arguments: - handler *file - ulonglong table_flags Adding a new argument instead: - column_definition_type_t type This allows to call Column_definition_prepare_stage1() and therefore to call mysql_prepare_create_table_stage1() before instantiation of a handler. This simplifies the code, because in case of a partitioned table, mysql_create_frm_image() creates a handler of the underlying partition first, the frees it and created a ha_partition instance instead. mysql_prepare_create_table() before the fix was called with the final (ha_partition) handler. 5. Moving parts of Column_definition_prepare_stage1() which need a pointer to handler and table_flags to Column_definition_prepare_stage2().
This commit is contained in:
@ -20,3 +20,24 @@ create table t1 (a varchar(1), primary key (a))
|
|||||||
partition by list (ascii(a))
|
partition by list (ascii(a))
|
||||||
(partition p1 values in (65));
|
(partition p1 values in (65));
|
||||||
ERROR HY000: This partition function is not allowed
|
ERROR HY000: This partition function is not allowed
|
||||||
|
#
|
||||||
|
# Start of 10.9 tests
|
||||||
|
#
|
||||||
|
#
|
||||||
|
# MDEV-30805 SIGSEGV in my_convert and UBSAN: member access within null pointer of type 'const struct MY_CHARSET_HANDLER' in my_convert
|
||||||
|
#
|
||||||
|
CREATE TABLE t1 (a CHAR CHARACTER SET ucs2)
|
||||||
|
PARTITION BY RANGE COLUMNS (a)
|
||||||
|
(PARTITION p0 VALUES LESS THAN ('a'));
|
||||||
|
ALTER TABLE t1 CHANGE COLUMN a a CHAR BINARY;
|
||||||
|
SHOW CREATE TABLE t1;
|
||||||
|
Table Create Table
|
||||||
|
t1 CREATE TABLE `t1` (
|
||||||
|
`a` char(1) CHARACTER SET latin1 COLLATE latin1_bin DEFAULT NULL
|
||||||
|
) ENGINE=MyISAM DEFAULT CHARSET=latin1 COLLATE=latin1_swedish_ci
|
||||||
|
PARTITION BY RANGE COLUMNS(`a`)
|
||||||
|
(PARTITION `p0` VALUES LESS THAN ('a') ENGINE = MyISAM)
|
||||||
|
DROP TABLE t1;
|
||||||
|
#
|
||||||
|
# End of 10.9 tests
|
||||||
|
#
|
||||||
|
@ -27,3 +27,23 @@ partition by list (ascii(a))
|
|||||||
#insert into t1 values ('A');
|
#insert into t1 values ('A');
|
||||||
#replace into t1 values ('A');
|
#replace into t1 values ('A');
|
||||||
#drop table t1;
|
#drop table t1;
|
||||||
|
|
||||||
|
--echo #
|
||||||
|
--echo # Start of 10.9 tests
|
||||||
|
--echo #
|
||||||
|
|
||||||
|
--echo #
|
||||||
|
--echo # MDEV-30805 SIGSEGV in my_convert and UBSAN: member access within null pointer of type 'const struct MY_CHARSET_HANDLER' in my_convert
|
||||||
|
--echo #
|
||||||
|
|
||||||
|
CREATE TABLE t1 (a CHAR CHARACTER SET ucs2)
|
||||||
|
PARTITION BY RANGE COLUMNS (a)
|
||||||
|
(PARTITION p0 VALUES LESS THAN ('a'));
|
||||||
|
ALTER TABLE t1 CHANGE COLUMN a a CHAR BINARY;
|
||||||
|
SHOW CREATE TABLE t1;
|
||||||
|
DROP TABLE t1;
|
||||||
|
|
||||||
|
--echo #
|
||||||
|
--echo # End of 10.9 tests
|
||||||
|
--echo #
|
||||||
|
|
||||||
|
@ -77,7 +77,7 @@ CREATE OR REPLACE TABLE t1 (a DATE) CHARACTER SET utf8
|
|||||||
PARTITION BY LIST COLUMNS (a) (PARTITION p0 VALUES IN (FROM_DAYS(100)));
|
PARTITION BY LIST COLUMNS (a) (PARTITION p0 VALUES IN (FROM_DAYS(100)));
|
||||||
Warnings:
|
Warnings:
|
||||||
Note 1003 PARTITION BY LIST COLUMNS(`a`)
|
Note 1003 PARTITION BY LIST COLUMNS(`a`)
|
||||||
(PARTITION `p0` VALUES IN (_utf8mb3 0x303030302d30302d3030) ENGINE = MyISAM)
|
(PARTITION `p0` VALUES IN (_latin1 0x303030302d30302d3030) ENGINE = MyISAM)
|
||||||
SELECT PARTITION_DESCRIPTION FROM INFORMATION_SCHEMA.PARTITIONS WHERE TABLE_NAME='t1';
|
SELECT PARTITION_DESCRIPTION FROM INFORMATION_SCHEMA.PARTITIONS WHERE TABLE_NAME='t1';
|
||||||
PARTITION_DESCRIPTION
|
PARTITION_DESCRIPTION
|
||||||
'0000-00-00'
|
'0000-00-00'
|
||||||
|
10
sql/field.h
10
sql/field.h
@ -5377,7 +5377,7 @@ public:
|
|||||||
bool sp_prepare_create_field(THD *thd, MEM_ROOT *mem_root);
|
bool sp_prepare_create_field(THD *thd, MEM_ROOT *mem_root);
|
||||||
|
|
||||||
bool prepare_stage1(THD *thd, MEM_ROOT *mem_root,
|
bool prepare_stage1(THD *thd, MEM_ROOT *mem_root,
|
||||||
handler *file, ulonglong table_flags,
|
column_definition_type_t type,
|
||||||
const Column_derived_attributes *derived_attr);
|
const Column_derived_attributes *derived_attr);
|
||||||
void prepare_stage1_simple(CHARSET_INFO *cs)
|
void prepare_stage1_simple(CHARSET_INFO *cs)
|
||||||
{
|
{
|
||||||
@ -5385,11 +5385,9 @@ public:
|
|||||||
create_length_to_internal_length_simple();
|
create_length_to_internal_length_simple();
|
||||||
}
|
}
|
||||||
bool prepare_stage1_typelib(THD *thd, MEM_ROOT *mem_root,
|
bool prepare_stage1_typelib(THD *thd, MEM_ROOT *mem_root,
|
||||||
handler *file, ulonglong table_flags);
|
column_definition_type_t deftype);
|
||||||
bool prepare_stage1_string(THD *thd, MEM_ROOT *mem_root,
|
bool prepare_stage1_string(THD *thd, MEM_ROOT *mem_root);
|
||||||
handler *file, ulonglong table_flags);
|
bool prepare_stage1_bit(THD *thd, MEM_ROOT *mem_root);
|
||||||
bool prepare_stage1_bit(THD *thd, MEM_ROOT *mem_root,
|
|
||||||
handler *file, ulonglong table_flags);
|
|
||||||
|
|
||||||
bool bulk_alter(const Column_derived_attributes *derived_attr,
|
bool bulk_alter(const Column_derived_attributes *derived_attr,
|
||||||
const Column_bulk_alter_attributes *bulk_attr)
|
const Column_bulk_alter_attributes *bulk_attr)
|
||||||
|
@ -787,8 +787,9 @@ bool Create_json_table::add_json_table_fields(THD *thd, TABLE *table,
|
|||||||
*/
|
*/
|
||||||
sql_f->length= sql_f->char_length;
|
sql_f->length= sql_f->char_length;
|
||||||
|
|
||||||
if (sql_f->prepare_stage1(thd, thd->mem_root, table->file,
|
if (sql_f->prepare_stage1(thd, thd->mem_root,
|
||||||
table->file->ha_table_flags(), &da))
|
COLUMN_DEFINITION_TABLE_FIELD,
|
||||||
|
&da))
|
||||||
goto err_exit;
|
goto err_exit;
|
||||||
|
|
||||||
while ((jc2= it2++) != jc)
|
while ((jc2= it2++) != jc)
|
||||||
|
221
sql/sql_table.cc
221
sql/sql_table.cc
@ -2395,17 +2395,16 @@ static void check_duplicate_key(THD *thd, const Key *key, const KEY *key_info,
|
|||||||
|
|
||||||
bool Column_definition::prepare_stage1_typelib(THD *thd,
|
bool Column_definition::prepare_stage1_typelib(THD *thd,
|
||||||
MEM_ROOT *mem_root,
|
MEM_ROOT *mem_root,
|
||||||
handler *file,
|
column_definition_type_t deftype)
|
||||||
ulonglong table_flags)
|
|
||||||
{
|
{
|
||||||
/*
|
/*
|
||||||
Pass the last parameter to prepare_interval_field() as follows:
|
Pass the last parameter to prepare_interval_field() as follows:
|
||||||
- If we are preparing for an SP variable (file is NULL), we pass "false",
|
- If we are preparing for an SP variable, we pass "false",
|
||||||
to force allocation and full copying of TYPELIB values on the given
|
to force allocation and full copying of TYPELIB values on the given
|
||||||
mem_root, even if no character set conversion is needed. This is needed
|
mem_root, even if no character set conversion is needed. This is needed
|
||||||
because a life cycle of an SP variable is longer than the current query.
|
because a life cycle of an SP variable is longer than the current query.
|
||||||
|
|
||||||
- If we are preparing for a CREATE TABLE, (file != NULL), we pass "true".
|
- If we are preparing for a CREATE TABLE, we pass "true".
|
||||||
This will create the typelib in runtime memory - we will free the
|
This will create the typelib in runtime memory - we will free the
|
||||||
occupied memory at the same time when we free this
|
occupied memory at the same time when we free this
|
||||||
sql_field -- at the end of execution.
|
sql_field -- at the end of execution.
|
||||||
@ -2413,11 +2412,11 @@ bool Column_definition::prepare_stage1_typelib(THD *thd,
|
|||||||
values in "interval" in cases when no character conversion is needed,
|
values in "interval" in cases when no character conversion is needed,
|
||||||
to avoid extra copying.
|
to avoid extra copying.
|
||||||
*/
|
*/
|
||||||
if (prepare_interval_field(mem_root, file != NULL))
|
if (prepare_interval_field(mem_root,
|
||||||
|
deftype == COLUMN_DEFINITION_TABLE_FIELD))
|
||||||
return true; // E.g. wrong values with commas: SET('a,b')
|
return true; // E.g. wrong values with commas: SET('a,b')
|
||||||
create_length_to_internal_length_typelib();
|
create_length_to_internal_length_typelib();
|
||||||
|
|
||||||
DBUG_ASSERT(file || !default_value); // SP variables have no default_value
|
|
||||||
if (default_value && default_value->expr->basic_const_item())
|
if (default_value && default_value->expr->basic_const_item())
|
||||||
{
|
{
|
||||||
if ((charset != default_value->expr->collation.collation &&
|
if ((charset != default_value->expr->collation.collation &&
|
||||||
@ -2430,14 +2429,11 @@ bool Column_definition::prepare_stage1_typelib(THD *thd,
|
|||||||
|
|
||||||
|
|
||||||
bool Column_definition::prepare_stage1_string(THD *thd,
|
bool Column_definition::prepare_stage1_string(THD *thd,
|
||||||
MEM_ROOT *mem_root,
|
MEM_ROOT *mem_root)
|
||||||
handler *file,
|
|
||||||
ulonglong table_flags)
|
|
||||||
{
|
{
|
||||||
create_length_to_internal_length_string();
|
create_length_to_internal_length_string();
|
||||||
if (prepare_blob_field(thd))
|
if (prepare_blob_field(thd))
|
||||||
return true;
|
return true;
|
||||||
DBUG_ASSERT(file || !default_value); // SP variables have no default_value
|
|
||||||
/*
|
/*
|
||||||
Convert the default value from client character
|
Convert the default value from client character
|
||||||
set into the column character set if necessary.
|
set into the column character set if necessary.
|
||||||
@ -2457,13 +2453,9 @@ bool Column_definition::prepare_stage1_string(THD *thd,
|
|||||||
|
|
||||||
|
|
||||||
bool Column_definition::prepare_stage1_bit(THD *thd,
|
bool Column_definition::prepare_stage1_bit(THD *thd,
|
||||||
MEM_ROOT *mem_root,
|
MEM_ROOT *mem_root)
|
||||||
handler *file,
|
|
||||||
ulonglong table_flags)
|
|
||||||
{
|
{
|
||||||
pack_flag= FIELDFLAG_NUMBER;
|
pack_flag= FIELDFLAG_NUMBER;
|
||||||
if (!(table_flags & HA_CAN_BIT_FIELD))
|
|
||||||
pack_flag|= FIELDFLAG_TREAT_BIT_AS_CHAR;
|
|
||||||
create_length_to_internal_length_bit();
|
create_length_to_internal_length_bit();
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
@ -2471,14 +2463,15 @@ bool Column_definition::prepare_stage1_bit(THD *thd,
|
|||||||
|
|
||||||
bool Column_definition::prepare_stage1(THD *thd,
|
bool Column_definition::prepare_stage1(THD *thd,
|
||||||
MEM_ROOT *mem_root,
|
MEM_ROOT *mem_root,
|
||||||
handler *file,
|
column_definition_type_t deftype,
|
||||||
ulonglong table_flags,
|
|
||||||
const Column_derived_attributes
|
const Column_derived_attributes
|
||||||
*derived_attr)
|
*derived_attr)
|
||||||
{
|
{
|
||||||
|
// SP variables have no default_value
|
||||||
|
DBUG_ASSERT(deftype == COLUMN_DEFINITION_TABLE_FIELD || !default_value);
|
||||||
|
|
||||||
return type_handler()->Column_definition_prepare_stage1(thd, mem_root,
|
return type_handler()->Column_definition_prepare_stage1(thd, mem_root,
|
||||||
this, file,
|
this, deftype,
|
||||||
table_flags,
|
|
||||||
derived_attr);
|
derived_attr);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -2702,10 +2695,77 @@ key_add_part_check_null(const handler *file, KEY *key_info,
|
|||||||
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
Preparation for table creation
|
Prepare for a table creation.
|
||||||
|
Stage 1: prepare the field list.
|
||||||
|
*/
|
||||||
|
static bool mysql_prepare_create_table_stage1(THD *thd,
|
||||||
|
HA_CREATE_INFO *create_info,
|
||||||
|
Alter_info *alter_info)
|
||||||
|
{
|
||||||
|
DBUG_ENTER("mysql_prepare_create_table_stage1");
|
||||||
|
const Column_derived_attributes dattr(create_info->default_table_charset);
|
||||||
|
const Column_bulk_alter_attributes
|
||||||
|
battr(create_info->alter_table_convert_to_charset);
|
||||||
|
Create_field *sql_field;
|
||||||
|
List_iterator_fast<Create_field> it(alter_info->create_list);
|
||||||
|
|
||||||
|
DBUG_EXECUTE_IF("test_pseudo_invisible",{
|
||||||
|
mysql_add_invisible_field(thd, &alter_info->create_list,
|
||||||
|
"invisible", &type_handler_slong, INVISIBLE_SYSTEM,
|
||||||
|
new (thd->mem_root)Item_int(thd, 9));
|
||||||
|
});
|
||||||
|
DBUG_EXECUTE_IF("test_completely_invisible",{
|
||||||
|
mysql_add_invisible_field(thd, &alter_info->create_list,
|
||||||
|
"invisible", &type_handler_slong, INVISIBLE_FULL,
|
||||||
|
new (thd->mem_root)Item_int(thd, 9));
|
||||||
|
});
|
||||||
|
DBUG_EXECUTE_IF("test_invisible_index",{
|
||||||
|
LEX_CSTRING temp;
|
||||||
|
temp.str= "invisible";
|
||||||
|
temp.length= strlen("invisible");
|
||||||
|
mysql_add_invisible_index(thd, &alter_info->key_list
|
||||||
|
, &temp, Key::MULTIPLE);
|
||||||
|
});
|
||||||
|
|
||||||
|
|
||||||
|
for ( ; (sql_field=it++) ; )
|
||||||
|
{
|
||||||
|
/* Virtual fields are always NULL */
|
||||||
|
if (sql_field->vcol_info)
|
||||||
|
sql_field->flags&= ~NOT_NULL_FLAG;
|
||||||
|
|
||||||
|
/*
|
||||||
|
Initialize length from its original value (number of characters),
|
||||||
|
which was set in the parser. This is necessary if we're
|
||||||
|
executing a prepared statement for the second time.
|
||||||
|
*/
|
||||||
|
sql_field->length= sql_field->char_length;
|
||||||
|
|
||||||
|
if (sql_field->bulk_alter(&dattr, &battr))
|
||||||
|
DBUG_RETURN(true);
|
||||||
|
|
||||||
|
if (sql_field->prepare_stage1(thd, thd->mem_root,
|
||||||
|
COLUMN_DEFINITION_TABLE_FIELD,
|
||||||
|
&dattr))
|
||||||
|
DBUG_RETURN(true);
|
||||||
|
|
||||||
|
DBUG_ASSERT(sql_field->charset);
|
||||||
|
|
||||||
|
if (check_column_name(sql_field->field_name.str))
|
||||||
|
{
|
||||||
|
my_error(ER_WRONG_COLUMN_NAME, MYF(0), sql_field->field_name.str);
|
||||||
|
DBUG_RETURN(TRUE);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
DBUG_RETURN(false);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/*
|
||||||
|
Preparation for table creation, final stage.
|
||||||
|
|
||||||
SYNOPSIS
|
SYNOPSIS
|
||||||
mysql_prepare_create_table()
|
mysql_prepare_create_table_finalize()
|
||||||
thd Thread object.
|
thd Thread object.
|
||||||
create_info Create information (like MAX_ROWS).
|
create_info Create information (like MAX_ROWS).
|
||||||
alter_info List of columns and indexes to create
|
alter_info List of columns and indexes to create
|
||||||
@ -2728,11 +2788,12 @@ key_add_part_check_null(const handler *file, KEY *key_info,
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
static int
|
static int
|
||||||
mysql_prepare_create_table(THD *thd, HA_CREATE_INFO *create_info,
|
mysql_prepare_create_table_finalize(THD *thd, HA_CREATE_INFO *create_info,
|
||||||
Alter_info *alter_info, uint *db_options,
|
Alter_info *alter_info, uint *db_options,
|
||||||
handler *file, KEY **key_info_buffer,
|
handler *file, KEY **key_info_buffer,
|
||||||
uint *key_count, int create_table_mode,
|
uint *key_count, int create_table_mode,
|
||||||
const LEX_CSTRING db, const LEX_CSTRING table_name)
|
const LEX_CSTRING db,
|
||||||
|
const LEX_CSTRING table_name)
|
||||||
{
|
{
|
||||||
const char *key_name;
|
const char *key_name;
|
||||||
Create_field *sql_field,*dup_field;
|
Create_field *sql_field,*dup_field;
|
||||||
@ -2748,28 +2809,8 @@ mysql_prepare_create_table(THD *thd, HA_CREATE_INFO *create_info,
|
|||||||
bool tmp_table= create_table_mode == C_ALTER_TABLE;
|
bool tmp_table= create_table_mode == C_ALTER_TABLE;
|
||||||
const bool create_simple= thd->lex->create_simple();
|
const bool create_simple= thd->lex->create_simple();
|
||||||
bool is_hash_field_needed= false;
|
bool is_hash_field_needed= false;
|
||||||
const Column_derived_attributes dattr(create_info->default_table_charset);
|
|
||||||
const Column_bulk_alter_attributes
|
|
||||||
battr(create_info->alter_table_convert_to_charset);
|
|
||||||
DBUG_ENTER("mysql_prepare_create_table");
|
DBUG_ENTER("mysql_prepare_create_table");
|
||||||
|
|
||||||
DBUG_EXECUTE_IF("test_pseudo_invisible",{
|
|
||||||
mysql_add_invisible_field(thd, &alter_info->create_list,
|
|
||||||
"invisible", &type_handler_slong, INVISIBLE_SYSTEM,
|
|
||||||
new (thd->mem_root)Item_int(thd, 9));
|
|
||||||
});
|
|
||||||
DBUG_EXECUTE_IF("test_completely_invisible",{
|
|
||||||
mysql_add_invisible_field(thd, &alter_info->create_list,
|
|
||||||
"invisible", &type_handler_slong, INVISIBLE_FULL,
|
|
||||||
new (thd->mem_root)Item_int(thd, 9));
|
|
||||||
});
|
|
||||||
DBUG_EXECUTE_IF("test_invisible_index",{
|
|
||||||
LEX_CSTRING temp;
|
|
||||||
temp.str= "invisible";
|
|
||||||
temp.length= strlen("invisible");
|
|
||||||
mysql_add_invisible_index(thd, &alter_info->key_list
|
|
||||||
, &temp, Key::MULTIPLE);
|
|
||||||
});
|
|
||||||
LEX_CSTRING* connect_string = &create_info->connect_string;
|
LEX_CSTRING* connect_string = &create_info->connect_string;
|
||||||
if (connect_string->length != 0 &&
|
if (connect_string->length != 0 &&
|
||||||
connect_string->length > CONNECT_STRING_MAXLEN &&
|
connect_string->length > CONNECT_STRING_MAXLEN &&
|
||||||
@ -2804,42 +2845,16 @@ mysql_prepare_create_table(THD *thd, HA_CREATE_INFO *create_info,
|
|||||||
DBUG_RETURN(TRUE);
|
DBUG_RETURN(TRUE);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
for (field_no=0; (sql_field=it++) ; field_no++)
|
for (field_no=0; (sql_field=it++) ; field_no++)
|
||||||
{
|
{
|
||||||
/* Virtual fields are always NULL */
|
if (!(sql_field->flags & NOT_NULL_FLAG))
|
||||||
if (sql_field->vcol_info)
|
null_fields++;
|
||||||
sql_field->flags&= ~NOT_NULL_FLAG;
|
|
||||||
|
|
||||||
/*
|
|
||||||
Initialize length from its original value (number of characters),
|
|
||||||
which was set in the parser. This is necessary if we're
|
|
||||||
executing a prepared statement for the second time.
|
|
||||||
*/
|
|
||||||
sql_field->length= sql_field->char_length;
|
|
||||||
|
|
||||||
if (sql_field->bulk_alter(&dattr, &battr))
|
|
||||||
DBUG_RETURN(true);
|
|
||||||
|
|
||||||
if (sql_field->prepare_stage1(thd, thd->mem_root,
|
|
||||||
file, file->ha_table_flags(),
|
|
||||||
&dattr))
|
|
||||||
DBUG_RETURN(true);
|
|
||||||
|
|
||||||
DBUG_ASSERT(sql_field->charset);
|
|
||||||
|
|
||||||
if (sql_field->real_field_type() == MYSQL_TYPE_BIT &&
|
if (sql_field->real_field_type() == MYSQL_TYPE_BIT &&
|
||||||
file->ha_table_flags() & HA_CAN_BIT_FIELD)
|
file->ha_table_flags() & HA_CAN_BIT_FIELD)
|
||||||
total_uneven_bit_length+= sql_field->length & 7;
|
total_uneven_bit_length+= sql_field->length & 7;
|
||||||
|
|
||||||
if (!(sql_field->flags & NOT_NULL_FLAG))
|
|
||||||
null_fields++;
|
|
||||||
|
|
||||||
if (check_column_name(sql_field->field_name.str))
|
|
||||||
{
|
|
||||||
my_error(ER_WRONG_COLUMN_NAME, MYF(0), sql_field->field_name.str);
|
|
||||||
DBUG_RETURN(TRUE);
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Check if we have used the same field name before */
|
/* Check if we have used the same field name before */
|
||||||
for (dup_no=0; (dup_field=it2++) != sql_field; dup_no++)
|
for (dup_no=0; (dup_field=it2++) != sql_field; dup_no++)
|
||||||
{
|
{
|
||||||
@ -3827,6 +3842,49 @@ without_overlaps_err:
|
|||||||
DBUG_RETURN(FALSE);
|
DBUG_RETURN(FALSE);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/*
|
||||||
|
Preparation for table creation
|
||||||
|
|
||||||
|
SYNOPSIS
|
||||||
|
mysql_prepare_create_table()
|
||||||
|
thd Thread object.
|
||||||
|
create_info Create information (like MAX_ROWS).
|
||||||
|
alter_info List of columns and indexes to create
|
||||||
|
db_options INOUT Table options (like HA_OPTION_PACK_RECORD).
|
||||||
|
file The handler for the new table.
|
||||||
|
key_info_buffer OUT An array of KEY structs for the indexes.
|
||||||
|
key_count OUT The number of elements in the array.
|
||||||
|
create_table_mode C_ORDINARY_CREATE, C_ALTER_TABLE,
|
||||||
|
C_CREATE_SELECT, C_ASSISTED_DISCOVERY
|
||||||
|
|
||||||
|
DESCRIPTION
|
||||||
|
Prepares the table and key structures for table creation.
|
||||||
|
|
||||||
|
NOTES
|
||||||
|
sets create_info->varchar if the table has a varchar
|
||||||
|
|
||||||
|
RETURN VALUES
|
||||||
|
FALSE OK
|
||||||
|
TRUE error
|
||||||
|
*/
|
||||||
|
|
||||||
|
static int
|
||||||
|
mysql_prepare_create_table(THD *thd, HA_CREATE_INFO *create_info,
|
||||||
|
Alter_info *alter_info, uint *db_options,
|
||||||
|
handler *file, KEY **key_info_buffer,
|
||||||
|
uint *key_count, int create_table_mode,
|
||||||
|
const LEX_CSTRING db,
|
||||||
|
const LEX_CSTRING table_name)
|
||||||
|
{
|
||||||
|
return mysql_prepare_create_table_stage1(thd, create_info, alter_info) ||
|
||||||
|
mysql_prepare_create_table_finalize(thd, create_info, alter_info,
|
||||||
|
db_options, file, key_info_buffer,
|
||||||
|
key_count, create_table_mode,
|
||||||
|
db, table_name);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
check comment length of table, column, index and partition
|
check comment length of table, column, index and partition
|
||||||
|
|
||||||
@ -3955,7 +4013,8 @@ bool Column_definition::prepare_blob_field(THD *thd)
|
|||||||
bool Column_definition::sp_prepare_create_field(THD *thd, MEM_ROOT *mem_root)
|
bool Column_definition::sp_prepare_create_field(THD *thd, MEM_ROOT *mem_root)
|
||||||
{
|
{
|
||||||
const Column_derived_attributes dattr(thd->variables.collation_database);
|
const Column_derived_attributes dattr(thd->variables.collation_database);
|
||||||
return prepare_stage1(thd, mem_root, NULL, HA_CAN_GEOMETRY, &dattr) ||
|
return prepare_stage1(thd, mem_root,
|
||||||
|
COLUMN_DEFINITION_ROUTINE_LOCAL, &dattr) ||
|
||||||
prepare_stage2(NULL, HA_CAN_GEOMETRY);
|
prepare_stage2(NULL, HA_CAN_GEOMETRY);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -4050,6 +4109,9 @@ handler *mysql_create_frm_image(THD *thd, const LEX_CSTRING &db,
|
|||||||
DBUG_RETURN(NULL);
|
DBUG_RETURN(NULL);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (mysql_prepare_create_table_stage1(thd, create_info, alter_info))
|
||||||
|
DBUG_RETURN(NULL);
|
||||||
|
|
||||||
db_options= create_info->table_options_with_row_type();
|
db_options= create_info->table_options_with_row_type();
|
||||||
|
|
||||||
if (unlikely(!(file= get_new_handler((TABLE_SHARE*) 0, thd->mem_root,
|
if (unlikely(!(file= get_new_handler((TABLE_SHARE*) 0, thd->mem_root,
|
||||||
@ -4266,9 +4328,10 @@ handler *mysql_create_frm_image(THD *thd, const LEX_CSTRING &db,
|
|||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
if (mysql_prepare_create_table(thd, create_info, alter_info, &db_options,
|
if (mysql_prepare_create_table_finalize(thd, create_info,
|
||||||
file, key_info, key_count,
|
alter_info, &db_options,
|
||||||
create_table_mode, db, table_name))
|
file, key_info, key_count,
|
||||||
|
create_table_mode, db, table_name))
|
||||||
goto err;
|
goto err;
|
||||||
create_info->table_options=db_options;
|
create_info->table_options=db_options;
|
||||||
|
|
||||||
|
@ -3008,8 +3008,7 @@ bool Type_handler::
|
|||||||
Column_definition_prepare_stage1(THD *thd,
|
Column_definition_prepare_stage1(THD *thd,
|
||||||
MEM_ROOT *mem_root,
|
MEM_ROOT *mem_root,
|
||||||
Column_definition *def,
|
Column_definition *def,
|
||||||
handler *file,
|
column_definition_type_t type,
|
||||||
ulonglong table_flags,
|
|
||||||
const Column_derived_attributes
|
const Column_derived_attributes
|
||||||
*derived_attr)
|
*derived_attr)
|
||||||
const
|
const
|
||||||
@ -3022,8 +3021,7 @@ bool Type_handler_null::
|
|||||||
Column_definition_prepare_stage1(THD *thd,
|
Column_definition_prepare_stage1(THD *thd,
|
||||||
MEM_ROOT *mem_root,
|
MEM_ROOT *mem_root,
|
||||||
Column_definition *def,
|
Column_definition *def,
|
||||||
handler *file,
|
column_definition_type_t type,
|
||||||
ulonglong table_flags,
|
|
||||||
const Column_derived_attributes
|
const Column_derived_attributes
|
||||||
*derived_attr)
|
*derived_attr)
|
||||||
const
|
const
|
||||||
@ -3037,8 +3035,7 @@ bool Type_handler_row::
|
|||||||
Column_definition_prepare_stage1(THD *thd,
|
Column_definition_prepare_stage1(THD *thd,
|
||||||
MEM_ROOT *mem_root,
|
MEM_ROOT *mem_root,
|
||||||
Column_definition *def,
|
Column_definition *def,
|
||||||
handler *file,
|
column_definition_type_t type,
|
||||||
ulonglong table_flags,
|
|
||||||
const Column_derived_attributes
|
const Column_derived_attributes
|
||||||
*derived_attr)
|
*derived_attr)
|
||||||
const
|
const
|
||||||
@ -3052,8 +3049,7 @@ bool Type_handler_temporal_result::
|
|||||||
Column_definition_prepare_stage1(THD *thd,
|
Column_definition_prepare_stage1(THD *thd,
|
||||||
MEM_ROOT *mem_root,
|
MEM_ROOT *mem_root,
|
||||||
Column_definition *def,
|
Column_definition *def,
|
||||||
handler *file,
|
column_definition_type_t type,
|
||||||
ulonglong table_flags,
|
|
||||||
const Column_derived_attributes
|
const Column_derived_attributes
|
||||||
*derived_attr)
|
*derived_attr)
|
||||||
const
|
const
|
||||||
@ -3067,8 +3063,7 @@ bool Type_handler_numeric::
|
|||||||
Column_definition_prepare_stage1(THD *thd,
|
Column_definition_prepare_stage1(THD *thd,
|
||||||
MEM_ROOT *mem_root,
|
MEM_ROOT *mem_root,
|
||||||
Column_definition *def,
|
Column_definition *def,
|
||||||
handler *file,
|
column_definition_type_t type,
|
||||||
ulonglong table_flags,
|
|
||||||
const Column_derived_attributes
|
const Column_derived_attributes
|
||||||
*derived_attr)
|
*derived_attr)
|
||||||
const
|
const
|
||||||
@ -3081,8 +3076,7 @@ bool Type_handler_newdecimal::
|
|||||||
Column_definition_prepare_stage1(THD *thd,
|
Column_definition_prepare_stage1(THD *thd,
|
||||||
MEM_ROOT *mem_root,
|
MEM_ROOT *mem_root,
|
||||||
Column_definition *def,
|
Column_definition *def,
|
||||||
handler *file,
|
column_definition_type_t type,
|
||||||
ulonglong table_flags,
|
|
||||||
const Column_derived_attributes
|
const Column_derived_attributes
|
||||||
*derived_attr)
|
*derived_attr)
|
||||||
const
|
const
|
||||||
@ -3096,28 +3090,26 @@ bool Type_handler_bit::
|
|||||||
Column_definition_prepare_stage1(THD *thd,
|
Column_definition_prepare_stage1(THD *thd,
|
||||||
MEM_ROOT *mem_root,
|
MEM_ROOT *mem_root,
|
||||||
Column_definition *def,
|
Column_definition *def,
|
||||||
handler *file,
|
column_definition_type_t type,
|
||||||
ulonglong table_flags,
|
|
||||||
const Column_derived_attributes
|
const Column_derived_attributes
|
||||||
*derived_attr)
|
*derived_attr)
|
||||||
const
|
const
|
||||||
{
|
{
|
||||||
def->charset= &my_charset_numeric;
|
def->charset= &my_charset_numeric;
|
||||||
return def->prepare_stage1_bit(thd, mem_root, file, table_flags);
|
return def->prepare_stage1_bit(thd, mem_root);
|
||||||
}
|
}
|
||||||
|
|
||||||
bool Type_handler_typelib::
|
bool Type_handler_typelib::
|
||||||
Column_definition_prepare_stage1(THD *thd,
|
Column_definition_prepare_stage1(THD *thd,
|
||||||
MEM_ROOT *mem_root,
|
MEM_ROOT *mem_root,
|
||||||
Column_definition *def,
|
Column_definition *def,
|
||||||
handler *file,
|
column_definition_type_t type,
|
||||||
ulonglong table_flags,
|
|
||||||
const Column_derived_attributes
|
const Column_derived_attributes
|
||||||
*derived_attr)
|
*derived_attr)
|
||||||
const
|
const
|
||||||
{
|
{
|
||||||
return def->prepare_charset_for_string(derived_attr) ||
|
return def->prepare_charset_for_string(derived_attr) ||
|
||||||
def->prepare_stage1_typelib(thd, mem_root, file, table_flags);
|
def->prepare_stage1_typelib(thd, mem_root, type);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@ -3125,14 +3117,13 @@ bool Type_handler_string_result::
|
|||||||
Column_definition_prepare_stage1(THD *thd,
|
Column_definition_prepare_stage1(THD *thd,
|
||||||
MEM_ROOT *mem_root,
|
MEM_ROOT *mem_root,
|
||||||
Column_definition *def,
|
Column_definition *def,
|
||||||
handler *file,
|
column_definition_type_t type,
|
||||||
ulonglong table_flags,
|
|
||||||
const Column_derived_attributes
|
const Column_derived_attributes
|
||||||
*derived_attr)
|
*derived_attr)
|
||||||
const
|
const
|
||||||
{
|
{
|
||||||
return def->prepare_charset_for_string(derived_attr) ||
|
return def->prepare_charset_for_string(derived_attr) ||
|
||||||
def->prepare_stage1_string(thd, mem_root, file, table_flags);
|
def->prepare_stage1_string(thd, mem_root);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@ -3343,10 +3334,11 @@ bool Type_handler_bit::
|
|||||||
handler *file,
|
handler *file,
|
||||||
ulonglong table_flags) const
|
ulonglong table_flags) const
|
||||||
{
|
{
|
||||||
/*
|
if (!(table_flags & HA_CAN_BIT_FIELD))
|
||||||
We have sql_field->pack_flag already set here, see
|
{
|
||||||
mysql_prepare_create_table().
|
def->pack_flag|= FIELDFLAG_TREAT_BIT_AS_CHAR;
|
||||||
*/
|
def->create_length_to_internal_length_bit();
|
||||||
|
}
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -3962,8 +3962,7 @@ public:
|
|||||||
virtual bool Column_definition_prepare_stage1(THD *thd,
|
virtual bool Column_definition_prepare_stage1(THD *thd,
|
||||||
MEM_ROOT *mem_root,
|
MEM_ROOT *mem_root,
|
||||||
Column_definition *c,
|
Column_definition *c,
|
||||||
handler *file,
|
column_definition_type_t type,
|
||||||
ulonglong table_flags,
|
|
||||||
const Column_derived_attributes
|
const Column_derived_attributes
|
||||||
*derived_attr)
|
*derived_attr)
|
||||||
const;
|
const;
|
||||||
@ -4441,8 +4440,7 @@ public:
|
|||||||
bool Column_definition_prepare_stage1(THD *thd,
|
bool Column_definition_prepare_stage1(THD *thd,
|
||||||
MEM_ROOT *mem_root,
|
MEM_ROOT *mem_root,
|
||||||
Column_definition *c,
|
Column_definition *c,
|
||||||
handler *file,
|
column_definition_type_t type,
|
||||||
ulonglong table_flags,
|
|
||||||
const Column_derived_attributes
|
const Column_derived_attributes
|
||||||
*derived_attr)
|
*derived_attr)
|
||||||
const override;
|
const override;
|
||||||
@ -4756,8 +4754,7 @@ public:
|
|||||||
bool Column_definition_prepare_stage1(THD *thd,
|
bool Column_definition_prepare_stage1(THD *thd,
|
||||||
MEM_ROOT *mem_root,
|
MEM_ROOT *mem_root,
|
||||||
Column_definition *c,
|
Column_definition *c,
|
||||||
handler *file,
|
column_definition_type_t type,
|
||||||
ulonglong table_flags,
|
|
||||||
const Column_derived_attributes
|
const Column_derived_attributes
|
||||||
*derived_attr)
|
*derived_attr)
|
||||||
const override;
|
const override;
|
||||||
@ -5310,8 +5307,7 @@ public:
|
|||||||
bool Column_definition_prepare_stage1(THD *thd,
|
bool Column_definition_prepare_stage1(THD *thd,
|
||||||
MEM_ROOT *mem_root,
|
MEM_ROOT *mem_root,
|
||||||
Column_definition *c,
|
Column_definition *c,
|
||||||
handler *file,
|
column_definition_type_t type,
|
||||||
ulonglong table_flags,
|
|
||||||
const Column_derived_attributes
|
const Column_derived_attributes
|
||||||
*derived_attr)
|
*derived_attr)
|
||||||
const override;
|
const override;
|
||||||
@ -5414,8 +5410,7 @@ public:
|
|||||||
bool Column_definition_prepare_stage1(THD *thd,
|
bool Column_definition_prepare_stage1(THD *thd,
|
||||||
MEM_ROOT *mem_root,
|
MEM_ROOT *mem_root,
|
||||||
Column_definition *c,
|
Column_definition *c,
|
||||||
handler *file,
|
column_definition_type_t type,
|
||||||
ulonglong table_flags,
|
|
||||||
const Column_derived_attributes
|
const Column_derived_attributes
|
||||||
*derived_attr)
|
*derived_attr)
|
||||||
const override;
|
const override;
|
||||||
@ -5947,8 +5942,7 @@ public:
|
|||||||
bool Column_definition_prepare_stage1(THD *thd,
|
bool Column_definition_prepare_stage1(THD *thd,
|
||||||
MEM_ROOT *mem_root,
|
MEM_ROOT *mem_root,
|
||||||
Column_definition *c,
|
Column_definition *c,
|
||||||
handler *file,
|
column_definition_type_t type,
|
||||||
ulonglong table_flags,
|
|
||||||
const Column_derived_attributes
|
const Column_derived_attributes
|
||||||
*derived_attr)
|
*derived_attr)
|
||||||
const override;
|
const override;
|
||||||
@ -6791,8 +6785,7 @@ public:
|
|||||||
bool Column_definition_prepare_stage1(THD *thd,
|
bool Column_definition_prepare_stage1(THD *thd,
|
||||||
MEM_ROOT *mem_root,
|
MEM_ROOT *mem_root,
|
||||||
Column_definition *c,
|
Column_definition *c,
|
||||||
handler *file,
|
column_definition_type_t type,
|
||||||
ulonglong table_flags,
|
|
||||||
const Column_derived_attributes
|
const Column_derived_attributes
|
||||||
*derived_attr)
|
*derived_attr)
|
||||||
const override;
|
const override;
|
||||||
@ -6849,8 +6842,7 @@ public:
|
|||||||
bool Column_definition_prepare_stage1(THD *thd,
|
bool Column_definition_prepare_stage1(THD *thd,
|
||||||
MEM_ROOT *mem_root,
|
MEM_ROOT *mem_root,
|
||||||
Column_definition *c,
|
Column_definition *c,
|
||||||
handler *file,
|
column_definition_type_t type,
|
||||||
ulonglong table_flags,
|
|
||||||
const Column_derived_attributes
|
const Column_derived_attributes
|
||||||
*derived_attr)
|
*derived_attr)
|
||||||
const override;
|
const override;
|
||||||
@ -7286,8 +7278,7 @@ public:
|
|||||||
bool Column_definition_prepare_stage1(THD *thd,
|
bool Column_definition_prepare_stage1(THD *thd,
|
||||||
MEM_ROOT *mem_root,
|
MEM_ROOT *mem_root,
|
||||||
Column_definition *c,
|
Column_definition *c,
|
||||||
handler *file,
|
column_definition_type_t type,
|
||||||
ulonglong table_flags,
|
|
||||||
const Column_derived_attributes
|
const Column_derived_attributes
|
||||||
*derived_attr)
|
*derived_attr)
|
||||||
const override;
|
const override;
|
||||||
|
@ -382,8 +382,8 @@ public:
|
|||||||
}
|
}
|
||||||
|
|
||||||
bool Column_definition_prepare_stage1(THD *thd, MEM_ROOT *mem_root,
|
bool Column_definition_prepare_stage1(THD *thd, MEM_ROOT *mem_root,
|
||||||
Column_definition *def, handler *file,
|
Column_definition *def,
|
||||||
ulonglong table_flags,
|
column_definition_type_t type,
|
||||||
const Column_derived_attributes *derived_attr)
|
const Column_derived_attributes *derived_attr)
|
||||||
const override
|
const override
|
||||||
{
|
{
|
||||||
|
@ -280,8 +280,7 @@ bool Type_handler_geometry::
|
|||||||
Column_definition_prepare_stage1(THD *thd,
|
Column_definition_prepare_stage1(THD *thd,
|
||||||
MEM_ROOT *mem_root,
|
MEM_ROOT *mem_root,
|
||||||
Column_definition *def,
|
Column_definition *def,
|
||||||
handler *file,
|
column_definition_type_t type,
|
||||||
ulonglong table_flags,
|
|
||||||
const Column_derived_attributes
|
const Column_derived_attributes
|
||||||
*derived_attr) const
|
*derived_attr) const
|
||||||
{
|
{
|
||||||
|
@ -108,8 +108,7 @@ public:
|
|||||||
bool Column_definition_prepare_stage1(THD *thd,
|
bool Column_definition_prepare_stage1(THD *thd,
|
||||||
MEM_ROOT *mem_root,
|
MEM_ROOT *mem_root,
|
||||||
Column_definition *c,
|
Column_definition *c,
|
||||||
handler *file,
|
column_definition_type_t type,
|
||||||
ulonglong table_flags,
|
|
||||||
const Column_derived_attributes
|
const Column_derived_attributes
|
||||||
*derived_attr)
|
*derived_attr)
|
||||||
const override;
|
const override;
|
||||||
|
Reference in New Issue
Block a user