1
/******************************************************
2
Interface between Innobase row operations and MySQL.
3
Contains also create table and other data dictionary operations.
7
Created 9/17/2000 Heikki Tuuri
8
*******************************************************/
10
#include "row0mysql.h"
13
#include "row0mysql.ic"
21
#include "pars0pars.h"
22
#include "dict0dict.h"
23
#include "dict0crea.h"
25
#include "trx0purge.h"
26
#include "lock0lock.h"
28
/***********************************************************************
29
Reads a MySQL format variable-length field (like VARCHAR) length and
30
returns pointer to the field data. */
33
row_mysql_read_var_ref_noninline(
34
/*=============================*/
36
ulint* len, /* out: variable-length field length */
37
byte* field) /* in: field */
39
return(row_mysql_read_var_ref(len, field));
42
/***********************************************************************
43
Stores a reference to a BLOB in the MySQL format. */
46
row_mysql_store_blob_ref(
47
/*=====================*/
48
byte* dest, /* in: where to store */
49
ulint col_len, /* in: dest buffer size: determines into
50
how many bytes the BLOB length is stored,
51
this may vary from 1 to 4 bytes */
52
byte* data, /* in: BLOB data */
53
ulint len) /* in: BLOB length */
55
/* In dest there are 1 - 4 bytes reserved for the BLOB length,
56
and after that 8 bytes reserved for the pointer to the data.
57
In 32-bit architectures we only use the first 4 bytes of the pointer
60
mach_write_to_n_little_endian(dest, col_len - 8, len);
62
ut_memcpy(dest + col_len - 8, (byte*)&data, sizeof(byte*));
65
/***********************************************************************
66
Reads a reference to a BLOB in the MySQL format. */
69
row_mysql_read_blob_ref(
70
/*====================*/
71
/* out: pointer to BLOB data */
72
ulint* len, /* out: BLOB length */
73
byte* ref, /* in: BLOB reference in the MySQL format */
74
ulint col_len) /* in: BLOB reference length (not BLOB
79
*len = mach_read_from_n_little_endian(ref, col_len - 8);
81
ut_memcpy((byte*)&data, ref + col_len - 8, sizeof(byte*));
86
/******************************************************************
87
Convert a row in the MySQL format to a row in the Innobase format. */
90
row_mysql_convert_row_to_innobase(
91
/*==============================*/
92
dtuple_t* row, /* in/out: Innobase row where the
93
field type information is already
94
copied there, or will be copied
96
byte* buf, /* in/out: buffer to use in converting
97
data in columns; this must be at least
98
the size of mysql_rec! */
99
row_prebuilt_t* prebuilt, /* in: prebuilt struct where template
100
must be of type ROW_MYSQL_WHOLE_ROW */
101
byte* mysql_rec) /* in: row in the MySQL format;
102
NOTE: do not discard as long as
103
row is used, as row may contain
104
pointers to this record! */
106
mysql_row_templ_t* templ;
110
ut_ad(prebuilt->template_type == ROW_MYSQL_WHOLE_ROW);
111
ut_ad(prebuilt->mysql_template);
113
for (i = 0; i < prebuilt->n_template; i++) {
115
templ = prebuilt->mysql_template + i;
116
dfield = dtuple_get_nth_field(row, i);
118
if (templ->mysql_null_bit_mask != 0) {
119
/* Column may be SQL NULL */
121
if (mysql_rec[templ->mysql_null_byte_offset] &
122
(byte) (templ->mysql_null_bit_mask)) {
126
dfield_set_data(dfield, NULL, UNIV_SQL_NULL);
132
row_mysql_store_col_in_innobase_format(dfield,
133
prebuilt->ins_upd_rec_buff
134
+ templ->mysql_col_offset,
135
mysql_rec + templ->mysql_col_offset,
136
templ->mysql_col_len,
137
templ->type, templ->is_unsigned);
143
/********************************************************************
144
Handles user errors and lock waits detected by the database engine. */
147
row_mysql_handle_errors(
148
/*====================*/
149
/* out: TRUE if it was a lock wait and
150
we should continue running the query thread */
151
ulint* new_err,/* out: possible new error encountered in
152
rollback, or the old error which was
153
during the function entry */
154
trx_t* trx, /* in: transaction */
155
que_thr_t* thr, /* in: query thread */
156
trx_savept_t* savept) /* in: savepoint */
158
ibool timeout_expired;
162
err = trx->error_state;
164
ut_a(err != DB_SUCCESS);
166
trx->error_state = DB_SUCCESS;
168
if (err == DB_DUPLICATE_KEY) {
170
/* Roll back the latest, possibly incomplete
171
insertion or update */
173
trx_general_rollback_for_mysql(trx, TRUE, savept);
175
} else if (err == DB_TOO_BIG_RECORD) {
177
/* Roll back the latest, possibly incomplete
178
insertion or update */
180
trx_general_rollback_for_mysql(trx, TRUE, savept);
182
} else if (err == DB_LOCK_WAIT) {
184
timeout_expired = srv_suspend_mysql_thread(thr);
186
if (timeout_expired) {
187
trx->error_state = DB_DEADLOCK;
189
que_thr_stop_for_mysql(thr);
191
goto handle_new_error;
198
} else if (err == DB_DEADLOCK) {
200
/* Roll back the whole transaction */
202
trx_general_rollback_for_mysql(trx, FALSE, NULL);
204
} else if (err == DB_OUT_OF_FILE_SPACE) {
206
/* Roll back the whole transaction */
208
trx_general_rollback_for_mysql(trx, FALSE, NULL);
209
} else if (err == DB_MUST_GET_MORE_FILE_SPACE) {
211
ut_a(0); /* TODO: print something to MySQL error log */
216
if (trx->error_state != DB_SUCCESS) {
217
*new_err = trx->error_state;
222
trx->error_state = DB_SUCCESS;
227
/************************************************************************
228
Create a prebuilt struct for a MySQL table handle. */
233
/* out, own: a prebuilt struct */
234
dict_table_t* table) /* in: Innobase table handle */
236
row_prebuilt_t* prebuilt;
238
dict_index_t* clust_index;
243
heap = mem_heap_create(128);
245
prebuilt = mem_heap_alloc(heap, sizeof(row_prebuilt_t));
247
prebuilt->table = table;
249
prebuilt->trx = NULL;
251
prebuilt->sql_stat_start = TRUE;
253
prebuilt->index = NULL;
254
prebuilt->n_template = 0;
255
prebuilt->mysql_template = NULL;
257
prebuilt->heap = heap;
258
prebuilt->ins_node = NULL;
260
prebuilt->ins_upd_rec_buff = NULL;
262
prebuilt->upd_node = NULL;
263
prebuilt->ins_graph = NULL;
264
prebuilt->upd_graph = NULL;
266
prebuilt->pcur = btr_pcur_create_for_mysql();
267
prebuilt->clust_pcur = btr_pcur_create_for_mysql();
269
prebuilt->select_lock_type = LOCK_NONE;
271
prebuilt->sel_graph = NULL;
273
prebuilt->search_tuple = dtuple_create(heap,
274
dict_table_get_n_cols(table));
276
clust_index = dict_table_get_first_index(table);
278
ref_len = dict_index_get_n_unique(clust_index);
280
ref = dtuple_create(heap, ref_len);
282
dict_index_copy_types(ref, clust_index, ref_len);
284
prebuilt->clust_ref = ref;
286
for (i = 0; i < MYSQL_FETCH_CACHE_SIZE; i++) {
287
prebuilt->fetch_cache[i] = NULL;
290
prebuilt->n_fetch_cached = 0;
292
prebuilt->blob_heap = NULL;
294
prebuilt->old_vers_heap = NULL;
299
/************************************************************************
300
Free a prebuilt struct for a MySQL table handle. */
305
row_prebuilt_t* prebuilt) /* in, own: prebuilt struct */
309
btr_pcur_free_for_mysql(prebuilt->pcur);
310
btr_pcur_free_for_mysql(prebuilt->clust_pcur);
312
if (prebuilt->mysql_template) {
313
mem_free(prebuilt->mysql_template);
316
if (prebuilt->ins_graph) {
317
que_graph_free_recursive(prebuilt->ins_graph);
320
if (prebuilt->sel_graph) {
321
que_graph_free_recursive(prebuilt->sel_graph);
324
if (prebuilt->upd_graph) {
325
que_graph_free_recursive(prebuilt->upd_graph);
328
if (prebuilt->blob_heap) {
329
mem_heap_free(prebuilt->blob_heap);
332
if (prebuilt->old_vers_heap) {
333
mem_heap_free(prebuilt->old_vers_heap);
336
for (i = 0; i < MYSQL_FETCH_CACHE_SIZE; i++) {
337
if (prebuilt->fetch_cache[i] != NULL) {
338
mem_free(prebuilt->fetch_cache[i]);
342
mem_heap_free(prebuilt->heap);
345
/*************************************************************************
346
Updates the transaction pointers in query graphs stored in the prebuilt
350
row_update_prebuilt_trx(
351
/*====================*/
352
/* out: prebuilt dtuple */
353
row_prebuilt_t* prebuilt, /* in: prebuilt struct in MySQL
355
trx_t* trx) /* in: transaction handle */
359
if (prebuilt->ins_graph) {
360
prebuilt->ins_graph->trx = trx;
363
if (prebuilt->upd_graph) {
364
prebuilt->upd_graph->trx = trx;
367
if (prebuilt->sel_graph) {
368
prebuilt->sel_graph->trx = trx;
372
/*************************************************************************
373
Gets pointer to a prebuilt dtuple used in insertions. If the insert graph
374
has not yet been built in the prebuilt struct, then this function first
378
row_get_prebuilt_insert_row(
379
/*========================*/
380
/* out: prebuilt dtuple */
381
row_prebuilt_t* prebuilt) /* in: prebuilt struct in MySQL
386
dict_table_t* table = prebuilt->table;
388
ut_ad(prebuilt && table && prebuilt->trx);
390
if (prebuilt->ins_node == NULL) {
392
/* Not called before for this handle: create an insert node
393
and query graph to the prebuilt struct */
395
node = ins_node_create(INS_DIRECT, table, prebuilt->heap);
397
prebuilt->ins_node = node;
399
if (prebuilt->ins_upd_rec_buff == NULL) {
400
prebuilt->ins_upd_rec_buff = mem_heap_alloc(
402
prebuilt->mysql_row_len);
405
row = dtuple_create(prebuilt->heap,
406
dict_table_get_n_cols(table));
408
dict_table_copy_types(row, table);
410
ins_node_set_new_row(node, row);
412
prebuilt->ins_graph =
414
pars_complete_graph_for_exec(node,
417
prebuilt->ins_graph->state = QUE_FORK_ACTIVE;
420
return(prebuilt->ins_node->row);
423
/*************************************************************************
424
Updates the table modification counter and calculates new estimates
425
for table and index statistics if necessary. */
428
row_update_statistics_if_needed(
429
/*============================*/
430
row_prebuilt_t* prebuilt) /* in: prebuilt struct */
435
counter = prebuilt->table->stat_modif_counter;
437
counter += prebuilt->mysql_row_len;
438
prebuilt->table->stat_modif_counter = counter;
440
old_counter = prebuilt->table->stat_last_estimate_counter;
442
if (counter - old_counter >= DICT_STAT_CALCULATE_INTERVAL
443
|| counter - old_counter >=
445
* prebuilt->table->stat_clustered_index_size / 2)) {
447
dict_update_statistics(prebuilt->table);
451
/*************************************************************************
452
Does an insert for MySQL. */
455
row_insert_for_mysql(
456
/*=================*/
457
/* out: error code or DB_SUCCESS */
458
byte* mysql_rec, /* in: row in the MySQL format */
459
row_prebuilt_t* prebuilt) /* in: prebuilt struct in MySQL
466
trx_t* trx = prebuilt->trx;
467
ins_node_t* node = prebuilt->ins_node;
470
ut_ad(trx->mysql_thread_id == os_thread_get_curr_id());
473
row_get_prebuilt_insert_row(prebuilt);
474
node = prebuilt->ins_node;
477
row_mysql_convert_row_to_innobase(node->row,
478
prebuilt->ins_upd_rec_buff,
479
prebuilt, mysql_rec);
480
savept = trx_savept_take(trx);
482
thr = que_fork_get_first_thr(prebuilt->ins_graph);
484
if (prebuilt->sql_stat_start) {
485
node->state = INS_NODE_SET_IX_LOCK;
486
prebuilt->sql_stat_start = FALSE;
488
node->state = INS_NODE_ALLOC_ROW_ID;
491
que_thr_move_to_run_state_for_mysql(thr, trx);
494
thr->run_node = node;
495
thr->prev_node = node;
499
err = trx->error_state;
501
if (err != DB_SUCCESS) {
502
que_thr_stop_for_mysql(thr);
504
was_lock_wait = row_mysql_handle_errors(&err, trx, thr,
513
que_thr_stop_for_mysql_no_error(thr, trx);
515
prebuilt->table->stat_n_rows++;
517
if (prebuilt->table->stat_n_rows == 0) {
518
/* Avoid wrap-over */
519
prebuilt->table->stat_n_rows--;
522
row_update_statistics_if_needed(prebuilt);
527
/*************************************************************************
528
Builds a dummy query graph used in selects. */
531
row_prebuild_sel_graph(
532
/*===================*/
533
row_prebuilt_t* prebuilt) /* in: prebuilt struct in MySQL
538
ut_ad(prebuilt && prebuilt->trx);
540
if (prebuilt->sel_graph == NULL) {
542
node = sel_node_create(prebuilt->heap);
544
prebuilt->sel_graph =
546
pars_complete_graph_for_exec(node,
550
prebuilt->sel_graph->state = QUE_FORK_ACTIVE;
554
/*************************************************************************
555
Gets pointer to a prebuilt update vector used in updates. If the update
556
graph has not yet been built in the prebuilt struct, then this function
560
row_get_prebuilt_update_vector(
561
/*===========================*/
562
/* out: prebuilt update vector */
563
row_prebuilt_t* prebuilt) /* in: prebuilt struct in MySQL
566
dict_table_t* table = prebuilt->table;
569
ut_ad(prebuilt && table && prebuilt->trx);
571
if (prebuilt->upd_node == NULL) {
573
/* Not called before for this handle: create an update node
574
and query graph to the prebuilt struct */
576
node = upd_node_create(prebuilt->heap);
578
prebuilt->upd_node = node;
580
node->in_mysql_interface = TRUE;
581
node->is_delete = FALSE;
582
node->searched_update = FALSE;
583
node->select_will_do_update = FALSE;
585
node->pcur = btr_pcur_create_for_mysql();
588
node->update = upd_create(dict_table_get_n_cols(table),
590
UT_LIST_INIT(node->columns);
591
node->has_clust_rec_x_lock = TRUE;
594
node->table_sym = NULL;
595
node->col_assign_list = NULL;
597
prebuilt->upd_graph =
599
pars_complete_graph_for_exec(node,
602
prebuilt->upd_graph->state = QUE_FORK_ACTIVE;
605
return(prebuilt->upd_node->update);
608
/*************************************************************************
609
Does an update or delete of a row for MySQL. */
612
row_update_for_mysql(
613
/*=================*/
614
/* out: error code or DB_SUCCESS */
615
byte* mysql_rec, /* in: the row to be updated, in
617
row_prebuilt_t* prebuilt) /* in: prebuilt struct in MySQL
624
dict_index_t* clust_index;
627
dict_table_t* table = prebuilt->table;
628
trx_t* trx = prebuilt->trx;
630
dtuple_t* search_tuple;
634
ut_ad(prebuilt && trx);
635
ut_ad(trx->mysql_thread_id == os_thread_get_curr_id());
637
node = prebuilt->upd_node;
639
clust_index = dict_table_get_first_index(table);
641
if (prebuilt->in_update_remember_pos) {
642
if (prebuilt->index == clust_index) {
643
btr_pcur_copy_stored_position(node->pcur,
646
btr_pcur_copy_stored_position(node->pcur,
647
prebuilt->clust_pcur);
650
ut_ad(node->pcur->rel_pos == BTR_PCUR_ON);
652
goto skip_cursor_search;
655
/* We have to search for the correct cursor position */
657
ref_len = dict_index_get_n_unique(clust_index);
659
heap = mem_heap_create(450);
661
row_tuple = dtuple_create(heap, dict_table_get_n_cols(table));
662
dict_table_copy_types(row_tuple, table);
664
if (prebuilt->ins_upd_rec_buff == NULL) {
665
prebuilt->ins_upd_rec_buff = mem_heap_alloc(prebuilt->heap,
666
prebuilt->mysql_row_len);
669
row_mysql_convert_row_to_innobase(row_tuple,
670
prebuilt->ins_upd_rec_buff,
671
prebuilt, mysql_rec);
673
search_tuple = dtuple_create(heap, ref_len);
675
row_build_row_ref_from_row(search_tuple, table, row_tuple);
679
btr_pcur_open_with_no_init(clust_index, search_tuple, PAGE_CUR_LE,
680
BTR_SEARCH_LEAF, node->pcur, 0, &mtr);
682
btr_pcur_store_position(node->pcur, &mtr);
689
savept = trx_savept_take(trx);
691
thr = que_fork_get_first_thr(prebuilt->upd_graph);
693
node->state = UPD_NODE_UPDATE_CLUSTERED;
695
ut_ad(!prebuilt->sql_stat_start);
697
que_thr_move_to_run_state_for_mysql(thr, trx);
699
thr->run_node = node;
700
thr->prev_node = node;
704
err = trx->error_state;
706
if (err != DB_SUCCESS) {
707
que_thr_stop_for_mysql(thr);
709
if (err == DB_RECORD_NOT_FOUND) {
710
trx->error_state = DB_SUCCESS;
715
was_lock_wait = row_mysql_handle_errors(&err, trx, thr,
724
que_thr_stop_for_mysql_no_error(thr, trx);
726
if (prebuilt->upd_node->is_delete) {
727
if (prebuilt->table->stat_n_rows > 0) {
728
prebuilt->table->stat_n_rows--;
732
row_update_statistics_if_needed(prebuilt);
737
/*************************************************************************
738
Checks if a table is such that we automatically created a clustered
739
index on it (on row id). */
742
row_table_got_default_clust_index(
743
/*==============================*/
746
dict_index_t* clust_index;
748
clust_index = dict_table_get_first_index(table);
750
if (dtype_get_mtype(dict_index_get_nth_type(clust_index, 0))
758
/*************************************************************************
759
Does a table creation operation for MySQL. */
762
row_create_table_for_mysql(
763
/*=======================*/
764
/* out: error code or DB_SUCCESS */
765
dict_table_t* table, /* in: table definition */
766
trx_t* trx) /* in: transaction handle */
773
ut_ad(trx->mysql_thread_id == os_thread_get_curr_id());
775
/* Serialize data dictionary operations with dictionary mutex:
776
no deadlocks can occur then in these operations */
778
mutex_enter(&(dict_sys->mutex));
780
heap = mem_heap_create(512);
782
trx->dict_operation = TRUE;
784
node = tab_create_graph_create(table, heap);
786
thr = pars_complete_graph_for_exec(node, trx, heap);
788
ut_a(thr == que_fork_start_command(que_node_get_parent(thr),
789
SESS_COMM_EXECUTE, 0));
790
que_run_threads(thr);
792
err = trx->error_state;
794
if (err != DB_SUCCESS) {
795
/* We have special error handling here */
796
ut_a(err == DB_OUT_OF_FILE_SPACE);
797
trx->error_state = DB_SUCCESS;
799
trx_general_rollback_for_mysql(trx, FALSE, NULL);
801
row_drop_table_for_mysql(table->name, trx, TRUE);
803
trx->error_state = DB_SUCCESS;
806
mutex_exit(&(dict_sys->mutex));
807
que_graph_free((que_t*) que_node_get_parent(thr));
812
/*************************************************************************
813
Does an index creation operation for MySQL. TODO: currently failure
814
to create an index results in dropping the whole table! This is no problem
815
currently as all indexes must be created at the same time as the table. */
818
row_create_index_for_mysql(
819
/*=======================*/
820
/* out: error number or DB_SUCCESS */
821
dict_index_t* index, /* in: index defintion */
822
trx_t* trx) /* in: transaction handle */
829
ut_ad(trx->mysql_thread_id == os_thread_get_curr_id());
831
/* Serialize data dictionary operations with dictionary mutex:
832
no deadlocks can occur then in these operations */
834
mutex_enter(&(dict_sys->mutex));
836
heap = mem_heap_create(512);
838
trx->dict_operation = TRUE;
840
node = ind_create_graph_create(index, heap);
842
thr = pars_complete_graph_for_exec(node, trx, heap);
844
ut_a(thr == que_fork_start_command(que_node_get_parent(thr),
845
SESS_COMM_EXECUTE, 0));
846
que_run_threads(thr);
848
err = trx->error_state;
850
if (err != DB_SUCCESS) {
851
/* We have special error handling here */
852
ut_a(err == DB_OUT_OF_FILE_SPACE);
854
trx->error_state = DB_SUCCESS;
856
trx_general_rollback_for_mysql(trx, FALSE, NULL);
858
row_drop_table_for_mysql(index->table_name, trx, TRUE);
860
trx->error_state = DB_SUCCESS;
863
mutex_exit(&(dict_sys->mutex));
865
que_graph_free((que_t*) que_node_get_parent(thr));
870
/*************************************************************************
871
Drops a table for MySQL. */
874
row_drop_table_for_mysql(
875
/*=====================*/
876
/* out: error code or DB_SUCCESS */
877
char* name, /* in: table name */
878
trx_t* trx, /* in: transaction handle */
879
ibool has_dict_mutex) /* in: TRUE if the caller already owns the
880
dictionary system mutex */
891
ut_ad(trx->mysql_thread_id == os_thread_get_curr_id());
894
/* We use the private SQL parser of Innobase to generate the
895
query graphs needed in deleting the dictionary data from system
896
tables in Innobase. Deleting a row from SYS_INDEXES table also
897
frees the file segments of the B-tree associated with the index. */
900
"PROCEDURE DROP_TABLE_PROC () IS\n"
905
"SELECT ID INTO table_id\n"
911
"IF (SQL % NOTFOUND) THEN\n"
916
"WHILE found = 1 LOOP\n"
917
" SELECT ID INTO index_id\n"
918
" FROM SYS_INDEXES\n"
919
" WHERE TABLE_ID = table_id;\n"
920
" IF (SQL % NOTFOUND) THEN\n"
923
" DELETE FROM SYS_FIELDS WHERE INDEX_ID = index_id;\n"
924
" DELETE FROM SYS_INDEXES WHERE ID = index_id;\n"
927
"DELETE FROM SYS_COLUMNS WHERE TABLE_ID = table_id;\n"
928
"DELETE FROM SYS_TABLES WHERE ID = table_id;\n"
932
len = ut_strlen(str1);
934
ut_memcpy(buf, str1, len);
935
ut_memcpy(buf + len, name, ut_strlen(name));
937
len += ut_strlen(name);
939
ut_memcpy(buf + len, str2, ut_strlen(str2) + 1);
941
/* Serialize data dictionary operations with dictionary mutex:
942
no deadlocks can occur then in these operations */
944
if (!has_dict_mutex) {
945
mutex_enter(&(dict_sys->mutex));
948
graph = pars_sql(buf);
955
graph->fork_type = QUE_FORK_MYSQL_INTERFACE;
957
/* Prevent purge from running while we are dropping the table */
958
rw_lock_s_lock(&(purge_sys->purge_is_running));
960
table = dict_table_get_low(name);
963
err = DB_TABLE_NOT_FOUND;
968
/* Check if there are any locks on the table: if yes, it cannot
969
be dropped: we have to wait for the locks to be released */
971
if (lock_is_on_table(table)) {
973
err = DB_TABLE_IS_BEING_USED;
978
/* TODO: check that MySQL prevents users from accessing the table
979
after this function row_drop_table_for_mysql has been called:
980
otherwise anyone with an open handle to the table could, for example,
981
come to read the table! */
983
trx->dict_operation = TRUE;
984
trx->table_id = table->id;
986
ut_a(thr = que_fork_start_command(graph, SESS_COMM_EXECUTE, 0));
988
que_run_threads(thr);
990
err = trx->error_state;
992
if (err != DB_SUCCESS) {
993
ut_a(err == DB_OUT_OF_FILE_SPACE);
995
err = DB_MUST_GET_MORE_FILE_SPACE;
997
row_mysql_handle_errors(&err, trx, thr, NULL);
1001
dict_table_remove_from_cache(table);
1004
rw_lock_s_unlock(&(purge_sys->purge_is_running));
1006
if (!has_dict_mutex) {
1007
mutex_exit(&(dict_sys->mutex));
1010
que_graph_free(graph);
1012
if (err == DB_TABLE_IS_BEING_USED) {
1013
os_thread_sleep(200000);
1021
/*************************************************************************
1022
Renames a table for MySQL. */
1025
row_rename_table_for_mysql(
1026
/*=======================*/
1027
/* out: error code or DB_SUCCESS */
1028
char* old_name, /* in: old table name */
1029
char* new_name, /* in: new table name */
1030
trx_t* trx) /* in: transaction handle */
1032
dict_table_t* table;
1042
ut_ad(trx->mysql_thread_id == os_thread_get_curr_id());
1043
ut_a(old_name != NULL);
1044
ut_a(new_name != NULL);
1047
"PROCEDURE RENAME_TABLE_PROC () IS\n"
1049
"UPDATE SYS_TABLES SET NAME ='";
1059
len = ut_strlen(str1);
1061
ut_memcpy(buf, str1, len);
1063
ut_memcpy(buf + len, new_name, ut_strlen(new_name));
1065
len += ut_strlen(new_name);
1067
ut_memcpy(buf + len, str2, ut_strlen(str2));
1069
len += ut_strlen(str2);
1071
ut_memcpy(buf + len, old_name, ut_strlen(old_name));
1073
len += ut_strlen(old_name);
1075
ut_memcpy(buf + len, str3, ut_strlen(str3) + 1);
1077
/* Serialize data dictionary operations with dictionary mutex:
1078
no deadlocks can occur then in these operations */
1080
mutex_enter(&(dict_sys->mutex));
1082
table = dict_table_get_low(old_name);
1084
graph = pars_sql(buf);
1091
graph->fork_type = QUE_FORK_MYSQL_INTERFACE;
1094
err = DB_TABLE_NOT_FOUND;
1099
ut_a(thr = que_fork_start_command(graph, SESS_COMM_EXECUTE, 0));
1101
que_run_threads(thr);
1103
err = trx->error_state;
1105
if (err != DB_SUCCESS) {
1106
row_mysql_handle_errors(&err, trx, thr, NULL);
1108
ut_a(dict_table_rename_in_cache(table, new_name));
1111
mutex_exit(&(dict_sys->mutex));
1113
que_graph_free(graph);