~ubuntu-branches/ubuntu/trusty/drizzle/trusty

« back to all changes in this revision

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

  • Committer: Bazaar Package Importer
  • Author(s): Monty Taylor
  • Date: 2010-12-09 06:02:39 UTC
  • mto: This revision was merged to the branch mainline in revision 5.
  • Revision ID: james.westby@ubuntu.com-20101209060239-t0ujftvcvd558yno
Tags: upstream-2010.12.05
ImportĀ upstreamĀ versionĀ 2010.12.05

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, 2010, 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
 
95
115
/***********************************************************//**
96
116
Checks if an update vector changes some of the first ordering fields of an
97
117
index record. This is only used in foreign key checks and we can assume
367
387
                                them */
368
388
        dict_index_t*   index,  /*!< in: clustered index */
369
389
        ulint           type,   /*!< in: DATA_TRX_ID or DATA_ROLL_PTR */
370
 
        dulint          val)    /*!< in: value to write */
 
390
        ib_uint64_t     val)    /*!< in: value to write */
371
391
{
372
392
        dfield_t*       dfield;
373
393
        byte*           field;
526
546
        trx_write_roll_ptr(log_ptr, roll_ptr);
527
547
        log_ptr += DATA_ROLL_PTR_LEN;
528
548
 
529
 
        log_ptr += mach_dulint_write_compressed(log_ptr, trx->id);
 
549
        log_ptr += mach_ull_write_compressed(log_ptr, trx->id);
530
550
 
531
551
        return(log_ptr);
532
552
}
560
580
        *roll_ptr = trx_read_roll_ptr(ptr);
561
581
        ptr += DATA_ROLL_PTR_LEN;
562
582
 
563
 
        ptr = mach_dulint_parse_compressed(ptr, end_ptr, trx_id);
 
583
        ptr = mach_ull_parse_compressed(ptr, end_ptr, trx_id);
564
584
 
565
585
        return(ptr);
566
586
}
939
959
                }
940
960
 
941
961
                len = dtype_get_at_most_n_mbchars(col->prtype,
942
 
                                                  col->mbminlen, col->mbmaxlen,
 
962
                                                  col->mbminmaxlen,
943
963
                                                  field->prefix_len, len,
944
964
                                                  (const char*) data);
945
965
 
1388
1408
        dict_index_t*   clust_index;
1389
1409
        rec_t*          rec;
1390
1410
        mem_heap_t*     heap            = NULL;
 
1411
        row_ext_t**     ext;
1391
1412
        ulint           offsets_[REC_OFFS_NORMAL_SIZE];
1392
1413
        const ulint*    offsets;
1393
1414
        rec_offs_init(offsets_);
1404
1425
 
1405
1426
        offsets = rec_get_offsets(rec, clust_index, offsets_,
1406
1427
                                  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
 
1407
1442
        node->row = row_build(ROW_COPY_DATA, clust_index, rec, offsets,
1408
 
                              NULL, &node->ext, node->heap);
 
1443
                              NULL, ext, node->heap);
1409
1444
        if (node->is_delete) {
1410
1445
                node->upd_row = NULL;
1411
1446
                node->upd_ext = NULL;
1431
1466
        upd_node_t*     node,   /*!< in: row update node */
1432
1467
        que_thr_t*      thr)    /*!< in: query thread */
1433
1468
{
1434
 
        ibool           check_ref;
1435
 
        ibool           found;
1436
 
        dict_index_t*   index;
1437
 
        dtuple_t*       entry;
1438
 
        btr_pcur_t      pcur;
1439
 
        btr_cur_t*      btr_cur;
1440
 
        mem_heap_t*     heap;
1441
 
        rec_t*          rec;
1442
 
        ulint           err     = DB_SUCCESS;
1443
 
        mtr_t           mtr;
1444
 
        trx_t*          trx     = thr_get_trx(thr);
 
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;
1445
1481
 
1446
1482
        index = node->index;
1447
1483
 
1448
 
        check_ref = row_upd_index_is_referenced(index, trx);
 
1484
        referenced = row_upd_index_is_referenced(index, trx);
1449
1485
 
1450
1486
        heap = mem_heap_create(1024);
1451
1487
 
1453
1489
        entry = row_build_index_entry(node->row, node->ext, index, heap);
1454
1490
        ut_a(entry);
1455
1491
 
1456
 
        log_free_check();
1457
1492
        mtr_start(&mtr);
1458
1493
 
1459
 
        found = row_search_index_entry(index, entry, BTR_MODIFY_LEAF, &pcur,
1460
 
                                       &mtr);
 
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
 
1461
1508
        btr_cur = btr_pcur_get_btr_cur(&pcur);
1462
1509
 
1463
1510
        rec = btr_cur_get_rec(btr_cur);
1464
1511
 
1465
 
        if (UNIV_UNLIKELY(!found)) {
 
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:
1466
1521
                fputs("InnoDB: error in sec index entry update in\n"
1467
1522
                      "InnoDB: ", stderr);
1468
1523
                dict_index_name_print(stderr, trx, index);
1479
1534
                fputs("\n"
1480
1535
                      "InnoDB: Submit a detailed bug report"
1481
1536
                      " to http://bugs.mysql.com\n", stderr);
1482
 
        } else {
 
1537
                break;
 
1538
        case ROW_FOUND:
1483
1539
                /* Delete mark the old index record; it can already be
1484
1540
                delete marked if we return after a lock wait in
1485
1541
                row_ins_index_entry below */
1486
1542
 
1487
 
                if (!rec_get_deleted_flag(rec,
1488
 
                                          dict_table_is_comp(index->table))) {
1489
 
                        err = btr_cur_del_mark_set_sec_rec(0, btr_cur, TRUE,
1490
 
                                                           thr, &mtr);
1491
 
                        if (err == DB_SUCCESS && check_ref) {
1492
 
 
1493
 
                                ulint*  offsets = rec_get_offsets(
1494
 
                                        rec, index, NULL,
1495
 
                                        ULINT_UNDEFINED, &heap);
 
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
 
1496
1557
                                /* NOTE that the following call loses
1497
1558
                                the position of pcur ! */
1498
1559
                                err = row_upd_check_references_constraints(
1500
1561
                                        index, offsets, thr, &mtr);
1501
1562
                        }
1502
1563
                }
 
1564
                break;
1503
1565
        }
1504
1566
 
1505
1567
        btr_pcur_close(&pcur);
1529
1591
deletes it if this is a delete.
1530
1592
@return DB_SUCCESS if operation successfully completed, else error
1531
1593
code or DB_LOCK_WAIT */
1532
 
UNIV_INLINE
 
1594
static
1533
1595
ulint
1534
1596
row_upd_sec_step(
1535
1597
/*=============*/
1563
1625
        upd_node_t*     node,   /*!< in: row update node */
1564
1626
        dict_index_t*   index,  /*!< in: clustered index of the record */
1565
1627
        que_thr_t*      thr,    /*!< in: query thread */
1566
 
        ibool           check_ref,/*!< in: TRUE if index may be referenced in
 
1628
        ibool           referenced,/*!< in: TRUE if index may be referenced in
1567
1629
                                a foreign key constraint */
1568
1630
        mtr_t*          mtr)    /*!< in: mtr; gets committed here */
1569
1631
{
1609
1671
                btr_cur_mark_extern_inherited_fields(
1610
1672
                        btr_cur_get_page_zip(btr_cur),
1611
1673
                        rec, index, offsets, node->update, mtr);
1612
 
                if (check_ref) {
 
1674
                if (referenced) {
1613
1675
                        /* NOTE that the following call loses
1614
1676
                        the position of pcur ! */
 
1677
 
1615
1678
                        err = row_upd_check_references_constraints(
1616
1679
                                node, pcur, table, index, offsets, thr, mtr);
 
1680
 
1617
1681
                        if (err != DB_SUCCESS) {
 
1682
 
1618
1683
                                mtr_commit(mtr);
 
1684
 
1619
1685
                                if (UNIV_LIKELY_NULL(heap)) {
1620
1686
                                        mem_heap_free(heap);
1621
1687
                                }
 
1688
 
1622
1689
                                return(err);
1623
1690
                        }
1624
1691
                }
1773
1840
        ulint*          offsets,/*!< in/out: rec_get_offsets() for the
1774
1841
                                record under the cursor */
1775
1842
        que_thr_t*      thr,    /*!< in: query thread */
1776
 
        ibool           check_ref,/*!< in: TRUE if index may be referenced in
 
1843
        ibool           referenced,
 
1844
                                /*!< in: TRUE if index may be referenced in
1777
1845
                                a foreign key constraint */
1778
1846
        mtr_t*          mtr)    /*!< in: mtr; gets committed here */
1779
1847
{
1798
1866
 
1799
1867
        err = btr_cur_del_mark_set_clust_rec(BTR_NO_LOCKING_FLAG,
1800
1868
                                             btr_cur, TRUE, thr, mtr);
1801
 
        if (err == DB_SUCCESS && check_ref) {
 
1869
        if (err == DB_SUCCESS && referenced) {
1802
1870
                /* NOTE that the following call loses the position of pcur ! */
1803
1871
 
1804
 
                err = row_upd_check_references_constraints(node,
1805
 
                                                           pcur, index->table,
1806
 
                                                           index, offsets,
1807
 
                                                           thr, mtr);
 
1872
                err = row_upd_check_references_constraints(
 
1873
                        node, pcur, index->table, index, offsets, thr, mtr);
1808
1874
        }
1809
1875
 
1810
1876
        mtr_commit(mtr);
1826
1892
        dict_index_t*   index;
1827
1893
        btr_pcur_t*     pcur;
1828
1894
        ibool           success;
1829
 
        ibool           check_ref;
1830
1895
        ulint           err;
1831
1896
        mtr_t*          mtr;
1832
1897
        mtr_t           mtr_buf;
1834
1899
        mem_heap_t*     heap            = NULL;
1835
1900
        ulint           offsets_[REC_OFFS_NORMAL_SIZE];
1836
1901
        ulint*          offsets;
 
1902
        ibool           referenced;
1837
1903
        rec_offs_init(offsets_);
1838
1904
 
1839
1905
        index = dict_table_get_first_index(node->table);
1840
1906
 
1841
 
        check_ref = row_upd_index_is_referenced(index, thr_get_trx(thr));
 
1907
        referenced = row_upd_index_is_referenced(index, thr_get_trx(thr));
1842
1908
 
1843
1909
        pcur = node->pcur;
1844
1910
 
1871
1937
        then we have to free the file segments of the index tree associated
1872
1938
        with the index */
1873
1939
 
1874
 
        if (node->is_delete
1875
 
            && ut_dulint_cmp(node->table->id, DICT_INDEXES_ID) == 0) {
 
1940
        if (node->is_delete && node->table->id == DICT_INDEXES_ID) {
1876
1941
 
1877
1942
                dict_drop_index_tree(btr_pcur_get_rec(pcur), mtr);
1878
1943
 
1908
1973
        /* NOTE: the following function calls will also commit mtr */
1909
1974
 
1910
1975
        if (node->is_delete) {
1911
 
                err = row_upd_del_mark_clust_rec(node, index, offsets,
1912
 
                                                 thr, check_ref, mtr);
 
1976
                err = row_upd_del_mark_clust_rec(
 
1977
                        node, index, offsets, thr, referenced, mtr);
 
1978
 
1913
1979
                if (err == DB_SUCCESS) {
1914
1980
                        node->state = UPD_NODE_UPDATE_ALL_SEC;
1915
1981
                        node->index = dict_table_get_next_index(index);
1957
2023
                choosing records to update. MySQL solves now the problem
1958
2024
                externally! */
1959
2025
 
1960
 
                err = row_upd_clust_rec_by_insert(node, index, thr, check_ref,
1961
 
                                                  mtr);
 
2026
                err = row_upd_clust_rec_by_insert(
 
2027
                        node, index, thr, referenced, mtr);
 
2028
 
1962
2029
                if (err != DB_SUCCESS) {
1963
2030
 
1964
2031
                        return(err);
2015
2082
        if (node->state == UPD_NODE_UPDATE_CLUSTERED
2016
2083
            || node->state == UPD_NODE_INSERT_CLUSTERED) {
2017
2084
 
 
2085
                log_free_check();
2018
2086
                err = row_upd_clust_step(node, thr);
2019
2087
 
2020
2088
                if (err != DB_SUCCESS) {
2029
2097
        }
2030
2098
 
2031
2099
        while (node->index != NULL) {
 
2100
 
 
2101
                log_free_check();
2032
2102
                err = row_upd_sec_step(node, thr);
2033
2103
 
2034
2104
                if (err != DB_SUCCESS) {