498
498
n_fields = upd_get_n_fields(update);
500
500
for (i = 0; i < n_fields; i++) {
501
#ifdef UNIV_BLOB_DEBUG
503
const byte* field_ref = NULL;
504
#endif /* UNIV_BLOB_DEBUG */
501
506
upd_field = upd_get_nth_field(update, i);
502
507
new_val = &(upd_field->new_val);
503
508
ut_ad(!dfield_is_ext(new_val) ==
504
509
!rec_offs_nth_extern(offsets, upd_field->field_no));
510
#ifdef UNIV_BLOB_DEBUG
511
if (dfield_is_ext(new_val)) {
513
field_ref = rec_get_nth_field(rec, offsets, i, &len);
514
ut_a(len != UNIV_SQL_NULL);
515
ut_a(len >= BTR_EXTERN_FIELD_REF_SIZE);
516
field_ref += len - BTR_EXTERN_FIELD_REF_SIZE;
518
b.ref_page_no = page_get_page_no(page_align(rec));
519
b.ref_heap_no = page_rec_get_heap_no(rec);
521
b.blob_page_no = mach_read_from_4(
522
field_ref + BTR_EXTERN_PAGE_NO);
523
ut_a(b.ref_field_no >= index->n_uniq);
524
btr_blob_dbg_rbt_delete(index, &b, "upd_in_place");
526
#endif /* UNIV_BLOB_DEBUG */
506
528
rec_set_nth_field(rec, offsets, upd_field->field_no,
507
529
dfield_get_data(new_val),
508
530
dfield_get_len(new_val));
532
#ifdef UNIV_BLOB_DEBUG
533
if (dfield_is_ext(new_val)) {
534
b.blob_page_no = mach_read_from_4(
535
field_ref + BTR_EXTERN_PAGE_NO);
536
b.always_owner = b.owner = !(field_ref[BTR_EXTERN_LEN]
537
& BTR_EXTERN_OWNER_FLAG);
538
b.del = rec_get_deleted_flag(
539
rec, rec_offs_comp(offsets));
541
btr_blob_dbg_rbt_insert(index, &b, "upd_in_place");
543
#endif /* UNIV_BLOB_DEBUG */
511
546
if (UNIV_LIKELY_NULL(page_zip)) {
1192
1227
@return TRUE if update vector changes an ordering field in the index record */
1195
row_upd_changes_ord_field_binary(
1196
/*=============================*/
1230
row_upd_changes_ord_field_binary_func(
1231
/*==================================*/
1232
dict_index_t* index, /*!< in: index of the record */
1233
const upd_t* update, /*!< in: update vector for the row; NOTE: the
1234
field numbers in this MUST be clustered index
1237
const que_thr_t*thr, /*!< in: query thread */
1238
#endif /* UNIV_DEBUG */
1197
1239
const dtuple_t* row, /*!< in: old value of row, or NULL if the
1198
1240
row and the data values in update are not
1199
1241
known when this function is called, e.g., at
1200
1242
compile time */
1201
dict_index_t* index, /*!< in: index of the record */
1202
const upd_t* update) /*!< in: update vector for the row; NOTE: the
1203
field numbers in this MUST be clustered index
1243
const row_ext_t*ext) /*!< NULL, or prefixes of the externally
1244
stored columns in the old row */
1209
dict_index_t* clust_index;
1248
const dict_index_t* clust_index;
1211
ut_ad(update && index);
1254
ut_ad(thr->graph->trx);
1213
1256
n_unique = dict_index_get_n_unique(index);
1214
n_upd_fields = upd_get_n_fields(update);
1216
1258
clust_index = dict_table_get_first_index(index->table);
1220
1262
const dict_field_t* ind_field;
1221
1263
const dict_col_t* col;
1265
const upd_field_t* upd_field;
1266
const dfield_t* dfield;
1267
dfield_t dfield_ext;
1225
1271
ind_field = dict_index_get_nth_field(index, i);
1226
1272
col = dict_field_get_col(ind_field);
1227
col_pos = dict_col_get_clust_pos(col, clust_index);
1228
1273
col_no = dict_col_get_no(col);
1230
for (j = 0; j < n_upd_fields; j++) {
1232
const upd_field_t* upd_field
1233
= upd_get_nth_field(update, j);
1235
/* Note that if the index field is a column prefix
1236
then it may be that row does not contain an externally
1237
stored part of the column value, and we cannot compare
1240
if (col_pos == upd_field->field_no
1242
|| ind_field->prefix_len > 0
1243
|| !dfield_datas_are_binary_equal(
1244
dtuple_get_nth_field(row, col_no),
1245
&(upd_field->new_val)))) {
1275
upd_field = upd_get_field_by_field_no(
1276
update, dict_col_get_clust_pos(col, clust_index));
1278
if (upd_field == NULL) {
1287
dfield = dtuple_get_nth_field(row, col_no);
1289
/* This treatment of column prefix indexes is loosely
1290
based on row_build_index_entry(). */
1292
if (UNIV_LIKELY(ind_field->prefix_len == 0)
1293
|| dfield_is_null(dfield)) {
1294
/* do nothing special */
1295
} else if (UNIV_LIKELY_NULL(ext)) {
1296
/* Silence a compiler warning without
1297
silencing a Valgrind error. */
1299
UNIV_MEM_INVALID(&dfield_len, sizeof dfield_len);
1300
/* See if the column is stored externally. */
1301
buf = row_ext_lookup(ext, col_no, &dfield_len);
1303
ut_ad(col->ord_part);
1305
if (UNIV_LIKELY_NULL(buf)) {
1306
if (UNIV_UNLIKELY(buf == field_ref_zero)) {
1307
/* The externally stored field
1308
was not written yet. This
1309
record should only be seen by
1310
recv_recovery_rollback_active(),
1311
when the server had crashed before
1312
storing the field. */
1313
ut_ad(thr->graph->trx->is_recovered);
1314
ut_ad(trx_is_recv(thr->graph->trx));
1320
} else if (dfield_is_ext(dfield)) {
1321
dfield_len = dfield_get_len(dfield);
1322
ut_a(dfield_len > BTR_EXTERN_FIELD_REF_SIZE);
1323
dfield_len -= BTR_EXTERN_FIELD_REF_SIZE;
1324
ut_a(dict_index_is_clust(index)
1325
|| ind_field->prefix_len <= dfield_len);
1326
buf = dfield_get_data(dfield);
1328
ut_a(dfield_len > 0);
1329
dfield_copy(&dfield_ext, dfield);
1330
dfield_set_data(&dfield_ext, buf, dfield_len);
1331
dfield = &dfield_ext;
1334
if (!dfield_datas_are_binary_equal(
1335
dfield, &upd_field->new_val,
1336
ind_field->prefix_len)) {
1568
1658
ut_ad(!dict_index_is_clust(node->index));
1570
1660
if (node->state == UPD_NODE_UPDATE_ALL_SEC
1571
|| row_upd_changes_ord_field_binary(node->row, node->index,
1661
|| row_upd_changes_ord_field_binary(node->index, node->update,
1662
thr, node->row, node->ext)) {
1573
1663
return(row_upd_sec_index_entry(node, thr));
1576
1666
return(DB_SUCCESS);
1670
# define row_upd_clust_rec_by_insert_inherit(rec,offsets,entry,update) \
1671
row_upd_clust_rec_by_insert_inherit_func(rec,offsets,entry,update)
1672
#else /* UNIV_DEBUG */
1673
# define row_upd_clust_rec_by_insert_inherit(rec,offsets,entry,update) \
1674
row_upd_clust_rec_by_insert_inherit_func(entry,update)
1675
#endif /* UNIV_DEBUG */
1676
/*******************************************************************//**
1677
Mark non-updated off-page columns inherited when the primary key is
1678
updated. We must mark them as inherited in entry, so that they are not
1679
freed in a rollback. A limited version of this function used to be
1680
called btr_cur_mark_dtuple_inherited_extern().
1681
@return TRUE if any columns were inherited */
1682
static __attribute__((warn_unused_result))
1684
row_upd_clust_rec_by_insert_inherit_func(
1685
/*=====================================*/
1687
const rec_t* rec, /*!< in: old record, or NULL */
1688
const ulint* offsets,/*!< in: rec_get_offsets(rec), or NULL */
1689
#endif /* UNIV_DEBUG */
1690
dtuple_t* entry, /*!< in/out: updated entry to be
1691
inserted into the clustered index */
1692
const upd_t* update) /*!< in: update vector */
1694
ibool inherit = FALSE;
1697
ut_ad(!rec == !offsets);
1698
ut_ad(!rec || rec_offs_any_extern(offsets));
1700
for (i = 0; i < dtuple_get_n_fields(entry); i++) {
1701
dfield_t* dfield = dtuple_get_nth_field(entry, i);
1706
|| !rec_offs_nth_extern(offsets, i)
1707
== !dfield_is_ext(dfield)
1708
|| upd_get_field_by_field_no(update, i));
1709
if (!dfield_is_ext(dfield)
1710
|| upd_get_field_by_field_no(update, i)) {
1715
if (UNIV_LIKELY(rec != NULL)) {
1716
const byte* rec_data
1717
= rec_get_nth_field(rec, offsets, i, &len);
1718
ut_ad(len == dfield_get_len(dfield));
1719
ut_ad(len != UNIV_SQL_NULL);
1720
ut_ad(len >= BTR_EXTERN_FIELD_REF_SIZE);
1722
rec_data += len - BTR_EXTERN_FIELD_REF_SIZE;
1724
/* The pointer must not be zero. */
1725
ut_ad(memcmp(rec_data, field_ref_zero,
1726
BTR_EXTERN_FIELD_REF_SIZE));
1727
/* The BLOB must be owned. */
1728
ut_ad(!(rec_data[BTR_EXTERN_LEN]
1729
& BTR_EXTERN_OWNER_FLAG));
1731
#endif /* UNIV_DEBUG */
1733
len = dfield_get_len(dfield);
1734
ut_a(len != UNIV_SQL_NULL);
1735
ut_a(len >= BTR_EXTERN_FIELD_REF_SIZE);
1736
data = dfield_get_data(dfield);
1737
data += len - BTR_EXTERN_FIELD_REF_SIZE;
1738
/* The pointer must not be zero. */
1739
ut_a(memcmp(data, field_ref_zero, BTR_EXTERN_FIELD_REF_SIZE));
1740
/* The BLOB must be owned. */
1741
ut_a(!(data[BTR_EXTERN_LEN] & BTR_EXTERN_OWNER_FLAG));
1743
data[BTR_EXTERN_LEN] |= BTR_EXTERN_INHERITED_FLAG;
1744
/* The BTR_EXTERN_INHERITED_FLAG only matters in
1745
rollback. Purge will always free the extern fields of
1746
a delete-marked row. */
1579
1754
/***********************************************************//**
1580
1755
Marks the clustered index record deleted and inserts the updated version
1581
1756
of the record to the index. This function should be used when the ordering
1611
1788
pcur = node->pcur;
1612
1789
btr_cur = btr_pcur_get_btr_cur(pcur);
1614
if (node->state != UPD_NODE_INSERT_CLUSTERED) {
1616
dict_index_t* index;
1617
ulint offsets_[REC_OFFS_NORMAL_SIZE];
1619
rec_offs_init(offsets_);
1621
err = btr_cur_del_mark_set_clust_rec(BTR_NO_LOCKING_FLAG,
1622
btr_cur, TRUE, thr, mtr);
1791
heap = mem_heap_create(1000);
1793
entry = row_build_index_entry(node->upd_row, node->upd_ext,
1797
row_upd_index_entry_sys_field(entry, index, DATA_TRX_ID, trx->id);
1799
switch (node->state) {
1802
case UPD_NODE_INSERT_BLOB:
1803
/* A lock wait occurred in row_ins_index_entry() in
1804
the previous invocation of this function. Mark the
1805
off-page columns in the entry inherited. */
1807
change_ownership = row_upd_clust_rec_by_insert_inherit(
1808
NULL, NULL, entry, node->update);
1809
ut_a(change_ownership);
1811
case UPD_NODE_INSERT_CLUSTERED:
1812
/* A lock wait occurred in row_ins_index_entry() in
1813
the previous invocation of this function. */
1815
case UPD_NODE_UPDATE_CLUSTERED:
1816
/* This is the first invocation of the function where
1817
we update the primary key. Delete-mark the old record
1818
in the clustered index and prepare to insert a new entry. */
1819
rec = btr_cur_get_rec(btr_cur);
1820
offsets = rec_get_offsets(rec, index, NULL,
1821
ULINT_UNDEFINED, &heap);
1822
ut_ad(page_rec_is_user_rec(rec));
1824
err = btr_cur_del_mark_set_clust_rec(
1825
BTR_NO_LOCKING_FLAG, btr_cur_get_block(btr_cur),
1826
rec, index, offsets, TRUE, thr, mtr);
1623
1827
if (err != DB_SUCCESS) {
1624
1829
mtr_commit(mtr);
1830
mem_heap_free(heap);
1628
/* Mark as not-owned the externally stored fields which the new
1629
row inherits from the delete marked record: purge should not
1630
free those externally stored fields even if the delete marked
1631
record is removed from the index tree, or updated. */
1633
rec = btr_cur_get_rec(btr_cur);
1634
index = dict_table_get_first_index(table);
1635
offsets = rec_get_offsets(rec, index, offsets_,
1636
ULINT_UNDEFINED, &heap);
1637
change_ownership = btr_cur_mark_extern_inherited_fields(
1638
btr_cur_get_page_zip(btr_cur), rec, index, offsets,
1834
/* If the the new row inherits externally stored
1835
fields (off-page columns a.k.a. BLOBs) from the
1836
delete-marked old record, mark them disowned by the
1837
old record and owned by the new entry. */
1839
if (rec_offs_any_extern(offsets)) {
1840
change_ownership = row_upd_clust_rec_by_insert_inherit(
1841
rec, offsets, entry, node->update);
1843
if (change_ownership) {
1844
btr_pcur_store_position(pcur, mtr);
1640
1848
if (check_ref) {
1641
1849
/* NOTE that the following call loses
1642
1850
the position of pcur ! */
1643
1851
err = row_upd_check_references_constraints(
1644
1852
node, pcur, table, index, offsets, thr, mtr);
1645
1853
if (err != DB_SUCCESS) {
1647
if (UNIV_LIKELY_NULL(heap)) {
1648
mem_heap_free(heap);
1655
1859
mtr_commit(mtr);
1658
heap = mem_heap_create(500);
1660
node->state = UPD_NODE_INSERT_CLUSTERED;
1662
entry = row_build_index_entry(node->upd_row, node->upd_ext,
1666
row_upd_index_entry_sys_field(entry, index, DATA_TRX_ID, trx->id);
1668
if (change_ownership) {
1669
/* If we return from a lock wait, for example, we may have
1670
extern fields marked as not-owned in entry (marked in the
1671
if-branch above). We must unmark them, take the ownership
1674
btr_cur_unmark_dtuple_extern_fields(entry);
1676
/* We must mark non-updated extern fields in entry as
1677
inherited, so that a possible rollback will not free them. */
1679
btr_cur_mark_dtuple_inherited_extern(entry, node->update);
1682
1861
err = row_ins_index_entry(index, entry,
1683
1862
node->upd_ext ? node->upd_ext->n_ext : 0,
1864
node->state = change_ownership
1865
? UPD_NODE_INSERT_BLOB
1866
: UPD_NODE_INSERT_CLUSTERED;
1868
if (err == DB_SUCCESS && change_ownership) {
1869
/* Mark the non-updated fields disowned by the old record. */
1871
/* NOTE: this transaction has an x-lock on the record
1872
and therefore other transactions cannot modify the
1873
record when we have no latch on the page. In addition,
1874
we assume that other query threads of the same
1875
transaction do not modify the record in the meantime.
1876
Therefore we can assert that the restoration of the
1881
if (!btr_pcur_restore_position(BTR_MODIFY_LEAF, pcur, mtr)) {
1885
rec = btr_cur_get_rec(btr_cur);
1886
offsets = rec_get_offsets(rec, index, offsets,
1887
ULINT_UNDEFINED, &heap);
1888
ut_ad(page_rec_is_user_rec(rec));
1890
btr_cur_disown_inherited_fields(
1891
btr_cur_get_page_zip(btr_cur),
1892
rec, index, offsets, node->update, mtr);
1685
1897
mem_heap_free(heap);