~ubuntu-branches/ubuntu/natty/mysql-5.1/natty-proposed

« back to all changes in this revision

Viewing changes to storage/innodb_plugin/row/row0upd.c

  • Committer: Package Import Robot
  • Author(s): Marc Deslauriers
  • Date: 2012-02-22 08:30:45 UTC
  • mfrom: (1.4.1)
  • Revision ID: package-import@ubuntu.com-20120222083045-2rd53r4bnyx7qus4
Tags: 5.1.61-0ubuntu0.11.04.1
* SECURITY UPDATE: Update to 5.1.61 to fix multiple security issues
  (LP: #937869)
  - http://www.oracle.com/technetwork/topics/security/cpujan2012-366304.html
  - CVE-2011-2262
  - CVE-2012-0075
  - CVE-2012-0112
  - CVE-2012-0113
  - CVE-2012-0114
  - CVE-2012-0115
  - CVE-2012-0116
  - CVE-2012-0117
  - CVE-2012-0118
  - CVE-2012-0119
  - CVE-2012-0120
  - CVE-2012-0484
  - CVE-2012-0485
  - CVE-2012-0486
  - CVE-2012-0487
  - CVE-2012-0488
  - CVE-2012-0489
  - CVE-2012-0490
  - CVE-2012-0491
  - CVE-2012-0492
  - CVE-2012-0493
  - CVE-2012-0494
  - CVE-2012-0495
  - CVE-2012-0496

Show diffs side-by-side

added added

removed removed

Lines of Context:
1
1
/*****************************************************************************
2
2
 
3
 
Copyright (c) 1996, 2009, Innobase Oy. All Rights Reserved.
 
3
Copyright (c) 1996, 2011, Oracle and/or its affiliates. All Rights Reserved.
4
4
 
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
498
498
        n_fields = upd_get_n_fields(update);
499
499
 
500
500
        for (i = 0; i < n_fields; i++) {
 
501
#ifdef UNIV_BLOB_DEBUG
 
502
                btr_blob_dbg_t  b;
 
503
                const byte*     field_ref       = NULL;
 
504
#endif /* UNIV_BLOB_DEBUG */
 
505
 
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)) {
 
512
                        ulint   len;
 
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;
 
517
 
 
518
                        b.ref_page_no = page_get_page_no(page_align(rec));
 
519
                        b.ref_heap_no = page_rec_get_heap_no(rec);
 
520
                        b.ref_field_no = i;
 
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");
 
525
                }
 
526
#endif /* UNIV_BLOB_DEBUG */
505
527
 
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));
 
531
 
 
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));
 
540
 
 
541
                        btr_blob_dbg_rbt_insert(index, &b, "upd_in_place");
 
542
                }
 
543
#endif /* UNIV_BLOB_DEBUG */
509
544
        }
510
545
 
511
546
        if (UNIV_LIKELY_NULL(page_zip)) {
1192
1227
@return TRUE if update vector changes an ordering field in the index record */
1193
1228
UNIV_INTERN
1194
1229
ibool
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
 
1235
                                positions! */
 
1236
#ifdef UNIV_DEBUG
 
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
1204
 
                                positions! */
 
1243
        const row_ext_t*ext)    /*!< NULL, or prefixes of the externally
 
1244
                                stored columns in the old row */
1205
1245
{
1206
 
        ulint           n_unique;
1207
 
        ulint           n_upd_fields;
1208
 
        ulint           i, j;
1209
 
        dict_index_t*   clust_index;
 
1246
        ulint                   n_unique;
 
1247
        ulint                   i;
 
1248
        const dict_index_t*     clust_index;
1210
1249
 
1211
 
        ut_ad(update && index);
 
1250
        ut_ad(index);
 
1251
        ut_ad(update);
 
1252
        ut_ad(thr);
 
1253
        ut_ad(thr->graph);
 
1254
        ut_ad(thr->graph->trx);
1212
1255
 
1213
1256
        n_unique = dict_index_get_n_unique(index);
1214
 
        n_upd_fields = upd_get_n_fields(update);
1215
1257
 
1216
1258
        clust_index = dict_table_get_first_index(index->table);
1217
1259
 
1219
1261
 
1220
1262
                const dict_field_t*     ind_field;
1221
1263
                const dict_col_t*       col;
1222
 
                ulint                   col_pos;
1223
1264
                ulint                   col_no;
 
1265
                const upd_field_t*      upd_field;
 
1266
                const dfield_t*         dfield;
 
1267
                dfield_t                dfield_ext;
 
1268
                ulint                   dfield_len;
 
1269
                const byte*             buf;
1224
1270
 
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);
1229
1274
 
1230
 
                for (j = 0; j < n_upd_fields; j++) {
1231
 
 
1232
 
                        const upd_field_t*      upd_field
1233
 
                                = upd_get_nth_field(update, j);
1234
 
 
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
1238
 
                        the datas */
1239
 
 
1240
 
                        if (col_pos == upd_field->field_no
1241
 
                            && (row == NULL
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)))) {
1246
 
 
1247
 
                                return(TRUE);
 
1275
                upd_field = upd_get_field_by_field_no(
 
1276
                        update, dict_col_get_clust_pos(col, clust_index));
 
1277
 
 
1278
                if (upd_field == NULL) {
 
1279
                        continue;
 
1280
                }
 
1281
 
 
1282
                if (row == NULL) {
 
1283
                        ut_ad(ext == NULL);
 
1284
                        return(TRUE);
 
1285
                }
 
1286
 
 
1287
                dfield = dtuple_get_nth_field(row, col_no);
 
1288
 
 
1289
                /* This treatment of column prefix indexes is loosely
 
1290
                based on row_build_index_entry(). */
 
1291
 
 
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. */
 
1298
                        dfield_len = 0;
 
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);
 
1302
 
 
1303
                        ut_ad(col->ord_part);
 
1304
 
 
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));
 
1315
                                        return(TRUE);
 
1316
                                }
 
1317
 
 
1318
                                goto copy_dfield;
1248
1319
                        }
 
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);
 
1327
copy_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;
 
1332
                }
 
1333
 
 
1334
                if (!dfield_datas_are_binary_equal(
 
1335
                            dfield, &upd_field->new_val,
 
1336
                            ind_field->prefix_len)) {
 
1337
 
 
1338
                        return(TRUE);
1249
1339
                }
1250
1340
        }
1251
1341
 
1329
1419
                        if (col_pos == upd_field->field_no
1330
1420
                            && !dfield_datas_are_binary_equal(
1331
1421
                                    dtuple_get_nth_field(entry, i),
1332
 
                                    &(upd_field->new_val))) {
 
1422
                                    &upd_field->new_val, 0)) {
1333
1423
 
1334
1424
                                return(TRUE);
1335
1425
                        }
1568
1658
        ut_ad(!dict_index_is_clust(node->index));
1569
1659
 
1570
1660
        if (node->state == UPD_NODE_UPDATE_ALL_SEC
1571
 
            || row_upd_changes_ord_field_binary(node->row, node->index,
1572
 
                                                node->update)) {
 
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));
1574
1664
        }
1575
1665
 
1576
1666
        return(DB_SUCCESS);
1577
1667
}
1578
1668
 
 
1669
#ifdef UNIV_DEBUG
 
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))
 
1683
ibool
 
1684
row_upd_clust_rec_by_insert_inherit_func(
 
1685
/*=====================================*/
 
1686
#ifdef UNIV_DEBUG
 
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 */
 
1693
{
 
1694
        ibool   inherit = FALSE;
 
1695
        ulint   i;
 
1696
 
 
1697
        ut_ad(!rec == !offsets);
 
1698
        ut_ad(!rec || rec_offs_any_extern(offsets));
 
1699
 
 
1700
        for (i = 0; i < dtuple_get_n_fields(entry); i++) {
 
1701
                dfield_t*       dfield  = dtuple_get_nth_field(entry, i);
 
1702
                byte*           data;
 
1703
                ulint           len;
 
1704
 
 
1705
                ut_ad(!offsets
 
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)) {
 
1711
                        continue;
 
1712
                }
 
1713
 
 
1714
#ifdef UNIV_DEBUG
 
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);
 
1721
 
 
1722
                        rec_data += len - BTR_EXTERN_FIELD_REF_SIZE;
 
1723
 
 
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));
 
1730
                }
 
1731
#endif /* UNIV_DEBUG */
 
1732
 
 
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));
 
1742
 
 
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. */
 
1747
 
 
1748
                inherit = TRUE;
 
1749
        }
 
1750
 
 
1751
        return(inherit);
 
1752
}
 
1753
 
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
1594
1769
                                a foreign key constraint */
1595
1770
        mtr_t*          mtr)    /*!< in/out: mtr; gets committed here */
1596
1771
{
1597
 
        mem_heap_t*     heap    = NULL;
 
1772
        mem_heap_t*     heap;
1598
1773
        btr_pcur_t*     pcur;
1599
1774
        btr_cur_t*      btr_cur;
1600
1775
        trx_t*          trx;
1601
1776
        dict_table_t*   table;
1602
1777
        dtuple_t*       entry;
1603
1778
        ulint           err;
1604
 
        ibool           change_ownership = FALSE;
 
1779
        ibool           change_ownership        = FALSE;
 
1780
        rec_t*          rec;
 
1781
        ulint*          offsets                 = NULL;
1605
1782
 
1606
1783
        ut_ad(node);
1607
1784
        ut_ad(dict_index_is_clust(index));
1611
1788
        pcur = node->pcur;
1612
1789
        btr_cur = btr_pcur_get_btr_cur(pcur);
1613
1790
 
1614
 
        if (node->state != UPD_NODE_INSERT_CLUSTERED) {
1615
 
                rec_t*          rec;
1616
 
                dict_index_t*   index;
1617
 
                ulint           offsets_[REC_OFFS_NORMAL_SIZE];
1618
 
                ulint*          offsets;
1619
 
                rec_offs_init(offsets_);
1620
 
 
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);
 
1792
 
 
1793
        entry = row_build_index_entry(node->upd_row, node->upd_ext,
 
1794
                                      index, heap);
 
1795
        ut_a(entry);
 
1796
 
 
1797
        row_upd_index_entry_sys_field(entry, index, DATA_TRX_ID, trx->id);
 
1798
 
 
1799
        switch (node->state) {
 
1800
        default:
 
1801
                ut_error;
 
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. */
 
1806
 
 
1807
                change_ownership = row_upd_clust_rec_by_insert_inherit(
 
1808
                        NULL, NULL, entry, node->update);
 
1809
                ut_a(change_ownership);
 
1810
                /* fall through */
 
1811
        case UPD_NODE_INSERT_CLUSTERED:
 
1812
                /* A lock wait occurred in row_ins_index_entry() in
 
1813
                the previous invocation of this function. */
 
1814
                break;
 
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));
 
1823
 
 
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) {
 
1828
err_exit:
1624
1829
                        mtr_commit(mtr);
 
1830
                        mem_heap_free(heap);
1625
1831
                        return(err);
1626
1832
                }
1627
1833
 
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. */
1632
 
 
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,
1639
 
                        node->update, mtr);
 
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. */
 
1838
 
 
1839
                if (rec_offs_any_extern(offsets)) {
 
1840
                        change_ownership = row_upd_clust_rec_by_insert_inherit(
 
1841
                                rec, offsets, entry, node->update);
 
1842
 
 
1843
                        if (change_ownership) {
 
1844
                                btr_pcur_store_position(pcur, mtr);
 
1845
                        }
 
1846
                }
 
1847
 
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) {
1646
 
                                mtr_commit(mtr);
1647
 
                                if (UNIV_LIKELY_NULL(heap)) {
1648
 
                                        mem_heap_free(heap);
1649
 
                                }
1650
 
                                return(err);
 
1854
                                goto err_exit;
1651
1855
                        }
1652
1856
                }
1653
1857
        }
1654
1858
 
1655
1859
        mtr_commit(mtr);
1656
1860
 
1657
 
        if (!heap) {
1658
 
                heap = mem_heap_create(500);
1659
 
        }
1660
 
        node->state = UPD_NODE_INSERT_CLUSTERED;
1661
 
 
1662
 
        entry = row_build_index_entry(node->upd_row, node->upd_ext,
1663
 
                                      index, heap);
1664
 
        ut_a(entry);
1665
 
 
1666
 
        row_upd_index_entry_sys_field(entry, index, DATA_TRX_ID, trx->id);
1667
 
 
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
1672
 
                back. */
1673
 
 
1674
 
                btr_cur_unmark_dtuple_extern_fields(entry);
1675
 
 
1676
 
                /* We must mark non-updated extern fields in entry as
1677
 
                inherited, so that a possible rollback will not free them. */
1678
 
 
1679
 
                btr_cur_mark_dtuple_inherited_extern(entry, node->update);
1680
 
        }
1681
 
 
1682
1861
        err = row_ins_index_entry(index, entry,
1683
1862
                                  node->upd_ext ? node->upd_ext->n_ext : 0,
1684
1863
                                  TRUE, thr);
 
1864
        node->state = change_ownership
 
1865
                ? UPD_NODE_INSERT_BLOB
 
1866
                : UPD_NODE_INSERT_CLUSTERED;
 
1867
 
 
1868
        if (err == DB_SUCCESS && change_ownership) {
 
1869
                /* Mark the non-updated fields disowned by the old record. */
 
1870
 
 
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
 
1877
                cursor succeeds. */
 
1878
 
 
1879
                mtr_start(mtr);
 
1880
 
 
1881
                if (!btr_pcur_restore_position(BTR_MODIFY_LEAF, pcur, mtr)) {
 
1882
                        ut_error;
 
1883
                }
 
1884
 
 
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));
 
1889
 
 
1890
                btr_cur_disown_inherited_fields(
 
1891
                        btr_cur_get_page_zip(btr_cur),
 
1892
                        rec, index, offsets, node->update, mtr);
 
1893
 
 
1894
                mtr_commit(mtr);
 
1895
        }
 
1896
 
1685
1897
        mem_heap_free(heap);
1686
1898
 
1687
1899
        return(err);
1775
1987
                        index, btr_cur_get_block(btr_cur), rec,
1776
1988
                        rec_get_offsets(rec, index, offsets_,
1777
1989
                                        ULINT_UNDEFINED, &heap),
1778
 
                        big_rec, mtr);
 
1990
                        mtr, TRUE, big_rec);
1779
1991
                mtr_commit(mtr);
1780
1992
        }
1781
1993
 
1825
2037
        /* Mark the clustered index record deleted; we do not have to check
1826
2038
        locks, because we assume that we have an x-lock on the record */
1827
2039
 
1828
 
        err = btr_cur_del_mark_set_clust_rec(BTR_NO_LOCKING_FLAG,
1829
 
                                             btr_cur, TRUE, thr, mtr);
 
2040
        err = btr_cur_del_mark_set_clust_rec(
 
2041
                BTR_NO_LOCKING_FLAG, btr_cur_get_block(btr_cur),
 
2042
                btr_cur_get_rec(btr_cur), index, offsets, TRUE, thr, mtr);
1830
2043
        if (err == DB_SUCCESS && check_ref) {
1831
2044
                /* NOTE that the following call loses the position of pcur ! */
1832
2045
 
1973
2186
 
1974
2187
        row_upd_store_row(node);
1975
2188
 
1976
 
        if (row_upd_changes_ord_field_binary(node->row, index, node->update)) {
 
2189
        if (row_upd_changes_ord_field_binary(index, node->update, thr,
 
2190
                                             node->row, node->ext)) {
1977
2191
 
1978
2192
                /* Update causes an ordering field (ordering fields within
1979
2193
                the B-tree) of the clustered index record to change: perform
2042
2256
        }
2043
2257
 
2044
2258
        if (node->state == UPD_NODE_UPDATE_CLUSTERED
2045
 
            || node->state == UPD_NODE_INSERT_CLUSTERED) {
 
2259
            || node->state == UPD_NODE_INSERT_CLUSTERED
 
2260
            || node->state == UPD_NODE_INSERT_BLOB) {
2046
2261
 
2047
2262
                log_free_check();
2048
2263
                err = row_upd_clust_step(node, thr);