1
1
/*****************************************************************************
3
Copyright (c) 1996, 2010, Innobase Oy. All Rights Reserved.
3
Copyright (C) 1996, 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
51
51
#define ROW_INS_PREV 1
52
52
#define ROW_INS_NEXT 2
54
/*************************************************************************
55
IMPORTANT NOTE: Any operation that generates redo MUST check that there
56
is enough space in the redo log before for that operation. This is
57
done by calling log_free_check(). The reason for checking the
58
availability of the redo log space before the start of the operation is
59
that we MUST not hold any synchonization objects when performing the
61
If you make a change in this module make sure that no codepath is
62
introduced where a call to log_free_check() is bypassed. */
55
64
/*********************************************************************//**
56
65
Creates an insert node struct.
142
151
dfield = dtuple_get_nth_field(row, dict_col_get_no(col));
144
ptr = mem_heap_zalloc(heap, DATA_ROW_ID_LEN);
153
ptr = static_cast<byte *>(mem_heap_zalloc(heap, DATA_ROW_ID_LEN));
146
155
dfield_set_data(dfield, ptr, DATA_ROW_ID_LEN);
152
161
col = dict_table_get_sys_col(table, DATA_TRX_ID);
154
163
dfield = dtuple_get_nth_field(row, dict_col_get_no(col));
155
ptr = mem_heap_zalloc(heap, DATA_TRX_ID_LEN);
164
ptr = static_cast<byte *>(mem_heap_zalloc(heap, DATA_TRX_ID_LEN));
157
166
dfield_set_data(dfield, ptr, DATA_TRX_ID_LEN);
163
172
col = dict_table_get_sys_col(table, DATA_ROLL_PTR);
165
174
dfield = dtuple_get_nth_field(row, dict_col_get_no(col));
166
ptr = mem_heap_zalloc(heap, DATA_ROLL_PTR_LEN);
175
ptr = static_cast<byte *>(mem_heap_zalloc(heap, DATA_ROLL_PTR_LEN));
168
177
dfield_set_data(dfield, ptr, DATA_ROLL_PTR_LEN);
507
516
if (!dfield_is_null(&ufield->new_val)
508
517
&& dtype_get_at_most_n_mbchars(
510
col->mbminlen, col->mbmaxlen,
518
col->prtype, col->mbminmaxlen,
513
dfield_get_data(&ufield->new_val))
521
static_cast<const char *>(dfield_get_data(&ufield->new_val)))
516
524
return(ULINT_UNDEFINED);
531
539
if (min_size > ufield_len) {
538
pad_start = padded_data + ufield_len;
539
pad_end = padded_data + min_size;
546
padded_data = static_cast<unsigned char *>(mem_heap_alloc(
549
pad = padded_data + ufield_len;
550
pad_len = min_size - ufield_len;
541
552
memcpy(padded_data,
542
553
dfield_get_data(&ufield
544
dfield_get_len(&ufield
547
switch (UNIV_EXPECT(col->mbminlen,1)) {
557
mbminlen = dict_col_get_mbminlen(col);
559
ut_ad(!(ufield_len % mbminlen));
560
ut_ad(!(min_size % mbminlen));
563
&& dtype_get_charset_coll(
565
== DATA_MYSQL_BINARY_CHARSET_COLL) {
566
/* Do not pad BINARY columns */
550
567
return(ULINT_UNDEFINED);
553
(dtype_get_charset_coll(
555
== DATA_MYSQL_BINARY_CHARSET_COLL)) {
558
return(ULINT_UNDEFINED);
562
memset(pad_start, 0x20,
563
pad_end - pad_start);
567
ut_a(!(ufield_len % 2));
568
ut_a(!(min_size % 2));
572
} while (pad_start < pad_end);
570
row_mysql_pad_col(mbminlen,
576
572
dfield_set_data(&ufield->new_val,
577
573
padded_data, min_size);
806
802
row_ins_invalidate_query_cache(thr, table->name);
808
node = thr->run_node;
804
node = static_cast<upd_node_t *>(thr->run_node);
810
806
if (node->is_delete && 0 == (foreign->type
811
807
& (DICT_FOREIGN_ON_DELETE_CASCADE
1122
1118
/*********************************************************************//**
1123
1119
Sets a shared lock on a record. Used in locking possible duplicate key
1124
1120
records and also in checking foreign key constraints.
1125
@return DB_SUCCESS or error code */
1121
@return DB_SUCCESS, DB_SUCCESS_LOCKED_REC, or error code */
1128
1124
row_ins_set_shared_rec_lock(
1129
1125
/*========================*/
1130
1126
ulint type, /*!< in: LOCK_ORDINARY, LOCK_GAP, or
1135
1131
const ulint* offsets,/*!< in: rec_get_offsets(rec, index) */
1136
1132
que_thr_t* thr) /*!< in: query thread */
1140
1136
ut_ad(rec_offs_validate(rec, index, offsets));
1153
1149
/*********************************************************************//**
1154
1150
Sets a exclusive lock on a record. Used in locking possible duplicate key
1156
@return DB_SUCCESS or error code */
1152
@return DB_SUCCESS, DB_SUCCESS_LOCKED_REC, or error code */
1159
1155
row_ins_set_exclusive_rec_lock(
1160
1156
/*===========================*/
1161
1157
ulint type, /*!< in: LOCK_ORDINARY, LOCK_GAP, or
1166
1162
const ulint* offsets,/*!< in: rec_get_offsets(rec, index) */
1167
1163
que_thr_t* thr) /*!< in: query thread */
1171
1167
ut_ad(rec_offs_validate(rec, index, offsets));
1245
1240
if (que_node_get_type(thr->run_node) == QUE_NODE_UPDATE) {
1246
upd_node = thr->run_node;
1241
upd_node = static_cast<upd_node_t *>(thr->run_node);
1248
1243
if (!(upd_node->is_delete) && upd_node->foreign == foreign) {
1249
1244
/* If a cascaded update is done as defined by a
1338
1333
/* Scan index records and check if there is a matching record */
1341
1336
const rec_t* rec = btr_pcur_get_rec(&pcur);
1342
1337
const buf_block_t* block = btr_pcur_get_block(&pcur);
1344
1339
if (page_rec_is_infimum(rec)) {
1349
1344
offsets = rec_get_offsets(rec, check_index,
1354
1349
err = row_ins_set_shared_rec_lock(LOCK_ORDINARY, block,
1355
1350
rec, check_index,
1357
if (err != DB_SUCCESS) {
1353
case DB_SUCCESS_LOCKED_REC:
1365
1361
cmp = cmp_dtuple_rec(entry, rec, offsets);
1370
1366
err = row_ins_set_shared_rec_lock(
1371
1367
LOCK_ORDINARY, block,
1372
1368
rec, check_index, offsets, thr);
1373
if (err != DB_SUCCESS) {
1370
case DB_SUCCESS_LOCKED_REC:
1378
1377
/* Found a matching record. Lock only
1383
1382
LOCK_REC_NOT_GAP, block,
1384
1383
rec, check_index, offsets, thr);
1386
if (err != DB_SUCCESS) {
1386
case DB_SUCCESS_LOCKED_REC:
1391
1393
if (check_ref) {
1392
1394
err = DB_SUCCESS;
1395
1397
} else if (foreign->type != 0) {
1396
1398
/* There is an ON UPDATE or ON DELETE
1397
1399
condition: check them in a separate
1430
1432
thr, foreign, rec, entry);
1432
1434
err = DB_ROW_IS_REFERENCED;
1439
1441
err = row_ins_set_shared_rec_lock(
1440
1442
LOCK_GAP, block,
1441
1443
rec, check_index, offsets, thr);
1442
if (err != DB_SUCCESS) {
1448
err = DB_NO_REFERENCED_ROW;
1449
row_ins_foreign_report_add_err(
1450
trx, foreign, rec, entry);
1460
moved = btr_pcur_move_to_next(&pcur, &mtr);
1464
rec = btr_pcur_get_rec(&pcur);
1465
row_ins_foreign_report_add_err(
1466
trx, foreign, rec, entry);
1467
err = DB_NO_REFERENCED_ROW;
1446
case DB_SUCCESS_LOCKED_REC:
1449
err = DB_NO_REFERENCED_ROW;
1450
row_ins_foreign_report_add_err(
1451
trx, foreign, rec, entry);
1459
} while (btr_pcur_move_to_next(&pcur, &mtr));
1462
row_ins_foreign_report_add_err(
1463
trx, foreign, btr_pcur_get_rec(&pcur), entry);
1464
err = DB_NO_REFERENCED_ROW;
1476
1470
btr_pcur_close(&pcur);
1478
1472
mtr_commit(&mtr);
1773
1769
row_ins_duplicate_error_in_clust(
1774
1770
/*=============================*/
1775
1771
btr_cur_t* cursor, /*!< in: B-tree cursor */
1776
dtuple_t* entry, /*!< in: entry to insert */
1772
const dtuple_t* entry, /*!< in: entry to insert */
1777
1773
que_thr_t* thr, /*!< in: query thread */
1778
1774
mtr_t* mtr) /*!< in: mtr */
1961
1965
depending on whether we wish optimistic or
1962
1966
pessimistic descent down the index tree */
1963
1967
dict_index_t* index, /*!< in: index */
1964
dtuple_t* entry, /*!< in: index entry to insert */
1968
dtuple_t* entry, /*!< in/out: index entry to insert */
1965
1969
ulint n_ext, /*!< in: number of externally stored columns */
1966
1970
que_thr_t* thr) /*!< in: query thread */
1968
1972
btr_cur_t cursor;
1969
ulint ignore_sec_unique = 0;
1970
1974
ulint modify = 0; /* remove warning */
1971
1975
rec_t* insert_rec;
1986
1990
the function will return in both low_match and up_match of the
1987
1991
cursor sensible values */
1989
if (!(thr_get_trx(thr)->check_unique_secondary)) {
1990
ignore_sec_unique = BTR_IGNORE_SEC_UNIQUE;
1993
if (dict_index_is_clust(index)) {
1995
} else if (!(thr_get_trx(thr)->check_unique_secondary)) {
1996
search_mode = mode | BTR_INSERT | BTR_IGNORE_SEC_UNIQUE;
1998
search_mode = mode | BTR_INSERT;
1993
2001
btr_cur_search_to_nth_level(index, 0, entry, PAGE_CUR_LE,
1994
mode | BTR_INSERT | ignore_sec_unique,
1995
2003
&cursor, 0, __FILE__, __LINE__, &mtr);
1997
2005
if (cursor.flag == BTR_CUR_INSERT_TO_IBUF) {
1998
2006
/* The insertion was made to the insert buffer already during
1999
2007
the search: we are done */
2009
ut_ad(search_mode & BTR_INSERT);
2001
2010
err = DB_SUCCESS;
2003
2012
goto function_exit;
2101
2110
mtr_commit(&mtr);
2103
2112
if (UNIV_LIKELY_NULL(big_rec)) {
2105
2114
ulint* offsets;
2106
2115
mtr_start(&mtr);
2108
2117
btr_cur_search_to_nth_level(index, 0, entry, PAGE_CUR_LE,
2109
2118
BTR_MODIFY_TREE, &cursor, 0,
2110
2119
__FILE__, __LINE__, &mtr);
2111
rec = btr_cur_get_rec(&cursor);
2112
offsets = rec_get_offsets(rec, index, NULL,
2120
exit_rec = btr_cur_get_rec(&cursor);
2121
offsets = rec_get_offsets(exit_rec, index, NULL,
2113
2122
ULINT_UNDEFINED, &heap);
2115
2124
err = btr_store_big_rec_extern_fields(
2116
2125
index, btr_cur_get_block(&cursor),
2117
rec, offsets, big_rec, &mtr);
2126
exit_rec, offsets, big_rec, &mtr);
2120
2129
dtuple_big_rec_free(big_rec);
2142
2151
row_ins_index_entry(
2143
2152
/*================*/
2144
2153
dict_index_t* index, /*!< in: index */
2145
dtuple_t* entry, /*!< in: index entry to insert */
2154
dtuple_t* entry, /*!< in/out: index entry to insert */
2146
2155
ulint n_ext, /*!< in: number of externally stored columns */
2147
ibool foreign,/*!< in: TRUE=check foreign key constraints */
2156
ibool foreign,/*!< in: TRUE=check foreign key constraints
2157
(foreign=FALSE only during CREATE INDEX) */
2148
2158
que_thr_t* thr) /*!< in: query thread */
2152
2162
if (foreign && UT_LIST_GET_FIRST(index->table->foreign_list)) {
2153
err = row_ins_check_foreign_constraints(index->table, index,
2163
err = static_cast<db_err>(row_ins_check_foreign_constraints(index->table, index,
2155
2165
if (err != DB_SUCCESS) {
2161
2171
/* Try first optimistic descent to the B-tree */
2163
err = row_ins_index_entry_low(BTR_MODIFY_LEAF, index, entry,
2173
err = static_cast<db_err>(row_ins_index_entry_low(BTR_MODIFY_LEAF, index, entry,
2165
2175
if (err != DB_FAIL) {
2170
2180
/* Try then pessimistic descent to the B-tree */
2172
err = row_ins_index_entry_low(BTR_MODIFY_TREE, index, entry,
2182
err = static_cast<db_err>(row_ins_index_entry_low(BTR_MODIFY_TREE, index, entry,
2211
2221
= dict_field_get_col(ind_field);
2213
2223
len = dtype_get_at_most_n_mbchars(
2214
col->prtype, col->mbminlen, col->mbmaxlen,
2224
col->prtype, col->mbminmaxlen,
2215
2225
ind_field->prefix_len,
2216
len, dfield_get_data(row_field));
2226
len, static_cast<const char *>(dfield_get_data(row_field)));
2218
2228
ut_ad(!dfield_is_ext(row_field));
2246
2256
ut_ad(dtuple_check_typed(node->entry));
2248
err = row_ins_index_entry(node->index, node->entry, 0, TRUE, thr);
2258
err = static_cast<db_err>(row_ins_index_entry(node->index, node->entry, 0, TRUE, thr));
2445
2455
/* It may be that the current session has not yet started
2446
2456
its transaction, or it has been committed: */
2448
if (UT_DULINT_EQ(trx->id, node->trx_id)) {
2458
if (trx->id == node->trx_id) {
2449
2459
/* No need to do IX-locking */