~drizzle-trunk/drizzle/development

« back to all changes in this revision

Viewing changes to plugin/innobase/row/row0upd.c

  • Committer: Monty Taylor
  • Date: 2010-10-12 20:20:44 UTC
  • mto: (1842.1.3 build) (1843.1.2 build)
  • mto: This revision was merged to the branch mainline in revision 1843.
  • Revision ID: mordred@inaugust.com-20101012202044-yfrmnmkznvkqfxe4
Added support for valgrind suppressions.
Run strip-valgrind as part of make valgrind.

Show diffs side-by-side

added added

removed removed

Lines of Context:
1
1
/*****************************************************************************
2
2
 
3
 
Copyright (c) 1996, 2010, Innobase Oy. All Rights Reserved.
 
3
Copyright (c) 1996, 2009, Innobase Oy. 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
92
92
searched delete is obviously to keep the x-latch for several
93
93
steps of query graph execution. */
94
94
 
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
101
 
check.
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. */
104
 
 
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
111
 
check.
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. */
114
 
 
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
387
367
                                them */
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 */
391
371
{
392
372
        dfield_t*       dfield;
393
373
        byte*           field;
546
526
        trx_write_roll_ptr(log_ptr, roll_ptr);
547
527
        log_ptr += DATA_ROLL_PTR_LEN;
548
528
 
549
 
        log_ptr += mach_ull_write_compressed(log_ptr, trx->id);
 
529
        log_ptr += mach_dulint_write_compressed(log_ptr, trx->id);
550
530
 
551
531
        return(log_ptr);
552
532
}
580
560
        *roll_ptr = trx_read_roll_ptr(ptr);
581
561
        ptr += DATA_ROLL_PTR_LEN;
582
562
 
583
 
        ptr = mach_ull_parse_compressed(ptr, end_ptr, trx_id);
 
563
        ptr = mach_dulint_parse_compressed(ptr, end_ptr, trx_id);
584
564
 
585
565
        return(ptr);
586
566
}
959
939
                }
960
940
 
961
941
                len = dtype_get_at_most_n_mbchars(col->prtype,
962
 
                                                  col->mbminmaxlen,
 
942
                                                  col->mbminlen, col->mbmaxlen,
963
943
                                                  field->prefix_len, len,
964
944
                                                  (const char*) data);
965
945
 
1364
1344
                data = rec_get_nth_field(rec, offsets,
1365
1345
                                         column->field_nos[SYM_CLUST_FIELD_NO],
1366
1346
                                         &len);
 
1347
                if (len == UNIV_SQL_NULL) {
 
1348
                        len = UNIV_SQL_NULL;
 
1349
                }
1367
1350
                eval_node_copy_and_alloc_val(column, data, len);
1368
1351
 
1369
1352
                column = UT_LIST_GET_NEXT(col_var_list, column);
1408
1391
        dict_index_t*   clust_index;
1409
1392
        rec_t*          rec;
1410
1393
        mem_heap_t*     heap            = NULL;
1411
 
        row_ext_t**     ext;
1412
1394
        ulint           offsets_[REC_OFFS_NORMAL_SIZE];
1413
1395
        const ulint*    offsets;
1414
1396
        rec_offs_init(offsets_);
1425
1407
 
1426
1408
        offsets = rec_get_offsets(rec, clust_index, offsets_,
1427
1409
                                  ULINT_UNDEFINED, &heap);
1428
 
 
1429
 
        if (dict_table_get_format(node->table) >= DICT_TF_FORMAT_ZIP) {
1430
 
                /* In DYNAMIC or COMPRESSED format, there is no prefix
1431
 
                of externally stored columns in the clustered index
1432
 
                record. Build a cache of column prefixes. */
1433
 
                ext = &node->ext;
1434
 
        } else {
1435
 
                /* REDUNDANT and COMPACT formats store a local
1436
 
                768-byte prefix of each externally stored column.
1437
 
                No cache is needed. */
1438
 
                ext = NULL;
1439
 
                node->ext = NULL;
1440
 
        }
1441
 
 
1442
1410
        node->row = row_build(ROW_COPY_DATA, clust_index, rec, offsets,
1443
 
                              NULL, ext, node->heap);
 
1411
                              NULL, &node->ext, node->heap);
1444
1412
        if (node->is_delete) {
1445
1413
                node->upd_row = NULL;
1446
1414
                node->upd_ext = NULL;
1466
1434
        upd_node_t*     node,   /*!< in: row update node */
1467
1435
        que_thr_t*      thr)    /*!< in: query thread */
1468
1436
{
1469
 
        mtr_t                   mtr;
1470
 
        const rec_t*            rec;
1471
 
        btr_pcur_t              pcur;
1472
 
        mem_heap_t*             heap;
1473
 
        dtuple_t*               entry;
1474
 
        dict_index_t*           index;
1475
 
        btr_cur_t*              btr_cur;
1476
 
        ibool                   referenced;
1477
 
        ulint                   err     = DB_SUCCESS;
1478
 
        trx_t*                  trx     = thr_get_trx(thr);
1479
 
        ulint                   mode    = BTR_MODIFY_LEAF;
1480
 
        enum row_search_result  search_result;
 
1437
        ibool           check_ref;
 
1438
        ibool           found;
 
1439
        dict_index_t*   index;
 
1440
        dtuple_t*       entry;
 
1441
        btr_pcur_t      pcur;
 
1442
        btr_cur_t*      btr_cur;
 
1443
        mem_heap_t*     heap;
 
1444
        rec_t*          rec;
 
1445
        ulint           err     = DB_SUCCESS;
 
1446
        mtr_t           mtr;
 
1447
        trx_t*          trx     = thr_get_trx(thr);
1481
1448
 
1482
1449
        index = node->index;
1483
1450
 
1484
 
        referenced = row_upd_index_is_referenced(index, trx);
 
1451
        check_ref = row_upd_index_is_referenced(index, trx);
1485
1452
 
1486
1453
        heap = mem_heap_create(1024);
1487
1454
 
1489
1456
        entry = row_build_index_entry(node->row, node->ext, index, heap);
1490
1457
        ut_a(entry);
1491
1458
 
 
1459
        log_free_check();
1492
1460
        mtr_start(&mtr);
1493
1461
 
1494
 
        /* Set the query thread, so that ibuf_insert_low() will be
1495
 
        able to invoke thd_get_trx(). */
1496
 
        btr_pcur_get_btr_cur(&pcur)->thr = thr;
1497
 
 
1498
 
        /* We can only try to use the insert/delete buffer to buffer
1499
 
        delete-mark operations if the index we're modifying has no foreign
1500
 
        key constraints referring to it. */
1501
 
        if (!referenced) {
1502
 
                mode |= BTR_DELETE_MARK;
1503
 
        }
1504
 
 
1505
 
        search_result = row_search_index_entry(index, entry, mode,
1506
 
                                               &pcur, &mtr);
1507
 
 
 
1462
        found = row_search_index_entry(index, entry, BTR_MODIFY_LEAF, &pcur,
 
1463
                                       &mtr);
1508
1464
        btr_cur = btr_pcur_get_btr_cur(&pcur);
1509
1465
 
1510
1466
        rec = btr_cur_get_rec(btr_cur);
1511
1467
 
1512
 
        switch (search_result) {
1513
 
        case ROW_NOT_DELETED_REF:       /* should only occur for BTR_DELETE */
1514
 
                ut_error;
1515
 
                break;
1516
 
        case ROW_BUFFERED:
1517
 
                /* Entry was delete marked already. */
1518
 
                break;
1519
 
 
1520
 
        case ROW_NOT_FOUND:
 
1468
        if (UNIV_UNLIKELY(!found)) {
1521
1469
                fputs("InnoDB: error in sec index entry update in\n"
1522
1470
                      "InnoDB: ", stderr);
1523
1471
                dict_index_name_print(stderr, trx, index);
1534
1482
                fputs("\n"
1535
1483
                      "InnoDB: Submit a detailed bug report"
1536
1484
                      " to http://bugs.mysql.com\n", stderr);
1537
 
                break;
1538
 
        case ROW_FOUND:
 
1485
        } else {
1539
1486
                /* Delete mark the old index record; it can already be
1540
1487
                delete marked if we return after a lock wait in
1541
1488
                row_ins_index_entry below */
1542
1489
 
1543
 
                if (!rec_get_deleted_flag(
1544
 
                        rec, dict_table_is_comp(index->table))) {
1545
 
 
1546
 
                        err = btr_cur_del_mark_set_sec_rec(
1547
 
                                0, btr_cur, TRUE, thr, &mtr);
1548
 
 
1549
 
                        if (err == DB_SUCCESS && referenced) {
1550
 
 
1551
 
                                ulint*  offsets;
1552
 
 
1553
 
                                offsets = rec_get_offsets(
1554
 
                                        rec, index, NULL, ULINT_UNDEFINED,
1555
 
                                        &heap);
1556
 
 
 
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,
 
1493
                                                           thr, &mtr);
 
1494
                        if (err == DB_SUCCESS && check_ref) {
 
1495
 
 
1496
                                ulint*  offsets = rec_get_offsets(
 
1497
                                        rec, index, NULL,
 
1498
                                        ULINT_UNDEFINED, &heap);
1557
1499
                                /* NOTE that the following call loses
1558
1500
                                the position of pcur ! */
1559
1501
                                err = row_upd_check_references_constraints(
1561
1503
                                        index, offsets, thr, &mtr);
1562
1504
                        }
1563
1505
                }
1564
 
                break;
1565
1506
        }
1566
1507
 
1567
1508
        btr_pcur_close(&pcur);
1591
1532
deletes it if this is a delete.
1592
1533
@return DB_SUCCESS if operation successfully completed, else error
1593
1534
code or DB_LOCK_WAIT */
1594
 
static
 
1535
UNIV_INLINE
1595
1536
ulint
1596
1537
row_upd_sec_step(
1597
1538
/*=============*/
1625
1566
        upd_node_t*     node,   /*!< in: row update node */
1626
1567
        dict_index_t*   index,  /*!< in: clustered index of the record */
1627
1568
        que_thr_t*      thr,    /*!< in: query thread */
1628
 
        ibool           referenced,/*!< in: TRUE if index may be referenced in
 
1569
        ibool           check_ref,/*!< in: TRUE if index may be referenced in
1629
1570
                                a foreign key constraint */
1630
1571
        mtr_t*          mtr)    /*!< in: mtr; gets committed here */
1631
1572
{
1636
1577
        dict_table_t*   table;
1637
1578
        dtuple_t*       entry;
1638
1579
        ulint           err;
1639
 
        ibool           change_ownership = FALSE;
1640
1580
 
1641
1581
        ut_ad(node);
1642
1582
        ut_ad(dict_index_is_clust(index));
1669
1609
                index = dict_table_get_first_index(table);
1670
1610
                offsets = rec_get_offsets(rec, index, offsets_,
1671
1611
                                          ULINT_UNDEFINED, &heap);
1672
 
                change_ownership = btr_cur_mark_extern_inherited_fields(
1673
 
                        btr_cur_get_page_zip(btr_cur), rec, index, offsets,
1674
 
                        node->update, mtr);
1675
 
                if (referenced) {
 
1612
                btr_cur_mark_extern_inherited_fields(
 
1613
                        btr_cur_get_page_zip(btr_cur),
 
1614
                        rec, index, offsets, node->update, mtr);
 
1615
                if (check_ref) {
1676
1616
                        /* NOTE that the following call loses
1677
1617
                        the position of pcur ! */
1678
 
 
1679
1618
                        err = row_upd_check_references_constraints(
1680
1619
                                node, pcur, table, index, offsets, thr, mtr);
1681
 
 
1682
1620
                        if (err != DB_SUCCESS) {
1683
 
 
1684
1621
                                mtr_commit(mtr);
1685
 
 
1686
1622
                                if (UNIV_LIKELY_NULL(heap)) {
1687
1623
                                        mem_heap_free(heap);
1688
1624
                                }
1689
 
 
1690
1625
                                return(err);
1691
1626
                        }
1692
1627
                }
1705
1640
 
1706
1641
        row_upd_index_entry_sys_field(entry, index, DATA_TRX_ID, trx->id);
1707
1642
 
1708
 
        if (change_ownership) {
 
1643
        if (node->upd_ext) {
1709
1644
                /* If we return from a lock wait, for example, we may have
1710
1645
                extern fields marked as not-owned in entry (marked in the
1711
 
                if-branch above). We must unmark them, take the ownership
1712
 
                back. */
 
1646
                if-branch above). We must unmark them. */
1713
1647
 
1714
1648
                btr_cur_unmark_dtuple_extern_fields(entry);
1715
1649
 
1842
1776
        ulint*          offsets,/*!< in/out: rec_get_offsets() for the
1843
1777
                                record under the cursor */
1844
1778
        que_thr_t*      thr,    /*!< in: query thread */
1845
 
        ibool           referenced,
1846
 
                                /*!< in: TRUE if index may be referenced in
 
1779
        ibool           check_ref,/*!< in: TRUE if index may be referenced in
1847
1780
                                a foreign key constraint */
1848
1781
        mtr_t*          mtr)    /*!< in: mtr; gets committed here */
1849
1782
{
1868
1801
 
1869
1802
        err = btr_cur_del_mark_set_clust_rec(BTR_NO_LOCKING_FLAG,
1870
1803
                                             btr_cur, TRUE, thr, mtr);
1871
 
        if (err == DB_SUCCESS && referenced) {
 
1804
        if (err == DB_SUCCESS && check_ref) {
1872
1805
                /* NOTE that the following call loses the position of pcur ! */
1873
1806
 
1874
 
                err = row_upd_check_references_constraints(
1875
 
                        node, pcur, index->table, index, offsets, thr, mtr);
 
1807
                err = row_upd_check_references_constraints(node,
 
1808
                                                           pcur, index->table,
 
1809
                                                           index, offsets,
 
1810
                                                           thr, mtr);
1876
1811
        }
1877
1812
 
1878
1813
        mtr_commit(mtr);
1894
1829
        dict_index_t*   index;
1895
1830
        btr_pcur_t*     pcur;
1896
1831
        ibool           success;
 
1832
        ibool           check_ref;
1897
1833
        ulint           err;
1898
1834
        mtr_t*          mtr;
1899
1835
        mtr_t           mtr_buf;
1901
1837
        mem_heap_t*     heap            = NULL;
1902
1838
        ulint           offsets_[REC_OFFS_NORMAL_SIZE];
1903
1839
        ulint*          offsets;
1904
 
        ibool           referenced;
1905
1840
        rec_offs_init(offsets_);
1906
1841
 
1907
1842
        index = dict_table_get_first_index(node->table);
1908
1843
 
1909
 
        referenced = row_upd_index_is_referenced(index, thr_get_trx(thr));
 
1844
        check_ref = row_upd_index_is_referenced(index, thr_get_trx(thr));
1910
1845
 
1911
1846
        pcur = node->pcur;
1912
1847
 
1939
1874
        then we have to free the file segments of the index tree associated
1940
1875
        with the index */
1941
1876
 
1942
 
        if (node->is_delete && node->table->id == DICT_INDEXES_ID) {
 
1877
        if (node->is_delete
 
1878
            && ut_dulint_cmp(node->table->id, DICT_INDEXES_ID) == 0) {
1943
1879
 
1944
1880
                dict_drop_index_tree(btr_pcur_get_rec(pcur), mtr);
1945
1881
 
1975
1911
        /* NOTE: the following function calls will also commit mtr */
1976
1912
 
1977
1913
        if (node->is_delete) {
1978
 
                err = row_upd_del_mark_clust_rec(
1979
 
                        node, index, offsets, thr, referenced, mtr);
1980
 
 
 
1914
                err = row_upd_del_mark_clust_rec(node, index, offsets,
 
1915
                                                 thr, check_ref, mtr);
1981
1916
                if (err == DB_SUCCESS) {
1982
1917
                        node->state = UPD_NODE_UPDATE_ALL_SEC;
1983
1918
                        node->index = dict_table_get_next_index(index);
2025
1960
                choosing records to update. MySQL solves now the problem
2026
1961
                externally! */
2027
1962
 
2028
 
                err = row_upd_clust_rec_by_insert(
2029
 
                        node, index, thr, referenced, mtr);
2030
 
 
 
1963
                err = row_upd_clust_rec_by_insert(node, index, thr, check_ref,
 
1964
                                                  mtr);
2031
1965
                if (err != DB_SUCCESS) {
2032
1966
 
2033
1967
                        return(err);
2084
2018
        if (node->state == UPD_NODE_UPDATE_CLUSTERED
2085
2019
            || node->state == UPD_NODE_INSERT_CLUSTERED) {
2086
2020
 
2087
 
                log_free_check();
2088
2021
                err = row_upd_clust_step(node, thr);
2089
2022
 
2090
2023
                if (err != DB_SUCCESS) {
2099
2032
        }
2100
2033
 
2101
2034
        while (node->index != NULL) {
2102
 
 
2103
 
                log_free_check();
2104
2035
                err = row_upd_sec_step(node, thr);
2105
2036
 
2106
2037
                if (err != DB_SUCCESS) {