1900
1900
if (create_info->options & HA_LEX_CREATE_TMP_TABLE)
1902
1902
/* Open table and put in temporary table list */
1903
if (!(open_temporary_table(session, path, db, table_name, 1, OTM_OPEN)))
1903
if (!(session->open_temporary_table(path, db, table_name, 1, OTM_OPEN)))
1905
(void) rm_temporary_table(create_info->db_type, path);
1905
(void) session->rm_temporary_table(create_info->db_type, path);
1906
1906
goto unlock_and_end;
2229
2229
lex->query_tables_own_last= 0;
2230
2230
session->no_warnings_for_error= no_warnings_for_error;
2232
session->open_and_lock_tables(table);
2232
session->openTablesLock(table);
2233
2233
session->no_warnings_for_error= 0;
2234
2234
table->next_global= save_next_global;
2235
2235
table->next_local= save_next_local;
2419
2419
session->close_thread_tables();
2420
2420
if (!result_code) // recreation went ok
2422
if ((table->table= session->open_ltable(table, lock_type)) &&
2422
if ((table->table= session->openTableLock(table, lock_type)) &&
2423
2423
((result_code= table->table->file->ha_analyze(session, check_opt)) > 0))
2424
2424
result_code= 0; // analyze went ok
2611
2611
we ensure that our statement is properly isolated from all concurrent
2612
2612
operations which matter.
2614
if (session->open_tables_from_list(&src_table, ¬_used, 0))
2614
if (session->open_tables_from_list(&src_table, ¬_used))
2617
2617
strncpy(src_path, src_table->table->s->path.str, sizeof(src_path));
2711
2711
if (create_info->options & HA_LEX_CREATE_TMP_TABLE)
2713
if (err || !open_temporary_table(session, dst_path, db, table_name, 1,
2713
if (err || !session->open_temporary_table(dst_path, db, table_name, 1, OTM_OPEN))
2716
(void) rm_temporary_table(create_info->db_type,
2715
(void) session->rm_temporary_table(create_info->db_type, dst_path);
2718
2716
goto err; /* purecov: inspected */
2850
2848
not complain when we lock the table
2852
2850
session->tablespace_op= true;
2853
if (!(table= session->open_ltable(table_list, TL_WRITE)))
2851
if (!(table= session->openTableLock(table_list, TL_WRITE)))
2855
2853
session->tablespace_op= false;
3461
bool mysql_alter_table(Session *session, char *new_db, char *new_name,
3459
bool mysql_alter_table(Session *session,
3462
3462
HA_CREATE_INFO *create_info,
3463
3463
TableList *table_list,
3464
3464
Alter_info *alter_info,
3465
uint32_t order_num, order_st *order, bool ignore)
3467
Table *table, *new_table=0, *name_lock= 0;;
3470
Table *new_table= NULL;
3471
Table *name_lock= NULL;
3468
3472
string new_name_str;
3470
char tmp_name[80],old_name[32],new_name_buff[FN_REFLEN];
3471
char new_alias_buff[FN_REFLEN], *table_name, *db;
3476
char new_name_buff[FN_REFLEN];
3477
char new_alias_buff[FN_REFLEN];
3472
3480
const char *new_alias;
3473
3481
char path[FN_REFLEN];
3474
ha_rows copied= 0,deleted= 0;
3475
StorageEngine *old_db_type, *new_db_type, *save_old_db_type;
3484
StorageEngine *old_db_type;
3485
StorageEngine *new_db_type;
3486
StorageEngine *save_old_db_type;
3476
3487
bitset<32> tmp;
3478
3489
new_name_buff[0]= '\0';
3497
session->set_proc_info("init");
3487
3500
Assign variables table_name, new_name, db, new_db, path
3488
3501
to simplify further comparisons: we want to see if it's a RENAME
3489
3502
later just by comparing the pointers, avoiding the need for strcmp.
3491
session->set_proc_info("init");
3492
3504
table_name= table_list->table_name;
3494
if (!new_db || !my_strcasecmp(table_alias_charset, new_db, db))
3506
if (! new_db || ! my_strcasecmp(table_alias_charset, new_db, db))
3509
if (alter_info->tablespace_op != NO_TABLESPACE_OP)
3511
/* DISCARD/IMPORT TABLESPACE is always alone in an ALTER Table */
3512
return mysql_discard_or_import_tablespace(session, table_list, alter_info->tablespace_op);
3496
3515
build_table_filename(path, sizeof(path), db, table_name, false);
3498
/* DISCARD/IMPORT TABLESPACE is always alone in an ALTER Table */
3499
if (alter_info->tablespace_op != NO_TABLESPACE_OP)
3500
/* Conditionally writes to binlog. */
3501
return(mysql_discard_or_import_tablespace(session,table_list,
3502
alter_info->tablespace_op));
3503
3517
ostringstream oss;
3504
3518
oss << drizzle_data_home << "/" << db << "/" << table_name;
3506
3520
(void) unpack_filename(new_name_buff, oss.str().c_str());
3508
3523
If this is just a rename of a view, short cut to the
3509
3524
following scenario: 1) lock LOCK_open 2) do a RENAME
3512
3527
ALTER (sic:) Table .. RENAME works for views. ALTER VIEW is handled
3513
3528
as an independent branch in mysql_execute_command. The need
3514
3529
for a copy-paste arose because the main code flow of ALTER Table
3515
... RENAME tries to use open_ltable, which does not work for views
3516
(open_ltable was never modified to merge table lists of child tables
3530
... RENAME tries to use openTableLock, which does not work for views
3531
(openTableLock was never modified to merge table lists of child tables
3517
3532
into the main table list, like open_tables does).
3518
3533
This code is wrong and will be removed, please do not copy.
3521
if (!(table= session->open_ltable(table_list, TL_WRITE_ALLOW_READ)))
3536
if (!(table= session->openTableLock(table_list, TL_WRITE_ALLOW_READ)))
3523
3539
table->use_all_columns();
3525
3541
/* Check that we are not trying to rename to an existing table */
3530
3546
new_alias= new_alias_buff;
3532
3548
my_casedn_str(files_charset_info, new_name_buff);
3533
new_alias= new_name; // Create lower case table name
3549
new_alias= new_name; // Create lower case table name
3534
3550
my_casedn_str(files_charset_info, new_name);
3536
3552
if (new_db == db &&
3537
!my_strcasecmp(table_alias_charset, new_name_buff, table_name))
3553
! my_strcasecmp(table_alias_charset, new_name_buff, table_name))
3540
Source and destination table names are equal: make later check
3556
Source and destination table names are equal: make later check
3543
3559
new_alias= new_name= table_name;
3547
3563
if (table->s->tmp_table != NO_TMP_TABLE)
3549
if (session->find_temporary_table(new_db, new_name_buff))
3551
my_error(ER_TABLE_EXISTS_ERROR, MYF(0), new_name_buff);
3565
if (session->find_temporary_table(new_db, new_name_buff))
3567
my_error(ER_TABLE_EXISTS_ERROR, MYF(0), new_name_buff);
3557
3573
if (session->lock_table_name_if_not_cached(new_db, new_name, &name_lock))
3562
my_error(ER_TABLE_EXISTS_ERROR, MYF(0), new_alias);
3578
my_error(ER_TABLE_EXISTS_ERROR, MYF(0), new_alias);
3566
build_table_filename(new_name_buff, sizeof(new_name_buff),
3567
new_db, new_name_buff, false);
3582
build_table_filename(new_name_buff, sizeof(new_name_buff), new_db, new_name_buff, false);
3568
3584
if (StorageEngine::getTableProto(new_name_buff, NULL) == EEXIST)
3570
/* Table will be closed by Session::executeCommand() */
3571
my_error(ER_TABLE_EXISTS_ERROR, MYF(0), new_alias);
3586
/* Table will be closed by Session::executeCommand() */
3587
my_error(ER_TABLE_EXISTS_ERROR, MYF(0), new_alias);
3583
3599
old_db_type= table->s->db_type();
3584
if (!create_info->db_type)
3600
if (! create_info->db_type)
3586
3602
create_info->db_type= old_db_type;
3589
if(table->s->tmp_table != NO_TMP_TABLE)
3605
if (table->s->tmp_table != NO_TMP_TABLE)
3590
3606
create_info->options|= HA_LEX_CREATE_TMP_TABLE;
3592
3608
if (check_engine(session, new_name, create_info))
3594
3611
new_db_type= create_info->db_type;
3596
3613
if (new_db_type != old_db_type &&
3697
*fn_ext(new_name)=0;
3718
*fn_ext(new_name)= 0;
3698
3719
if (mysql_rename_table(old_db_type, db, table_name, new_db, new_alias, 0))
3702
mysql_rename_table(old_db_type, new_db, new_alias, db,
3719
3734
write_bin_log(session, true, session->query, session->query_length);
3720
3735
session->my_ok();
3722
3737
else if (error > 0)
3724
3739
table->file->print_error(error, MYF(0));
3728
3744
session->unlink_open_table(name_lock);
3729
3746
pthread_mutex_unlock(&LOCK_open);
3730
table_list->table= NULL; // For query cache
3747
table_list->table= NULL;
3734
3751
/* We have to do full alter table. */
3737
3754
If the old table had partitions and we are doing ALTER Table ...
3738
3755
engine= <new_engine>, the new table must preserve the original
3739
3756
partitioning. That means that the new engine is still the
3747
3764
new_db_type= create_info->db_type;
3749
3766
if (mysql_prepare_alter_table(session, table, create_info, alter_info))
3752
3769
set_table_default_charset(create_info, db);
3754
3771
alter_info->build_method= HA_BUILD_OFFLINE;
3756
snprintf(tmp_name, sizeof(tmp_name), "%s-%lx_%"PRIx64, TMP_FILE_PREFIX,
3757
(unsigned long)current_pid, session->thread_id);
3773
snprintf(tmp_name, sizeof(tmp_name), "%s-%lx_%"PRIx64, TMP_FILE_PREFIX, (unsigned long) current_pid, session->thread_id);
3758
3775
/* Safety fix for innodb */
3759
3776
my_casedn_str(files_charset_info, tmp_name);
3762
3778
/* Create a temporary table with the new format */
3763
if ((error= create_temporary_table(session, table, new_db, tmp_name,
3764
create_info, alter_info,
3765
!strcmp(db, new_db))))
3779
error= create_temporary_table(session, table, new_db, tmp_name, create_info, alter_info, ! strcmp(db, new_db));
3770
3784
/* Open the table so we need to copy the data to it. */
3771
3785
if (table->s->tmp_table)
3776
3790
tbl.table_name= tmp_name;
3778
3792
/* Table is in session->temporary_tables */
3779
new_table= session->open_table(&tbl, (bool*) 0, DRIZZLE_LOCK_IGNORE_FLUSH);
3793
new_table= session->openTable(&tbl, (bool*) 0, DRIZZLE_LOCK_IGNORE_FLUSH);
3784
3798
/* table is a normal table: Create temporary table in same directory */
3785
3799
build_table_filename(tmp_path, sizeof(tmp_path), new_db, tmp_name, true);
3786
3800
/* Open our intermediate table */
3787
new_table= open_temporary_table(session, tmp_path, new_db, tmp_name, 0, OTM_OPEN);
3801
new_table= session->open_temporary_table(tmp_path, new_db, tmp_name, 0, OTM_OPEN);
3790
3804
if (new_table == NULL)
3793
3807
/* Copy the data if necessary. */
3794
3808
session->count_cuted_fields= CHECK_FIELD_WARN; // calc cuted fields
3795
session->cuted_fields=0L;
3809
session->cuted_fields= 0L;
3796
3810
session->set_proc_info("copy to tmp table");
3797
3811
copied= deleted= 0;
3801
3815
/* We don't want update TIMESTAMP fields during ALTER Table. */
3802
3816
new_table->timestamp_field_type= TIMESTAMP_NO_AUTO_SET;
3803
new_table->next_number_field=new_table->found_next_number_field;
3804
error= copy_data_between_tables(table, new_table,
3805
alter_info->create_list, ignore,
3806
order_num, order, &copied, &deleted,
3817
new_table->next_number_field= new_table->found_next_number_field;
3818
error= copy_data_between_tables(table,
3820
alter_info->create_list,
3807
3826
alter_info->keys_onoff,
3808
3827
alter_info->error_if_not_empty);
3810
/* We must not ignore bad input! */;
3829
/* We must not ignore bad input! */
3811
3830
session->count_cuted_fields= CHECK_FIELD_ERROR_FOR_NULL;
3813
3832
if (table->s->tmp_table != NO_TMP_TABLE)
3815
3834
/* We changed a temporary table */
3818
3838
/* Close lock if this is a transactional table */
3819
3839
if (session->lock)
3821
3841
mysql_unlock_tables(session, session->lock);
3824
3845
/* Remove link to old table and rename the new one */
3825
3846
session->close_temporary_table(table, true, true);
3826
3848
/* Should pass the 'new_name' as we store table name in the cache */
3827
if (rename_temporary_table(new_table, new_db, new_name))
3849
if (new_table->rename_temporary_table(new_db, new_name))
3829
3852
goto end_temporary;
3835
3858
Close the intermediate table that will be the new table.
3836
3859
Note that MERGE tables do not have their children attached here.
3838
intern_close_table(new_table);
3861
new_table->intern_close_table();
3839
3862
free(new_table);
3841
3865
pthread_mutex_lock(&LOCK_open); /* ALTER TABLE */
3844
3869
quick_rm_table(new_db_type, new_db, tmp_name, true);
3865
3890
session->set_proc_info("rename result table");
3866
snprintf(old_name, sizeof(old_name), "%s2-%lx-%"PRIx64, TMP_FILE_PREFIX,
3867
(unsigned long)current_pid, session->thread_id);
3892
snprintf(old_name, sizeof(old_name), "%s2-%lx-%"PRIx64, TMP_FILE_PREFIX, (unsigned long) current_pid, session->thread_id);
3868
3894
my_casedn_str(files_charset_info, old_name);
3870
3896
wait_while_table_is_used(session, table, HA_EXTRA_PREPARE_FOR_RENAME);
3871
3897
session->close_data_files_and_morph_locks(db, table_name);
3874
3900
save_old_db_type= old_db_type;
3886
3912
table is renamed and the SE is also changed, then an intermediate table
3887
3913
is created and the additional call will not take place.
3889
if (mysql_rename_table(old_db_type, db, table_name, db, old_name,
3893
quick_rm_table(new_db_type, new_db, tmp_name, true);
3895
else if (mysql_rename_table(new_db_type, new_db, tmp_name, new_db,
3896
new_alias, FN_FROM_IS_TMP) || ((new_name != table_name || new_db != db) && 0))
3898
/* Try to get everything back. */
3915
if (mysql_rename_table(old_db_type, db, table_name, db, old_name, FN_TO_IS_TMP))
3900
quick_rm_table(new_db_type, new_db, new_alias, false);
3901
3918
quick_rm_table(new_db_type, new_db, tmp_name, true);
3902
mysql_rename_table(old_db_type, db, old_name, db, table_name,
3922
if (mysql_rename_table(new_db_type, new_db, tmp_name, new_db, new_alias, FN_FROM_IS_TMP) != 0)
3924
/* Try to get everything back. */
3926
quick_rm_table(new_db_type, new_db, new_alias, false);
3927
quick_rm_table(new_db_type, new_db, tmp_name, true);
3928
mysql_rename_table(old_db_type, db, old_name, db, table_name, FN_FROM_IS_TMP);
3927
3953
char table_path[FN_REFLEN];
3928
3954
Table *t_table;
3929
3955
build_table_filename(table_path, sizeof(table_path), new_db, table_name, false);
3930
t_table= open_temporary_table(session, table_path, new_db, tmp_name, false, OTM_OPEN);
3956
t_table= session->open_temporary_table(table_path, new_db, tmp_name, false, OTM_OPEN);
3933
intern_close_table(t_table);
3959
t_table->intern_close_table();
3937
errmsg_printf(ERRMSG_LVL_WARN,
3938
_("Could not open table %s.%s after rename\n"),
3963
errmsg_printf(ERRMSG_LVL_WARN, _("Could not open table %s.%s after rename\n"), new_db, table_name);
3940
3965
ha_flush_logs(old_db_type);
3942
table_list->table=0; // For query cache
3967
table_list->table= NULL;
4296
4321
sprintf(table_name,"%s.%s",table->db,table->table_name);
4298
t= table->table= session->open_ltable(table, TL_READ);
4323
t= table->table= session->openTableLock(table, TL_READ);
4299
4324
session->clear_error(); // these errors shouldn't get client
4301
4326
protocol->prepareForResend();