summaryrefslogtreecommitdiff
path: root/sql/sql_table.cc
diff options
context:
space:
mode:
Diffstat (limited to 'sql/sql_table.cc')
-rw-r--r--sql/sql_table.cc394
1 files changed, 253 insertions, 141 deletions
diff --git a/sql/sql_table.cc b/sql/sql_table.cc
index 37c897aca3b..691b248fb2e 100644
--- a/sql/sql_table.cc
+++ b/sql/sql_table.cc
@@ -70,15 +70,21 @@ static void wait_for_kill_signal(THD *thd)
/**
@brief Helper function for explain_filename
+ @param thd Thread handle
+ @param to_p Explained name in system_charset_info
+ @param end_p End of the to_p buffer
+ @param name Name to be converted
+ @param name_len Length of the name, in bytes
*/
-static char* add_identifier(char *to_p, const char * end_p,
- const char* name, uint name_len, bool add_quotes)
+static char* add_identifier(THD* thd, char *to_p, const char * end_p,
+ const char* name, uint name_len)
{
uint res;
uint errors;
const char *conv_name;
char tmp_name[FN_REFLEN];
char conv_string[FN_REFLEN];
+ int quote;
DBUG_ENTER("add_identifier");
if (!name[name_len])
@@ -102,19 +108,21 @@ static char* add_identifier(char *to_p, const char * end_p,
conv_name= conv_string;
}
- if (add_quotes && (end_p - to_p > 2))
+ quote = thd ? get_quote_char_for_identifier(thd, conv_name, res - 1) : '"';
+
+ if (quote != EOF && (end_p - to_p > 2))
{
- *(to_p++)= '`';
+ *(to_p++)= (char) quote;
while (*conv_name && (end_p - to_p - 1) > 0)
{
uint length= my_mbcharlen(system_charset_info, *conv_name);
if (!length)
length= 1;
- if (length == 1 && *conv_name == '`')
+ if (length == 1 && *conv_name == (char) quote)
{
if ((end_p - to_p) < 3)
break;
- *(to_p++)= '`';
+ *(to_p++)= (char) quote;
*(to_p++)= *(conv_name++);
}
else if (((long) length) < (end_p - to_p))
@@ -125,7 +133,11 @@ static char* add_identifier(char *to_p, const char * end_p,
else
break; /* string already filled */
}
- to_p= strnmov(to_p, "`", end_p - to_p);
+ if (end_p > to_p) {
+ *(to_p++)= (char) quote;
+ if (end_p > to_p)
+ *to_p= 0; /* terminate by NUL, but do not include it in the count */
+ }
}
else
to_p= strnmov(to_p, conv_name, end_p - to_p);
@@ -145,6 +157,7 @@ static char* add_identifier(char *to_p, const char * end_p,
diagnostic, error etc. when it would be useful to know what a particular
file [and directory] means. Such as SHOW ENGINE STATUS, error messages etc.
+ @param thd Thread handle
@param from Path name in my_charset_filename
Null terminated in my_charset_filename, normalized
to use '/' as directory separation character.
@@ -161,13 +174,12 @@ static char* add_identifier(char *to_p, const char * end_p,
[,[ Temporary| Renamed] Partition `p`
[, Subpartition `sp`]] *|
(| is really a /, and it is all in one line)
- EXPLAIN_PARTITIONS_AS_COMMENT_NO_QUOTING ->
- same as above but no quotes are added.
@retval Length of returned string
*/
-uint explain_filename(const char *from,
+uint explain_filename(THD* thd,
+ const char *from,
char *to,
uint to_length,
enum_explain_filename_mode explain_mode)
@@ -281,14 +293,12 @@ uint explain_filename(const char *from,
{
to_p= strnmov(to_p, ER(ER_DATABASE_NAME), end_p - to_p);
*(to_p++)= ' ';
- to_p= add_identifier(to_p, end_p, db_name, db_name_len, 1);
+ to_p= add_identifier(thd, to_p, end_p, db_name, db_name_len);
to_p= strnmov(to_p, ", ", end_p - to_p);
}
else
{
- to_p= add_identifier(to_p, end_p, db_name, db_name_len,
- (explain_mode !=
- EXPLAIN_PARTITIONS_AS_COMMENT_NO_QUOTING));
+ to_p= add_identifier(thd, to_p, end_p, db_name, db_name_len);
to_p= strnmov(to_p, ".", end_p - to_p);
}
}
@@ -296,16 +306,13 @@ uint explain_filename(const char *from,
{
to_p= strnmov(to_p, ER(ER_TABLE_NAME), end_p - to_p);
*(to_p++)= ' ';
- to_p= add_identifier(to_p, end_p, table_name, table_name_len, 1);
+ to_p= add_identifier(thd, to_p, end_p, table_name, table_name_len);
}
else
- to_p= add_identifier(to_p, end_p, table_name, table_name_len,
- (explain_mode !=
- EXPLAIN_PARTITIONS_AS_COMMENT_NO_QUOTING));
+ to_p= add_identifier(thd, to_p, end_p, table_name, table_name_len);
if (part_name)
{
- if (explain_mode == EXPLAIN_PARTITIONS_AS_COMMENT ||
- explain_mode == EXPLAIN_PARTITIONS_AS_COMMENT_NO_QUOTING)
+ if (explain_mode == EXPLAIN_PARTITIONS_AS_COMMENT)
to_p= strnmov(to_p, " /* ", end_p - to_p);
else if (explain_mode == EXPLAIN_PARTITIONS_VERBOSE)
to_p= strnmov(to_p, " ", end_p - to_p);
@@ -321,20 +328,15 @@ uint explain_filename(const char *from,
}
to_p= strnmov(to_p, ER(ER_PARTITION_NAME), end_p - to_p);
*(to_p++)= ' ';
- to_p= add_identifier(to_p, end_p, part_name, part_name_len,
- (explain_mode !=
- EXPLAIN_PARTITIONS_AS_COMMENT_NO_QUOTING));
+ to_p= add_identifier(thd, to_p, end_p, part_name, part_name_len);
if (subpart_name)
{
to_p= strnmov(to_p, ", ", end_p - to_p);
to_p= strnmov(to_p, ER(ER_SUBPARTITION_NAME), end_p - to_p);
*(to_p++)= ' ';
- to_p= add_identifier(to_p, end_p, subpart_name, subpart_name_len,
- (explain_mode !=
- EXPLAIN_PARTITIONS_AS_COMMENT_NO_QUOTING));
+ to_p= add_identifier(thd, to_p, end_p, subpart_name, subpart_name_len);
}
- if (explain_mode == EXPLAIN_PARTITIONS_AS_COMMENT ||
- explain_mode == EXPLAIN_PARTITIONS_AS_COMMENT_NO_QUOTING)
+ if (explain_mode == EXPLAIN_PARTITIONS_AS_COMMENT)
to_p= strnmov(to_p, " */", end_p - to_p);
}
DBUG_PRINT("exit", ("to '%s'", to));
@@ -1583,7 +1585,9 @@ bool mysql_write_frm(ALTER_PARTITION_PARAM_TYPE *lpt, uint flags)
{
if (!(part_syntax_buf= generate_partition_syntax(part_info,
&syntax_len,
- TRUE, TRUE)))
+ TRUE, TRUE,
+ lpt->create_info,
+ lpt->alter_info)))
{
DBUG_RETURN(TRUE);
}
@@ -1675,7 +1679,9 @@ bool mysql_write_frm(ALTER_PARTITION_PARAM_TYPE *lpt, uint flags)
char *tmp_part_syntax_str;
if (!(part_syntax_buf= generate_partition_syntax(part_info,
&syntax_len,
- TRUE, TRUE)))
+ TRUE, TRUE,
+ lpt->create_info,
+ lpt->alter_info)))
{
error= 1;
goto err;
@@ -1729,9 +1735,10 @@ end:
file
*/
-void write_bin_log(THD *thd, bool clear_error,
- char const *query, ulong query_length)
+int write_bin_log(THD *thd, bool clear_error,
+ char const *query, ulong query_length)
{
+ int error= 0;
if (mysql_bin_log.is_open())
{
int errcode= 0;
@@ -1739,9 +1746,10 @@ void write_bin_log(THD *thd, bool clear_error,
thd->clear_error();
else
errcode= query_error_code(thd, TRUE);
- thd->binlog_query(THD::STMT_QUERY_TYPE,
- query, query_length, FALSE, FALSE, errcode);
+ error= thd->binlog_query(THD::STMT_QUERY_TYPE,
+ query, query_length, FALSE, FALSE, errcode);
}
+ return error;
}
@@ -1949,7 +1957,7 @@ int mysql_rm_table_part2(THD *thd, TABLE_LIST *tables, bool if_exists,
being built. The string always end in a comma and the comma
will be chopped off before being written to the binary log.
*/
- if (thd->current_stmt_binlog_row_based && !dont_log_query)
+ if (!drop_temporary && thd->current_stmt_binlog_row_based && !dont_log_query)
{
non_temp_tables_count++;
/*
@@ -2054,6 +2062,12 @@ int mysql_rm_table_part2(THD *thd, TABLE_LIST *tables, bool if_exists,
}
DBUG_PRINT("table", ("table: 0x%lx s: 0x%lx", (long) table->table,
table->table ? (long) table->table->s : (long) -1));
+
+ DBUG_EXECUTE_IF("bug43138",
+ my_printf_error(ER_BAD_TABLE_ERROR,
+ ER(ER_BAD_TABLE_ERROR), MYF(0),
+ table->table_name););
+
}
/*
It's safe to unlock LOCK_open: we have an exclusive lock
@@ -2087,7 +2101,7 @@ int mysql_rm_table_part2(THD *thd, TABLE_LIST *tables, bool if_exists,
tables). In this case, we can write the original query into
the binary log.
*/
- write_bin_log(thd, !error, thd->query, thd->query_length);
+ error |= write_bin_log(thd, !error, thd->query(), thd->query_length());
}
else if (thd->current_stmt_binlog_row_based &&
tmp_table_deleted)
@@ -2109,7 +2123,7 @@ int mysql_rm_table_part2(THD *thd, TABLE_LIST *tables, bool if_exists,
*/
built_query.chop(); // Chop of the last comma
built_query.append(" /* generated by server */");
- write_bin_log(thd, !error, built_query.ptr(), built_query.length());
+ error|= write_bin_log(thd, !error, built_query.ptr(), built_query.length());
}
/*
@@ -2128,7 +2142,7 @@ int mysql_rm_table_part2(THD *thd, TABLE_LIST *tables, bool if_exists,
*/
built_tmp_query.chop(); // Chop of the last comma
built_tmp_query.append(" /* generated by server */");
- write_bin_log(thd, !error, built_tmp_query.ptr(), built_tmp_query.length());
+ error|= write_bin_log(thd, !error, built_tmp_query.ptr(), built_tmp_query.length());
}
}
@@ -2267,17 +2281,19 @@ bool check_duplicates_in_interval(const char *set_or_name,
tmp.count--;
if (find_type2(&tmp, (const char*)*cur_value, *cur_length, cs))
{
+ THD *thd= current_thd;
+ ErrConvString err(*cur_value, *cur_length, cs);
if ((current_thd->variables.sql_mode &
(MODE_STRICT_TRANS_TABLES | MODE_STRICT_ALL_TABLES)))
{
my_error(ER_DUPLICATED_VALUE_IN_TYPE, MYF(0),
- name,*cur_value,set_or_name);
+ name, err.ptr(), set_or_name);
return 1;
}
- push_warning_printf(current_thd,MYSQL_ERROR::WARN_LEVEL_NOTE,
- ER_DUPLICATED_VALUE_IN_TYPE,
- ER(ER_DUPLICATED_VALUE_IN_TYPE),
- name,*cur_value,set_or_name);
+ push_warning_printf(thd,MYSQL_ERROR::WARN_LEVEL_NOTE,
+ ER_DUPLICATED_VALUE_IN_TYPE,
+ ER(ER_DUPLICATED_VALUE_IN_TYPE),
+ name, err.ptr(), set_or_name);
(*dup_val_count)++;
}
}
@@ -2494,6 +2510,39 @@ int prepare_create_field(Create_field *sql_field,
DBUG_RETURN(0);
}
+
+/*
+ Get character set from field object generated by parser using
+ default values when not set.
+
+ SYNOPSIS
+ get_sql_field_charset()
+ sql_field The sql_field object
+ create_info Info generated by parser
+
+ RETURN VALUES
+ cs Character set
+*/
+
+CHARSET_INFO* get_sql_field_charset(Create_field *sql_field,
+ HA_CREATE_INFO *create_info)
+{
+ CHARSET_INFO *cs= sql_field->charset;
+
+ if (!cs)
+ cs= create_info->default_table_charset;
+ /*
+ table_charset is set only in ALTER TABLE t1 CONVERT TO CHARACTER SET csname
+ if we want change character set for all varchar/char columns.
+ But the table charset must not affect the BLOB fields, so don't
+ allow to change my_charset_bin to somethig else.
+ */
+ if (create_info->table_charset && cs != &my_charset_bin)
+ cs= create_info->table_charset;
+ return cs;
+}
+
+
/*
Preparation for table creation
@@ -2557,18 +2606,8 @@ mysql_prepare_create_table(THD *thd, HA_CREATE_INFO *create_info,
executing a prepared statement for the second time.
*/
sql_field->length= sql_field->char_length;
- if (!sql_field->charset)
- sql_field->charset= create_info->default_table_charset;
- /*
- table_charset is set in ALTER TABLE if we want change character set
- for all varchar/char columns.
- But the table charset must not affect the BLOB fields, so don't
- allow to change my_charset_bin to somethig else.
- */
- if (create_info->table_charset && sql_field->charset != &my_charset_bin)
- sql_field->charset= create_info->table_charset;
-
- save_cs= sql_field->charset;
+ save_cs= sql_field->charset= get_sql_field_charset(sql_field,
+ create_info);
if ((sql_field->flags & BINCMP_FLAG) &&
!(sql_field->charset= get_charset_by_csname(sql_field->charset->csname,
MY_CS_BINSORT,MYF(0))))
@@ -2663,7 +2702,8 @@ mysql_prepare_create_table(THD *thd, HA_CREATE_INFO *create_info,
interval->type_lengths[i],
comma_buf, comma_length, NULL, 0))
{
- my_error(ER_ILLEGAL_VALUE_FOR_TYPE, MYF(0), "set", tmp->ptr());
+ ErrConvString err(tmp->ptr(), tmp->length(), cs);
+ my_error(ER_ILLEGAL_VALUE_FOR_TYPE, MYF(0), "set", err.ptr());
DBUG_RETURN(TRUE);
}
}
@@ -2877,9 +2917,8 @@ mysql_prepare_create_table(THD *thd, HA_CREATE_INFO *create_info,
while ((key=key_iterator++))
{
- DBUG_PRINT("info", ("key name: '%s' type: %d", key->name ? key->name :
+ DBUG_PRINT("info", ("key name: '%s' type: %d", key->name.str ? key->name.str :
"(none)" , key->type));
- LEX_STRING key_name_str;
if (key->type == Key::FOREIGN_KEY)
{
fk_key_count++;
@@ -2888,7 +2927,8 @@ mysql_prepare_create_table(THD *thd, HA_CREATE_INFO *create_info,
fk_key->ref_columns.elements != fk_key->columns.elements)
{
my_error(ER_WRONG_FK_DEF, MYF(0),
- (fk_key->name ? fk_key->name : "foreign key without name"),
+ (fk_key->name.str ? fk_key->name.str :
+ "foreign key without name"),
ER(ER_KEY_REF_DO_NOT_MATCH_TABLE_REF));
DBUG_RETURN(TRUE);
}
@@ -2901,12 +2941,10 @@ mysql_prepare_create_table(THD *thd, HA_CREATE_INFO *create_info,
my_error(ER_TOO_MANY_KEY_PARTS,MYF(0),tmp);
DBUG_RETURN(TRUE);
}
- key_name_str.str= (char*) key->name;
- key_name_str.length= key->name ? strlen(key->name) : 0;
- if (check_string_char_length(&key_name_str, "", NAME_CHAR_LEN,
+ if (check_string_char_length(&key->name, "", NAME_CHAR_LEN,
system_charset_info, 1))
{
- my_error(ER_TOO_LONG_IDENT, MYF(0), key->name);
+ my_error(ER_TOO_LONG_IDENT, MYF(0), key->name.str);
DBUG_RETURN(TRUE);
}
key_iterator2.rewind ();
@@ -2920,7 +2958,7 @@ mysql_prepare_create_table(THD *thd, HA_CREATE_INFO *create_info,
Then we do not need the generated shorter key.
*/
if ((key2->type != Key::FOREIGN_KEY &&
- key2->name != ignore_key &&
+ key2->name.str != ignore_key &&
!foreign_key_prefix(key, key2)))
{
/* TODO: issue warning message */
@@ -2928,10 +2966,10 @@ mysql_prepare_create_table(THD *thd, HA_CREATE_INFO *create_info,
if (!key2->generated ||
(key->generated && key->columns.elements <
key2->columns.elements))
- key->name= ignore_key;
+ key->name.str= ignore_key;
else
{
- key2->name= ignore_key;
+ key2->name.str= ignore_key;
key_parts-= key2->columns.elements;
(*key_count)--;
}
@@ -2939,14 +2977,14 @@ mysql_prepare_create_table(THD *thd, HA_CREATE_INFO *create_info,
}
}
}
- if (key->name != ignore_key)
+ if (key->name.str != ignore_key)
key_parts+=key->columns.elements;
else
(*key_count)--;
- if (key->name && !tmp_table && (key->type != Key::PRIMARY) &&
- !my_strcasecmp(system_charset_info,key->name,primary_key_name))
+ if (key->name.str && !tmp_table && (key->type != Key::PRIMARY) &&
+ !my_strcasecmp(system_charset_info, key->name.str, primary_key_name))
{
- my_error(ER_WRONG_NAME_FOR_INDEX, MYF(0), key->name);
+ my_error(ER_WRONG_NAME_FOR_INDEX, MYF(0), key->name.str);
DBUG_RETURN(TRUE);
}
}
@@ -2969,12 +3007,12 @@ mysql_prepare_create_table(THD *thd, HA_CREATE_INFO *create_info,
uint key_length=0;
Key_part_spec *column;
- if (key->name == ignore_key)
+ if (key->name.str == ignore_key)
{
/* ignore redundant keys */
do
key=key_iterator++;
- while (key && key->name == ignore_key);
+ while (key && key->name.str == ignore_key);
if (!key)
break;
}
@@ -3087,22 +3125,22 @@ mysql_prepare_create_table(THD *thd, HA_CREATE_INFO *create_info,
field=0;
while ((sql_field=it++) &&
my_strcasecmp(system_charset_info,
- column->field_name,
+ column->field_name.str,
sql_field->field_name))
field++;
if (!sql_field)
{
- my_error(ER_KEY_COLUMN_DOES_NOT_EXITS, MYF(0), column->field_name);
+ my_error(ER_KEY_COLUMN_DOES_NOT_EXITS, MYF(0), column->field_name.str);
DBUG_RETURN(TRUE);
}
while ((dup_column= cols2++) != column)
{
if (!my_strcasecmp(system_charset_info,
- column->field_name, dup_column->field_name))
+ column->field_name.str, dup_column->field_name.str))
{
my_printf_error(ER_DUP_FIELDNAME,
ER(ER_DUP_FIELDNAME),MYF(0),
- column->field_name);
+ column->field_name.str);
DBUG_RETURN(TRUE);
}
}
@@ -3116,7 +3154,7 @@ mysql_prepare_create_table(THD *thd, HA_CREATE_INFO *create_info,
sql_field->charset->mbminlen > 1 || // ucs2 doesn't work yet
(ft_key_charset && sql_field->charset != ft_key_charset))
{
- my_error(ER_BAD_FT_COLUMN, MYF(0), column->field_name);
+ my_error(ER_BAD_FT_COLUMN, MYF(0), column->field_name.str);
DBUG_RETURN(-1);
}
ft_key_charset=sql_field->charset;
@@ -3144,7 +3182,7 @@ mysql_prepare_create_table(THD *thd, HA_CREATE_INFO *create_info,
{
if (!(file->ha_table_flags() & HA_CAN_INDEX_BLOBS))
{
- my_error(ER_BLOB_USED_AS_KEY, MYF(0), column->field_name);
+ my_error(ER_BLOB_USED_AS_KEY, MYF(0), column->field_name.str);
DBUG_RETURN(TRUE);
}
if (f_is_geom(sql_field->pack_flag) && sql_field->geom_type ==
@@ -3152,7 +3190,7 @@ mysql_prepare_create_table(THD *thd, HA_CREATE_INFO *create_info,
column->length= 25;
if (!column->length)
{
- my_error(ER_BLOB_KEY_WITHOUT_LENGTH, MYF(0), column->field_name);
+ my_error(ER_BLOB_KEY_WITHOUT_LENGTH, MYF(0), column->field_name.str);
DBUG_RETURN(TRUE);
}
}
@@ -3183,7 +3221,7 @@ mysql_prepare_create_table(THD *thd, HA_CREATE_INFO *create_info,
key_info->flags|= HA_NULL_PART_KEY;
if (!(file->ha_table_flags() & HA_NULL_IN_KEY))
{
- my_error(ER_NULL_COLUMN_IN_INDEX, MYF(0), column->field_name);
+ my_error(ER_NULL_COLUMN_IN_INDEX, MYF(0), column->field_name.str);
DBUG_RETURN(TRUE);
}
if (key->type == Key::SPATIAL)
@@ -3233,13 +3271,21 @@ mysql_prepare_create_table(THD *thd, HA_CREATE_INFO *create_info,
}
}
else if (!f_is_geom(sql_field->pack_flag) &&
- (column->length > length ||
- !Field::type_can_have_key_part (sql_field->sql_type) ||
- ((f_is_packed(sql_field->pack_flag) ||
- ((file->ha_table_flags() & HA_NO_PREFIX_CHAR_KEYS) &&
- (key_info->flags & HA_NOSAME))) &&
- column->length != length)))
- {
+ ((column->length > length &&
+ !Field::type_can_have_key_part (sql_field->sql_type)) ||
+ ((f_is_packed(sql_field->pack_flag) ||
+ ((file->ha_table_flags() & HA_NO_PREFIX_CHAR_KEYS) &&
+ (key_info->flags & HA_NOSAME))) &&
+ column->length != length)))
+ {
+ /* Catch invalid uses of partial keys.
+ A key is identified as 'partial' if column->length != length.
+ A partial key is invalid if they data type does
+ not allow it, or the field is packed (as in MyISAM),
+ or the storage engine doesn't allow prefixed search and
+ the key is primary key.
+ */
+
my_message(ER_WRONG_SUB_KEY, ER(ER_WRONG_SUB_KEY), MYF(0));
DBUG_RETURN(TRUE);
}
@@ -3248,7 +3294,7 @@ mysql_prepare_create_table(THD *thd, HA_CREATE_INFO *create_info,
}
else if (length == 0)
{
- my_error(ER_WRONG_KEY_COLUMN, MYF(0), column->field_name);
+ my_error(ER_WRONG_KEY_COLUMN, MYF(0), column->field_name.str);
DBUG_RETURN(TRUE);
}
if (length > file->max_key_part_length() && key->type != Key::FULLTEXT)
@@ -3306,7 +3352,7 @@ mysql_prepare_create_table(THD *thd, HA_CREATE_INFO *create_info,
key_name=primary_key_name;
primary_key=1;
}
- else if (!(key_name = key->name))
+ else if (!(key_name= key->name.str))
key_name=make_unique_key_name(sql_field->field_name,
*key_info_buffer, key_info);
if (check_if_keyname_exists(key_name, *key_info_buffer, key_info))
@@ -3537,9 +3583,9 @@ void sp_prepare_create_field(THD *thd, Create_field *sql_field)
RETURN VALUES
NONE
*/
-static inline void write_create_table_bin_log(THD *thd,
- const HA_CREATE_INFO *create_info,
- bool internal_tmp_table)
+static inline int write_create_table_bin_log(THD *thd,
+ const HA_CREATE_INFO *create_info,
+ bool internal_tmp_table)
{
/*
Don't write statement if:
@@ -3552,7 +3598,8 @@ static inline void write_create_table_bin_log(THD *thd,
(!thd->current_stmt_binlog_row_based ||
(thd->current_stmt_binlog_row_based &&
!(create_info->options & HA_LEX_CREATE_TMP_TABLE))))
- write_bin_log(thd, TRUE, thd->query, thd->query_length);
+ return write_bin_log(thd, TRUE, thd->query(), thd->query_length());
+ return 0;
}
@@ -3617,6 +3664,9 @@ bool mysql_create_table_no_lock(THD *thd,
}
if (check_engine(thd, table_name, create_info))
DBUG_RETURN(TRUE);
+
+ set_table_default_charset(thd, create_info, (char*) db);
+
db_options= create_info->table_options;
if (create_info->row_type == ROW_TYPE_DYNAMIC)
db_options|=HA_OPTION_PACK_RECORD;
@@ -3710,7 +3760,7 @@ bool mysql_create_table_no_lock(THD *thd,
ha_resolve_storage_engine_name(part_info->default_engine_type),
ha_resolve_storage_engine_name(create_info->db_type)));
if (part_info->check_partition_info(thd, &engine_type, file,
- create_info, TRUE))
+ create_info, FALSE))
goto err;
part_info->default_engine_type= engine_type;
@@ -3720,7 +3770,9 @@ bool mysql_create_table_no_lock(THD *thd,
*/
if (!(part_syntax_buf= generate_partition_syntax(part_info,
&syntax_len,
- TRUE, TRUE)))
+ TRUE, TRUE,
+ create_info,
+ alter_info)))
goto err;
part_info->part_info_string= part_syntax_buf;
part_info->part_info_len= syntax_len;
@@ -3746,9 +3798,9 @@ bool mysql_create_table_no_lock(THD *thd,
creates a proper .par file. The current part_info object is
only used to create the frm-file and .par-file.
*/
- if (part_info->use_default_no_partitions &&
- part_info->no_parts &&
- (int)part_info->no_parts !=
+ if (part_info->use_default_num_partitions &&
+ part_info->num_parts &&
+ (int)part_info->num_parts !=
file->get_default_no_partitions(create_info))
{
uint i;
@@ -3759,13 +3811,13 @@ bool mysql_create_table_no_lock(THD *thd,
(part_it++)->part_state= PART_TO_BE_DROPPED;
}
else if (part_info->is_sub_partitioned() &&
- part_info->use_default_no_subpartitions &&
- part_info->no_subparts &&
- (int)part_info->no_subparts !=
+ part_info->use_default_num_subpartitions &&
+ part_info->num_subparts &&
+ (int)part_info->num_subparts !=
file->get_default_no_partitions(create_info))
{
DBUG_ASSERT(thd->lex->sql_command != SQLCOM_CREATE_TABLE);
- part_info->no_subparts= file->get_default_no_partitions(create_info);
+ part_info->num_subparts= file->get_default_no_partitions(create_info);
}
}
else if (create_info->db_type != engine_type)
@@ -3787,8 +3839,6 @@ bool mysql_create_table_no_lock(THD *thd,
}
#endif
- set_table_default_charset(thd, create_info, (char*) db);
-
if (mysql_prepare_create_table(thd, create_info, alter_info,
internal_tmp_table,
&db_options, file,
@@ -3818,8 +3868,7 @@ bool mysql_create_table_no_lock(THD *thd,
push_warning_printf(thd, MYSQL_ERROR::WARN_LEVEL_NOTE,
ER_TABLE_EXISTS_ERROR, ER(ER_TABLE_EXISTS_ERROR),
alias);
- error= 0;
- write_create_table_bin_log(thd, create_info, internal_tmp_table);
+ error= write_create_table_bin_log(thd, create_info, internal_tmp_table);
goto err;
}
my_error(ER_TABLE_EXISTS_ERROR, MYF(0), alias);
@@ -3844,7 +3893,7 @@ bool mysql_create_table_no_lock(THD *thd,
Then she could create the table. This case is pretty obscure and
therefore we don't introduce a new error message only for it.
*/
- if (get_cached_table_share(db, alias))
+ if (get_cached_table_share(db, table_name))
{
my_error(ER_TABLE_EXISTS_ERROR, MYF(0), table_name);
goto unlock_and_end;
@@ -3940,8 +3989,7 @@ bool mysql_create_table_no_lock(THD *thd,
thd->thread_specific_used= TRUE;
}
- write_create_table_bin_log(thd, create_info, internal_tmp_table);
- error= FALSE;
+ error= write_create_table_bin_log(thd, create_info, internal_tmp_table);
unlock_and_end:
VOID(pthread_mutex_unlock(&LOCK_open));
@@ -3956,7 +4004,7 @@ warn:
ER_TABLE_EXISTS_ERROR, ER(ER_TABLE_EXISTS_ERROR),
alias);
create_info->table_existed= 1; // Mark that table existed
- write_create_table_bin_log(thd, create_info, internal_tmp_table);
+ error= write_create_table_bin_log(thd, create_info, internal_tmp_table);
goto unlock_and_end;
}
@@ -3978,7 +4026,7 @@ bool mysql_create_table(THD *thd, const char *db, const char *table_name,
/* Wait for any database locks */
pthread_mutex_lock(&LOCK_lock_db);
while (!thd->killed &&
- hash_search(&lock_db_cache,(uchar*) db, strlen(db)))
+ my_hash_search(&lock_db_cache,(uchar*) db, strlen(db)))
{
wait_for_condition(thd, &LOCK_lock_db, &COND_refresh);
pthread_mutex_lock(&LOCK_lock_db);
@@ -4518,7 +4566,7 @@ static bool mysql_admin_table(THD* thd, TABLE_LIST* tables,
item->maybe_null = 1;
field_list.push_back(item = new Item_empty_string("Msg_text", 255));
item->maybe_null = 1;
- if (protocol->send_fields(&field_list,
+ if (protocol->send_result_set_metadata(&field_list,
Protocol::SEND_NUM_ROWS | Protocol::SEND_EOF))
DBUG_RETURN(TRUE);
@@ -4578,11 +4626,11 @@ static bool mysql_admin_table(THD* thd, TABLE_LIST* tables,
my_error(ER_PARTITION_MGMT_ON_NONPARTITIONED, MYF(0));
DBUG_RETURN(TRUE);
}
- uint no_parts_found;
- uint no_parts_opt= alter_info->partition_names.elements;
- no_parts_found= set_part_state(alter_info, table->table->part_info,
- PART_ADMIN);
- if (no_parts_found != no_parts_opt &&
+ uint num_parts_found;
+ uint num_parts_opt= alter_info->partition_names.elements;
+ num_parts_found= set_part_state(alter_info, table->table->part_info,
+ PART_ADMIN);
+ if (num_parts_found != num_parts_opt &&
(!(alter_info->flags & ALTER_ALL_PARTITION)))
{
char buff[FN_REFLEN + MYSQL_ERRMSG_SIZE];
@@ -5418,22 +5466,24 @@ binlog:
}
VOID(pthread_mutex_unlock(&LOCK_open));
- IF_DBUG(int result=)
+ int result __attribute__((unused))=
store_create_info(thd, table, &query,
create_info, FALSE /* show_database */);
DBUG_ASSERT(result == 0); // store_create_info() always return 0
- write_bin_log(thd, TRUE, query.ptr(), query.length());
+ if (write_bin_log(thd, TRUE, query.ptr(), query.length()))
+ goto err;
}
else // Case 1
- write_bin_log(thd, TRUE, thd->query, thd->query_length);
+ if (write_bin_log(thd, TRUE, thd->query(), thd->query_length()))
+ goto err;
}
/*
Case 3 and 4 does nothing under RBR
*/
}
- else
- write_bin_log(thd, TRUE, thd->query, thd->query_length);
+ else if (write_bin_log(thd, TRUE, thd->query(), thd->query_length()))
+ goto err;
res= FALSE;
@@ -5521,7 +5571,7 @@ mysql_discard_or_import_tablespace(THD *thd,
error=1;
if (error)
goto err;
- write_bin_log(thd, FALSE, thd->query, thd->query_length);
+ error= write_bin_log(thd, FALSE, thd->query(), thd->query_length());
err:
ha_autocommit_or_rollback(thd, error);
@@ -5929,6 +5979,35 @@ bool alter_table_manage_keys(TABLE *table, int indexes_were_disabled,
/**
+ maximum possible length for certain blob types.
+
+ @param[in] type Blob type (e.g. MYSQL_TYPE_TINY_BLOB)
+
+ @return
+ length
+*/
+
+static uint
+blob_length_by_type(enum_field_types type)
+{
+ switch (type)
+ {
+ case MYSQL_TYPE_TINY_BLOB:
+ return 255;
+ case MYSQL_TYPE_BLOB:
+ return 65535;
+ case MYSQL_TYPE_MEDIUM_BLOB:
+ return 16777215;
+ case MYSQL_TYPE_LONG_BLOB:
+ return 4294967295U;
+ default:
+ DBUG_ASSERT(0); // we should never go here
+ return 0;
+ }
+}
+
+
+/**
Prepare column and key definitions for CREATE TABLE in ALTER TABLE.
This function transforms parse output of ALTER TABLE - lists of
@@ -6223,6 +6302,14 @@ mysql_prepare_alter_table(THD *thd, TABLE *table,
BLOBs may have cfield->length == 0, which is why we test it before
checking whether cfield->length < key_part_length (in chars).
+
+ In case of TEXTs we check the data type maximum length *in bytes*
+ to key part length measured *in characters* (i.e. key_part_length
+ devided to mbmaxlen). This is because it's OK to have:
+ CREATE TABLE t1 (a tinytext, key(a(254)) character set utf8);
+ In case of this example:
+ - data type maximum length is 255.
+ - key_part_length is 1016 (=254*4, where 4 is mbmaxlen)
*/
if (!Field::type_can_have_key_part(cfield->field->type()) ||
!Field::type_can_have_key_part(cfield->sql_type) ||
@@ -6230,12 +6317,16 @@ mysql_prepare_alter_table(THD *thd, TABLE *table,
(key_info->flags & HA_SPATIAL) ||
(cfield->field->field_length == key_part_length &&
!f_is_blob(key_part->key_type)) ||
- (cfield->length && (cfield->length < key_part_length /
- key_part->field->charset()->mbmaxlen)))
+ (cfield->length && (((cfield->sql_type >= MYSQL_TYPE_TINY_BLOB &&
+ cfield->sql_type <= MYSQL_TYPE_BLOB) ?
+ blob_length_by_type(cfield->sql_type) :
+ cfield->length) <
+ key_part_length / key_part->field->charset()->mbmaxlen)))
key_part_length= 0; // Use whole field
}
key_part_length /= key_part->field->charset()->mbmaxlen;
key_parts.push_back(new Key_part_spec(cfield->field_name,
+ strlen(cfield->field_name),
key_part_length));
}
if (key_parts.elements)
@@ -6265,7 +6356,7 @@ mysql_prepare_alter_table(THD *thd, TABLE *table,
else
key_type= Key::MULTIPLE;
- key= new Key(key_type, key_name,
+ key= new Key(key_type, key_name, strlen(key_name),
&key_create_info,
test(key_info->flags & HA_GENERATED_KEY),
key_parts);
@@ -6278,10 +6369,10 @@ mysql_prepare_alter_table(THD *thd, TABLE *table,
{
if (key->type != Key::FOREIGN_KEY)
new_key_list.push_back(key);
- if (key->name &&
- !my_strcasecmp(system_charset_info,key->name,primary_key_name))
+ if (key->name.str &&
+ !my_strcasecmp(system_charset_info, key->name.str, primary_key_name))
{
- my_error(ER_WRONG_NAME_FOR_INDEX, MYF(0), key->name);
+ my_error(ER_WRONG_NAME_FOR_INDEX, MYF(0), key->name.str);
goto err;
}
}
@@ -6530,13 +6621,15 @@ bool mysql_alter_table(THD *thd,char *new_db, char *new_name,
if (mysql_bin_log.is_open())
{
thd->clear_error();
- Query_log_event qinfo(thd, thd->query, thd->query_length,
+ Query_log_event qinfo(thd, thd->query(), thd->query_length(),
0, FALSE, 0);
- mysql_bin_log.write(&qinfo);
+ if (error= mysql_bin_log.write(&qinfo))
+ goto view_err_unlock;
}
my_ok(thd);
}
+view_err_unlock:
unlock_table_names(thd, table_list, (TABLE_LIST*) 0);
view_err:
@@ -6657,9 +6750,19 @@ view_err:
goto err;
}
+ /*
+ If this is an ALTER TABLE and no explicit row type specified reuse
+ the table's row type.
+ Note : this is the same as if the row type was specified explicitly.
+ */
if (create_info->row_type == ROW_TYPE_NOT_USED)
{
+ /* ALTER TABLE without explicit row type */
create_info->row_type= table->s->row_type;
+ }
+ else
+ {
+ /* ALTER TABLE with specific row type */
create_info->used_fields |= HA_CREATE_USED_ROW_FORMAT;
}
@@ -6774,8 +6877,9 @@ view_err:
if (!error)
{
- write_bin_log(thd, TRUE, thd->query, thd->query_length);
- my_ok(thd);
+ error= write_bin_log(thd, TRUE, thd->query(), thd->query_length());
+ if (!error)
+ my_ok(thd);
}
else if (error > 0)
{
@@ -7263,8 +7367,9 @@ view_err:
if (rename_temporary_table(thd, new_table, new_db, new_name))
goto err1;
/* We don't replicate alter table statement on temporary tables */
- if (!thd->current_stmt_binlog_row_based)
- write_bin_log(thd, TRUE, thd->query, thd->query_length);
+ if (!thd->current_stmt_binlog_row_based &&
+ write_bin_log(thd, TRUE, thd->query(), thd->query_length()))
+ DBUG_RETURN(TRUE);
goto end_temporary;
}
@@ -7421,13 +7526,14 @@ view_err:
DBUG_EXECUTE_IF("sleep_alter_before_main_binlog", my_sleep(6000000););
ha_binlog_log_query(thd, create_info->db_type, LOGCOM_ALTER_TABLE,
- thd->query, thd->query_length,
+ thd->query(), thd->query_length(),
db, table_name);
DBUG_ASSERT(!(mysql_bin_log.is_open() &&
thd->current_stmt_binlog_row_based &&
(create_info->options & HA_LEX_CREATE_TMP_TABLE)));
- write_bin_log(thd, TRUE, thd->query, thd->query_length);
+ if (write_bin_log(thd, TRUE, thd->query(), thd->query_length()))
+ DBUG_RETURN(TRUE);
if (ha_check_storage_engine_flag(old_db_type, HTON_FLUSH_AFTER_RENAME))
{
@@ -7470,7 +7576,7 @@ view_err:
end_temporary:
my_snprintf(tmp_name, sizeof(tmp_name), ER(ER_INSERT_INFO),
(ulong) (copied + deleted), (ulong) deleted,
- (ulong) thd->cuted_fields);
+ (ulong) thd->warning_info->statement_warn_count());
my_ok(thd, copied + deleted, 0L, tmp_name);
thd->some_tables_deleted=0;
DBUG_RETURN(FALSE);
@@ -7812,7 +7918,7 @@ bool mysql_checksum_table(THD *thd, TABLE_LIST *tables,
field_list.push_back(item= new Item_int("Checksum", (longlong) 1,
MY_INT64_NUM_DECIMAL_DIGITS));
item->maybe_null= 1;
- if (protocol->send_fields(&field_list,
+ if (protocol->send_result_set_metadata(&field_list,
Protocol::SEND_NUM_ROWS | Protocol::SEND_EOF))
DBUG_RETURN(TRUE);
@@ -7889,8 +7995,14 @@ bool mysql_checksum_table(THD *thd, TABLE_LIST *tables,
for (uint i= 0; i < t->s->fields; i++ )
{
Field *f= t->field[i];
- if ((f->type() == MYSQL_TYPE_BLOB) ||
- (f->type() == MYSQL_TYPE_VARCHAR))
+ enum_field_types field_type= f->type();
+ /*
+ BLOB and VARCHAR have pointers in their field, we must convert
+ to string; GEOMETRY is implemented on top of BLOB.
+ */
+ if ((field_type == MYSQL_TYPE_BLOB) ||
+ (field_type == MYSQL_TYPE_VARCHAR) ||
+ (field_type == MYSQL_TYPE_GEOMETRY))
{
String tmp;
f->val_str(&tmp);