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
92
92
searched delete is obviously to keep the x-latch for several
93
93
steps of query graph execution. */
95
/*************************************************************************
96
IMPORTANT NOTE: Any operation that generates redo MUST check that there
97
is enough space in the redo log before for that operation. This is
98
done by calling log_free_check(). The reason for checking the
99
availability of the redo log space before the start of the operation is
100
that we MUST not hold any synchonization objects when performing the
102
If you make a change in this module make sure that no codepath is
103
introduced where a call to log_free_check() is bypassed. */
105
/*************************************************************************
106
IMPORTANT NOTE: Any operation that generates redo MUST check that there
107
is enough space in the redo log before for that operation. This is
108
done by calling log_free_check(). The reason for checking the
109
availability of the redo log space before the start of the operation is
110
that we MUST not hold any synchonization objects when performing the
112
If you make a change in this module make sure that no codepath is
113
introduced where a call to log_free_check() is bypassed. */
115
95
/***********************************************************//**
116
96
Checks if an update vector changes some of the first ordering fields of an
117
97
index record. This is only used in foreign key checks and we can assume
314
294
upd_node_t* node;
316
node = static_cast<upd_node_t *>(mem_heap_alloc(heap, sizeof(upd_node_t)));
296
node = mem_heap_alloc(heap, sizeof(upd_node_t));
317
297
node->common.type = QUE_NODE_UPDATE;
319
299
node->state = UPD_NODE_UPDATE_CLUSTERED;
382
362
row_upd_index_entry_sys_field(
383
363
/*==========================*/
384
dtuple_t* entry, /*!< in/out: index entry, where the memory
385
buffers for sys fields are already allocated:
364
const dtuple_t* entry, /*!< in: index entry, where the memory buffers
365
for sys fields are already allocated:
386
366
the function just copies the new values to
388
368
dict_index_t* index, /*!< in: clustered index */
389
369
ulint type, /*!< in: DATA_TRX_ID or DATA_ROLL_PTR */
390
ib_uint64_t val) /*!< in: value to write */
370
dulint val) /*!< in: value to write */
392
372
dfield_t* dfield;
398
378
pos = dict_index_get_sys_col_pos(index, type);
400
380
dfield = dtuple_get_nth_field(entry, pos);
401
field = static_cast<byte *>(dfield_get_data(dfield));
381
field = dfield_get_data(dfield);
403
383
if (type == DATA_TRX_ID) {
404
384
trx_write_trx_id(field, val);
476
456
#endif /* !UNIV_HOTBACKUP */
478
458
/***********************************************************//**
479
Replaces the new column values stored in the update vector to the
480
record given. No field size changes are allowed. This function is
481
usually invoked on a clustered index. The only use case for a
482
secondary index is row_ins_sec_index_entry_by_modify() or its
483
counterpart in ibuf_insert_to_index_page(). */
459
Replaces the new column values stored in the update vector to the record
460
given. No field size changes are allowed. */
486
463
row_upd_rec_in_place(
537
514
roll_ptr_t roll_ptr,/*!< in: roll ptr of the undo log record */
538
515
byte* log_ptr,/*!< pointer to a buffer of size > 20 opened
540
mtr_t* /*mtr __attribute__((unused))*/) /*!< in: mtr */
517
mtr_t* mtr __attribute__((unused))) /*!< in: mtr */
542
519
ut_ad(dict_index_is_clust(index));
549
526
trx_write_roll_ptr(log_ptr, roll_ptr);
550
527
log_ptr += DATA_ROLL_PTR_LEN;
552
log_ptr += mach_ull_write_compressed(log_ptr, trx->id);
529
log_ptr += mach_dulint_write_compressed(log_ptr, trx->id);
583
560
*roll_ptr = trx_read_roll_ptr(ptr);
584
561
ptr += DATA_ROLL_PTR_LEN;
586
ptr = mach_ull_parse_compressed(ptr, end_ptr, trx_id);
563
ptr = mach_dulint_parse_compressed(ptr, end_ptr, trx_id);
648
625
mlog_close(mtr, log_ptr);
650
627
mlog_catenate_string(mtr,
651
static_cast<byte *>(dfield_get_data(new_val)),
628
dfield_get_data(new_val),
654
631
log_ptr = mlog_open(mtr, MLOG_BUF_MARGIN);
907
884
out: fetched length of the prefix */
908
885
mem_heap_t* heap) /*!< in: heap where to allocate */
910
byte* buf = static_cast<byte *>(mem_heap_alloc(heap, *len));
887
byte* buf = mem_heap_alloc(heap, *len);
912
889
*len = btr_copy_externally_stored_field_prefix(buf, *len,
947
924
len = dfield_get_len(dfield);
948
data = static_cast<const byte *>(dfield_get_data(dfield));
925
data = dfield_get_data(dfield);
950
927
if (field->prefix_len > 0) {
951
928
ibool fetch_ext = dfield_is_ext(dfield)
996
973
stored part of the column. The data
997
974
will have to be copied. */
998
975
ut_a(uf->orig_len > BTR_EXTERN_FIELD_REF_SIZE);
999
buf = static_cast<byte *>(mem_heap_alloc(heap, uf->orig_len));
976
buf = mem_heap_alloc(heap, uf->orig_len);
1000
977
/* Copy the locally stored prefix. */
1001
978
memcpy(buf, data,
1002
979
uf->orig_len - BTR_EXTERN_FIELD_REF_SIZE);
1146
1123
table = index->table;
1147
1124
ut_ad(n_cols == dict_table_get_n_cols(table));
1149
ext_cols = static_cast<ulint *>(mem_heap_alloc(heap, n_cols * sizeof *ext_cols));
1126
ext_cols = mem_heap_alloc(heap, n_cols * sizeof *ext_cols);
1150
1127
n_ext_cols = 0;
1152
1129
dtuple_set_info_bits(row, update->info_bits);
1367
1344
data = rec_get_nth_field(rec, offsets,
1368
1345
column->field_nos[SYM_CLUST_FIELD_NO],
1347
if (len == UNIV_SQL_NULL) {
1348
len = UNIV_SQL_NULL;
1370
1350
eval_node_copy_and_alloc_val(column, data, len);
1372
1352
column = UT_LIST_GET_NEXT(col_var_list, column);
1429
1408
offsets = rec_get_offsets(rec, clust_index, offsets_,
1430
1409
ULINT_UNDEFINED, &heap);
1432
if (dict_table_get_format(node->table) >= DICT_TF_FORMAT_ZIP) {
1433
/* In DYNAMIC or COMPRESSED format, there is no prefix
1434
of externally stored columns in the clustered index
1435
record. Build a cache of column prefixes. */
1438
/* REDUNDANT and COMPACT formats store a local
1439
768-byte prefix of each externally stored column.
1440
No cache is needed. */
1445
1410
node->row = row_build(ROW_COPY_DATA, clust_index, rec, offsets,
1446
NULL, ext, node->heap);
1411
NULL, &node->ext, node->heap);
1447
1412
if (node->is_delete) {
1448
1413
node->upd_row = NULL;
1449
1414
node->upd_ext = NULL;
1469
1434
upd_node_t* node, /*!< in: row update node */
1470
1435
que_thr_t* thr) /*!< in: query thread */
1477
dict_index_t* index;
1480
ulint err = DB_SUCCESS;
1481
trx_t* trx = thr_get_trx(thr);
1482
ulint mode = BTR_MODIFY_LEAF;
1483
enum row_search_result search_result;
1439
dict_index_t* index;
1445
ulint err = DB_SUCCESS;
1447
trx_t* trx = thr_get_trx(thr);
1485
1449
index = node->index;
1487
referenced = row_upd_index_is_referenced(index, trx);
1451
check_ref = row_upd_index_is_referenced(index, trx);
1489
1453
heap = mem_heap_create(1024);
1492
1456
entry = row_build_index_entry(node->row, node->ext, index, heap);
1495
1460
mtr_start(&mtr);
1497
/* Set the query thread, so that ibuf_insert_low() will be
1498
able to invoke thd_get_trx(). */
1499
btr_pcur_get_btr_cur(&pcur)->thr = thr;
1501
/* We can only try to use the insert/delete buffer to buffer
1502
delete-mark operations if the index we're modifying has no foreign
1503
key constraints referring to it. */
1505
mode |= BTR_DELETE_MARK;
1508
search_result = row_search_index_entry(index, entry, mode,
1462
found = row_search_index_entry(index, entry, BTR_MODIFY_LEAF, &pcur,
1511
1464
btr_cur = btr_pcur_get_btr_cur(&pcur);
1513
1466
rec = btr_cur_get_rec(btr_cur);
1515
switch (search_result) {
1516
case ROW_NOT_DELETED_REF: /* should only occur for BTR_DELETE */
1520
/* Entry was delete marked already. */
1468
if (UNIV_UNLIKELY(!found)) {
1524
1469
fputs("InnoDB: error in sec index entry update in\n"
1525
1470
"InnoDB: ", stderr);
1526
1471
dict_index_name_print(stderr, trx, index);
1538
1483
"InnoDB: Submit a detailed bug report"
1539
1484
" to http://bugs.mysql.com\n", stderr);
1542
1486
/* Delete mark the old index record; it can already be
1543
1487
delete marked if we return after a lock wait in
1544
1488
row_ins_index_entry below */
1546
if (!rec_get_deleted_flag(
1547
rec, dict_table_is_comp(index->table))) {
1549
err = btr_cur_del_mark_set_sec_rec(
1550
0, btr_cur, TRUE, thr, &mtr);
1552
if (err == DB_SUCCESS && referenced) {
1556
offsets = rec_get_offsets(
1557
rec, index, NULL, ULINT_UNDEFINED,
1490
if (!rec_get_deleted_flag(rec,
1491
dict_table_is_comp(index->table))) {
1492
err = btr_cur_del_mark_set_sec_rec(0, btr_cur, TRUE,
1494
if (err == DB_SUCCESS && check_ref) {
1496
ulint* offsets = rec_get_offsets(
1498
ULINT_UNDEFINED, &heap);
1560
1499
/* NOTE that the following call loses
1561
1500
the position of pcur ! */
1562
1501
err = row_upd_check_references_constraints(
1626
1564
row_upd_clust_rec_by_insert(
1627
1565
/*========================*/
1628
upd_node_t* node, /*!< in/out: row update node */
1566
upd_node_t* node, /*!< in: row update node */
1629
1567
dict_index_t* index, /*!< in: clustered index of the record */
1630
1568
que_thr_t* thr, /*!< in: query thread */
1631
ibool referenced,/*!< in: TRUE if index may be referenced in
1569
ibool check_ref,/*!< in: TRUE if index may be referenced in
1632
1570
a foreign key constraint */
1633
mtr_t* mtr) /*!< in/out: mtr; gets committed here */
1571
mtr_t* mtr) /*!< in: mtr; gets committed here */
1635
1573
mem_heap_t* heap = NULL;
1636
1574
btr_pcur_t* pcur;
1669
1606
record is removed from the index tree, or updated. */
1671
1608
rec = btr_cur_get_rec(btr_cur);
1672
node_index = dict_table_get_first_index(table);
1673
offsets = rec_get_offsets(rec, node_index, offsets_,
1609
index = dict_table_get_first_index(table);
1610
offsets = rec_get_offsets(rec, index, offsets_,
1674
1611
ULINT_UNDEFINED, &heap);
1675
change_ownership = btr_cur_mark_extern_inherited_fields(
1676
btr_cur_get_page_zip(btr_cur), rec, node_index, offsets,
1612
btr_cur_mark_extern_inherited_fields(
1613
btr_cur_get_page_zip(btr_cur),
1614
rec, index, offsets, node->update, mtr);
1679
1616
/* NOTE that the following call loses
1680
1617
the position of pcur ! */
1682
1618
err = row_upd_check_references_constraints(
1683
node, pcur, table, node_index, offsets, thr, mtr);
1619
node, pcur, table, index, offsets, thr, mtr);
1685
1620
if (err != DB_SUCCESS) {
1687
1621
mtr_commit(mtr);
1689
1622
if (UNIV_LIKELY_NULL(heap)) {
1690
1623
mem_heap_free(heap);
1709
1641
row_upd_index_entry_sys_field(entry, index, DATA_TRX_ID, trx->id);
1711
if (change_ownership) {
1643
if (node->upd_ext) {
1712
1644
/* If we return from a lock wait, for example, we may have
1713
1645
extern fields marked as not-owned in entry (marked in the
1714
if-branch above). We must unmark them, take the ownership
1646
if-branch above). We must unmark them. */
1717
1648
btr_cur_unmark_dtuple_extern_fields(entry);
1845
1776
ulint* offsets,/*!< in/out: rec_get_offsets() for the
1846
1777
record under the cursor */
1847
1778
que_thr_t* thr, /*!< in: query thread */
1849
/*!< in: TRUE if index may be referenced in
1779
ibool check_ref,/*!< in: TRUE if index may be referenced in
1850
1780
a foreign key constraint */
1851
1781
mtr_t* mtr) /*!< in: mtr; gets committed here */
1872
1802
err = btr_cur_del_mark_set_clust_rec(BTR_NO_LOCKING_FLAG,
1873
1803
btr_cur, TRUE, thr, mtr);
1874
if (err == DB_SUCCESS && referenced) {
1804
if (err == DB_SUCCESS && check_ref) {
1875
1805
/* NOTE that the following call loses the position of pcur ! */
1877
err = row_upd_check_references_constraints(
1878
node, pcur, index->table, index, offsets, thr, mtr);
1807
err = row_upd_check_references_constraints(node,
1881
1813
mtr_commit(mtr);
1904
1837
mem_heap_t* heap = NULL;
1905
1838
ulint offsets_[REC_OFFS_NORMAL_SIZE];
1906
1839
ulint* offsets;
1908
1840
rec_offs_init(offsets_);
1910
1842
index = dict_table_get_first_index(node->table);
1912
referenced = row_upd_index_is_referenced(index, thr_get_trx(thr));
1844
check_ref = row_upd_index_is_referenced(index, thr_get_trx(thr));
1914
1846
pcur = node->pcur;
1942
1874
then we have to free the file segments of the index tree associated
1943
1875
with the index */
1945
if (node->is_delete && node->table->id == DICT_INDEXES_ID) {
1878
&& ut_dulint_cmp(node->table->id, DICT_INDEXES_ID) == 0) {
1947
1880
dict_drop_index_tree(btr_pcur_get_rec(pcur), mtr);
1978
1911
/* NOTE: the following function calls will also commit mtr */
1980
1913
if (node->is_delete) {
1981
err = row_upd_del_mark_clust_rec(
1982
node, index, offsets, thr, referenced, mtr);
1914
err = row_upd_del_mark_clust_rec(node, index, offsets,
1915
thr, check_ref, mtr);
1984
1916
if (err == DB_SUCCESS) {
1985
1917
node->state = UPD_NODE_UPDATE_ALL_SEC;
1986
1918
node->index = dict_table_get_next_index(index);
2028
1960
choosing records to update. MySQL solves now the problem
2031
err = row_upd_clust_rec_by_insert(
2032
node, index, thr, referenced, mtr);
1963
err = row_upd_clust_rec_by_insert(node, index, thr, check_ref,
2034
1965
if (err != DB_SUCCESS) {