~drizzle-trunk/drizzle/development

« back to all changes in this revision

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

  • Committer: Brian Aker
  • Date: 2010-10-28 17:12:01 UTC
  • mfrom: (1887.1.3 merge)
  • Revision ID: brian@tangent.org-20101028171201-baj6l1bnntn1s4ad
Merge in POTFILES changes.

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
313
293
{
314
294
        upd_node_t*     node;
315
295
 
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;
318
298
 
319
299
        node->state = UPD_NODE_UPDATE_CLUSTERED;
381
361
void
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
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;
398
378
        pos = dict_index_get_sys_col_pos(index, type);
399
379
 
400
380
        dfield = dtuple_get_nth_field(entry, pos);
401
 
        field = static_cast<byte *>(dfield_get_data(dfield));
 
381
        field = dfield_get_data(dfield);
402
382
 
403
383
        if (type == DATA_TRX_ID) {
404
384
                trx_write_trx_id(field, val);
476
456
#endif /* !UNIV_HOTBACKUP */
477
457
 
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. */
484
461
UNIV_INTERN
485
462
void
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
539
516
                                in mlog */
540
 
        mtr_t*          /*mtr __attribute__((unused))*/) /*!< in: mtr */
 
517
        mtr_t*          mtr __attribute__((unused))) /*!< in: mtr */
541
518
{
542
519
        ut_ad(dict_index_is_clust(index));
543
520
        ut_ad(mtr);
549
526
        trx_write_roll_ptr(log_ptr, roll_ptr);
550
527
        log_ptr += DATA_ROLL_PTR_LEN;
551
528
 
552
 
        log_ptr += mach_ull_write_compressed(log_ptr, trx->id);
 
529
        log_ptr += mach_dulint_write_compressed(log_ptr, trx->id);
553
530
 
554
531
        return(log_ptr);
555
532
}
583
560
        *roll_ptr = trx_read_roll_ptr(ptr);
584
561
        ptr += DATA_ROLL_PTR_LEN;
585
562
 
586
 
        ptr = mach_ull_parse_compressed(ptr, end_ptr, trx_id);
 
563
        ptr = mach_dulint_parse_compressed(ptr, end_ptr, trx_id);
587
564
 
588
565
        return(ptr);
589
566
}
648
625
                                mlog_close(mtr, log_ptr);
649
626
 
650
627
                                mlog_catenate_string(mtr,
651
 
                                                     static_cast<byte *>(dfield_get_data(new_val)),
 
628
                                                     dfield_get_data(new_val),
652
629
                                                     len);
653
630
 
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 */
909
886
{
910
 
        byte* buf = static_cast<byte *>(mem_heap_alloc(heap, *len));
 
887
        byte*   buf = mem_heap_alloc(heap, *len);
911
888
 
912
889
        *len = btr_copy_externally_stored_field_prefix(buf, *len,
913
890
                                                       zip_size,
945
922
        }
946
923
 
947
924
        len = dfield_get_len(dfield);
948
 
        data = static_cast<const byte *>(dfield_get_data(dfield));
 
925
        data = dfield_get_data(dfield);
949
926
 
950
927
        if (field->prefix_len > 0) {
951
928
                ibool           fetch_ext = dfield_is_ext(dfield)
962
939
                }
963
940
 
964
941
                len = dtype_get_at_most_n_mbchars(col->prtype,
965
 
                                                  col->mbminmaxlen,
 
942
                                                  col->mbminlen, col->mbmaxlen,
966
943
                                                  field->prefix_len, len,
967
944
                                                  (const char*) data);
968
945
 
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));
1148
1125
 
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;
1151
1128
 
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],
1369
1346
                                         &len);
 
1347
                if (len == UNIV_SQL_NULL) {
 
1348
                        len = UNIV_SQL_NULL;
 
1349
                }
1370
1350
                eval_node_copy_and_alloc_val(column, data, len);
1371
1351
 
1372
1352
                column = UT_LIST_GET_NEXT(col_var_list, column);
1411
1391
        dict_index_t*   clust_index;
1412
1392
        rec_t*          rec;
1413
1393
        mem_heap_t*     heap            = NULL;
1414
 
        row_ext_t**     ext;
1415
1394
        ulint           offsets_[REC_OFFS_NORMAL_SIZE];
1416
1395
        const ulint*    offsets;
1417
1396
        rec_offs_init(offsets_);
1428
1407
 
1429
1408
        offsets = rec_get_offsets(rec, clust_index, offsets_,
1430
1409
                                  ULINT_UNDEFINED, &heap);
1431
 
 
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. */
1436
 
                ext = &node->ext;
1437
 
        } else {
1438
 
                /* REDUNDANT and COMPACT formats store a local
1439
 
                768-byte prefix of each externally stored column.
1440
 
                No cache is needed. */
1441
 
                ext = NULL;
1442
 
                node->ext = NULL;
1443
 
        }
1444
 
 
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 */
1471
1436
{
1472
 
        mtr_t                   mtr;
1473
 
        const rec_t*            rec;
1474
 
        btr_pcur_t              pcur;
1475
 
        mem_heap_t*             heap;
1476
 
        dtuple_t*               entry;
1477
 
        dict_index_t*           index;
1478
 
        btr_cur_t*              btr_cur;
1479
 
        ibool                   referenced;
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;
 
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);
1484
1448
 
1485
1449
        index = node->index;
1486
1450
 
1487
 
        referenced = row_upd_index_is_referenced(index, trx);
 
1451
        check_ref = row_upd_index_is_referenced(index, trx);
1488
1452
 
1489
1453
        heap = mem_heap_create(1024);
1490
1454
 
1492
1456
        entry = row_build_index_entry(node->row, node->ext, index, heap);
1493
1457
        ut_a(entry);
1494
1458
 
 
1459
        log_free_check();
1495
1460
        mtr_start(&mtr);
1496
1461
 
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;
1500
 
 
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. */
1504
 
        if (!referenced) {
1505
 
                mode |= BTR_DELETE_MARK;
1506
 
        }
1507
 
 
1508
 
        search_result = row_search_index_entry(index, entry, mode,
1509
 
                                               &pcur, &mtr);
1510
 
 
 
1462
        found = row_search_index_entry(index, entry, BTR_MODIFY_LEAF, &pcur,
 
1463
                                       &mtr);
1511
1464
        btr_cur = btr_pcur_get_btr_cur(&pcur);
1512
1465
 
1513
1466
        rec = btr_cur_get_rec(btr_cur);
1514
1467
 
1515
 
        switch (search_result) {
1516
 
        case ROW_NOT_DELETED_REF:       /* should only occur for BTR_DELETE */
1517
 
                ut_error;
1518
 
                break;
1519
 
        case ROW_BUFFERED:
1520
 
                /* Entry was delete marked already. */
1521
 
                break;
1522
 
 
1523
 
        case ROW_NOT_FOUND:
 
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);
1537
1482
                fputs("\n"
1538
1483
                      "InnoDB: Submit a detailed bug report"
1539
1484
                      " to http://bugs.mysql.com\n", stderr);
1540
 
                break;
1541
 
        case ROW_FOUND:
 
1485
        } else {
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 */
1545
1489
 
1546
 
                if (!rec_get_deleted_flag(
1547
 
                        rec, dict_table_is_comp(index->table))) {
1548
 
 
1549
 
                        err = btr_cur_del_mark_set_sec_rec(
1550
 
                                0, btr_cur, TRUE, thr, &mtr);
1551
 
 
1552
 
                        if (err == DB_SUCCESS && referenced) {
1553
 
 
1554
 
                                ulint*  offsets;
1555
 
 
1556
 
                                offsets = rec_get_offsets(
1557
 
                                        rec, index, NULL, ULINT_UNDEFINED,
1558
 
                                        &heap);
1559
 
 
 
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);
1560
1499
                                /* NOTE that the following call loses
1561
1500
                                the position of pcur ! */
1562
1501
                                err = row_upd_check_references_constraints(
1564
1503
                                        index, offsets, thr, &mtr);
1565
1504
                        }
1566
1505
                }
1567
 
                break;
1568
1506
        }
1569
1507
 
1570
1508
        btr_pcur_close(&pcur);
1594
1532
deletes it if this is a delete.
1595
1533
@return DB_SUCCESS if operation successfully completed, else error
1596
1534
code or DB_LOCK_WAIT */
1597
 
static
 
1535
UNIV_INLINE
1598
1536
ulint
1599
1537
row_upd_sec_step(
1600
1538
/*=============*/
1625
1563
ulint
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 */
1634
1572
{
1635
1573
        mem_heap_t*     heap    = NULL;
1636
1574
        btr_pcur_t*     pcur;
1639
1577
        dict_table_t*   table;
1640
1578
        dtuple_t*       entry;
1641
1579
        ulint           err;
1642
 
        ibool           change_ownership = FALSE;
1643
1580
 
1644
1581
        ut_ad(node);
1645
1582
        ut_ad(dict_index_is_clust(index));
1651
1588
 
1652
1589
        if (node->state != UPD_NODE_INSERT_CLUSTERED) {
1653
1590
                rec_t*          rec;
1654
 
                dict_index_t*   node_index;
 
1591
                dict_index_t*   index;
1655
1592
                ulint           offsets_[REC_OFFS_NORMAL_SIZE];
1656
1593
                ulint*          offsets;
1657
1594
                rec_offs_init(offsets_);
1669
1606
                record is removed from the index tree, or updated. */
1670
1607
 
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,
1677
 
                        node->update, mtr);
1678
 
                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) {
1679
1616
                        /* NOTE that the following call loses
1680
1617
                        the position of pcur ! */
1681
 
 
1682
1618
                        err = row_upd_check_references_constraints(
1683
 
                                node, pcur, table, node_index, offsets, thr, mtr);
1684
 
 
 
1619
                                node, pcur, table, index, offsets, thr, mtr);
1685
1620
                        if (err != DB_SUCCESS) {
1686
 
 
1687
1621
                                mtr_commit(mtr);
1688
 
 
1689
1622
                                if (UNIV_LIKELY_NULL(heap)) {
1690
1623
                                        mem_heap_free(heap);
1691
1624
                                }
1692
 
 
1693
1625
                                return(err);
1694
1626
                        }
1695
1627
                }
1708
1640
 
1709
1641
        row_upd_index_entry_sys_field(entry, index, DATA_TRX_ID, trx->id);
1710
1642
 
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
1715
 
                back. */
 
1646
                if-branch above). We must unmark them. */
1716
1647
 
1717
1648
                btr_cur_unmark_dtuple_extern_fields(entry);
1718
1649
 
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 */
1848
 
        ibool           referenced,
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 */
1852
1782
{
1871
1801
 
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 ! */
1876
1806
 
1877
 
                err = row_upd_check_references_constraints(
1878
 
                        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);
1879
1811
        }
1880
1812
 
1881
1813
        mtr_commit(mtr);
1897
1829
        dict_index_t*   index;
1898
1830
        btr_pcur_t*     pcur;
1899
1831
        ibool           success;
 
1832
        ibool           check_ref;
1900
1833
        ulint           err;
1901
1834
        mtr_t*          mtr;
1902
1835
        mtr_t           mtr_buf;
1904
1837
        mem_heap_t*     heap            = NULL;
1905
1838
        ulint           offsets_[REC_OFFS_NORMAL_SIZE];
1906
1839
        ulint*          offsets;
1907
 
        ibool           referenced;
1908
1840
        rec_offs_init(offsets_);
1909
1841
 
1910
1842
        index = dict_table_get_first_index(node->table);
1911
1843
 
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));
1913
1845
 
1914
1846
        pcur = node->pcur;
1915
1847
 
1942
1874
        then we have to free the file segments of the index tree associated
1943
1875
        with the index */
1944
1876
 
1945
 
        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) {
1946
1879
 
1947
1880
                dict_drop_index_tree(btr_pcur_get_rec(pcur), mtr);
1948
1881
 
1978
1911
        /* NOTE: the following function calls will also commit mtr */
1979
1912
 
1980
1913
        if (node->is_delete) {
1981
 
                err = row_upd_del_mark_clust_rec(
1982
 
                        node, index, offsets, thr, referenced, mtr);
1983
 
 
 
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
2029
1961
                externally! */
2030
1962
 
2031
 
                err = row_upd_clust_rec_by_insert(
2032
 
                        node, index, thr, referenced, mtr);
2033
 
 
 
1963
                err = row_upd_clust_rec_by_insert(node, index, thr, check_ref,
 
1964
                                                  mtr);
2034
1965
                if (err != DB_SUCCESS) {
2035
1966
 
2036
1967
                        return(err);
2087
2018
        if (node->state == UPD_NODE_UPDATE_CLUSTERED
2088
2019
            || node->state == UPD_NODE_INSERT_CLUSTERED) {
2089
2020
 
2090
 
                log_free_check();
2091
2021
                err = row_upd_clust_step(node, thr);
2092
2022
 
2093
2023
                if (err != DB_SUCCESS) {
2102
2032
        }
2103
2033
 
2104
2034
        while (node->index != NULL) {
2105
 
 
2106
 
                log_free_check();
2107
2035
                err = row_upd_sec_step(node, thr);
2108
2036
 
2109
2037
                if (err != DB_SUCCESS) {
2154
2082
 
2155
2083
        trx_start_if_not_started(trx);
2156
2084
 
2157
 
        node = static_cast<upd_node_t *>(thr->run_node);
 
2085
        node = thr->run_node;
2158
2086
 
2159
2087
        sel_node = node->select;
2160
2088