summaryrefslogtreecommitdiff
path: root/sql/sql_table.cc
diff options
context:
space:
mode:
authorSergey Petrunya <psergey@askmonty.org>2009-09-08 00:50:10 +0400
committerSergey Petrunya <psergey@askmonty.org>2009-09-08 00:50:10 +0400
commit29f0dcb56337a3e352ad7a70dcff6b25bb605325 (patch)
tree84935c21dc958724ae7dcbeeca0c0f08986fc430 /sql/sql_table.cc
parent915a624cbcb58a10a2cfb2e2e4fd5029191fa86a (diff)
parent8a2454f8e9fce648272577fcf8006ae6e6806cf9 (diff)
downloadmariadb-git-29f0dcb56337a3e352ad7a70dcff6b25bb605325.tar.gz
Merge MySQL->MariaDB
* Finished Monty and Jani's merge * Some InnoDB tests still fail (because it's old xtradb code run against newer testsuite). They are expected to go after mergning with the latest xtradb.
Diffstat (limited to 'sql/sql_table.cc')
-rw-r--r--sql/sql_table.cc421
1 files changed, 357 insertions, 64 deletions
diff --git a/sql/sql_table.cc b/sql/sql_table.cc
index eb01ab872a0..97400554bff 100644
--- a/sql/sql_table.cc
+++ b/sql/sql_table.cc
@@ -68,6 +68,234 @@ static void wait_for_kill_signal(THD *thd)
#endif
+/**
+ @brief Helper function for explain_filename
+*/
+static char* add_identifier(char *to_p, const char * end_p,
+ const char* name, uint name_len, int errcode)
+{
+ uint res;
+ uint errors;
+ const char *conv_name;
+ char tmp_name[FN_REFLEN];
+ char conv_string[FN_REFLEN];
+
+ DBUG_ENTER("add_identifier");
+ if (!name[name_len])
+ conv_name= name;
+ else
+ {
+ strnmov(tmp_name, name, name_len);
+ tmp_name[name_len]= 0;
+ conv_name= tmp_name;
+ }
+ res= strconvert(&my_charset_filename, conv_name, system_charset_info,
+ conv_string, FN_REFLEN, &errors);
+ if (!res || errors)
+ conv_name= name;
+ else
+ {
+ DBUG_PRINT("info", ("conv '%s' -> '%s'", conv_name, conv_string));
+ conv_name= conv_string;
+ }
+
+ if (errcode)
+ to_p+= my_snprintf(to_p, end_p - to_p, ER(errcode), conv_name);
+ else
+ to_p+= my_snprintf(to_p, end_p - to_p, "`%s`", conv_name);
+ return to_p;
+}
+
+
+/**
+ @brief Explain a path name by split it to database, table etc.
+
+ @details Break down the path name to its logic parts
+ (database, table, partition, subpartition).
+ filename_to_tablename cannot be used on partitions, due to the #P# part.
+ There can be up to 6 '#', #P# for partition, #SP# for subpartition
+ and #TMP# or #REN# for temporary or renamed partitions.
+ This should be used when something should be presented to a user in a
+ 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 from Path name in my_charset_filename
+ Null terminated in my_charset_filename, normalized
+ to use '/' as directory separation character.
+ @param to Explained name in system_charset_info
+ @param to_length Size of to buffer
+ @param explain_mode Requested output format.
+ EXPLAIN_ALL_VERBOSE ->
+ [Database `db`, ]Table `tbl`[,[ Temporary| Renamed]
+ Partition `p` [, Subpartition `sp`]]
+ EXPLAIN_PARTITIONS_VERBOSE -> `db`.`tbl`
+ [[ Temporary| Renamed] Partition `p`
+ [, Subpartition `sp`]]
+ EXPLAIN_PARTITIONS_AS_COMMENT -> `db`.`tbl` |*
+ [,[ Temporary| Renamed] Partition `p`
+ [, Subpartition `sp`]] *|
+ (| is really a /, and it is all in one line)
+
+ @retval Length of returned string
+*/
+
+uint explain_filename(const char *from,
+ char *to,
+ uint to_length,
+ enum_explain_filename_mode explain_mode)
+{
+ uint res= 0;
+ char *to_p= to;
+ char *end_p= to_p + to_length;
+ const char *db_name= NULL;
+ int db_name_len= 0;
+ const char *table_name;
+ int table_name_len= 0;
+ const char *part_name= NULL;
+ int part_name_len= 0;
+ const char *subpart_name= NULL;
+ int subpart_name_len= 0;
+ enum enum_file_name_type {NORMAL, TEMP, RENAMED} name_type= NORMAL;
+ const char *tmp_p;
+ DBUG_ENTER("explain_filename");
+ DBUG_PRINT("enter", ("from '%s'", from));
+ tmp_p= from;
+ table_name= from;
+ /*
+ If '/' then take last directory part as database.
+ '/' is the directory separator, not FN_LIB_CHAR
+ */
+ while ((tmp_p= strchr(tmp_p, '/')))
+ {
+ db_name= table_name;
+ /* calculate the length */
+ db_name_len= tmp_p - db_name;
+ tmp_p++;
+ table_name= tmp_p;
+ }
+ tmp_p= table_name;
+ while (!res && (tmp_p= strchr(tmp_p, '#')))
+ {
+ tmp_p++;
+ switch (tmp_p[0]) {
+ case 'P':
+ case 'p':
+ if (tmp_p[1] == '#')
+ part_name= tmp_p + 2;
+ else
+ res= 1;
+ tmp_p+= 2;
+ break;
+ case 'S':
+ case 's':
+ if ((tmp_p[1] == 'P' || tmp_p[1] == 'p') && tmp_p[2] == '#')
+ {
+ part_name_len= tmp_p - part_name - 1;
+ subpart_name= tmp_p + 3;
+ }
+ else
+ res= 2;
+ tmp_p+= 3;
+ break;
+ case 'T':
+ case 't':
+ if ((tmp_p[1] == 'M' || tmp_p[1] == 'm') &&
+ (tmp_p[2] == 'P' || tmp_p[2] == 'p') &&
+ tmp_p[3] == '#' && !tmp_p[4])
+ name_type= TEMP;
+ else
+ res= 3;
+ tmp_p+= 4;
+ break;
+ case 'R':
+ case 'r':
+ if ((tmp_p[1] == 'E' || tmp_p[1] == 'e') &&
+ (tmp_p[2] == 'N' || tmp_p[2] == 'n') &&
+ tmp_p[3] == '#' && !tmp_p[4])
+ name_type= RENAMED;
+ else
+ res= 4;
+ tmp_p+= 4;
+ break;
+ default:
+ res= 5;
+ }
+ }
+ if (res)
+ {
+ /* Better to give something back if we fail parsing, than nothing at all */
+ DBUG_PRINT("info", ("Error in explain_filename: %u", res));
+ sql_print_warning("Invalid (old?) table or database name '%s'", from);
+ DBUG_RETURN(my_snprintf(to, to_length,
+ "<result %u when explaining filename '%s'>",
+ res, from));
+ }
+ if (part_name)
+ {
+ table_name_len= part_name - table_name - 3;
+ if (subpart_name)
+ subpart_name_len= strlen(subpart_name);
+ else
+ part_name_len= strlen(part_name);
+ if (name_type != NORMAL)
+ {
+ if (subpart_name)
+ subpart_name_len-= 5;
+ else
+ part_name_len-= 5;
+ }
+ }
+ if (db_name)
+ {
+ if (explain_mode == EXPLAIN_ALL_VERBOSE)
+ {
+ to_p= add_identifier(to_p, end_p, db_name, db_name_len,
+ ER_DATABASE_NAME);
+ to_p= strnmov(to_p, ", ", end_p - to_p);
+ }
+ else
+ {
+ to_p= add_identifier(to_p, end_p, db_name, db_name_len, 0);
+ to_p= strnmov(to_p, ".", end_p - to_p);
+ }
+ }
+ if (explain_mode == EXPLAIN_ALL_VERBOSE)
+ to_p= add_identifier(to_p, end_p, table_name, table_name_len,
+ ER_TABLE_NAME);
+ else
+ to_p= add_identifier(to_p, end_p, table_name, table_name_len, 0);
+ if (part_name)
+ {
+ 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);
+ else
+ to_p= strnmov(to_p, ", ", end_p - to_p);
+ if (name_type != NORMAL)
+ {
+ if (name_type == TEMP)
+ to_p= strnmov(to_p, ER(ER_TEMPORARY_NAME), end_p - to_p);
+ else
+ to_p= strnmov(to_p, ER(ER_RENAMED_NAME), end_p - to_p);
+ to_p= strnmov(to_p, " ", end_p - to_p);
+ }
+ to_p= add_identifier(to_p, end_p, part_name, part_name_len,
+ ER_PARTITION_NAME);
+ if (subpart_name)
+ {
+ to_p= strnmov(to_p, ", ", end_p - to_p);
+ to_p= add_identifier(to_p, end_p, subpart_name, subpart_name_len,
+ ER_SUBPARTITION_NAME);
+ }
+ if (explain_mode == EXPLAIN_PARTITIONS_AS_COMMENT)
+ to_p= strnmov(to_p, " */", end_p - to_p);
+ }
+ DBUG_PRINT("exit", ("to '%s'", to));
+ DBUG_RETURN(to_p - to);
+}
+
+
/*
Translate a file name to a table name (WL #1324).
@@ -1287,7 +1515,7 @@ bool mysql_write_frm(ALTER_PARTITION_PARAM_TYPE *lpt, uint flags)
/*
Build shadow frm file name
*/
- build_table_shadow_filename(shadow_path, sizeof(shadow_path), lpt);
+ build_table_shadow_filename(shadow_path, sizeof(shadow_path) - 1, lpt);
strxmov(shadow_frm_name, shadow_path, reg_ext, NullS);
if (flags & WFRM_WRITE_SHADOW)
{
@@ -1362,7 +1590,7 @@ bool mysql_write_frm(ALTER_PARTITION_PARAM_TYPE *lpt, uint flags)
/*
Build frm file name
*/
- build_table_filename(path, sizeof(path), lpt->db,
+ build_table_filename(path, sizeof(path) - 1, lpt->db,
lpt->table_name, "", 0);
strxmov(frm_name, path, reg_ext, NullS);
/*
@@ -1460,10 +1688,13 @@ void write_bin_log(THD *thd, bool clear_error,
{
if (mysql_bin_log.is_open())
{
+ int errcode= 0;
if (clear_error)
thd->clear_error();
+ else
+ errcode= query_error_code(thd, TRUE);
thd->binlog_query(THD::STMT_QUERY_TYPE,
- query, query_length, FALSE, FALSE);
+ query, query_length, FALSE, FALSE, errcode);
}
}
@@ -1561,13 +1792,14 @@ int mysql_rm_table_part2(THD *thd, TABLE_LIST *tables, bool if_exists,
bool dont_log_query)
{
TABLE_LIST *table;
- char path[FN_REFLEN], *alias;
+ char path[FN_REFLEN + 1], *alias;
uint path_length;
String wrong_tables;
int error= 0;
int non_temp_tables_count= 0;
bool some_tables_deleted=0, tmp_table_deleted=0, foreign_key_error=0;
String built_query;
+ String built_tmp_query;
DBUG_ENTER("mysql_rm_table_part2");
LINT_INIT(alias);
@@ -1635,6 +1867,25 @@ int mysql_rm_table_part2(THD *thd, TABLE_LIST *tables, bool if_exists,
case 0:
// removed temporary table
tmp_table_deleted= 1;
+ if (thd->variables.binlog_format == BINLOG_FORMAT_MIXED &&
+ thd->current_stmt_binlog_row_based)
+ {
+ if (built_tmp_query.is_empty())
+ {
+ built_tmp_query.set_charset(system_charset_info);
+ built_tmp_query.append("DROP TEMPORARY TABLE IF EXISTS ");
+ }
+
+ built_tmp_query.append("`");
+ if (thd->db == NULL || strcmp(db,thd->db) != 0)
+ {
+ built_tmp_query.append(db);
+ built_tmp_query.append("`.`");
+ }
+ built_tmp_query.append(table->table_name);
+ built_tmp_query.append("`,");
+ }
+
continue;
case -1:
DBUG_ASSERT(thd->in_sub_stmt);
@@ -1691,14 +1942,15 @@ int mysql_rm_table_part2(THD *thd, TABLE_LIST *tables, bool if_exists,
}
alias= (lower_case_table_names == 2) ? table->alias : table->table_name;
/* remove .frm file and engine files */
- path_length= build_table_filename(path, sizeof(path), db, alias, reg_ext,
+ path_length= build_table_filename(path, sizeof(path) - 1, db, alias,
+ reg_ext,
table->internal_tmp_table ?
FN_IS_TMP : 0);
}
if (drop_temporary ||
- ((table_type == NULL &&
- (access(path, F_OK) &&
- ha_create_table_from_engine(thd, db, alias))) ||
+ ((table_type == NULL &&
+ access(path, F_OK) &&
+ ha_create_table_from_engine(thd, db, alias)) ||
(!drop_view &&
mysql_frm_type(thd, path, &frm_db_type) != FRMTYPE_TABLE)))
{
@@ -1791,29 +2043,52 @@ int mysql_rm_table_part2(THD *thd, TABLE_LIST *tables, bool if_exists,
write_bin_log(thd, !error, thd->query, thd->query_length);
}
else if (thd->current_stmt_binlog_row_based &&
- non_temp_tables_count > 0 &&
tmp_table_deleted)
{
+ if (non_temp_tables_count > 0)
+ {
+ /*
+ In this case we have deleted both temporary and
+ non-temporary tables, so:
+ - since we have deleted a non-temporary table we have to
+ binlog the statement, but
+ - since we have deleted a temporary table we cannot binlog
+ the statement (since the table may have not been created on the
+ slave - check "if" branch below, this might cause the slave to
+ stop).
+
+ Instead, we write a built statement, only containing the
+ non-temporary tables, to the binary log
+ */
+ 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());
+ }
+
/*
- In this case we have deleted both temporary and
- non-temporary tables, so:
- - since we have deleted a non-temporary table we have to
- binlog the statement, but
- - since we have deleted a temporary table we cannot binlog
- the statement (since the table has not been created on the
- slave, this might cause the slave to stop).
-
- Instead, we write a built statement, only containing the
- non-temporary tables, to the binary log
+ One needs to always log any temporary table drop, if:
+ 1. thread logging format is mixed mode; AND
+ 2. current statement logging format is set to row.
*/
- 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());
+ if (thd->variables.binlog_format == BINLOG_FORMAT_MIXED)
+ {
+ /*
+ In this case we have deleted some temporary tables but we are using
+ row based logging for the statement. However, thread uses mixed mode
+ format, thence we need to log the dropping as we cannot tell for
+ sure whether the create was logged as statement previously or not, ie,
+ before switching to row mode.
+ */
+ 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());
+ }
}
+
/*
The remaining cases are:
- - no tables where deleted and
- - only temporary tables where deleted and row-based
+ - no tables were deleted and
+ - only temporary tables were deleted and row-based
replication is used.
In both these cases, nothing should be written to the binary
log.
@@ -1847,11 +2122,11 @@ err_with_placeholders:
bool quick_rm_table(handlerton *base,const char *db,
const char *table_name, uint flags)
{
- char path[FN_REFLEN];
+ char path[FN_REFLEN + 1];
bool error= 0;
DBUG_ENTER("quick_rm_table");
- uint path_length= build_table_filename(path, sizeof(path),
+ uint path_length= build_table_filename(path, sizeof(path) - 1,
db, table_name, reg_ext, flags);
if (my_delete(path,MYF(0)))
error= 1; /* purecov: inspected */
@@ -3126,7 +3401,7 @@ static bool prepare_blob_field(THD *thd, Create_field *sql_field)
}
sql_field->sql_type= MYSQL_TYPE_BLOB;
sql_field->flags|= BLOB_FLAG;
- sprintf(warn_buff, ER(ER_AUTO_CONVERT), sql_field->field_name,
+ my_snprintf(warn_buff, sizeof(warn_buff), ER(ER_AUTO_CONVERT), sql_field->field_name,
(sql_field->charset == &my_charset_bin) ? "VARBINARY" : "VARCHAR",
(sql_field->charset == &my_charset_bin) ? "BLOB" : "TEXT");
push_warning(thd, MYSQL_ERROR::WARN_LEVEL_NOTE, ER_AUTO_CONVERT,
@@ -3240,7 +3515,7 @@ bool mysql_create_table_no_lock(THD *thd,
bool internal_tmp_table,
uint select_field_count)
{
- char path[FN_REFLEN];
+ char path[FN_REFLEN + 1];
uint path_length;
const char *alias;
uint db_options, key_count;
@@ -3449,7 +3724,7 @@ bool mysql_create_table_no_lock(THD *thd,
}
else
{
- path_length= build_table_filename(path, sizeof(path), db, alias, reg_ext,
+ path_length= build_table_filename(path, sizeof(path) - 1, db, alias, reg_ext,
internal_tmp_table ? FN_IS_TMP : 0);
}
@@ -3770,7 +4045,8 @@ mysql_rename_table(handlerton *base, const char *old_db,
const char *new_name, uint flags)
{
THD *thd= current_thd;
- char from[FN_REFLEN], to[FN_REFLEN], lc_from[FN_REFLEN], lc_to[FN_REFLEN];
+ char from[FN_REFLEN + 1], to[FN_REFLEN + 1],
+ lc_from[FN_REFLEN + 1], lc_to[FN_REFLEN + 1];
char *from_base= from, *to_base= to;
char tmp_name[NAME_LEN+1];
handler *file;
@@ -3782,9 +4058,9 @@ mysql_rename_table(handlerton *base, const char *old_db,
file= (base == NULL ? 0 :
get_new_handler((TABLE_SHARE*) 0, thd->mem_root, base));
- build_table_filename(from, sizeof(from), old_db, old_name, "",
+ build_table_filename(from, sizeof(from) - 1, old_db, old_name, "",
flags & FN_FROM_IS_TMP);
- build_table_filename(to, sizeof(to), new_db, new_name, "",
+ build_table_filename(to, sizeof(to) - 1, new_db, new_name, "",
flags & FN_TO_IS_TMP);
/*
@@ -3797,13 +4073,13 @@ mysql_rename_table(handlerton *base, const char *old_db,
{
strmov(tmp_name, old_name);
my_casedn_str(files_charset_info, tmp_name);
- build_table_filename(lc_from, sizeof(lc_from), old_db, tmp_name, "",
+ build_table_filename(lc_from, sizeof(lc_from) - 1, old_db, tmp_name, "",
flags & FN_FROM_IS_TMP);
from_base= lc_from;
strmov(tmp_name, new_name);
my_casedn_str(files_charset_info, tmp_name);
- build_table_filename(lc_to, sizeof(lc_to), new_db, tmp_name, "",
+ build_table_filename(lc_to, sizeof(lc_to) - 1, new_db, tmp_name, "",
flags & FN_TO_IS_TMP);
to_base= lc_to;
}
@@ -3935,16 +4211,16 @@ static int prepare_for_restore(THD* thd, TABLE_LIST* table,
else
{
char* backup_dir= thd->lex->backup_dir;
- char src_path[FN_REFLEN], dst_path[FN_REFLEN], uname[FN_REFLEN];
+ char src_path[FN_REFLEN], dst_path[FN_REFLEN + 1], uname[FN_REFLEN];
char* table_name= table->table_name;
char* db= table->db;
- VOID(tablename_to_filename(table->table_name, uname, sizeof(uname)));
+ VOID(tablename_to_filename(table->table_name, uname, sizeof(uname) - 1));
if (fn_format_relative_to_data_home(src_path, uname, backup_dir, reg_ext))
DBUG_RETURN(-1); // protect buffer overflow
- build_table_filename(dst_path, sizeof(dst_path),
+ build_table_filename(dst_path, sizeof(dst_path) - 1,
db, table_name, reg_ext, 0);
if (lock_and_wait_for_table_name(thd,table))
@@ -4556,7 +4832,7 @@ send_result_message:
const char *err_msg= thd->main_da.message();
if (!thd->vio_ok())
{
- sql_print_error(err_msg);
+ sql_print_error("%s", err_msg);
}
else
{
@@ -4866,7 +5142,7 @@ bool mysql_create_like_table(THD* thd, TABLE_LIST* table, TABLE_LIST* src_table,
HA_CREATE_INFO *create_info)
{
TABLE *name_lock= 0;
- char src_path[FN_REFLEN], dst_path[FN_REFLEN];
+ char src_path[FN_REFLEN], dst_path[FN_REFLEN + 1];
uint dst_path_length;
char *db= table->db;
char *table_name= table->table_name;
@@ -4876,7 +5152,7 @@ bool mysql_create_like_table(THD* thd, TABLE_LIST* table, TABLE_LIST* src_table,
#ifdef WITH_PARTITION_STORAGE_ENGINE
char tmp_path[FN_REFLEN];
#endif
- char ts_name[FN_LEN];
+ char ts_name[FN_LEN + 1];
DBUG_ENTER("mysql_create_like_table");
@@ -4925,7 +5201,7 @@ bool mysql_create_like_table(THD* thd, TABLE_LIST* table, TABLE_LIST* src_table,
goto err;
if (!name_lock)
goto table_exists;
- dst_path_length= build_table_filename(dst_path, sizeof(dst_path),
+ dst_path_length= build_table_filename(dst_path, sizeof(dst_path) - 1,
db, table_name, reg_ext, 0);
if (!access(dst_path, F_OK))
goto table_exists;
@@ -5675,12 +5951,10 @@ mysql_prepare_alter_table(THD *thd, TABLE *table,
}
if (!(used_fields & HA_CREATE_USED_KEY_BLOCK_SIZE))
create_info->key_block_size= table->s->key_block_size;
- if (!(used_fields & HA_CREATE_USED_TRANSACTIONAL))
- create_info->transactional= table->s->transactional;
if (!create_info->tablespace && create_info->storage_media != HA_SM_MEMORY)
{
- char *tablespace= static_cast<char *>(thd->alloc(FN_LEN));
+ char *tablespace= static_cast<char *>(thd->alloc(FN_LEN + 1));
/*
Regular alter table of disk stored table (no tablespace/storage change)
Copy tablespace name
@@ -6049,10 +6323,10 @@ bool mysql_alter_table(THD *thd,char *new_db, char *new_name,
{
TABLE *table, *new_table= 0, *name_lock= 0;
int error= 0;
- char tmp_name[80],old_name[32],new_name_buff[FN_REFLEN];
+ char tmp_name[80],old_name[32],new_name_buff[FN_REFLEN + 1];
char new_alias_buff[FN_REFLEN], *table_name, *db, *new_alias, *alias;
char index_file[FN_REFLEN], data_file[FN_REFLEN];
- char path[FN_REFLEN];
+ char path[FN_REFLEN + 1];
char reg_path[FN_REFLEN+1];
ha_rows copied,deleted;
handlerton *old_db_type, *new_db_type, *save_old_db_type;
@@ -6065,20 +6339,14 @@ bool mysql_alter_table(THD *thd,char *new_db, char *new_name,
#endif
bool need_lock_for_indexes= TRUE;
KEY *key_info_buffer;
- uint index_drop_count;
- uint *index_drop_buffer;
- uint index_add_count;
- uint *index_add_buffer;
- uint candidate_key_count;
+ uint index_drop_count= 0;
+ uint *index_drop_buffer= NULL;
+ uint index_add_count= 0;
+ uint *index_add_buffer= NULL;
+ uint candidate_key_count= 0;
bool no_pk;
DBUG_ENTER("mysql_alter_table");
- LINT_INIT(index_add_count);
- LINT_INIT(index_drop_count);
- LINT_INIT(index_add_buffer);
- LINT_INIT(index_drop_buffer);
- LINT_INIT(candidate_key_count);
-
/*
Check if we attempt to alter mysql.slow_log or
mysql.general_log table and return an error if
@@ -6132,8 +6400,8 @@ bool mysql_alter_table(THD *thd,char *new_db, char *new_name,
db=table_list->db;
if (!new_db || !my_strcasecmp(table_alias_charset, new_db, db))
new_db= db;
- build_table_filename(reg_path, sizeof(reg_path), db, table_name, reg_ext, 0);
- build_table_filename(path, sizeof(path), db, table_name, "", 0);
+ build_table_filename(reg_path, sizeof(reg_path) - 1, db, table_name, reg_ext, 0);
+ build_table_filename(path, sizeof(path) - 1, db, table_name, "", 0);
mysql_ha_rm_tables(thd, table_list, FALSE);
@@ -6164,6 +6432,20 @@ bool mysql_alter_table(THD *thd,char *new_db, char *new_name,
if (frm_type == FRMTYPE_VIEW && !(alter_info->flags & ~ALTER_RENAME))
{
/*
+ The following branch handles "ALTER VIEW v1 /no arguments/;"
+ This feature is not documented one.
+ However, before "OPTIMIZE TABLE t1;" was implemented,
+ ALTER TABLE with no alter_specifications was used to force-rebuild
+ the table. That's why this grammar is allowed. That's why we ignore
+ it for views. So just do nothing in such a case.
+ */
+ if (!new_name)
+ {
+ my_ok(thd);
+ DBUG_RETURN(FALSE);
+ }
+
+ /*
Avoid problems with a rename on a table that we have locked or
if the user is trying to to do this in a transcation context
*/
@@ -6189,7 +6471,8 @@ 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, 0, FALSE);
+ Query_log_event qinfo(thd, thd->query, thd->query_length,
+ 0, FALSE, 0);
mysql_bin_log.write(&qinfo);
}
my_ok(thd);
@@ -6265,7 +6548,7 @@ view_err:
DBUG_RETURN(TRUE);
}
- build_table_filename(new_name_buff, sizeof(new_name_buff),
+ build_table_filename(new_name_buff, sizeof(new_name_buff) - 1,
new_db, new_name_buff, reg_ext, 0);
if (!access(new_name_buff, F_OK))
{
@@ -6766,9 +7049,9 @@ view_err:
}
else
{
- char path[FN_REFLEN];
+ char path[FN_REFLEN + 1];
/* table is a normal table: Create temporary table in same directory */
- build_table_filename(path, sizeof(path), new_db, tmp_name, "",
+ build_table_filename(path, sizeof(path) - 1, new_db, tmp_name, "",
FN_IS_TMP);
/* Open our intermediate table */
new_table=open_temporary_table(thd, path, new_db, tmp_name,0);
@@ -7095,7 +7378,7 @@ view_err:
*/
char path[FN_REFLEN];
TABLE *t_table;
- build_table_filename(path, sizeof(path), new_db, table_name, "", 0);
+ build_table_filename(path + 1, sizeof(path) - 1, new_db, table_name, "", 0);
t_table= open_temporary_table(thd, path, new_db, tmp_name, 0);
if (t_table)
{
@@ -7519,6 +7802,16 @@ bool mysql_checksum_table(THD *thd, TABLE_LIST *tables,
{
for (;;)
{
+ if (thd->killed)
+ {
+ /*
+ we've been killed; let handler clean up, and remove the
+ partial current row from the recordset (embedded lib)
+ */
+ t->file->ha_rnd_end();
+ thd->protocol->remove_last_row();
+ goto err;
+ }
ha_checksum row_crc= 0;
int error= t->file->rnd_next(t->record[0]);
if (unlikely(error))