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