mirror of
https://github.com/MariaDB/server.git
synced 2025-07-30 16:24:05 +03:00
Merge on pull
BitKeeper/etc/ignore: auto-union mysql-test/r/grant2.result: Auto merged mysql-test/r/sql_mode.result: Auto merged mysql-test/t/grant2.test: Auto merged sql/handler.cc: Auto merged sql/handler.h: Auto merged sql/mysql_priv.h: Auto merged sql/mysqld.cc: Auto merged sql/opt_range.cc: Auto merged sql/set_var.cc: Auto merged sql/sql_acl.cc: Auto merged sql/sql_lex.h: Auto merged sql/sql_parse.cc: Auto merged sql/sql_yacc.yy: Auto merged
This commit is contained in:
177
sql/sql_table.cc
177
sql/sql_table.cc
@ -29,7 +29,13 @@
|
||||
#include <io.h>
|
||||
#endif
|
||||
|
||||
const char *primary_key_name= "PRIMARY";
|
||||
#define tmp_disable_binlog(A) \
|
||||
ulong save_options= (A)->options; \
|
||||
(A)->options&= ~OPTION_BIN_LOG;
|
||||
|
||||
#define reenable_binlog(A) (A)->options= save_options;
|
||||
|
||||
const char *primary_key_name="PRIMARY";
|
||||
|
||||
static bool check_if_keyname_exists(const char *name,KEY *start, KEY *end);
|
||||
static char *make_unique_key_name(const char *field_name,KEY *start,KEY *end);
|
||||
@ -193,7 +199,7 @@ int mysql_rm_table_part2(THD *thd, TABLE_LIST *tables, bool if_exists,
|
||||
for (table= tables; table; table= table->next_local)
|
||||
{
|
||||
char *db=table->db;
|
||||
mysql_ha_close(thd, table, /*dont_send_ok*/ 1, /*dont_lock*/ 1);
|
||||
mysql_ha_flush(thd, table, MYSQL_HA_CLOSE_FINAL);
|
||||
if (!close_temporary_table(thd, db, table->real_name))
|
||||
{
|
||||
tmp_table_deleted=1;
|
||||
@ -218,8 +224,9 @@ int mysql_rm_table_part2(THD *thd, TABLE_LIST *tables, bool if_exists,
|
||||
strxmov(path, mysql_data_home, "/", db, "/", alias, reg_ext, NullS);
|
||||
(void) unpack_filename(path,path);
|
||||
}
|
||||
if (drop_temporary || access(path,F_OK) ||
|
||||
(!drop_view && mysql_frm_type(path) != FRMTYPE_TABLE))
|
||||
if (drop_temporary ||
|
||||
(access(path,F_OK) && ha_create_table_from_engine(thd,db,alias,TRUE)) ||
|
||||
(!drop_view && mysql_frm_type(path) != FRMTYPE_TABLE))
|
||||
{
|
||||
if (if_exists)
|
||||
push_warning_printf(thd, MYSQL_ERROR::WARN_LEVEL_NOTE,
|
||||
@ -362,19 +369,19 @@ static int sort_keys(KEY *a, KEY *b)
|
||||
*/
|
||||
|
||||
void check_duplicates_in_interval(const char *set_or_name,
|
||||
const char *name, TYPELIB *typelib)
|
||||
const char *name, TYPELIB *typelib,
|
||||
CHARSET_INFO *cs)
|
||||
{
|
||||
unsigned int old_count= typelib->count;
|
||||
const char **old_type_names= typelib->type_names;
|
||||
|
||||
old_count= typelib->count;
|
||||
old_type_names= typelib->type_names;
|
||||
TYPELIB tmp= *typelib;
|
||||
const char **cur_value= typelib->type_names;
|
||||
for ( ; typelib->count > 1; cur_value++)
|
||||
unsigned int *cur_length= typelib->type_lengths;
|
||||
|
||||
for ( ; tmp.count > 1; cur_value++, cur_length++)
|
||||
{
|
||||
typelib->type_names++;
|
||||
typelib->count--;
|
||||
if (find_type((char*)*cur_value,typelib,1))
|
||||
tmp.type_names++;
|
||||
tmp.type_lengths++;
|
||||
tmp.count--;
|
||||
if (find_type2(&tmp, (const char*)*cur_value, *cur_length, cs))
|
||||
{
|
||||
push_warning_printf(current_thd,MYSQL_ERROR::WARN_LEVEL_NOTE,
|
||||
ER_DUPLICATED_VALUE_IN_TYPE,
|
||||
@ -382,8 +389,6 @@ void check_duplicates_in_interval(const char *set_or_name,
|
||||
name,*cur_value,set_or_name);
|
||||
}
|
||||
}
|
||||
typelib->count= old_count;
|
||||
typelib->type_names= old_type_names;
|
||||
}
|
||||
|
||||
/*
|
||||
@ -563,7 +568,8 @@ int mysql_prepare_table(THD *thd, HA_CREATE_INFO *create_info,
|
||||
sql_field->pack_flag|=FIELDFLAG_BINARY;
|
||||
sql_field->unireg_check=Field::INTERVAL_FIELD;
|
||||
check_duplicates_in_interval("ENUM",sql_field->field_name,
|
||||
sql_field->interval);
|
||||
sql_field->interval,
|
||||
sql_field->charset);
|
||||
break;
|
||||
case FIELD_TYPE_SET:
|
||||
sql_field->pack_flag=pack_length_to_packflag(sql_field->pack_length) |
|
||||
@ -572,7 +578,8 @@ int mysql_prepare_table(THD *thd, HA_CREATE_INFO *create_info,
|
||||
sql_field->pack_flag|=FIELDFLAG_BINARY;
|
||||
sql_field->unireg_check=Field::BIT_FIELD;
|
||||
check_duplicates_in_interval("SET",sql_field->field_name,
|
||||
sql_field->interval);
|
||||
sql_field->interval,
|
||||
sql_field->charset);
|
||||
break;
|
||||
case FIELD_TYPE_DATE: // Rest of string types
|
||||
case FIELD_TYPE_NEWDATE:
|
||||
@ -1238,8 +1245,8 @@ int mysql_create_table(THD *thd,const char *db, const char *table_name,
|
||||
{
|
||||
bool create_if_not_exists =
|
||||
create_info->options & HA_LEX_CREATE_IF_NOT_EXISTS;
|
||||
if (!create_table_from_handler(db, table_name,
|
||||
create_if_not_exists))
|
||||
if (!ha_create_table_from_engine(thd, db, table_name,
|
||||
create_if_not_exists))
|
||||
{
|
||||
DBUG_PRINT("info", ("Table already existed in handler"));
|
||||
|
||||
@ -1344,10 +1351,9 @@ TABLE *create_table_from_items(THD *thd, HA_CREATE_INFO *create_info,
|
||||
MYSQL_LOCK **lock)
|
||||
{
|
||||
TABLE tmp_table; // Used during 'create_field()'
|
||||
TABLE *table;
|
||||
TABLE *table= 0;
|
||||
tmp_table.table_name=0;
|
||||
uint select_field_count= items->elements;
|
||||
Disable_binlog disable_binlog(thd);
|
||||
DBUG_ENTER("create_table_from_items");
|
||||
|
||||
/* Add selected items to field list */
|
||||
@ -1368,7 +1374,7 @@ TABLE *create_table_from_items(THD *thd, HA_CREATE_INFO *create_info,
|
||||
field=item->tmp_table_field(&tmp_table);
|
||||
else
|
||||
field=create_tmp_field(thd, &tmp_table, item, item->type(),
|
||||
(Item ***) 0, &tmp_field,0,0);
|
||||
(Item ***) 0, &tmp_field,0,0,0);
|
||||
if (!field ||
|
||||
!(cr_field=new create_field(field,(item->type() == Item::FIELD_ITEM ?
|
||||
((Item_field *)item)->field :
|
||||
@ -1376,25 +1382,34 @@ TABLE *create_table_from_items(THD *thd, HA_CREATE_INFO *create_info,
|
||||
DBUG_RETURN(0);
|
||||
extra_fields->push_back(cr_field);
|
||||
}
|
||||
/* create and lock table */
|
||||
/* QQ: This should be done atomic ! */
|
||||
if (mysql_create_table(thd, create_table->db, create_table->real_name,
|
||||
create_info, *extra_fields, *keys, 0,
|
||||
select_field_count))
|
||||
DBUG_RETURN(0);
|
||||
/*
|
||||
create and lock table
|
||||
|
||||
We don't log the statement, it will be logged later.
|
||||
|
||||
If this is a HEAP table, the automatic DELETE FROM which is written to the
|
||||
binlog when a HEAP table is opened for the first time since startup, must
|
||||
not be written: 1) it would be wrong (imagine we're in CREATE SELECT: we
|
||||
don't want to delete from it) 2) it would be written before the CREATE
|
||||
TABLE, which is a wrong order. So we keep binary logging disabled.
|
||||
TABLE, which is a wrong order. So we keep binary logging disabled when we
|
||||
open_table().
|
||||
TODO: create and open should be done atomic !
|
||||
*/
|
||||
if (!(table= open_table(thd, create_table, &thd->mem_root, (bool*) 0)))
|
||||
{
|
||||
quick_rm_table(create_info->db_type, create_table->db,
|
||||
table_case_name(create_info, create_table->real_name));
|
||||
DBUG_RETURN(0);
|
||||
tmp_disable_binlog(thd);
|
||||
if (!mysql_create_table(thd, create_table->db, create_table->real_name,
|
||||
create_info, *extra_fields, *keys, 0,
|
||||
select_field_count))
|
||||
{
|
||||
if (!(table= open_table(thd, create_table, &thd->mem_root, (bool*) 0)))
|
||||
quick_rm_table(create_info->db_type, create_table->db,
|
||||
table_case_name(create_info, create_table->real_name));
|
||||
}
|
||||
reenable_binlog(thd);
|
||||
if (!table) // open failed
|
||||
DBUG_RETURN(0);
|
||||
}
|
||||
|
||||
table->reginfo.lock_type=TL_WRITE;
|
||||
if (!((*lock)= mysql_lock_tables(thd, &table,1)))
|
||||
{
|
||||
@ -1754,7 +1769,7 @@ static int mysql_admin_table(THD* thd, TABLE_LIST* tables,
|
||||
Protocol::SEND_NUM_ROWS | Protocol::SEND_EOF))
|
||||
DBUG_RETURN(-1);
|
||||
|
||||
mysql_ha_close(thd, tables, /*dont_send_ok*/ 1, /*dont_lock*/ 1);
|
||||
mysql_ha_flush(thd, tables, MYSQL_HA_CLOSE_FINAL);
|
||||
for (table= tables; table; table= table->next_local)
|
||||
{
|
||||
char table_name[NAME_LEN*2+2];
|
||||
@ -2258,31 +2273,32 @@ int mysql_check_table(THD* thd, TABLE_LIST* tables,HA_CHECK_OPT* check_opt)
|
||||
&handler::check));
|
||||
}
|
||||
|
||||
|
||||
/* table_list should contain just one table */
|
||||
int mysql_discard_or_import_tablespace(THD *thd,
|
||||
TABLE_LIST *table_list,
|
||||
enum tablespace_op_type tablespace_op)
|
||||
static int
|
||||
mysql_discard_or_import_tablespace(THD *thd,
|
||||
TABLE_LIST *table_list,
|
||||
enum tablespace_op_type tablespace_op)
|
||||
{
|
||||
TABLE *table;
|
||||
my_bool discard;
|
||||
int error;
|
||||
DBUG_ENTER("mysql_discard_or_import_tablespace");
|
||||
|
||||
/* Note that DISCARD/IMPORT TABLESPACE always is the only operation in an
|
||||
ALTER TABLE */
|
||||
/*
|
||||
Note that DISCARD/IMPORT TABLESPACE always is the only operation in an
|
||||
ALTER TABLE
|
||||
*/
|
||||
|
||||
thd->proc_info="discard_or_import_tablespace";
|
||||
|
||||
if (tablespace_op == DISCARD_TABLESPACE)
|
||||
discard = TRUE;
|
||||
else
|
||||
discard = FALSE;
|
||||
|
||||
thd->tablespace_op=TRUE; /* we set this flag so that ha_innobase::open
|
||||
and ::external_lock() do not complain when we
|
||||
lock the table */
|
||||
mysql_ha_close(thd, table_list, /*dont_send_ok*/ 1, /*dont_lock*/ 1);
|
||||
discard= test(tablespace_op == DISCARD_TABLESPACE);
|
||||
|
||||
/*
|
||||
We set this flag so that ha_innobase::open and ::external_lock() do
|
||||
not complain when we lock the table
|
||||
*/
|
||||
thd->tablespace_op= TRUE;
|
||||
if (!(table=open_ltable(thd,table_list,TL_WRITE)))
|
||||
{
|
||||
thd->tablespace_op=FALSE;
|
||||
@ -2296,8 +2312,10 @@ int mysql_discard_or_import_tablespace(THD *thd,
|
||||
if (error)
|
||||
goto err;
|
||||
|
||||
/* The 0 in the call below means 'not in a transaction', which means
|
||||
immediate invalidation; that is probably what we wish here */
|
||||
/*
|
||||
The 0 in the call below means 'not in a transaction', which means
|
||||
immediate invalidation; that is probably what we wish here
|
||||
*/
|
||||
query_cache_invalidate3(thd, table_list, 0);
|
||||
|
||||
/* The ALTER TABLE is always in its own transaction */
|
||||
@ -2560,8 +2578,7 @@ int mysql_alter_table(THD *thd,char *new_db, char *new_name,
|
||||
new_db= db;
|
||||
used_fields=create_info->used_fields;
|
||||
|
||||
mysql_ha_close(thd, table_list, /*dont_send_ok*/ 1, /*dont_lock*/ 1);
|
||||
|
||||
mysql_ha_flush(thd, table_list, MYSQL_HA_CLOSE_FINAL);
|
||||
/* DISCARD/IMPORT TABLESPACE is always alone in an ALTER TABLE */
|
||||
if (alter_info->tablespace_op != NO_TABLESPACE_OP)
|
||||
DBUG_RETURN(mysql_discard_or_import_tablespace(thd,table_list,
|
||||
@ -2604,7 +2621,9 @@ int mysql_alter_table(THD *thd,char *new_db, char *new_name,
|
||||
}
|
||||
else
|
||||
{
|
||||
if (!access(fn_format(new_name_buff,new_name_buff,new_db,reg_ext,0),
|
||||
char dir_buff[FN_REFLEN];
|
||||
strxnmov(dir_buff, FN_REFLEN, mysql_real_data_home, new_db, NullS);
|
||||
if (!access(fn_format(new_name_buff,new_name_buff,dir_buff,reg_ext,0),
|
||||
F_OK))
|
||||
{
|
||||
/* Table will be closed in do_command() */
|
||||
@ -3030,12 +3049,14 @@ int mysql_alter_table(THD *thd,char *new_db, char *new_name,
|
||||
}
|
||||
else
|
||||
create_info->data_file_name=create_info->index_file_name=0;
|
||||
|
||||
/* We don't log the statement, it will be logged later. */
|
||||
{
|
||||
/* We don't log the statement, it will be logged later */
|
||||
Disable_binlog disable_binlog(thd);
|
||||
if ((error=mysql_create_table(thd, new_db, tmp_name,
|
||||
create_info,
|
||||
create_list,key_list,1,0)))
|
||||
tmp_disable_binlog(thd);
|
||||
error= mysql_create_table(thd, new_db, tmp_name,
|
||||
create_info,create_list,key_list,1,0);
|
||||
reenable_binlog(thd);
|
||||
if (error)
|
||||
DBUG_RETURN(error);
|
||||
}
|
||||
if (need_copy_table)
|
||||
@ -3063,11 +3084,8 @@ int mysql_alter_table(THD *thd,char *new_db, char *new_name,
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
We don't want update TIMESTAMP fields during ALTER TABLE
|
||||
and copy_data_between_tables uses only write_row() for new_table so
|
||||
don't need to set up timestamp_on_update_now member.
|
||||
*/
|
||||
/* We don't want update TIMESTAMP fields during ALTER TABLE. */
|
||||
new_table->timestamp_field_type= TIMESTAMP_NO_AUTO_SET;
|
||||
thd->count_cuted_fields= CHECK_FIELD_WARN; // calc cuted fields
|
||||
thd->cuted_fields=0L;
|
||||
thd->proc_info="copy to tmp table";
|
||||
@ -3271,8 +3289,8 @@ int mysql_alter_table(THD *thd,char *new_db, char *new_name,
|
||||
my_free((char*) table, MYF(0));
|
||||
}
|
||||
else
|
||||
sql_print_error("Warning: Could not open BDB table %s.%s after rename\n",
|
||||
new_db,table_name);
|
||||
sql_print_warning("Could not open BDB table %s.%s after rename\n",
|
||||
new_db,table_name);
|
||||
(void) berkeley_flush_logs();
|
||||
}
|
||||
#endif
|
||||
@ -3313,15 +3331,19 @@ copy_data_between_tables(TABLE *from,TABLE *to,
|
||||
List<Item> all_fields;
|
||||
ha_rows examined_rows;
|
||||
bool auto_increment_field_copied= 0;
|
||||
ulong save_sql_mode;
|
||||
DBUG_ENTER("copy_data_between_tables");
|
||||
|
||||
if (!(copy= new Copy_field[to->fields]))
|
||||
DBUG_RETURN(-1); /* purecov: inspected */
|
||||
|
||||
to->file->external_lock(thd,F_WRLCK);
|
||||
if (to->file->external_lock(thd, F_WRLCK))
|
||||
DBUG_RETURN(-1);
|
||||
from->file->info(HA_STATUS_VARIABLE);
|
||||
to->file->start_bulk_insert(from->file->records);
|
||||
|
||||
save_sql_mode= thd->variables.sql_mode;
|
||||
|
||||
List_iterator<create_field> it(create);
|
||||
create_field *def;
|
||||
copy_end=copy;
|
||||
@ -3331,7 +3353,17 @@ copy_data_between_tables(TABLE *from,TABLE *to,
|
||||
if (def->field)
|
||||
{
|
||||
if (*ptr == to->next_number_field)
|
||||
{
|
||||
auto_increment_field_copied= TRUE;
|
||||
/*
|
||||
If we are going to copy contents of one auto_increment column to
|
||||
another auto_increment column it is sensible to preserve zeroes.
|
||||
This condition also covers case when we are don't actually alter
|
||||
auto_increment column.
|
||||
*/
|
||||
if (def->field == from->found_next_number_field)
|
||||
thd->variables.sql_mode|= MODE_NO_AUTO_VALUE_ON_ZERO;
|
||||
}
|
||||
(copy_end++)->set(*ptr,def->field,0);
|
||||
}
|
||||
|
||||
@ -3364,7 +3396,7 @@ copy_data_between_tables(TABLE *from,TABLE *to,
|
||||
Turn off recovery logging since rollback of an alter table is to
|
||||
delete the new table so there is no need to log the changes to it.
|
||||
*/
|
||||
error= ha_recovery_logging(thd,FALSE);
|
||||
error= ha_enable_transaction(thd,FALSE);
|
||||
if (error)
|
||||
{
|
||||
error= 1;
|
||||
@ -3427,7 +3459,8 @@ copy_data_between_tables(TABLE *from,TABLE *to,
|
||||
}
|
||||
to->file->extra(HA_EXTRA_NO_IGNORE_DUP_KEY);
|
||||
|
||||
ha_recovery_logging(thd,TRUE);
|
||||
ha_enable_transaction(thd,TRUE);
|
||||
|
||||
/*
|
||||
Ensure that the new table is saved properly to disk so that we
|
||||
can do a rename
|
||||
@ -3436,12 +3469,14 @@ copy_data_between_tables(TABLE *from,TABLE *to,
|
||||
error=1;
|
||||
if (ha_commit(thd))
|
||||
error=1;
|
||||
if (to->file->external_lock(thd,F_UNLCK))
|
||||
error=1;
|
||||
|
||||
err:
|
||||
thd->variables.sql_mode= save_sql_mode;
|
||||
free_io_cache(from);
|
||||
*copied= found_count;
|
||||
*deleted=delete_count;
|
||||
if (to->file->external_lock(thd,F_UNLCK))
|
||||
error=1;
|
||||
DBUG_RETURN(error > 0 ? -1 : 0);
|
||||
}
|
||||
|
||||
|
Reference in New Issue
Block a user