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