~drizzle-trunk/drizzle/development

« back to all changes in this revision

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

  • Committer: Monty Taylor
  • Date: 2010-11-08 18:26:08 UTC
  • mto: This revision was merged to the branch mainline in revision 1931.
  • Revision ID: mordred@inaugust.com-20101108182608-lci86acl7r53sbi3
Replaced auto_ptr with scoped_ptr.

Show diffs side-by-side

added added

removed removed

Lines of Context:
1
1
/*****************************************************************************
2
2
 
3
 
Copyright (C) 1997, 2010, Innobase Oy. All Rights Reserved.
4
 
Copyright (C) 2008, Google Inc.
 
3
Copyright (c) 1997, 2010, Innobase Oy. All Rights Reserved.
 
4
Copyright (c) 2008, Google Inc.
5
5
 
6
6
Portions of this file contain modifications contributed and copyrighted by
7
7
Google, Inc. Those modifications are gratefully acknowledged and are described
88
88
/*========================*/
89
89
        ulint           mtype,          /*!< in: main type */
90
90
        ulint           prtype,         /*!< in: precise type */
91
 
        ulint           mbminmaxlen,    /*!< in: minimum and maximum length of
92
 
                                        a multi-byte character */
 
91
        ulint           mbminlen,       /*!< in: minimum length of a
 
92
                                        multi-byte character */
 
93
        ulint           mbmaxlen,       /*!< in: maximum length of a
 
94
                                        multi-byte character */
93
95
        const byte*     clust_field,    /*!< in: the locally stored part of
94
96
                                        the clustered index column, including
95
97
                                        the BLOB pointer; the clustered
104
106
        ulint   len;
105
107
        byte    buf[DICT_MAX_INDEX_COL_LEN];
106
108
 
107
 
        ut_a(clust_len >= BTR_EXTERN_FIELD_REF_SIZE);
108
 
 
109
 
        if (UNIV_UNLIKELY
110
 
            (!memcmp(clust_field + clust_len - BTR_EXTERN_FIELD_REF_SIZE,
111
 
                     field_ref_zero, BTR_EXTERN_FIELD_REF_SIZE))) {
112
 
                /* The externally stored field was not written yet.
113
 
                This record should only be seen by
114
 
                recv_recovery_rollback_active() or any
115
 
                TRX_ISO_READ_UNCOMMITTED transactions. */
116
 
                return(FALSE);
117
 
        }
118
 
 
119
109
        len = btr_copy_externally_stored_field_prefix(buf, sizeof buf,
120
110
                                                      zip_size,
121
111
                                                      clust_field, clust_len);
129
119
                return(FALSE);
130
120
        }
131
121
 
132
 
        len = dtype_get_at_most_n_mbchars(prtype, mbminmaxlen,
 
122
        len = dtype_get_at_most_n_mbchars(prtype, mbminlen, mbmaxlen,
133
123
                                          sec_len, len, (const char*) buf);
134
124
 
135
125
        return(!cmp_data_data(mtype, prtype, buf, len, sec_field, sec_len));
212
202
                        }
213
203
 
214
204
                        len = dtype_get_at_most_n_mbchars(
215
 
                                col->prtype, col->mbminmaxlen,
 
205
                                col->prtype, col->mbminlen, col->mbmaxlen,
216
206
                                ifield->prefix_len, len, (char*) clust_field);
217
207
 
218
208
                        if (rec_offs_nth_extern(clust_offs, clust_pos)
219
209
                            && len < sec_len) {
220
210
                                if (!row_sel_sec_rec_is_for_blob(
221
211
                                            col->mtype, col->prtype,
222
 
                                            col->mbminmaxlen,
 
212
                                            col->mbminlen, col->mbmaxlen,
223
213
                                            clust_field, clust_len,
224
214
                                            sec_field, sec_len,
225
215
                                            dict_table_zip_size(
258
248
{
259
249
        sel_node_t*     node;
260
250
 
261
 
        node = static_cast<sel_node_t *>(mem_heap_alloc(heap, sizeof(sel_node_t)));
 
251
        node = mem_heap_alloc(heap, sizeof(sel_node_t));
262
252
        node->common.type = QUE_NODE_SELECT;
263
253
        node->state = SEL_NODE_OPEN;
264
254
 
338
328
                eval_node_copy_val(var->alias, exp);
339
329
 
340
330
                exp = que_node_get_next(exp);
341
 
                var = static_cast<sym_node_t *>(que_node_get_next(var));
 
331
                var = que_node_get_next(var);
342
332
        }
343
333
}
344
334
 
355
345
 
356
346
        ut_ad(node->is_aggregate);
357
347
 
358
 
        func_node = static_cast<func_node_t *>(node->select_list);
 
348
        func_node = node->select_list;
359
349
 
360
350
        while (func_node) {
361
351
                eval_node_set_int_val(func_node, 0);
362
352
 
363
 
                func_node = static_cast<func_node_t *>(que_node_get_next(func_node));
 
353
                func_node = que_node_get_next(func_node);
364
354
        }
365
355
 
366
356
        node->aggregate_already_fetched = FALSE;
426
416
                                                              field_no))) {
427
417
 
428
418
                                /* Copy an externally stored field to the
429
 
                                temporary heap, if possible. */
 
419
                                temporary heap */
430
420
 
431
421
                                heap = mem_heap_create(1);
432
422
 
435
425
                                        dict_table_zip_size(index->table),
436
426
                                        field_no, &len, heap);
437
427
 
438
 
                                /* data == NULL means that the
439
 
                                externally stored field was not
440
 
                                written yet. This record
441
 
                                should only be seen by
442
 
                                recv_recovery_rollback_active() or any
443
 
                                TRX_ISO_READ_UNCOMMITTED
444
 
                                transactions. The InnoDB SQL parser
445
 
                                (the sole caller of this function)
446
 
                                does not implement READ UNCOMMITTED,
447
 
                                and it is not involved during rollback. */
448
 
                                ut_a(data);
449
428
                                ut_a(len != UNIV_SQL_NULL);
450
429
 
451
430
                                needs_copy = TRUE;
486
465
 
487
466
        ut_ad(que_node_get_type(column) == QUE_NODE_SYMBOL);
488
467
 
489
 
        column->prefetch_buf = static_cast<sel_buf_t *>(mem_alloc(SEL_MAX_N_PREFETCH
490
 
                                                                  * sizeof(sel_buf_t)));
 
468
        column->prefetch_buf = mem_alloc(SEL_MAX_N_PREFETCH
 
469
                                         * sizeof(sel_buf_t));
491
470
        for (i = 0; i < SEL_MAX_N_PREFETCH; i++) {
492
471
                sel_buf = column->prefetch_buf + i;
493
472
 
566
545
                column values to be able to free it later: therefore
567
546
                we swap the values for sel_buf and val */
568
547
 
569
 
                sel_buf->data = static_cast<byte *>(dfield_get_data(val));
 
548
                sel_buf->data = dfield_get_data(val);
570
549
                sel_buf->len = dfield_get_len(val);
571
550
                sel_buf->val_buf_size = que_node_get_val_buf_size(column);
572
551
 
634
613
 
635
614
                val = que_node_get_val(column);
636
615
 
637
 
                data = static_cast<byte *>(dfield_get_data(val));
 
616
                data = dfield_get_data(val);
638
617
                len = dfield_get_len(val);
639
618
                val_buf_size = que_node_get_val_buf_size(column);
640
619
 
746
725
                /* Evaluate the left side of the comparison, i.e., get the
747
726
                column value if there is an indirection */
748
727
 
749
 
          eval_sym(static_cast<sym_node_t *>(cond->args));
 
728
                eval_sym(cond->args);
750
729
 
751
730
                /* Do the comparison */
752
731
 
882
861
                err = lock_clust_rec_read_check_and_lock(
883
862
                        0, btr_pcur_get_block(&plan->clust_pcur),
884
863
                        clust_rec, index, offsets,
885
 
                        static_cast<lock_mode>(node->row_lock_mode), lock_type, thr);
886
 
 
887
 
                switch (err) {
888
 
                case DB_SUCCESS:
889
 
                case DB_SUCCESS_LOCKED_REC:
890
 
                        /* Declare the variable uninitialized in Valgrind.
891
 
                        It should be set to DB_SUCCESS at func_exit. */
892
 
                        UNIV_MEM_INVALID(&err, sizeof err);
893
 
                        break;
894
 
                default:
 
864
                        node->row_lock_mode, lock_type, thr);
 
865
 
 
866
                if (err != DB_SUCCESS) {
 
867
 
895
868
                        goto err_exit;
896
869
                }
897
870
        } else {
947
920
        when plan->clust_pcur was positioned.  The latch will not be
948
921
        released until mtr_commit(mtr). */
949
922
 
950
 
        ut_ad(!rec_get_deleted_flag(clust_rec, rec_offs_comp(offsets)));
951
923
        row_sel_fetch_columns(index, clust_rec, offsets,
952
924
                              UT_LIST_GET_FIRST(plan->columns));
953
925
        *out_rec = clust_rec;
962
934
 
963
935
/*********************************************************************//**
964
936
Sets a lock on a record.
965
 
@return DB_SUCCESS, DB_SUCCESS_LOCKED_REC, or error code */
 
937
@return DB_SUCCESS or error code */
966
938
UNIV_INLINE
967
 
enum db_err
 
939
ulint
968
940
sel_set_rec_lock(
969
941
/*=============*/
970
942
        const buf_block_t*      block,  /*!< in: buffer block of rec */
976
948
                                        LOC_REC_NOT_GAP */
977
949
        que_thr_t*              thr)    /*!< in: query thread */
978
950
{
979
 
        trx_t*          trx;
980
 
        enum db_err     err;
 
951
        trx_t*  trx;
 
952
        ulint   err;
981
953
 
982
954
        trx = thr_get_trx(thr);
983
955
 
989
961
        }
990
962
 
991
963
        if (dict_index_is_clust(index)) {
992
 
                err = lock_clust_rec_read_check_and_lock(0, block, rec, index,
993
 
                                                         offsets, static_cast<lock_mode>(mode), type, thr);
 
964
                err = lock_clust_rec_read_check_and_lock(
 
965
                        0, block, rec, index, offsets, mode, type, thr);
994
966
        } else {
995
 
                err = lock_sec_rec_read_check_and_lock(0, block, rec, index,
996
 
                                                       offsets, static_cast<lock_mode>(mode), type, thr);
 
967
                err = lock_sec_rec_read_check_and_lock(
 
968
                        0, block, rec, index, offsets, mode, type, thr);
997
969
        }
998
970
 
999
971
        return(err);
1510
1482
                                               node->row_lock_mode,
1511
1483
                                               lock_type, thr);
1512
1484
 
1513
 
                        switch (err) {
1514
 
                        case DB_SUCCESS_LOCKED_REC:
1515
 
                                err = DB_SUCCESS;
1516
 
                        case DB_SUCCESS:
1517
 
                                break;
1518
 
                        default:
 
1485
                        if (err != DB_SUCCESS) {
1519
1486
                                /* Note that in this case we will store in pcur
1520
1487
                                the PREDECESSOR of the record we are waiting
1521
1488
                                the lock for */
 
1489
 
1522
1490
                                goto lock_wait_or_error;
1523
1491
                        }
1524
1492
                }
1570
1538
                                       rec, index, offsets,
1571
1539
                                       node->row_lock_mode, lock_type, thr);
1572
1540
 
1573
 
                switch (err) {
1574
 
                case DB_SUCCESS_LOCKED_REC:
1575
 
                        err = DB_SUCCESS;
1576
 
                case DB_SUCCESS:
1577
 
                        break;
1578
 
                default:
 
1541
                if (err != DB_SUCCESS) {
 
1542
 
1579
1543
                        goto lock_wait_or_error;
1580
1544
                }
1581
1545
        }
1650
1614
                                }
1651
1615
 
1652
1616
                                if (old_vers == NULL) {
1653
 
                                        /* The record does not exist
1654
 
                                        in our read view. Skip it, but
1655
 
                                        first attempt to determine
1656
 
                                        whether the index segment we
1657
 
                                        are searching through has been
1658
 
                                        exhausted. */
1659
 
 
1660
1617
                                        offsets = rec_get_offsets(
1661
1618
                                                rec, index, offsets,
1662
1619
                                                ULINT_UNDEFINED, &heap);
1741
1698
                                            &mtr);
1742
1699
                mtr_has_extra_clust_latch = TRUE;
1743
1700
 
1744
 
                switch (err) {
1745
 
                case DB_SUCCESS_LOCKED_REC:
1746
 
                        err = DB_SUCCESS;
1747
 
                case DB_SUCCESS:
1748
 
                        break;
1749
 
                default:
 
1701
                if (err != DB_SUCCESS) {
 
1702
 
1750
1703
                        goto lock_wait_or_error;
1751
1704
                }
1752
1705
 
1931
1884
                        thr->run_node = que_node_get_parent(node);
1932
1885
                }
1933
1886
 
1934
 
                err = DB_SUCCESS;
1935
1887
                goto func_exit;
1936
1888
        }
1937
1889
 
2023
1975
 
2024
1976
        ut_ad(thr);
2025
1977
 
2026
 
        node = static_cast<sel_node_t *>(thr->run_node);
 
1978
        node = thr->run_node;
2027
1979
 
2028
1980
        ut_ad(que_node_get_type(node) == QUE_NODE_SELECT);
2029
1981
 
2060
2012
 
2061
2013
                        while (table_node) {
2062
2014
                                err = lock_table(0, table_node->table,
2063
 
                                                 static_cast<lock_mode>(i_lock_mode), thr);
 
2015
                                                 i_lock_mode, thr);
2064
2016
                                if (err != DB_SUCCESS) {
2065
2017
                                        thr_get_trx(thr)->error_state = err;
2066
2018
 
2067
2019
                                        return(NULL);
2068
2020
                                }
2069
2021
 
2070
 
                                table_node = static_cast<sym_node_t *>(que_node_get_next(table_node));
 
2022
                                table_node = que_node_get_next(table_node);
2071
2023
                        }
2072
2024
                }
2073
2025
 
2089
2041
                        /* Reset the aggregate total values */
2090
2042
                        sel_reset_aggregate_vals(node);
2091
2043
                }
2092
 
 
2093
 
                err = DB_SUCCESS;
2094
2044
        }
2095
2045
 
2096
2046
        err = row_sel(node, thr);
2124
2074
 
2125
2075
        ut_ad(thr);
2126
2076
 
2127
 
        node = static_cast<fetch_node_t *>(thr->run_node);
 
2077
        node = thr->run_node;
2128
2078
        sel_node = node->cursor_def;
2129
2079
 
2130
2080
        ut_ad(que_node_get_type(node) == QUE_NODE_FETCH);
2183
2133
        void*   row,            /*!< in:  sel_node_t* */
2184
2134
        void*   user_arg)       /*!< in:  not used */
2185
2135
{
2186
 
        sel_node_t *node = static_cast<sel_node_t *>(row);
 
2136
        sel_node_t*     node = row;
2187
2137
        que_node_t*     exp;
2188
2138
        ulint           i = 0;
2189
2139
 
2232
2182
 
2233
2183
        ut_ad(thr);
2234
2184
 
2235
 
        node = static_cast<row_printf_node_t *>(thr->run_node);
 
2185
        node = thr->run_node;
2236
2186
 
2237
2187
        sel_node = node->sel_node;
2238
2188
 
2544
2494
        ulint           len)    /*!< in: length of the data */
2545
2495
{
2546
2496
        byte*   ptr;
 
2497
        byte*   field_end;
 
2498
        byte*   pad_ptr;
2547
2499
 
2548
2500
        ut_ad(len != UNIV_SQL_NULL);
2549
 
        UNIV_MEM_ASSERT_RW(data, len);
2550
2501
 
2551
2502
        switch (templ->type) {
2552
 
                const byte*     field_end;
2553
 
                byte*           pad;
2554
2503
        case DATA_INT:
2555
2504
                /* Convert integer data from Innobase to a little-endian
2556
2505
                format, sign bit restored to normal */
2594
2543
                unused end of a >= 5.0.3 true VARCHAR column, just in case
2595
2544
                MySQL expects its contents to be deterministic. */
2596
2545
 
2597
 
                pad = dest + len;
 
2546
                pad_ptr = dest + len;
2598
2547
 
2599
2548
                ut_ad(templ->mbminlen <= templ->mbmaxlen);
2600
2549
 
2601
 
                /* We treat some Unicode charset strings specially. */
2602
 
                switch (templ->mbminlen) {
2603
 
                case 4:
2604
 
                        /* InnoDB should never have stripped partial
2605
 
                        UTF-32 characters. */
2606
 
                        ut_a(!(len & 3));
2607
 
                        break;
2608
 
                case 2:
2609
 
                        /* A space char is two bytes,
2610
 
                        0x0020 in UCS2 and UTF-16 */
 
2550
                /* We handle UCS2 charset strings differently. */
 
2551
                if (templ->mbminlen == 2) {
 
2552
                        /* A space char is two bytes, 0x0020 in UCS2 */
2611
2553
 
2612
 
                        if (UNIV_UNLIKELY(len & 1)) {
 
2554
                        if (len & 1) {
2613
2555
                                /* A 0x20 has been stripped from the column.
2614
2556
                                Pad it back. */
2615
2557
 
2616
 
                                if (pad < field_end) {
2617
 
                                        *pad++ = 0x20;
 
2558
                                if (pad_ptr < field_end) {
 
2559
                                        *pad_ptr = 0x20;
 
2560
                                        pad_ptr++;
2618
2561
                                }
2619
2562
                        }
 
2563
 
 
2564
                        /* Pad the rest of the string with 0x0020 */
 
2565
 
 
2566
                        while (pad_ptr < field_end) {
 
2567
                                *pad_ptr = 0x00;
 
2568
                                pad_ptr++;
 
2569
                                *pad_ptr = 0x20;
 
2570
                                pad_ptr++;
 
2571
                        }
 
2572
                } else {
 
2573
                        ut_ad(templ->mbminlen == 1);
 
2574
                        /* space=0x20 */
 
2575
 
 
2576
                        memset(pad_ptr, 0x20, field_end - pad_ptr);
2620
2577
                }
2621
 
 
2622
 
                row_mysql_pad_col(templ->mbminlen, pad, field_end - pad);
2623
2578
                break;
2624
2579
 
2625
2580
        case DATA_BLOB:
2644
2599
                      || !(templ->mysql_col_len % templ->mbmaxlen));
2645
2600
                ut_ad(len * templ->mbmaxlen >= templ->mysql_col_len);
2646
2601
 
2647
 
                if (templ->mbminlen == 1 && templ->mbmaxlen != 1) {
 
2602
                if (templ->mbminlen != templ->mbmaxlen) {
2648
2603
                        /* Pad with spaces. This undoes the stripping
2649
 
                        done in row0mysql.c, function
 
2604
                        done in row0mysql.ic, function
2650
2605
                        row_mysql_store_col_in_innobase_format(). */
2651
2606
 
2652
2607
                        memset(dest + len, 0x20, templ->mysql_col_len - len);
2677
2632
Note that the template in prebuilt may advise us to copy only a few
2678
2633
columns to mysql_rec, other columns are left blank. All columns may not
2679
2634
be needed in the query.
2680
 
@return TRUE on success, FALSE if not all columns could be retrieved */
 
2635
@return TRUE if success, FALSE if could not allocate memory for a BLOB
 
2636
(though we may also assert in that case) */
2681
2637
static
2682
 
#ifdef __GNUC__
2683
 
 __attribute__((warn_unused_result))
2684
 
#endif
2685
2638
ibool
2686
2639
row_sel_store_mysql_rec(
2687
2640
/*====================*/
2689
2642
        row_prebuilt_t* prebuilt,       /*!< in: prebuilt struct */
2690
2643
        const rec_t*    rec,            /*!< in: Innobase record in the index
2691
2644
                                        which was described in prebuilt's
2692
 
                                        template, or in the clustered index;
2693
 
                                        must be protected by a page latch */
2694
 
        ibool           rec_clust,      /*!< in: TRUE if rec is in the
2695
 
                                        clustered index instead of
2696
 
                                        prebuilt->index */
 
2645
                                        template; must be protected by
 
2646
                                        a page latch */
2697
2647
        const ulint*    offsets)        /*!< in: array returned by
2698
 
                                        rec_get_offsets(rec) */
 
2648
                                        rec_get_offsets() */
2699
2649
{
2700
 
        mem_heap_t*     extern_field_heap       = NULL;
2701
 
        mem_heap_t*     heap;
2702
 
        ulint           i;
 
2650
        mysql_row_templ_t*      templ;
 
2651
        mem_heap_t*             extern_field_heap       = NULL;
 
2652
        mem_heap_t*             heap;
 
2653
        const byte*             data;
 
2654
        ulint                   len;
 
2655
        ulint                   i;
2703
2656
 
2704
2657
        ut_ad(prebuilt->mysql_template);
2705
2658
        ut_ad(prebuilt->default_rec);
2706
2659
        ut_ad(rec_offs_validate(rec, NULL, offsets));
2707
 
        ut_ad(!rec_get_deleted_flag(rec, rec_offs_comp(offsets)));
2708
2660
 
2709
2661
        if (UNIV_LIKELY_NULL(prebuilt->blob_heap)) {
2710
2662
                mem_heap_free(prebuilt->blob_heap);
2713
2665
 
2714
2666
        for (i = 0; i < prebuilt->n_template ; i++) {
2715
2667
 
2716
 
                const mysql_row_templ_t*templ = prebuilt->mysql_template + i;
2717
 
                const byte*             data;
2718
 
                ulint                   len;
2719
 
                ulint                   field_no;
2720
 
 
2721
 
                field_no = rec_clust
2722
 
                        ? templ->clust_rec_field_no : templ->rec_field_no;
2723
 
 
2724
 
                if (UNIV_UNLIKELY(rec_offs_nth_extern(offsets, field_no))) {
 
2668
                templ = prebuilt->mysql_template + i;
 
2669
 
 
2670
                if (UNIV_UNLIKELY(rec_offs_nth_extern(offsets,
 
2671
                                                      templ->rec_field_no))) {
2725
2672
 
2726
2673
                        /* Copy an externally stored field to the temporary
2727
2674
                        heap */
2749
2696
                        data = btr_rec_copy_externally_stored_field(
2750
2697
                                rec, offsets,
2751
2698
                                dict_table_zip_size(prebuilt->table),
2752
 
                                field_no, &len, heap);
2753
 
 
2754
 
                        if (UNIV_UNLIKELY(!data)) {
2755
 
                                /* The externally stored field
2756
 
                                was not written yet. This
2757
 
                                record should only be seen by
2758
 
                                recv_recovery_rollback_active()
2759
 
                                or any TRX_ISO_READ_UNCOMMITTED
2760
 
                                transactions. */
2761
 
 
2762
 
                                if (extern_field_heap) {
2763
 
                                        mem_heap_free(extern_field_heap);
2764
 
                                }
2765
 
 
2766
 
                                return(FALSE);
2767
 
                        }
2768
 
 
2769
 
                        if (UNIV_UNLIKELY(!data)) {
2770
 
                                /* The externally stored field
2771
 
                                was not written yet. This
2772
 
                                record should only be seen by
2773
 
                                recv_recovery_rollback_active()
2774
 
                                or any TRX_ISO_READ_UNCOMMITTED
2775
 
                                transactions. */
2776
 
 
2777
 
                                if (extern_field_heap) {
2778
 
                                        mem_heap_free(extern_field_heap);
2779
 
                                }
2780
 
 
2781
 
                                return(FALSE);
2782
 
                        }
 
2699
                                templ->rec_field_no, &len, heap);
2783
2700
 
2784
2701
                        ut_a(len != UNIV_SQL_NULL);
2785
2702
                } else {
2786
2703
                        /* Field is stored in the row. */
2787
2704
 
2788
 
                        data = rec_get_nth_field(rec, offsets, field_no, &len);
 
2705
                        data = rec_get_nth_field(rec, offsets,
 
2706
                                                 templ->rec_field_no, &len);
2789
2707
 
2790
2708
                        if (UNIV_UNLIKELY(templ->type == DATA_BLOB)
2791
2709
                            && len != UNIV_SQL_NULL) {
2801
2719
                                                UNIV_PAGE_SIZE);
2802
2720
                                }
2803
2721
 
2804
 
                                data = static_cast<byte *>(memcpy(mem_heap_alloc(
 
2722
                                data = memcpy(mem_heap_alloc(
2805
2723
                                                prebuilt->blob_heap, len),
2806
 
                                                                  data, len));
 
2724
                                                data, len);
2807
2725
                        }
2808
2726
                }
2809
2727
 
2828
2746
                        /* MySQL assumes that the field for an SQL
2829
2747
                        NULL value is set to the default value. */
2830
2748
 
2831
 
                        UNIV_MEM_ASSERT_RW(prebuilt->default_rec
2832
 
                                           + templ->mysql_col_offset,
2833
 
                                           templ->mysql_col_len);
2834
2749
                        mysql_rec[templ->mysql_null_byte_offset]
2835
2750
                                |= (byte) templ->mysql_null_bit_mask;
2836
2751
                        memcpy(mysql_rec + templ->mysql_col_offset,
2882
2797
Retrieves the clustered index record corresponding to a record in a
2883
2798
non-clustered index. Does the necessary locking. Used in the MySQL
2884
2799
interface.
2885
 
@return DB_SUCCESS, DB_SUCCESS_LOCKED_REC, or error code */
 
2800
@return DB_SUCCESS or error code */
2886
2801
static
2887
 
enum db_err
 
2802
ulint
2888
2803
row_sel_get_clust_rec_for_mysql(
2889
2804
/*============================*/
2890
2805
        row_prebuilt_t* prebuilt,/*!< in: prebuilt struct in the handle */
2911
2826
        dict_index_t*   clust_index;
2912
2827
        const rec_t*    clust_rec;
2913
2828
        rec_t*          old_vers;
2914
 
        enum db_err     err;
 
2829
        ulint           err;
2915
2830
        trx_t*          trx;
2916
2831
 
2917
2832
        *out_rec = NULL;
2970
2885
 
2971
2886
                clust_rec = NULL;
2972
2887
 
2973
 
                err = DB_SUCCESS;
2974
2888
                goto func_exit;
2975
2889
        }
2976
2890
 
2985
2899
                err = lock_clust_rec_read_check_and_lock(
2986
2900
                        0, btr_pcur_get_block(prebuilt->clust_pcur),
2987
2901
                        clust_rec, clust_index, *offsets,
2988
 
                        static_cast<lock_mode>(prebuilt->select_lock_type),
2989
 
                        LOCK_REC_NOT_GAP, thr);
2990
 
                switch (err) {
2991
 
                case DB_SUCCESS:
2992
 
                case DB_SUCCESS_LOCKED_REC:
2993
 
                        break;
2994
 
                default:
 
2902
                        prebuilt->select_lock_type, LOCK_REC_NOT_GAP, thr);
 
2903
                if (err != DB_SUCCESS) {
 
2904
 
2995
2905
                        goto err_exit;
2996
2906
                }
2997
2907
        } else {
3010
2920
 
3011
2921
                        /* The following call returns 'offsets' associated with
3012
2922
                        'old_vers' */
3013
 
                  err = static_cast<db_err>(row_sel_build_prev_vers_for_mysql(
 
2923
                        err = row_sel_build_prev_vers_for_mysql(
3014
2924
                                trx->read_view, clust_index, prebuilt,
3015
2925
                                clust_rec, offsets, offset_heap, &old_vers,
3016
 
                                mtr));
 
2926
                                mtr);
3017
2927
 
3018
2928
                        if (err != DB_SUCCESS || old_vers == NULL) {
3019
2929
 
3051
2961
                                     rec, sec_index, clust_rec, clust_index));
3052
2962
#endif
3053
2963
                }
3054
 
 
3055
 
                err = DB_SUCCESS;
3056
2964
        }
3057
2965
 
3058
2966
func_exit:
3065
2973
                btr_pcur_store_position(prebuilt->clust_pcur, mtr);
3066
2974
        }
3067
2975
 
 
2976
        err = DB_SUCCESS;
3068
2977
err_exit:
3069
2978
        return(err);
3070
2979
}
3148
3057
        row_prebuilt_t* prebuilt)       /*!< in: prebuilt struct */
3149
3058
{
3150
3059
        ulint                   i;
3151
 
        const mysql_row_templ_t*templ;
 
3060
        mysql_row_templ_t*      templ;
3152
3061
        byte*                   cached_rec;
3153
3062
        ut_ad(prebuilt->n_fetch_cached > 0);
3154
3063
        ut_ad(prebuilt->mysql_prefix_len <= prebuilt->mysql_row_len);
3161
3070
 
3162
3071
                for (i = 0; i < prebuilt->n_template; i++) {
3163
3072
                        templ = prebuilt->mysql_template + i;
3164
 
#if 0 /* Some of the cached_rec may legitimately be uninitialized. */
3165
 
                        UNIV_MEM_ASSERT_RW(cached_rec
3166
 
                                           + templ->mysql_col_offset,
3167
 
                                           templ->mysql_col_len);
3168
 
#endif
3169
3073
                        ut_memcpy(buf + templ->mysql_col_offset,
3170
3074
                                  cached_rec + templ->mysql_col_offset,
3171
3075
                                  templ->mysql_col_len);
3180
3084
                }
3181
3085
        }
3182
3086
        else {
3183
 
#if 0 /* Some of the cached_rec may legitimately be uninitialized. */
3184
 
                UNIV_MEM_ASSERT_RW(prebuilt->fetch_cache
3185
 
                                   [prebuilt->fetch_cache_first],
3186
 
                                   prebuilt->mysql_prefix_len);
3187
 
#endif
3188
3087
                ut_memcpy(buf,
3189
3088
                          prebuilt->fetch_cache[prebuilt->fetch_cache_first],
3190
3089
                          prebuilt->mysql_prefix_len);
3198
3097
}
3199
3098
 
3200
3099
/********************************************************************//**
3201
 
Pushes a row for MySQL to the fetch cache.
3202
 
@return TRUE on success, FALSE if the record contains incomplete BLOBs */
 
3100
Pushes a row for MySQL to the fetch cache. */
3203
3101
UNIV_INLINE
3204
 
#ifdef __GNUC__
3205
 
__attribute__((warn_unused_result))
3206
 
#endif
3207
 
ibool
 
3102
void
3208
3103
row_sel_push_cache_row_for_mysql(
3209
3104
/*=============================*/
3210
3105
        row_prebuilt_t* prebuilt,       /*!< in: prebuilt struct */
3211
 
        const rec_t*    rec,            /*!< in: record to push, in the index
3212
 
                                        which was described in prebuilt's
3213
 
                                        template, or in the clustered index;
3214
 
                                        must be protected by a page latch */
3215
 
        ibool           rec_clust,      /*!< in: TRUE if rec is in the
3216
 
                                        clustered index instead of
3217
 
                                        prebuilt->index */
3218
 
        const ulint*    offsets)        /*!< in: rec_get_offsets(rec) */
 
3106
        const rec_t*    rec,            /*!< in: record to push; must
 
3107
                                        be protected by a page latch */
 
3108
        const ulint*    offsets)        /*!<in: rec_get_offsets() */
3219
3109
{
3220
3110
        byte*   buf;
3221
3111
        ulint   i;
3222
3112
 
3223
3113
        ut_ad(prebuilt->n_fetch_cached < MYSQL_FETCH_CACHE_SIZE);
3224
3114
        ut_ad(rec_offs_validate(rec, NULL, offsets));
3225
 
        ut_ad(!rec_get_deleted_flag(rec, rec_offs_comp(offsets)));
3226
3115
        ut_a(!prebuilt->templ_contains_blob);
3227
3116
 
3228
3117
        if (prebuilt->fetch_cache[0] == NULL) {
3234
3123
                        buffers in Linux. Put magic numbers there to help
3235
3124
                        to track a possible bug. */
3236
3125
 
3237
 
                        buf = static_cast<byte *>(mem_alloc(prebuilt->mysql_row_len + 8));
 
3126
                        buf = mem_alloc(prebuilt->mysql_row_len + 8);
3238
3127
 
3239
3128
                        prebuilt->fetch_cache[i] = buf + 4;
3240
3129
 
3245
3134
        }
3246
3135
 
3247
3136
        ut_ad(prebuilt->fetch_cache_first == 0);
3248
 
        UNIV_MEM_INVALID(prebuilt->fetch_cache[prebuilt->n_fetch_cached],
3249
 
                         prebuilt->mysql_row_len);
3250
3137
 
3251
3138
        if (UNIV_UNLIKELY(!row_sel_store_mysql_rec(
3252
3139
                                  prebuilt->fetch_cache[
3253
3140
                                          prebuilt->n_fetch_cached],
3254
 
                                  prebuilt, rec, rec_clust, offsets))) {
3255
 
                return(FALSE);
 
3141
                                  prebuilt, rec, offsets))) {
 
3142
                ut_error;
3256
3143
        }
3257
3144
 
3258
3145
        prebuilt->n_fetch_cached++;
3259
 
        return(TRUE);
3260
3146
}
3261
3147
 
3262
3148
/*********************************************************************//**
3394
3280
        mem_heap_t*     heap                            = NULL;
3395
3281
        ulint           offsets_[REC_OFFS_NORMAL_SIZE];
3396
3282
        ulint*          offsets                         = offsets_;
3397
 
        ibool           table_lock_waited               = FALSE;
3398
3283
 
3399
3284
        rec_offs_init(offsets_);
3400
3285
 
3625
3510
                                row_sel_try_search_shortcut_for_mysql().
3626
3511
                                The latch will not be released until
3627
3512
                                mtr_commit(&mtr). */
3628
 
                                ut_ad(!rec_get_deleted_flag(rec, comp));
3629
3513
 
3630
3514
                                if (!row_sel_store_mysql_rec(buf, prebuilt,
3631
 
                                                             rec, FALSE,
3632
 
                                                             offsets)) {
3633
 
                                        /* Only fresh inserts may contain
3634
 
                                        incomplete externally stored
3635
 
                                        columns. Pretend that such
3636
 
                                        records do not exist. Such
3637
 
                                        records may only be accessed
3638
 
                                        at the READ UNCOMMITTED
3639
 
                                        isolation level or when
3640
 
                                        rolling back a recovered
3641
 
                                        transaction. Rollback happens
3642
 
                                        at a lower level, not here. */
3643
 
                                        ut_a(trx->isolation_level
3644
 
                                             == TRX_ISO_READ_UNCOMMITTED);
 
3515
                                                             rec, offsets)) {
 
3516
                                        err = DB_TOO_BIG_RECORD;
3645
3517
 
3646
 
                                        /* Proceed as in case SEL_RETRY. */
3647
 
                                        break;
 
3518
                                        /* We let the main loop to do the
 
3519
                                        error handling */
 
3520
                                        goto shortcut_fails_too_big_rec;
3648
3521
                                }
3649
3522
 
3650
3523
                                mtr_commit(&mtr);
3684
3557
                        default:
3685
3558
                                ut_ad(0);
3686
3559
                        }
3687
 
 
 
3560
shortcut_fails_too_big_rec:
3688
3561
                        mtr_commit(&mtr);
3689
3562
                        mtr_start(&mtr);
3690
3563
                }
3698
3571
                trx->has_search_latch = FALSE;
3699
3572
        }
3700
3573
 
3701
 
        ut_ad(prebuilt->sql_stat_start || trx->conc_state == TRX_ACTIVE);
3702
 
        ut_ad(trx->conc_state == TRX_NOT_STARTED
3703
 
              || trx->conc_state == TRX_ACTIVE);
3704
 
        ut_ad(prebuilt->sql_stat_start
3705
 
              || prebuilt->select_lock_type != LOCK_NONE
3706
 
              || trx->read_view);
3707
 
 
3708
 
        ut_ad(prebuilt->sql_stat_start || trx->conc_state == TRX_ACTIVE);
3709
 
        ut_ad(trx->conc_state == TRX_NOT_STARTED
3710
 
              || trx->conc_state == TRX_ACTIVE);
3711
 
        ut_ad(prebuilt->sql_stat_start
3712
 
              || prebuilt->select_lock_type != LOCK_NONE
3713
 
              || trx->read_view);
3714
 
 
3715
3574
        trx_start_if_not_started(trx);
3716
3575
 
3717
3576
        if (trx->isolation_level <= TRX_ISO_READ_COMMITTED
3742
3601
 
3743
3602
        clust_index = dict_table_get_first_index(index->table);
3744
3603
 
3745
 
        /* Do some start-of-statement preparations */
3746
 
 
3747
 
        if (!prebuilt->sql_stat_start) {
3748
 
                /* No need to set an intention lock or assign a read view */
3749
 
 
3750
 
                if (trx->read_view == NULL
3751
 
                    && prebuilt->select_lock_type == LOCK_NONE) {
3752
 
 
3753
 
                        fputs("InnoDB: Error: MySQL is trying to"
3754
 
                              " perform a consistent read\n"
3755
 
                              "InnoDB: but the read view is not assigned!\n",
3756
 
                              stderr);
3757
 
                        trx_print(stderr, trx, 600);
3758
 
                        fputc('\n', stderr);
3759
 
                        ut_error;
3760
 
                }
3761
 
        } else if (prebuilt->select_lock_type == LOCK_NONE) {
3762
 
                /* This is a consistent read */
3763
 
                /* Assign a read view for the query */
3764
 
 
3765
 
                trx_assign_read_view(trx);
3766
 
                prebuilt->sql_stat_start = FALSE;
3767
 
        } else {
3768
 
wait_table_again:
3769
 
                err = lock_table(0, index->table,
3770
 
                                 prebuilt->select_lock_type == LOCK_S
3771
 
                                 ? LOCK_IS : LOCK_IX, thr);
3772
 
 
3773
 
                if (err != DB_SUCCESS) {
3774
 
 
3775
 
                        table_lock_waited = TRUE;
3776
 
                        goto lock_table_wait;
3777
 
                }
3778
 
                prebuilt->sql_stat_start = FALSE;
3779
 
        }
3780
 
 
3781
 
        /* Open or restore index cursor position */
3782
 
 
3783
3604
        if (UNIV_LIKELY(direction != 0)) {
3784
3605
                ibool   need_to_process = sel_restore_position_for_mysql(
3785
3606
                        &same_user_rec, BTR_SEARCH_LEAF,
3834
3655
                                               prebuilt->select_lock_type,
3835
3656
                                               LOCK_GAP, thr);
3836
3657
 
3837
 
                        switch (err) {
3838
 
                        case DB_SUCCESS_LOCKED_REC:
3839
 
                                err = DB_SUCCESS;
3840
 
                        case DB_SUCCESS:
3841
 
                                break;
3842
 
                        default:
 
3658
                        if (err != DB_SUCCESS) {
 
3659
 
3843
3660
                                goto lock_wait_or_error;
3844
3661
                        }
3845
3662
                }
3855
3672
                }
3856
3673
        }
3857
3674
 
 
3675
        if (!prebuilt->sql_stat_start) {
 
3676
                /* No need to set an intention lock or assign a read view */
 
3677
 
 
3678
                if (trx->read_view == NULL
 
3679
                    && prebuilt->select_lock_type == LOCK_NONE) {
 
3680
 
 
3681
                        fputs("InnoDB: Error: MySQL is trying to"
 
3682
                              " perform a consistent read\n"
 
3683
                              "InnoDB: but the read view is not assigned!\n",
 
3684
                              stderr);
 
3685
                        trx_print(stderr, trx, 600);
 
3686
                        fputc('\n', stderr);
 
3687
                        ut_a(0);
 
3688
                }
 
3689
        } else if (prebuilt->select_lock_type == LOCK_NONE) {
 
3690
                /* This is a consistent read */
 
3691
                /* Assign a read view for the query */
 
3692
 
 
3693
                trx_assign_read_view(trx);
 
3694
                prebuilt->sql_stat_start = FALSE;
 
3695
        } else {
 
3696
                ulint   lock_mode;
 
3697
                if (prebuilt->select_lock_type == LOCK_S) {
 
3698
                        lock_mode = LOCK_IS;
 
3699
                } else {
 
3700
                        lock_mode = LOCK_IX;
 
3701
                }
 
3702
                err = lock_table(0, index->table, lock_mode, thr);
 
3703
 
 
3704
                if (err != DB_SUCCESS) {
 
3705
 
 
3706
                        goto lock_wait_or_error;
 
3707
                }
 
3708
                prebuilt->sql_stat_start = FALSE;
 
3709
        }
 
3710
 
3858
3711
rec_loop:
3859
3712
        /*-------------------------------------------------------------*/
3860
3713
        /* PHASE 4: Look for matching records in a loop */
3901
3754
                                               prebuilt->select_lock_type,
3902
3755
                                               LOCK_ORDINARY, thr);
3903
3756
 
3904
 
                        switch (err) {
3905
 
                        case DB_SUCCESS_LOCKED_REC:
3906
 
                                err = DB_SUCCESS;
3907
 
                        case DB_SUCCESS:
3908
 
                                break;
3909
 
                        default:
 
3757
                        if (err != DB_SUCCESS) {
 
3758
 
3910
3759
                                goto lock_wait_or_error;
3911
3760
                        }
3912
3761
                }
4036
3885
                                        prebuilt->select_lock_type, LOCK_GAP,
4037
3886
                                        thr);
4038
3887
 
4039
 
                                switch (err) {
4040
 
                                case DB_SUCCESS_LOCKED_REC:
4041
 
                                case DB_SUCCESS:
4042
 
                                        break;
4043
 
                                default:
 
3888
                                if (err != DB_SUCCESS) {
 
3889
 
4044
3890
                                        goto lock_wait_or_error;
4045
3891
                                }
4046
3892
                        }
4075
3921
                                        prebuilt->select_lock_type, LOCK_GAP,
4076
3922
                                        thr);
4077
3923
 
4078
 
                                switch (err) {
4079
 
                                case DB_SUCCESS_LOCKED_REC:
4080
 
                                case DB_SUCCESS:
4081
 
                                        break;
4082
 
                                default:
 
3924
                                if (err != DB_SUCCESS) {
 
3925
 
4083
3926
                                        goto lock_wait_or_error;
4084
3927
                                }
4085
3928
                        }
4149
3992
 
4150
3993
                switch (err) {
4151
3994
                        const rec_t*    old_vers;
4152
 
                case DB_SUCCESS_LOCKED_REC:
 
3995
                case DB_SUCCESS:
4153
3996
                        if (srv_locks_unsafe_for_binlog
4154
 
                            || trx->isolation_level
4155
 
                            <= TRX_ISO_READ_COMMITTED) {
 
3997
                            || trx->isolation_level <= TRX_ISO_READ_COMMITTED) {
4156
3998
                                /* Note that a record of
4157
3999
                                prebuilt->index was locked. */
4158
4000
                                prebuilt->new_rec_locks = 1;
4159
4001
                        }
4160
 
                        err = DB_SUCCESS;
4161
 
                case DB_SUCCESS:
4162
4002
                        break;
4163
4003
                case DB_LOCK_WAIT:
4164
 
                        /* Never unlock rows that were part of a conflict. */
4165
 
                        prebuilt->new_rec_locks = 0;
4166
 
 
4167
4004
                        if (UNIV_LIKELY(prebuilt->row_read_type
4168
4005
                                        != ROW_READ_TRY_SEMI_CONSISTENT)
4169
4006
                            || unique_search
4178
4015
                                clust_index, prebuilt, rec,
4179
4016
                                &offsets, &heap, &old_vers, &mtr);
4180
4017
 
4181
 
                        switch (err) {
4182
 
                        case DB_SUCCESS_LOCKED_REC:
4183
 
                                err = DB_SUCCESS;
4184
 
                        case DB_SUCCESS:
4185
 
                                break;
4186
 
                        default:
 
4018
                        if (err != DB_SUCCESS) {
 
4019
 
4187
4020
                                goto lock_wait_or_error;
4188
4021
                        }
4189
4022
 
4197
4030
                        if (UNIV_LIKELY(trx->wait_lock != NULL)) {
4198
4031
                                lock_cancel_waiting_and_release(
4199
4032
                                        trx->wait_lock);
 
4033
                                prebuilt->new_rec_locks = 0;
4200
4034
                        } else {
4201
4035
                                mutex_exit(&kernel_mutex);
4202
4036
 
4208
4042
                                                          ULINT_UNDEFINED,
4209
4043
                                                          &heap);
4210
4044
                                err = DB_SUCCESS;
 
4045
                                /* Note that a record of
 
4046
                                prebuilt->index was locked. */
 
4047
                                prebuilt->new_rec_locks = 1;
4211
4048
                                break;
4212
4049
                        }
4213
4050
                        mutex_exit(&kernel_mutex);
4253
4090
                                        prebuilt, rec, &offsets, &heap,
4254
4091
                                        &old_vers, &mtr);
4255
4092
 
4256
 
                                switch (err) {
4257
 
                                case DB_SUCCESS_LOCKED_REC:
4258
 
                                case DB_SUCCESS:
4259
 
                                        break;
4260
 
                                default:
 
4093
                                if (err != DB_SUCCESS) {
 
4094
 
4261
4095
                                        goto lock_wait_or_error;
4262
4096
                                }
4263
4097
 
4270
4104
 
4271
4105
                                rec = old_vers;
4272
4106
                        }
4273
 
                } else {
 
4107
                } else if (!lock_sec_rec_cons_read_sees(rec, trx->read_view)) {
4274
4108
                        /* We are looking into a non-clustered index,
4275
4109
                        and to get the right version of the record we
4276
4110
                        have to look also into the clustered index: this
4277
4111
                        is necessary, because we can only get the undo
4278
4112
                        information via the clustered index record. */
4279
4113
 
4280
 
                        ut_ad(!dict_index_is_clust(index));
4281
 
                        if (!lock_sec_rec_cons_read_sees(
4282
 
                                    rec, trx->read_view)) {
4283
 
                                goto requires_clust_rec;
4284
 
                        }
 
4114
                        ut_ad(index != clust_index);
 
4115
                        goto requires_clust_rec;
4285
4116
                }
4286
4117
        }
4287
4118
 
4349
4180
                err = row_sel_get_clust_rec_for_mysql(prebuilt, index, rec,
4350
4181
                                                      thr, &clust_rec,
4351
4182
                                                      &offsets, &heap, &mtr);
4352
 
                switch (err) {
4353
 
                case DB_SUCCESS:
4354
 
                        if (clust_rec == NULL) {
4355
 
                                /* The record did not exist in the read view */
4356
 
                                ut_ad(prebuilt->select_lock_type == LOCK_NONE);
 
4183
                if (err != DB_SUCCESS) {
4357
4184
 
4358
 
                                goto next_rec;
4359
 
                        }
4360
 
                        break;
4361
 
                case DB_SUCCESS_LOCKED_REC:
4362
 
                        ut_a(clust_rec != NULL);
4363
 
                        if (srv_locks_unsafe_for_binlog
4364
 
                             || trx->isolation_level
4365
 
                            <= TRX_ISO_READ_COMMITTED) {
4366
 
                                /* Note that the clustered index record
4367
 
                                was locked. */
4368
 
                                prebuilt->new_rec_locks = 2;
4369
 
                        }
4370
 
                        err = DB_SUCCESS;
4371
 
                        break;
4372
 
                default:
4373
4185
                        goto lock_wait_or_error;
4374
4186
                }
4375
4187
 
 
4188
                if (clust_rec == NULL) {
 
4189
                        /* The record did not exist in the read view */
 
4190
                        ut_ad(prebuilt->select_lock_type == LOCK_NONE);
 
4191
 
 
4192
                        goto next_rec;
 
4193
                }
 
4194
 
 
4195
                if ((srv_locks_unsafe_for_binlog
 
4196
                     || trx->isolation_level <= TRX_ISO_READ_COMMITTED)
 
4197
                    && prebuilt->select_lock_type != LOCK_NONE) {
 
4198
                        /* Note that both the secondary index record
 
4199
                        and the clustered index record were locked. */
 
4200
                        ut_ad(prebuilt->new_rec_locks == 1);
 
4201
                        prebuilt->new_rec_locks = 2;
 
4202
                }
 
4203
 
4376
4204
                if (UNIV_UNLIKELY(rec_get_deleted_flag(clust_rec, comp))) {
4377
4205
 
4378
4206
                        /* The record is delete marked: we can skip it */
4391
4219
                        goto next_rec;
4392
4220
                }
4393
4221
 
4394
 
                result_rec = clust_rec;
4395
 
                ut_ad(rec_offs_validate(result_rec, clust_index, offsets));
 
4222
                if (prebuilt->need_to_access_clustered) {
 
4223
 
 
4224
                        result_rec = clust_rec;
 
4225
 
 
4226
                        ut_ad(rec_offs_validate(result_rec, clust_index,
 
4227
                                                offsets));
 
4228
                } else {
 
4229
                        /* We used 'offsets' for the clust rec, recalculate
 
4230
                        them for 'rec' */
 
4231
                        offsets = rec_get_offsets(rec, index, offsets,
 
4232
                                                  ULINT_UNDEFINED, &heap);
 
4233
                        result_rec = rec;
 
4234
                }
4396
4235
        } else {
4397
4236
                result_rec = rec;
4398
4237
        }
4403
4242
        ut_ad(rec_offs_validate(result_rec,
4404
4243
                                result_rec != rec ? clust_index : index,
4405
4244
                                offsets));
4406
 
        ut_ad(!rec_get_deleted_flag(result_rec, comp));
4407
4245
 
4408
4246
        /* At this point, the clustered index record is protected
4409
4247
        by a page latch that was acquired when pcur was positioned.
4426
4264
                not cache rows because there the cursor is a scrollable
4427
4265
                cursor. */
4428
4266
 
4429
 
                if (!row_sel_push_cache_row_for_mysql(prebuilt, result_rec,
4430
 
                                                      result_rec != rec,
4431
 
                                                      offsets)) {
4432
 
                        /* Only fresh inserts may contain incomplete
4433
 
                        externally stored columns. Pretend that such
4434
 
                        records do not exist. Such records may only be
4435
 
                        accessed at the READ UNCOMMITTED isolation
4436
 
                        level or when rolling back a recovered
4437
 
                        transaction. Rollback happens at a lower
4438
 
                        level, not here. */
4439
 
                        ut_a(trx->isolation_level == TRX_ISO_READ_UNCOMMITTED);
4440
 
                } else if (prebuilt->n_fetch_cached
4441
 
                           == MYSQL_FETCH_CACHE_SIZE) {
 
4267
                row_sel_push_cache_row_for_mysql(prebuilt, result_rec,
 
4268
                                                 offsets);
 
4269
                if (prebuilt->n_fetch_cached == MYSQL_FETCH_CACHE_SIZE) {
4442
4270
 
4443
4271
                        goto got_row;
4444
4272
                }
4445
4273
 
4446
4274
                goto next_rec;
4447
4275
        } else {
4448
 
                if (UNIV_UNLIKELY
4449
 
                    (prebuilt->template_type == ROW_MYSQL_DUMMY_TEMPLATE)) {
4450
 
                        /* CHECK TABLE: fetch the row */
4451
 
 
4452
 
                        if (result_rec != rec
4453
 
                            && !prebuilt->need_to_access_clustered) {
4454
 
                                /* We used 'offsets' for the clust
4455
 
                                rec, recalculate them for 'rec' */
4456
 
                                offsets = rec_get_offsets(rec, index, offsets,
4457
 
                                                          ULINT_UNDEFINED,
4458
 
                                                          &heap);
4459
 
                                result_rec = rec;
4460
 
                        }
4461
 
 
 
4276
                if (prebuilt->template_type == ROW_MYSQL_DUMMY_TEMPLATE) {
4462
4277
                        memcpy(buf + 4, result_rec
4463
4278
                               - rec_offs_extra_size(offsets),
4464
4279
                               rec_offs_size(offsets));
4465
4280
                        mach_write_to_4(buf,
4466
4281
                                        rec_offs_extra_size(offsets) + 4);
4467
4282
                } else {
4468
 
                        /* Returning a row to MySQL */
 
4283
                        if (!row_sel_store_mysql_rec(buf, prebuilt,
 
4284
                                                     result_rec, offsets)) {
 
4285
                                err = DB_TOO_BIG_RECORD;
4469
4286
 
4470
 
                        if (!row_sel_store_mysql_rec(buf, prebuilt, result_rec,
4471
 
                                                     result_rec != rec,
4472
 
                                                     offsets)) {
4473
 
                                /* Only fresh inserts may contain
4474
 
                                incomplete externally stored
4475
 
                                columns. Pretend that such records do
4476
 
                                not exist. Such records may only be
4477
 
                                accessed at the READ UNCOMMITTED
4478
 
                                isolation level or when rolling back a
4479
 
                                recovered transaction. Rollback
4480
 
                                happens at a lower level, not here. */
4481
 
                                ut_a(trx->isolation_level
4482
 
                                     == TRX_ISO_READ_UNCOMMITTED);
4483
 
                                goto next_rec;
 
4287
                                goto lock_wait_or_error;
4484
4288
                        }
4485
4289
                }
4486
4290
 
4589
4393
 
4590
4394
        btr_pcur_store_position(pcur, &mtr);
4591
4395
 
4592
 
lock_table_wait:
4593
4396
        mtr_commit(&mtr);
4594
4397
        mtr_has_extra_clust_latch = FALSE;
4595
4398
 
4607
4410
                thr->lock_state = QUE_THR_LOCK_NOLOCK;
4608
4411
                mtr_start(&mtr);
4609
4412
 
4610
 
                /* Table lock waited, go try to obtain table lock
4611
 
                again */
4612
 
                if (table_lock_waited) {
4613
 
                        table_lock_waited = FALSE;
4614
 
 
4615
 
                        goto wait_table_again;
4616
 
                }
4617
 
 
4618
4413
                sel_restore_position_for_mysql(&same_user_rec,
4619
4414
                                               BTR_SEARCH_LEAF, pcur,
4620
4415
                                               moves_up, &mtr);
4733
4528
        IX type locks actually would require ret = FALSE. */
4734
4529
 
4735
4530
        if (UT_LIST_GET_LEN(table->locks) == 0
4736
 
            && trx->id >= table->query_cache_inv_trx_id) {
 
4531
            && ut_dulint_cmp(trx->id,
 
4532
                             table->query_cache_inv_trx_id) >= 0) {
4737
4533
 
4738
4534
                ret = TRUE;
4739
4535