1
1
/*****************************************************************************
3
Copyright (C) 2000, 2010, Innobase Oy. All Rights Reserved.
3
Copyright (c) 2000, 2010, Innobase Oy. All Rights Reserved.
5
5
This program is free software; you can redistribute it and/or modify it under
6
6
the terms of the GNU General Public License as published by the Free Software
251
251
/**************************************************************//**
252
Pad a column with spaces. */
257
ulint mbminlen, /*!< in: minimum size of a character,
259
byte* pad, /*!< out: padded buffer */
260
ulint len) /*!< in: number of bytes to pad */
264
switch (UNIV_EXPECT(mbminlen, 1)) {
269
memset(pad, 0x20, len);
278
} while (pad < pad_end);
281
/* space=0x00000020 */
289
} while (pad < pad_end);
294
/**************************************************************//**
295
252
Stores a non-SQL-NULL field given in the MySQL format in the InnoDB format.
296
253
The counterpart of this function is row_sel_field_store_in_mysql_format() in
383
340
/* Remove trailing spaces from old style VARCHAR
386
/* Handle Unicode strings differently. */
343
/* Handle UCS2 strings differently. */
387
344
ulint mbminlen = dtype_get_mbminlen(dtype);
389
346
ptr = mysql_data;
395
/* space=0x00000020 */
396
/* Trim "half-chars", just in case. */
400
&& ptr[col_len - 4] == 0x00
401
&& ptr[col_len - 3] == 0x00
402
&& ptr[col_len - 2] == 0x00
403
&& ptr[col_len - 1] == 0x20) {
408
349
/* space=0x0020 */
409
350
/* Trim "half-chars", just in case. */
486
427
row is used, as row may contain
487
428
pointers to this record! */
489
const mysql_row_templ_t*templ;
430
mysql_row_templ_t* templ;
490
431
dfield_t* dfield;
618
559
"InnoDB: " REFMAN "forcing-recovery.html"
619
560
" for help.\n", stderr);
621
case DB_FOREIGN_EXCEED_MAX_CASCADE:
622
fprintf(stderr, "InnoDB: Cannot delete/update rows with"
623
" cascading foreign key constraints that exceed max"
625
"Please drop excessive foreign constraints"
626
" and try again\n", (ulong) DICT_FK_MAX_RECURSIVE_LOAD);
629
563
fprintf(stderr, "InnoDB: unknown error code %lu\n",
660
594
heap = mem_heap_create(sizeof *prebuilt + 128);
662
prebuilt = static_cast<row_prebuilt_t *>(mem_heap_zalloc(heap, sizeof *prebuilt));
596
prebuilt = mem_heap_zalloc(heap, sizeof *prebuilt);
664
598
prebuilt->magic_n = ROW_PREBUILT_ALLOCATED;
665
599
prebuilt->magic_n2 = ROW_PREBUILT_ALLOCATED;
675
609
prebuilt->select_lock_type = LOCK_NONE;
676
610
prebuilt->stored_select_lock_type = 99999999;
677
UNIV_MEM_INVALID(&prebuilt->stored_select_lock_type,
678
sizeof prebuilt->stored_select_lock_type);
680
612
prebuilt->search_tuple = dtuple_create(
681
613
heap, 2 * dict_table_get_n_cols(table));
843
dtuple_t* row_get_prebuilt_insert_row(row_prebuilt_t* prebuilt);
845
775
/*********************************************************************//**
846
776
Gets pointer to a prebuilt dtuple used in insertions. If the insert graph
847
777
has not yet been built in the prebuilt struct, then this function first
849
779
@return prebuilt dtuple; the column type information is also set in it */
851
782
row_get_prebuilt_insert_row(
852
783
/*========================*/
869
800
prebuilt->ins_node = node;
871
802
if (prebuilt->ins_upd_rec_buff == NULL) {
872
prebuilt->ins_upd_rec_buff = static_cast<byte *>(mem_heap_alloc(
873
prebuilt->heap, prebuilt->mysql_row_len));
803
prebuilt->ins_upd_rec_buff = mem_heap_alloc(
804
prebuilt->heap, prebuilt->mysql_row_len);
876
807
row = dtuple_create(prebuilt->heap,
881
812
ins_node_set_new_row(node, row);
883
prebuilt->ins_graph = static_cast<que_fork_t *>(que_node_get_parent(
814
prebuilt->ins_graph = que_node_get_parent(
884
815
pars_complete_graph_for_exec(node,
887
818
prebuilt->ins_graph->state = QUE_FORK_ACTIVE;
1066
996
trx_start_if_not_started(trx);
1069
err = lock_table(0, table, static_cast<lock_mode>(mode), thr);
999
err = lock_table(0, table, mode, thr);
1071
1001
err = lock_table(0, prebuilt->table,
1072
static_cast<lock_mode>(prebuilt->select_lock_type), thr);
1002
prebuilt->select_lock_type, thr);
1075
1005
trx->error_state = err;
1245
1175
node = sel_node_create(prebuilt->heap);
1247
prebuilt->sel_graph = static_cast<que_fork_t *>(que_node_get_parent(
1177
prebuilt->sel_graph = que_node_get_parent(
1248
1178
pars_complete_graph_for_exec(node,
1252
1182
prebuilt->sel_graph->state = QUE_FORK_ACTIVE;
1316
1246
prebuilt->upd_node = node;
1318
prebuilt->upd_graph = static_cast<que_fork_t *>(que_node_get_parent(
1248
prebuilt->upd_graph = que_node_get_parent(
1319
1249
pars_complete_graph_for_exec(node,
1322
1252
prebuilt->upd_graph->state = QUE_FORK_ACTIVE;
1433
1363
thr->run_node = node;
1434
1364
thr->prev_node = node;
1435
thr->fk_cascade_depth = 0;
1437
1366
row_upd_step(thr);
1439
/* The recursive call for cascading update/delete happens
1440
in above row_upd_step(), reset the counter once we come
1441
out of the recursive call, so it does not accumulate for
1442
different row deletes */
1443
thr->fk_cascade_depth = 0;
1445
1368
err = trx->error_state;
1447
/* Reset fk_cascade_depth back to 0 */
1448
thr->fk_cascade_depth = 0;
1450
1370
if (err != DB_SUCCESS) {
1451
1371
que_thr_stop_for_mysql(thr);
1483
1403
srv_n_rows_updated++;
1486
/* We update table statistics only if it is a DELETE or UPDATE
1487
that changes indexed columns, UPDATEs that change only non-indexed
1488
columns would not affect statistics. */
1489
if (node->is_delete || !(node->cmpl_info & UPD_NODE_NO_ORD_CHANGE)) {
1490
row_update_statistics_if_needed(prebuilt->table);
1406
row_update_statistics_if_needed(prebuilt->table);
1493
1408
trx->op_info = "";
1498
1413
/*********************************************************************//**
1499
This can only be used when srv_locks_unsafe_for_binlog is TRUE or this
1500
session is using a READ COMMITTED or READ UNCOMMITTED isolation level.
1501
Before calling this function row_search_for_mysql() must have
1502
initialized prebuilt->new_rec_locks to store the information which new
1503
record locks really were set. This function removes a newly set
1504
clustered index record lock under prebuilt->pcur or
1505
prebuilt->clust_pcur. Thus, this implements a 'mini-rollback' that
1506
releases the latest clustered index record lock we set.
1507
@return error code or DB_SUCCESS */
1414
This can only be used when srv_locks_unsafe_for_binlog is TRUE or
1415
this session is using a READ COMMITTED isolation level. Before
1416
calling this function we must use trx_reset_new_rec_lock_info() and
1417
trx_register_new_rec_lock() to store the information which new record locks
1418
really were set. This function removes a newly set lock under prebuilt->pcur,
1419
and also under prebuilt->clust_pcur. Currently, this is only used and tested
1420
in the case of an UPDATE or a DELETE statement, where the row lock is of the
1422
Thus, this implements a 'mini-rollback' that releases the latest record
1424
@return error code or DB_SUCCESS */
1510
1427
row_unlock_for_mysql(
1511
1428
/*=================*/
1512
row_prebuilt_t* prebuilt, /*!< in/out: prebuilt struct in MySQL
1429
row_prebuilt_t* prebuilt, /*!< in: prebuilt struct in MySQL
1514
ibool has_latches_on_recs)/*!< in: TRUE if called so
1515
that we have the latches on
1516
the records under pcur and
1517
clust_pcur, and we do not need
1518
to reposition the cursors. */
1431
ibool has_latches_on_recs)/*!< TRUE if called so that we have
1432
the latches on the records under pcur
1433
and clust_pcur, and we do not need to
1434
reposition the cursors. */
1520
1436
btr_pcur_t* pcur = prebuilt->pcur;
1521
1437
btr_pcur_t* clust_pcur = prebuilt->clust_pcur;
1601
if (rec_trx_id != trx->id) {
1517
if (ut_dulint_cmp(rec_trx_id, trx->id) != 0) {
1602
1518
/* We did not update the record: unlock it */
1604
1520
rec = btr_pcur_get_rec(pcur);
1605
1521
index = btr_pcur_get_btr_cur(pcur)->index;
1607
1523
lock_rec_unlock(trx, btr_pcur_get_block(pcur),
1608
rec, static_cast<lock_mode>(prebuilt->select_lock_type));
1524
rec, prebuilt->select_lock_type);
1610
1526
if (prebuilt->new_rec_locks >= 2) {
1611
1527
rec = btr_pcur_get_rec(clust_pcur);
1644
1560
trx = thr_get_trx(thr);
1646
/* Increment fk_cascade_depth to record the recursive call depth on
1647
a single update/delete that affects multiple tables chained
1648
together with foreign key relations. */
1649
thr->fk_cascade_depth++;
1651
if (thr->fk_cascade_depth > FK_MAX_CASCADE_DEL) {
1652
return (DB_FOREIGN_EXCEED_MAX_CASCADE);
1655
1562
thr->run_node = node;
1656
1563
thr->prev_node = node;
1658
1565
row_upd_step(thr);
1660
/* The recursive call for cascading update/delete happens
1661
in above row_upd_step(), reset the counter once we come
1662
out of the recursive call, so it does not accumulate for
1663
different row deletes */
1664
thr->fk_cascade_depth = 0;
1666
1567
err = trx->error_state;
1668
1569
/* Note that the cascade node is a subnode of another InnoDB
1913
1814
thr = pars_complete_graph_for_exec(node, trx, heap);
1915
ut_a(thr == que_fork_start_command(static_cast<que_fork_t *>(que_node_get_parent(thr))));
1816
ut_a(thr == que_fork_start_command(que_node_get_parent(thr)));
1916
1817
que_run_threads(thr);
1918
1819
err = trx->error_state;
1821
if (UNIV_UNLIKELY(err != DB_SUCCESS)) {
1822
trx->error_state = DB_SUCCESS;
1823
trx_general_rollback_for_mysql(trx, NULL);
1824
/* TO DO: free table? The code below will dereference
1825
table->name, though. */
1923
1829
case DB_OUT_OF_FILE_SPACE:
1924
trx->error_state = DB_SUCCESS;
1925
trx_general_rollback_for_mysql(trx, NULL);
1927
1830
ut_print_timestamp(stderr);
1928
1831
fputs(" InnoDB: Warning: cannot create table ",
1940
1843
case DB_DUPLICATE_KEY:
1942
1844
/* We may also get err == DB_ERROR if the .ibd file for the
1943
1845
table already exists */
1945
trx->error_state = DB_SUCCESS;
1946
trx_general_rollback_for_mysql(trx, NULL);
1947
dict_mem_table_free(table);
2127
2026
name, reject_fks);
2128
2027
if (err == DB_SUCCESS) {
2129
2028
/* Check that also referencing constraints are ok */
2130
err = dict_load_foreigns(name, FALSE, TRUE);
2029
err = dict_load_foreigns(name, TRUE);
2133
2032
if (err != DB_SUCCESS) {
2326
2225
drop = UT_LIST_GET_NEXT(row_mysql_drop_list, drop);
2329
drop = static_cast<row_mysql_drop_t *>(mem_alloc(sizeof(row_mysql_drop_t)));
2228
drop = mem_alloc(sizeof(row_mysql_drop_t));
2331
2230
drop->table_name = mem_strdup(name);
2476
2375
info = pars_info_create();
2478
2377
pars_info_add_str_literal(info, "table_name", name);
2479
pars_info_add_ull_literal(info, "new_id", new_id);
2378
pars_info_add_dulint_literal(info, "new_id", new_id);
2481
2380
err = que_eval_sql(info,
2482
2381
"PROCEDURE DISCARD_TABLESPACE_PROC () IS\n"
2833
2732
dict_hdr_get_new_id(NULL, NULL, &space);
2835
/* Lock all index trees for this table. We must
2836
do so after dict_hdr_get_new_id() to preserve
2838
dict_table_x_lock_indexes(table);
2840
2734
if (space == ULINT_UNDEFINED
2841
2735
|| fil_create_new_single_table_tablespace(
2842
2736
space, table->name, FALSE, flags,
2843
2737
FIL_IBD_FILE_INITIAL_SIZE) != DB_SUCCESS) {
2844
dict_table_x_unlock_indexes(table);
2845
2738
ut_print_timestamp(stderr);
2846
2739
fprintf(stderr,
2847
2740
" InnoDB: TRUNCATE TABLE %s failed to"
2870
2763
FIL_IBD_FILE_INITIAL_SIZE, &mtr);
2871
2764
mtr_commit(&mtr);
2874
/* Lock all index trees for this table, as we will
2875
truncate the table/index and possibly change their metadata.
2876
All DML/DDL are blocked by table level lock, with
2877
a few exceptions such as queries into information schema
2878
about the table, MySQL could try to access index stats
2879
for this kind of query, we need to use index locks to
2881
dict_table_x_lock_indexes(table);
2884
2768
/* scan SYS_INDEXES for all indexes of the table */
2887
2771
tuple = dtuple_create(heap, 1);
2888
2772
dfield = dtuple_get_nth_field(tuple, 0);
2890
buf = static_cast<byte *>(mem_heap_alloc(heap, 8));
2774
buf = mem_heap_alloc(heap, 8);
2891
2775
mach_write_to_8(buf, table->id);
2893
2777
dfield_set_data(dfield, buf, 8);
2955
2839
mem_heap_free(heap);
2957
/* Done with index truncation, release index tree locks,
2958
subsequent work relates to table level metadata change */
2959
dict_table_x_unlock_indexes(table);
2961
2841
dict_hdr_get_new_id(&new_id, NULL, NULL);
2963
2843
info = pars_info_create();
2965
2845
pars_info_add_int4_literal(info, "space", (lint) table->space);
2966
pars_info_add_ull_literal(info, "old_id", table->id);
2967
pars_info_add_ull_literal(info, "new_id", new_id);
2846
pars_info_add_dulint_literal(info, "old_id", table->id);
2847
pars_info_add_dulint_literal(info, "new_id", new_id);
2969
2849
err = que_eval_sql(info,
2970
2850
"PROCEDURE RENUMBER_TABLESPACE_PROC () IS\n"
3004
2884
dict_table_autoinc_lock(table);
3005
2885
dict_table_autoinc_initialize(table, 1);
3006
2886
dict_table_autoinc_unlock(table);
3007
dict_update_statistics(table, FALSE /* update even if stats are
2887
dict_update_statistics(table);
3010
2889
trx_commit_for_mysql(trx);
3214
3093
if (table->n_foreign_key_checks_running > 0) {
3216
const char* i_table_name = table->name;
3095
const char* table_name = table->name;
3219
added = row_add_table_to_background_drop_list(i_table_name);
3098
added = row_add_table_to_background_drop_list(table_name);
3222
3101
ut_print_timestamp(stderr);
3223
3102
fputs(" InnoDB: You are trying to drop table ",
3225
ut_print_name(stderr, trx, TRUE, i_table_name);
3104
ut_print_name(stderr, trx, TRUE, table_name);
3227
3106
"InnoDB: though there is a"
3228
3107
" foreign key check running on it.\n"
3353
3232
dict_table_remove_from_cache(table);
3355
if (dict_load_table(name, TRUE) != NULL) {
3234
if (dict_load_table(name) != NULL) {
3356
3235
ut_print_timestamp(stderr);
3357
3236
fputs(" InnoDB: Error: not able to remove table ",
3498
3377
btr_pcur_store_position(&pcur, &mtr);
3499
3378
btr_pcur_commit_specify_mtr(&pcur, &mtr);
3501
table = dict_load_table(table_name, TRUE);
3380
table = dict_load_table(table_name);
3504
3383
row_drop_table_for_mysql(table_name, trx, FALSE);
4010
3889
an ALTER, not in a RENAME. */
4012
3891
err = dict_load_foreigns(
4013
new_name, FALSE, !old_is_tmp || trx->check_foreigns);
3892
new_name, !old_is_tmp || trx->check_foreigns);
4015
3894
if (err != DB_SUCCESS) {
4016
3895
ut_print_timestamp(stderr);
4196
4075
* sizeof *offsets;
4198
4077
tmp_heap = mem_heap_create(size);
4199
offsets = static_cast<ulint *>(mem_heap_dup(tmp_heap, offsets, size));
4078
offsets = mem_heap_dup(tmp_heap, offsets, size);
4202
4081
mem_heap_empty(heap);