104
104
index = dict_table_get_first_index(node->table);
106
106
while (index != NULL) {
107
entry = row_build_index_entry(node->row, index,
107
entry = row_build_index_entry(node->row, NULL, index,
108
108
node->entry_sys_heap);
109
109
UT_LIST_ADD_LAST(tuple_list, node->entry_list, entry);
213
213
depending on whether mtr holds just a leaf
214
214
latch or also a tree latch */
215
215
btr_cur_t* cursor, /* in: B-tree cursor */
216
dtuple_t* entry, /* in: index entry to insert */
216
const dtuple_t* entry, /* in: index entry to insert */
217
217
que_thr_t* thr, /* in: query thread */
218
mtr_t* mtr) /* in: mtr */
218
mtr_t* mtr) /* in: mtr; must be committed before
219
latching any further pages */
220
221
big_rec_t* dummy_big_rec;
221
222
mem_heap_t* heap;
279
284
depending on whether mtr holds just a leaf
280
285
latch or also a tree latch */
281
286
btr_cur_t* cursor, /* in: B-tree cursor */
287
mem_heap_t** heap, /* in/out: pointer to memory heap, or NULL */
282
288
big_rec_t** big_rec,/* out: possible big rec vector of fields
283
289
which have to be stored externally by the
285
dtuple_t* entry, /* in: index entry to insert */
286
ulint* ext_vec,/* in: array containing field numbers of
287
externally stored fields in entry, or NULL */
288
ulint n_ext_vec,/* in: number of fields in ext_vec */
291
const dtuple_t* entry, /* in: index entry to insert */
289
292
que_thr_t* thr, /* in: query thread */
290
mtr_t* mtr) /* in: mtr */
293
mtr_t* mtr) /* in: mtr; must be committed before
294
latching any further pages */
297
ut_ad(cursor->index->type & DICT_CLUSTERED);
300
ut_ad(dict_index_is_clust(cursor->index));
303
306
ut_ad(rec_get_deleted_flag(rec,
304
307
dict_table_is_comp(cursor->index->table)));
306
heap = mem_heap_create(1024);
310
*heap = mem_heap_create(1024);
308
313
/* Build an update vector containing all the fields to be modified;
309
314
NOTE that this vector may NOT contain system columns trx_id or
312
update = row_upd_build_difference_binary(cursor->index, entry, ext_vec,
314
thr_get_trx(thr), heap);
317
update = row_upd_build_difference_binary(cursor->index, entry, rec,
318
thr_get_trx(thr), *heap);
315
319
if (mode == BTR_MODIFY_LEAF) {
316
320
/* Try optimistic updating of the record, keeping changes
317
321
within the page */
319
323
err = btr_cur_optimistic_update(0, cursor, update, 0, thr,
321
if (err == DB_OVERFLOW || err == DB_UNDERFLOW) {
328
case DB_ZIP_OVERFLOW:
325
332
ut_a(mode == BTR_MODIFY_TREE);
326
333
if (buf_LRU_buf_pool_running_out()) {
328
err = DB_LOCK_TABLE_FULL;
335
return(DB_LOCK_TABLE_FULL);
332
err = btr_cur_pessimistic_update(0, cursor, big_rec, update,
338
err = btr_cur_pessimistic_update(0, cursor,
339
heap, big_rec, update,
484
490
ufield->exp = NULL;
486
492
ufield->new_val = parent_ufield->new_val;
493
ufield_len = dfield_get_len(&ufield->new_val);
495
/* Clear the "external storage" flag */
496
dfield_set_len(&ufield->new_val, ufield_len);
488
498
/* Do not allow a NOT NULL column to be
489
499
updated as NULL */
491
if (ufield->new_val.len == UNIV_SQL_NULL
501
if (dfield_is_null(&ufield->new_val)
492
502
&& (col->prtype & DATA_NOT_NULL)) {
494
504
return(ULINT_UNDEFINED);
497
507
/* If the new value would not fit in the
498
508
column, do not allow the update */
500
if (ufield->new_val.len != UNIV_SQL_NULL
510
if (!dfield_is_null(&ufield->new_val)
501
511
&& dtype_get_at_most_n_mbchars(
503
513
col->mbminlen, col->mbmaxlen,
506
ufield->new_val.data)
507
< ufield->new_val.len) {
516
dfield_get_data(&ufield->new_val))
509
519
return(ULINT_UNDEFINED);
517
527
min_size = dict_col_get_min_size(col);
520
&& ufield->new_val.len != UNIV_SQL_NULL
521
&& ufield->new_val.len < min_size) {
529
/* Because UNIV_SQL_NULL (the marker
530
of SQL NULL values) exceeds all possible
531
values of min_size, the test below will
532
not hold for SQL NULL columns. */
534
if (min_size > ufield_len) {
524
537
const char* pad_end;
525
ufield->new_val.data = mem_heap_alloc(
527
pad_start = ((char*) ufield
529
+ ufield->new_val.len;
530
pad_end = ((char*) ufield
533
ufield->new_val.len = min_size;
534
ut_memcpy(ufield->new_val.data,
535
parent_ufield->new_val.data,
536
parent_ufield->new_val.len);
541
pad_start = padded_data + ufield_len;
542
pad_end = padded_data + min_size;
545
dfield_get_data(&ufield
547
dfield_get_len(&ufield
538
550
switch (UNIV_EXPECT(col->mbminlen,1)) {
553
return(ULINT_UNDEFINED);
542
555
if (UNIV_UNLIKELY
543
556
(dtype_get_charset_coll(
545
== DATA_DRIZZLE_BINARY_CHARSET_COLL)) {
558
== DATA_MYSQL_BINARY_CHARSET_COLL)) {
546
559
/* Do not pad BINARY
548
561
return(ULINT_UNDEFINED);
615
628
que_thr_t* thr, /* in: query thread whose run_node
616
629
is an update node */
617
630
dict_foreign_t* foreign, /* in: foreign key constraint */
618
rec_t* rec, /* in: a matching index record in the
631
const rec_t* rec, /* in: a matching index record in the
620
dtuple_t* entry) /* in: index entry in the parent
633
const dtuple_t* entry) /* in: index entry in the parent
623
636
FILE* ef = dict_foreign_err_file;
669
682
/*===========================*/
670
683
trx_t* trx, /* in: transaction */
671
684
dict_foreign_t* foreign, /* in: foreign key constraint */
672
rec_t* rec, /* in: a record in the parent table:
685
const rec_t* rec, /* in: a record in the parent table:
673
686
it does not match entry because we
674
687
have an error! */
675
dtuple_t* entry) /* in: index entry to insert in the
688
const dtuple_t* entry) /* in: index entry to insert in the
678
691
FILE* ef = dict_foreign_err_file;
693
706
ut_print_name(ef, trx, FALSE, foreign->foreign_index->name);
695
708
fputs(" tuple:\n", ef);
709
/* TODO: DB_TRX_ID and DB_ROLL_PTR may be uninitialized.
710
It would be better to only display the user columns. */
696
711
dtuple_print(ef, entry);
698
713
fputs("\nBut in parent table ", ef);
704
719
/* If the cursor ended on a supremum record, it is better
705
720
to report the previous record in the error message, so that
706
721
the user gets a more descriptive error message. */
707
rec = page_rec_get_prev(rec);
722
rec = page_rec_get_prev_const(rec);
900
916
rec = btr_pcur_get_rec(pcur);
902
if (index->type & DICT_CLUSTERED) {
918
if (dict_index_is_clust(index)) {
903
919
/* pcur is already positioned in the clustered index of
904
920
the child table */
906
922
clust_index = index;
924
clust_block = btr_pcur_get_block(pcur);
909
926
/* We have to look for the record in the clustered index
910
927
in the child table */
955
973
gap if the search criterion was not unique */
957
975
err = lock_clust_rec_read_check_and_lock_alt(
958
0, clust_rec, clust_index, LOCK_X, LOCK_REC_NOT_GAP,
976
0, clust_block, clust_rec, clust_index,
977
LOCK_X, LOCK_REC_NOT_GAP, thr);
962
980
if (err != DB_SUCCESS) {
987
1005
update->n_fields = foreign->n_fields;
989
1007
for (i = 0; i < foreign->n_fields; i++) {
990
(update->fields + i)->field_no
991
= dict_table_get_nth_col_pos(
993
dict_index_get_nth_col_no(index, i));
994
(update->fields + i)->exp = NULL;
995
(update->fields + i)->new_val.len = UNIV_SQL_NULL;
996
(update->fields + i)->new_val.data = NULL;
997
(update->fields + i)->extern_storage = FALSE;
1008
upd_field_t* ufield = &update->fields[i];
1010
ufield->field_no = dict_table_get_nth_col_pos(
1012
dict_index_get_nth_col_no(index, i));
1013
ufield->orig_len = 0;
1015
dfield_set_null(&ufield->new_val);
1115
1133
row_ins_set_shared_rec_lock(
1116
1134
/*========================*/
1117
/* out: DB_SUCCESS or error code */
1118
ulint type, /* in: LOCK_ORDINARY, LOCK_GAP, or
1119
LOCK_REC_NOT_GAP type lock */
1120
rec_t* rec, /* in: record */
1121
dict_index_t* index, /* in: index */
1122
const ulint* offsets,/* in: rec_get_offsets(rec, index) */
1123
que_thr_t* thr) /* in: query thread */
1135
/* out: DB_SUCCESS or error code */
1136
ulint type, /* in: LOCK_ORDINARY, LOCK_GAP, or
1137
LOCK_REC_NOT_GAP type lock */
1138
const buf_block_t* block, /* in: buffer block of rec */
1139
const rec_t* rec, /* in: record */
1140
dict_index_t* index, /* in: index */
1141
const ulint* offsets,/* in: rec_get_offsets(rec, index) */
1142
que_thr_t* thr) /* in: query thread */
1127
1146
ut_ad(rec_offs_validate(rec, index, offsets));
1129
if (index->type & DICT_CLUSTERED) {
1148
if (dict_index_is_clust(index)) {
1130
1149
err = lock_clust_rec_read_check_and_lock(
1131
0, rec, index, offsets, LOCK_S, type, thr);
1150
0, block, rec, index, offsets, LOCK_S, type, thr);
1133
1152
err = lock_sec_rec_read_check_and_lock(
1134
0, rec, index, offsets, LOCK_S, type, thr);
1153
0, block, rec, index, offsets, LOCK_S, type, thr);
1146
1165
row_ins_set_exclusive_rec_lock(
1147
1166
/*===========================*/
1148
/* out: DB_SUCCESS or error code */
1149
ulint type, /* in: LOCK_ORDINARY, LOCK_GAP, or
1150
LOCK_REC_NOT_GAP type lock */
1151
rec_t* rec, /* in: record */
1152
dict_index_t* index, /* in: index */
1153
const ulint* offsets,/* in: rec_get_offsets(rec, index) */
1154
que_thr_t* thr) /* in: query thread */
1167
/* out: DB_SUCCESS or error code */
1168
ulint type, /* in: LOCK_ORDINARY, LOCK_GAP, or
1169
LOCK_REC_NOT_GAP type lock */
1170
const buf_block_t* block, /* in: buffer block of rec */
1171
const rec_t* rec, /* in: record */
1172
dict_index_t* index, /* in: index */
1173
const ulint* offsets,/* in: rec_get_offsets(rec, index) */
1174
que_thr_t* thr) /* in: query thread */
1158
1178
ut_ad(rec_offs_validate(rec, index, offsets));
1160
if (index->type & DICT_CLUSTERED) {
1180
if (dict_index_is_clust(index)) {
1161
1181
err = lock_clust_rec_read_check_and_lock(
1162
0, rec, index, offsets, LOCK_X, type, thr);
1182
0, block, rec, index, offsets, LOCK_X, type, thr);
1164
1184
err = lock_sec_rec_read_check_and_lock(
1165
0, rec, index, offsets, LOCK_X, type, thr);
1185
0, block, rec, index, offsets, LOCK_X, type, thr);
1342
1362
if (page_rec_is_supremum(rec)) {
1344
err = row_ins_set_shared_rec_lock(
1345
LOCK_ORDINARY, rec, check_index, offsets, thr);
1364
err = row_ins_set_shared_rec_lock(LOCK_ORDINARY, block,
1346
1367
if (err != DB_SUCCESS) {
1357
1378
if (rec_get_deleted_flag(rec,
1358
1379
rec_offs_comp(offsets))) {
1359
1380
err = row_ins_set_shared_rec_lock(
1360
LOCK_ORDINARY, rec, check_index,
1381
LOCK_ORDINARY, block,
1382
rec, check_index, offsets, thr);
1362
1383
if (err != DB_SUCCESS) {
1423
1449
err = row_ins_set_shared_rec_lock(
1424
LOCK_GAP, rec, check_index, offsets, thr);
1451
rec, check_index, offsets, thr);
1425
1452
if (err != DB_SUCCESS) {
1577
1604
row_ins_dupl_error_with_rec(
1578
1605
/*========================*/
1579
1606
/* out: TRUE if error */
1580
rec_t* rec, /* in: user record; NOTE that we assume
1607
const rec_t* rec, /* in: user record; NOTE that we assume
1581
1608
that the caller already has a record lock on
1583
dtuple_t* entry, /* in: entry to insert */
1610
const dtuple_t* entry, /* in: entry to insert */
1584
1611
dict_index_t* index, /* in: index */
1585
1612
const ulint* offsets)/* in: rec_get_offsets(rec, index) */
1681
1706
/* Scan index records and check if there is a duplicate */
1684
rec = btr_pcur_get_rec(&pcur);
1709
const rec_t* rec = btr_pcur_get_rec(&pcur);
1710
const buf_block_t* block = btr_pcur_get_block(&pcur);
1686
1712
if (page_rec_is_infimum(rec)) {
1691
1717
offsets = rec_get_offsets(rec, index, offsets,
1699
1725
INSERT ON DUPLICATE KEY UPDATE). */
1701
1727
err = row_ins_set_exclusive_rec_lock(
1702
LOCK_ORDINARY, rec, index, offsets, thr);
1728
LOCK_ORDINARY, block,
1729
rec, index, offsets, thr);
1705
1732
err = row_ins_set_shared_rec_lock(
1706
LOCK_ORDINARY, rec, index, offsets, thr);
1733
LOCK_ORDINARY, block,
1734
rec, index, offsets, thr);
1709
1737
if (err != DB_SUCCESS) {
1785
1807
mem_heap_t*heap = NULL;
1786
1808
ulint offsets_[REC_OFFS_NORMAL_SIZE];
1787
1809
ulint* offsets = offsets_;
1788
*offsets_ = (sizeof offsets_) / sizeof *offsets_;
1810
rec_offs_init(offsets_);
1790
1812
UT_NOT_USED(mtr);
1792
ut_a(cursor->index->type & DICT_CLUSTERED);
1793
ut_ad(cursor->index->type & DICT_UNIQUE);
1814
ut_a(dict_index_is_clust(cursor->index));
1815
ut_ad(dict_index_is_unique(cursor->index));
1795
1817
/* NOTE: For unique non-clustered indexes there may be any number
1796
1818
of delete marked records with the same value for the non-clustered
1828
1850
INSERT ON DUPLICATE KEY UPDATE). */
1830
1852
err = row_ins_set_exclusive_rec_lock(
1831
LOCK_REC_NOT_GAP, rec,
1832
cursor->index, offsets, thr);
1854
btr_cur_get_block(cursor),
1855
rec, cursor->index, offsets, thr);
1835
1858
err = row_ins_set_shared_rec_lock(
1836
LOCK_REC_NOT_GAP, rec,
1860
btr_cur_get_block(cursor), rec,
1837
1861
cursor->index, offsets, thr);
1866
1890
INSERT ON DUPLICATE KEY UPDATE). */
1868
1892
err = row_ins_set_exclusive_rec_lock(
1869
LOCK_REC_NOT_GAP, rec,
1870
cursor->index, offsets, thr);
1894
btr_cur_get_block(cursor),
1895
rec, cursor->index, offsets, thr);
1873
1898
err = row_ins_set_shared_rec_lock(
1874
LOCK_REC_NOT_GAP, rec,
1875
cursor->index, offsets, thr);
1900
btr_cur_get_block(cursor),
1901
rec, cursor->index, offsets, thr);
1878
1904
if (err != DB_SUCCESS) {
1968
1994
pessimistic descent down the index tree */
1969
1995
dict_index_t* index, /* in: index */
1970
1996
dtuple_t* entry, /* in: index entry to insert */
1971
ulint* ext_vec,/* in: array containing field numbers of
1972
externally stored fields in entry, or NULL */
1973
ulint n_ext_vec,/* in: number of fields in ext_vec */
1997
ulint n_ext, /* in: number of externally stored columns */
1974
1998
que_thr_t* thr) /* in: query thread */
1976
2000
btr_cur_t cursor;
2020
2041
rec_t* first_rec = page_rec_get_next(
2021
2042
page_get_infimum_rec(page));
2023
if (UNIV_LIKELY(first_rec != page_get_supremum_rec(page))) {
2024
ut_a(rec_get_n_fields(first_rec, index)
2025
== dtuple_get_n_fields(entry));
2044
ut_ad(page_rec_is_supremum(first_rec)
2045
|| rec_get_n_fields(first_rec, index)
2046
== dtuple_get_n_fields(entry));
2030
2050
n_unique = dict_index_get_n_unique(index);
2032
if (index->type & DICT_UNIQUE && (cursor.up_match >= n_unique
2033
|| cursor.low_match >= n_unique)) {
2052
if (dict_index_is_unique(index) && (cursor.up_match >= n_unique
2053
|| cursor.low_match >= n_unique)) {
2035
if (index->type & DICT_CLUSTERED) {
2055
if (dict_index_is_clust(index)) {
2036
2056
/* Note that the following may return also
2037
2057
DB_LOCK_WAIT */
2076
2096
if (modify == ROW_INS_NEXT) {
2077
2097
rec = page_rec_get_next(btr_cur_get_rec(&cursor));
2079
btr_cur_position(index, rec, &cursor);
2099
btr_cur_position(index, rec,
2100
btr_cur_get_block(&cursor),&cursor);
2082
if (index->type & DICT_CLUSTERED) {
2103
if (dict_index_is_clust(index)) {
2083
2104
err = row_ins_clust_index_entry_by_modify(
2084
mode, &cursor, &big_rec, entry,
2085
ext_vec, n_ext_vec, thr, &mtr);
2105
mode, &cursor, &heap, &big_rec, entry,
2087
2109
err = row_ins_sec_index_entry_by_modify(
2088
2110
mode, &cursor, entry, thr, &mtr);
2092
2113
if (mode == BTR_MODIFY_LEAF) {
2093
2114
err = btr_cur_optimistic_insert(
2094
2115
0, &cursor, entry, &insert_rec, &big_rec,
2097
2118
ut_a(mode == BTR_MODIFY_TREE);
2098
2119
if (buf_LRU_buf_pool_running_out()) {
2104
2125
err = btr_cur_pessimistic_insert(
2105
2126
0, &cursor, entry, &insert_rec, &big_rec,
2109
if (err == DB_SUCCESS) {
2111
rec_set_field_extern_bits(insert_rec, index,
2119
2132
mtr_commit(&mtr);
2134
if (UNIV_LIKELY_NULL(big_rec)) {
2123
2137
mtr_start(&mtr);
2125
2139
btr_cur_search_to_nth_level(index, 0, entry, PAGE_CUR_LE,
2126
2140
BTR_MODIFY_TREE, &cursor, 0, &mtr);
2127
2141
rec = btr_cur_get_rec(&cursor);
2128
offsets = rec_get_offsets(rec, index, offsets,
2142
offsets = rec_get_offsets(rec, index, NULL,
2129
2143
ULINT_UNDEFINED, &heap);
2131
err = btr_store_big_rec_extern_fields(index, rec,
2132
offsets, big_rec, &mtr);
2145
err = btr_store_big_rec_extern_fields(
2146
index, btr_cur_get_block(&cursor),
2147
rec, offsets, big_rec, &mtr);
2135
2150
dtuple_big_rec_free(big_rec);
2159
2174
DB_DUPLICATE_KEY, or some other error code */
2160
2175
dict_index_t* index, /* in: index */
2161
2176
dtuple_t* entry, /* in: index entry to insert */
2162
ulint* ext_vec,/* in: array containing field numbers of
2163
externally stored fields in entry, or NULL */
2164
ulint n_ext_vec,/* in: number of fields in ext_vec */
2177
ulint n_ext, /* in: number of externally stored columns */
2178
ibool foreign,/* in: TRUE=check foreign key constraints */
2165
2179
que_thr_t* thr) /* in: query thread */
2169
if (UT_LIST_GET_FIRST(index->table->foreign_list)) {
2183
if (foreign && UT_LIST_GET_FIRST(index->table->foreign_list)) {
2170
2184
err = row_ins_check_foreign_constraints(index->table, index,
2172
2186
if (err != DB_SUCCESS) {
2200
2214
/*=========================*/
2201
2215
dict_index_t* index, /* in: index */
2202
2216
dtuple_t* entry, /* in: index entry to make */
2203
dtuple_t* row) /* in: row */
2217
const dtuple_t* row) /* in: row */
2205
dict_field_t* ind_field;
2207
dfield_t* row_field;
2211
2222
ut_ad(entry && row);
2213
2224
n_fields = dtuple_get_n_fields(entry);
2215
2226
for (i = 0; i < n_fields; i++) {
2227
dict_field_t* ind_field;
2229
const dfield_t* row_field;
2216
2232
field = dtuple_get_nth_field(entry, i);
2217
2233
ind_field = dict_index_get_nth_field(index, i);
2219
2234
row_field = dtuple_get_nth_field(row, ind_field->col->ind);
2235
len = dfield_get_len(row_field);
2221
2237
/* Check column prefix indexes */
2222
2238
if (ind_field->prefix_len > 0
2225
2241
const dict_col_t* col
2226
2242
= dict_field_get_col(ind_field);
2228
field->len = dtype_get_at_most_n_mbchars(
2244
len = dtype_get_at_most_n_mbchars(
2229
2245
col->prtype, col->mbminlen, col->mbmaxlen,
2230
2246
ind_field->prefix_len,
2231
row_field->len, row_field->data);
2233
field->len = row_field->len;
2236
field->data = row_field->data;
2247
len, dfield_get_data(row_field));
2249
ut_ad(!dfield_is_ext(row_field));
2252
dfield_set_data(field, dfield_get_data(row_field), len);
2253
if (dfield_is_ext(row_field)) {
2254
ut_ad(dict_index_is_clust(index));
2255
dfield_set_ext(field);
2257
2277
ut_ad(dtuple_check_typed(node->entry));
2259
err = row_ins_index_entry(node->index, node->entry, NULL, 0, thr);
2279
err = row_ins_index_entry(node->index, node->entry, 0, TRUE, thr);