~drizzle-trunk/drizzle/development

« back to all changes in this revision

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

  • Committer: Lee Bieber
  • Date: 2010-01-30 23:42:02 UTC
  • mto: This revision was merged to the branch mainline in revision 1282.
  • Revision ID: lbieber@lee-biebers-macbook-pro.local-20100130234202-sxmqfteqwiq15ptg
add target to japanese tests

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.
 
3
Copyright (c) 1997, 2009, Innobase Oy. All Rights Reserved.
4
4
Copyright (c) 2008, Google Inc.
5
5
 
6
6
Portions of this file contain modifications contributed and copyrighted by
18
18
FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.
19
19
 
20
20
You should have received a copy of the GNU General Public License along with
21
 
this program; if not, write to the Free Software Foundation, Inc., 51 Franklin
22
 
St, Fifth Floor, Boston, MA 02110-1301 USA
 
21
this program; if not, write to the Free Software Foundation, Inc., 59 Temple
 
22
Place, Suite 330, Boston, MA 02111-1307 USA
23
23
 
24
24
*****************************************************************************/
25
25
 
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
117
119
                return(FALSE);
118
120
        }
119
121
 
120
 
        len = dtype_get_at_most_n_mbchars(prtype, mbminmaxlen,
 
122
        len = dtype_get_at_most_n_mbchars(prtype, mbminlen, mbmaxlen,
121
123
                                          sec_len, len, (const char*) buf);
122
124
 
123
125
        return(!cmp_data_data(mtype, prtype, buf, len, sec_field, sec_len));
130
132
NOTE: the comparison is NOT done as a binary comparison, but character
131
133
fields are compared with collation!
132
134
@return TRUE if the secondary record is equal to the corresponding
133
 
fields in the clustered record, when compared with collation;
134
 
FALSE if not equal or if the clustered record has been marked for deletion */
 
135
fields in the clustered record, when compared with collation */
135
136
static
136
137
ibool
137
138
row_sel_sec_rec_is_for_clust_rec(
200
201
                        }
201
202
 
202
203
                        len = dtype_get_at_most_n_mbchars(
203
 
                                col->prtype, col->mbminmaxlen,
 
204
                                col->prtype, col->mbminlen, col->mbmaxlen,
204
205
                                ifield->prefix_len, len, (char*) clust_field);
205
206
 
206
207
                        if (rec_offs_nth_extern(clust_offs, clust_pos)
207
208
                            && len < sec_len) {
208
209
                                if (!row_sel_sec_rec_is_for_blob(
209
210
                                            col->mtype, col->prtype,
210
 
                                            col->mbminmaxlen,
 
211
                                            col->mbminlen, col->mbmaxlen,
211
212
                                            clust_field, clust_len,
212
213
                                            sec_field, sec_len,
213
214
                                            dict_table_zip_size(
414
415
                                                              field_no))) {
415
416
 
416
417
                                /* Copy an externally stored field to the
417
 
                                temporary heap, if possible. */
 
418
                                temporary heap */
418
419
 
419
420
                                heap = mem_heap_create(1);
420
421
 
423
424
                                        dict_table_zip_size(index->table),
424
425
                                        field_no, &len, heap);
425
426
 
426
 
                                /* data == NULL means that the
427
 
                                externally stored field was not
428
 
                                written yet. This record
429
 
                                should only be seen by
430
 
                                recv_recovery_rollback_active() or any
431
 
                                TRX_ISO_READ_UNCOMMITTED
432
 
                                transactions. The InnoDB SQL parser
433
 
                                (the sole caller of this function)
434
 
                                does not implement READ UNCOMMITTED,
435
 
                                and it is not involved during rollback. */
436
 
                                ut_a(data);
437
427
                                ut_a(len != UNIV_SQL_NULL);
438
428
 
439
429
                                needs_copy = TRUE;
441
431
                                data = rec_get_nth_field(rec, offsets,
442
432
                                                         field_no, &len);
443
433
 
 
434
                                if (len == UNIV_SQL_NULL) {
 
435
                                        len = UNIV_SQL_NULL;
 
436
                                }
 
437
 
444
438
                                needs_copy = column->copy_val;
445
439
                        }
446
440
 
861
855
                trx = thr_get_trx(thr);
862
856
 
863
857
                if (srv_locks_unsafe_for_binlog
864
 
                    || trx->isolation_level <= TRX_ISO_READ_COMMITTED) {
 
858
                    || trx->isolation_level == TRX_ISO_READ_COMMITTED) {
865
859
                        lock_type = LOCK_REC_NOT_GAP;
866
860
                } else {
867
861
                        lock_type = LOCK_ORDINARY;
872
866
                        clust_rec, index, offsets,
873
867
                        node->row_lock_mode, lock_type, thr);
874
868
 
875
 
                switch (err) {
876
 
                case DB_SUCCESS:
877
 
                case DB_SUCCESS_LOCKED_REC:
878
 
                        /* Declare the variable uninitialized in Valgrind.
879
 
                        It should be set to DB_SUCCESS at func_exit. */
880
 
                        UNIV_MEM_INVALID(&err, sizeof err);
881
 
                        break;
882
 
                default:
 
869
                if (err != DB_SUCCESS) {
 
870
 
883
871
                        goto err_exit;
884
872
                }
885
873
        } else {
935
923
        when plan->clust_pcur was positioned.  The latch will not be
936
924
        released until mtr_commit(mtr). */
937
925
 
938
 
        ut_ad(!rec_get_deleted_flag(clust_rec, rec_offs_comp(offsets)));
939
926
        row_sel_fetch_columns(index, clust_rec, offsets,
940
927
                              UT_LIST_GET_FIRST(plan->columns));
941
928
        *out_rec = clust_rec;
950
937
 
951
938
/*********************************************************************//**
952
939
Sets a lock on a record.
953
 
@return DB_SUCCESS, DB_SUCCESS_LOCKED_REC, or error code */
 
940
@return DB_SUCCESS or error code */
954
941
UNIV_INLINE
955
 
enum db_err
 
942
ulint
956
943
sel_set_rec_lock(
957
944
/*=============*/
958
945
        const buf_block_t*      block,  /*!< in: buffer block of rec */
964
951
                                        LOC_REC_NOT_GAP */
965
952
        que_thr_t*              thr)    /*!< in: query thread */
966
953
{
967
 
        trx_t*          trx;
968
 
        enum db_err     err;
 
954
        trx_t*  trx;
 
955
        ulint   err;
969
956
 
970
957
        trx = thr_get_trx(thr);
971
958
 
1481
1468
 
1482
1469
                        if (srv_locks_unsafe_for_binlog
1483
1470
                            || trx->isolation_level
1484
 
                            <= TRX_ISO_READ_COMMITTED) {
 
1471
                            == TRX_ISO_READ_COMMITTED) {
1485
1472
 
1486
1473
                                if (page_rec_is_supremum(next_rec)) {
1487
1474
 
1498
1485
                                               node->row_lock_mode,
1499
1486
                                               lock_type, thr);
1500
1487
 
1501
 
                        switch (err) {
1502
 
                        case DB_SUCCESS_LOCKED_REC:
1503
 
                                err = DB_SUCCESS;
1504
 
                        case DB_SUCCESS:
1505
 
                                break;
1506
 
                        default:
 
1488
                        if (err != DB_SUCCESS) {
1507
1489
                                /* Note that in this case we will store in pcur
1508
1490
                                the PREDECESSOR of the record we are waiting
1509
1491
                                the lock for */
 
1492
 
1510
1493
                                goto lock_wait_or_error;
1511
1494
                        }
1512
1495
                }
1542
1525
                trx = thr_get_trx(thr);
1543
1526
 
1544
1527
                if (srv_locks_unsafe_for_binlog
1545
 
                    || trx->isolation_level <= TRX_ISO_READ_COMMITTED) {
 
1528
                    || trx->isolation_level == TRX_ISO_READ_COMMITTED) {
1546
1529
 
1547
1530
                        if (page_rec_is_supremum(rec)) {
1548
1531
 
1558
1541
                                       rec, index, offsets,
1559
1542
                                       node->row_lock_mode, lock_type, thr);
1560
1543
 
1561
 
                switch (err) {
1562
 
                case DB_SUCCESS_LOCKED_REC:
1563
 
                        err = DB_SUCCESS;
1564
 
                case DB_SUCCESS:
1565
 
                        break;
1566
 
                default:
 
1544
                if (err != DB_SUCCESS) {
 
1545
 
1567
1546
                        goto lock_wait_or_error;
1568
1547
                }
1569
1548
        }
1638
1617
                                }
1639
1618
 
1640
1619
                                if (old_vers == NULL) {
1641
 
                                        /* The record does not exist
1642
 
                                        in our read view. Skip it, but
1643
 
                                        first attempt to determine
1644
 
                                        whether the index segment we
1645
 
                                        are searching through has been
1646
 
                                        exhausted. */
1647
 
 
1648
1620
                                        offsets = rec_get_offsets(
1649
1621
                                                rec, index, offsets,
1650
1622
                                                ULINT_UNDEFINED, &heap);
1729
1701
                                            &mtr);
1730
1702
                mtr_has_extra_clust_latch = TRUE;
1731
1703
 
1732
 
                switch (err) {
1733
 
                case DB_SUCCESS_LOCKED_REC:
1734
 
                        err = DB_SUCCESS;
1735
 
                case DB_SUCCESS:
1736
 
                        break;
1737
 
                default:
 
1704
                if (err != DB_SUCCESS) {
 
1705
 
1738
1706
                        goto lock_wait_or_error;
1739
1707
                }
1740
1708
 
1919
1887
                        thr->run_node = que_node_get_parent(node);
1920
1888
                }
1921
1889
 
1922
 
                err = DB_SUCCESS;
1923
1890
                goto func_exit;
1924
1891
        }
1925
1892
 
2077
2044
                        /* Reset the aggregate total values */
2078
2045
                        sel_reset_aggregate_vals(node);
2079
2046
                }
2080
 
 
2081
 
                err = DB_SUCCESS;
2082
2047
        }
2083
2048
 
2084
2049
        err = row_sel(node, thr);
2205
2170
        return((void*)42);
2206
2171
}
2207
2172
 
 
2173
/****************************************************************//**
 
2174
Callback function for fetch that stores an unsigned 4 byte integer to the
 
2175
location pointed. The column's type must be DATA_INT, DATA_UNSIGNED, length
 
2176
= 4.
 
2177
@return always returns NULL */
 
2178
UNIV_INTERN
 
2179
void*
 
2180
row_fetch_store_uint4(
 
2181
/*==================*/
 
2182
        void*   row,            /*!< in:  sel_node_t* */
 
2183
        void*   user_arg)       /*!< in:  data pointer */
 
2184
{
 
2185
        sel_node_t*     node = row;
 
2186
        ib_uint32_t*    val = user_arg;
 
2187
        ulint           tmp;
 
2188
 
 
2189
        dfield_t*       dfield = que_node_get_val(node->select_list);
 
2190
        const dtype_t*  type = dfield_get_type(dfield);
 
2191
        ulint           len = dfield_get_len(dfield);
 
2192
 
 
2193
        ut_a(dtype_get_mtype(type) == DATA_INT);
 
2194
        ut_a(dtype_get_prtype(type) & DATA_UNSIGNED);
 
2195
        ut_a(len == 4);
 
2196
 
 
2197
        tmp = mach_read_from_4(dfield_get_data(dfield));
 
2198
        *val = (ib_uint32_t) tmp;
 
2199
 
 
2200
        return(NULL);
 
2201
}
 
2202
 
2208
2203
/***********************************************************//**
2209
2204
Prints a row in a select result.
2210
2205
@return query thread to run next or NULL */
2532
2527
        ulint           len)    /*!< in: length of the data */
2533
2528
{
2534
2529
        byte*   ptr;
 
2530
        byte*   field_end;
 
2531
        byte*   pad_ptr;
2535
2532
 
2536
2533
        ut_ad(len != UNIV_SQL_NULL);
2537
 
        UNIV_MEM_ASSERT_RW(data, len);
2538
2534
 
2539
2535
        switch (templ->type) {
2540
 
                const byte*     field_end;
2541
 
                byte*           pad;
2542
2536
        case DATA_INT:
2543
2537
                /* Convert integer data from Innobase to a little-endian
2544
2538
                format, sign bit restored to normal */
2582
2576
                unused end of a >= 5.0.3 true VARCHAR column, just in case
2583
2577
                MySQL expects its contents to be deterministic. */
2584
2578
 
2585
 
                pad = dest + len;
 
2579
                pad_ptr = dest + len;
2586
2580
 
2587
2581
                ut_ad(templ->mbminlen <= templ->mbmaxlen);
2588
2582
 
2589
 
                /* We treat some Unicode charset strings specially. */
2590
 
                switch (templ->mbminlen) {
2591
 
                case 4:
2592
 
                        /* InnoDB should never have stripped partial
2593
 
                        UTF-32 characters. */
2594
 
                        ut_a(!(len & 3));
2595
 
                        break;
2596
 
                case 2:
2597
 
                        /* A space char is two bytes,
2598
 
                        0x0020 in UCS2 and UTF-16 */
 
2583
                /* We handle UCS2 charset strings differently. */
 
2584
                if (templ->mbminlen == 2) {
 
2585
                        /* A space char is two bytes, 0x0020 in UCS2 */
2599
2586
 
2600
 
                        if (UNIV_UNLIKELY(len & 1)) {
 
2587
                        if (len & 1) {
2601
2588
                                /* A 0x20 has been stripped from the column.
2602
2589
                                Pad it back. */
2603
2590
 
2604
 
                                if (pad < field_end) {
2605
 
                                        *pad++ = 0x20;
 
2591
                                if (pad_ptr < field_end) {
 
2592
                                        *pad_ptr = 0x20;
 
2593
                                        pad_ptr++;
2606
2594
                                }
2607
2595
                        }
 
2596
 
 
2597
                        /* Pad the rest of the string with 0x0020 */
 
2598
 
 
2599
                        while (pad_ptr < field_end) {
 
2600
                                *pad_ptr = 0x00;
 
2601
                                pad_ptr++;
 
2602
                                *pad_ptr = 0x20;
 
2603
                                pad_ptr++;
 
2604
                        }
 
2605
                } else {
 
2606
                        ut_ad(templ->mbminlen == 1);
 
2607
                        /* space=0x20 */
 
2608
 
 
2609
                        memset(pad_ptr, 0x20, field_end - pad_ptr);
2608
2610
                }
2609
 
 
2610
 
                row_mysql_pad_col(templ->mbminlen, pad, field_end - pad);
2611
2611
                break;
2612
2612
 
2613
2613
        case DATA_BLOB:
2632
2632
                      || !(templ->mysql_col_len % templ->mbmaxlen));
2633
2633
                ut_ad(len * templ->mbmaxlen >= templ->mysql_col_len);
2634
2634
 
2635
 
                if (templ->mbminlen == 1 && templ->mbmaxlen != 1) {
 
2635
                if (templ->mbminlen != templ->mbmaxlen) {
2636
2636
                        /* Pad with spaces. This undoes the stripping
2637
 
                        done in row0mysql.c, function
 
2637
                        done in row0mysql.ic, function
2638
2638
                        row_mysql_store_col_in_innobase_format(). */
2639
2639
 
2640
2640
                        memset(dest + len, 0x20, templ->mysql_col_len - len);
2665
2665
Note that the template in prebuilt may advise us to copy only a few
2666
2666
columns to mysql_rec, other columns are left blank. All columns may not
2667
2667
be needed in the query.
2668
 
@return TRUE on success, FALSE if not all columns could be retrieved */
 
2668
@return TRUE if success, FALSE if could not allocate memory for a BLOB
 
2669
(though we may also assert in that case) */
2669
2670
static
2670
 
#ifdef __GNUC__
2671
 
 __attribute__((warn_unused_result))
2672
 
#endif
2673
2671
ibool
2674
2672
row_sel_store_mysql_rec(
2675
2673
/*====================*/
2733
2731
                                dict_table_zip_size(prebuilt->table),
2734
2732
                                templ->rec_field_no, &len, heap);
2735
2733
 
2736
 
                        if (UNIV_UNLIKELY(!data)) {
2737
 
                                /* The externally stored field
2738
 
                                was not written yet. This
2739
 
                                record should only be seen by
2740
 
                                recv_recovery_rollback_active()
2741
 
                                or any TRX_ISO_READ_UNCOMMITTED
2742
 
                                transactions. */
2743
 
 
2744
 
                                if (extern_field_heap) {
2745
 
                                        mem_heap_free(extern_field_heap);
2746
 
                                }
2747
 
 
2748
 
                                return(FALSE);
2749
 
                        }
2750
 
 
2751
 
                        if (UNIV_UNLIKELY(!data)) {
2752
 
                                /* The externally stored field
2753
 
                                was not written yet. This
2754
 
                                record should only be seen by
2755
 
                                recv_recovery_rollback_active()
2756
 
                                or any TRX_ISO_READ_UNCOMMITTED
2757
 
                                transactions. */
2758
 
 
2759
 
                                if (extern_field_heap) {
2760
 
                                        mem_heap_free(extern_field_heap);
2761
 
                                }
2762
 
 
2763
 
                                return(FALSE);
2764
 
                        }
2765
 
 
2766
2734
                        ut_a(len != UNIV_SQL_NULL);
2767
2735
                } else {
2768
2736
                        /* Field is stored in the row. */
2811
2779
                        /* MySQL assumes that the field for an SQL
2812
2780
                        NULL value is set to the default value. */
2813
2781
 
2814
 
                        UNIV_MEM_ASSERT_RW(prebuilt->default_rec
2815
 
                                           + templ->mysql_col_offset,
2816
 
                                           templ->mysql_col_len);
2817
2782
                        mysql_rec[templ->mysql_null_byte_offset]
2818
2783
                                |= (byte) templ->mysql_null_bit_mask;
2819
2784
                        memcpy(mysql_rec + templ->mysql_col_offset,
2865
2830
Retrieves the clustered index record corresponding to a record in a
2866
2831
non-clustered index. Does the necessary locking. Used in the MySQL
2867
2832
interface.
2868
 
@return DB_SUCCESS, DB_SUCCESS_LOCKED_REC, or error code */
 
2833
@return DB_SUCCESS or error code */
2869
2834
static
2870
 
enum db_err
 
2835
ulint
2871
2836
row_sel_get_clust_rec_for_mysql(
2872
2837
/*============================*/
2873
2838
        row_prebuilt_t* prebuilt,/*!< in: prebuilt struct in the handle */
2894
2859
        dict_index_t*   clust_index;
2895
2860
        const rec_t*    clust_rec;
2896
2861
        rec_t*          old_vers;
2897
 
        enum db_err     err;
 
2862
        ulint           err;
2898
2863
        trx_t*          trx;
2899
2864
 
2900
2865
        *out_rec = NULL;
2953
2918
 
2954
2919
                clust_rec = NULL;
2955
2920
 
2956
 
                err = DB_SUCCESS;
2957
2921
                goto func_exit;
2958
2922
        }
2959
2923
 
2969
2933
                        0, btr_pcur_get_block(prebuilt->clust_pcur),
2970
2934
                        clust_rec, clust_index, *offsets,
2971
2935
                        prebuilt->select_lock_type, LOCK_REC_NOT_GAP, thr);
2972
 
                switch (err) {
2973
 
                case DB_SUCCESS:
2974
 
                case DB_SUCCESS_LOCKED_REC:
2975
 
                        break;
2976
 
                default:
 
2936
                if (err != DB_SUCCESS) {
 
2937
 
2977
2938
                        goto err_exit;
2978
2939
                }
2979
2940
        } else {
3020
2981
 
3021
2982
                if (clust_rec
3022
2983
                    && (old_vers
3023
 
                        || trx->isolation_level <= TRX_ISO_READ_UNCOMMITTED
3024
2984
                        || rec_get_deleted_flag(rec, dict_table_is_comp(
3025
2985
                                                        sec_index->table)))
3026
2986
                    && !row_sel_sec_rec_is_for_clust_rec(
3033
2993
                                     rec, sec_index, clust_rec, clust_index));
3034
2994
#endif
3035
2995
                }
3036
 
 
3037
 
                err = DB_SUCCESS;
3038
2996
        }
3039
2997
 
3040
2998
func_exit:
3047
3005
                btr_pcur_store_position(prebuilt->clust_pcur, mtr);
3048
3006
        }
3049
3007
 
 
3008
        err = DB_SUCCESS;
3050
3009
err_exit:
3051
3010
        return(err);
3052
3011
}
3143
3102
 
3144
3103
                for (i = 0; i < prebuilt->n_template; i++) {
3145
3104
                        templ = prebuilt->mysql_template + i;
3146
 
#if 0 /* Some of the cached_rec may legitimately be uninitialized. */
3147
 
                        UNIV_MEM_ASSERT_RW(cached_rec
3148
 
                                           + templ->mysql_col_offset,
3149
 
                                           templ->mysql_col_len);
3150
 
#endif
3151
3105
                        ut_memcpy(buf + templ->mysql_col_offset,
3152
3106
                                  cached_rec + templ->mysql_col_offset,
3153
3107
                                  templ->mysql_col_len);
3162
3116
                }
3163
3117
        }
3164
3118
        else {
3165
 
#if 0 /* Some of the cached_rec may legitimately be uninitialized. */
3166
 
                UNIV_MEM_ASSERT_RW(prebuilt->fetch_cache
3167
 
                                   [prebuilt->fetch_cache_first],
3168
 
                                   prebuilt->mysql_prefix_len);
3169
 
#endif
3170
3119
                ut_memcpy(buf,
3171
3120
                          prebuilt->fetch_cache[prebuilt->fetch_cache_first],
3172
3121
                          prebuilt->mysql_prefix_len);
3180
3129
}
3181
3130
 
3182
3131
/********************************************************************//**
3183
 
Pushes a row for MySQL to the fetch cache.
3184
 
@return TRUE on success, FALSE if the record contains incomplete BLOBs */
 
3132
Pushes a row for MySQL to the fetch cache. */
3185
3133
UNIV_INLINE
3186
 
#ifdef __GNUC__
3187
 
__attribute__((warn_unused_result))
3188
 
#endif
3189
 
ibool
 
3134
void
3190
3135
row_sel_push_cache_row_for_mysql(
3191
3136
/*=============================*/
3192
3137
        row_prebuilt_t* prebuilt,       /*!< in: prebuilt struct */
3221
3166
        }
3222
3167
 
3223
3168
        ut_ad(prebuilt->fetch_cache_first == 0);
3224
 
        UNIV_MEM_INVALID(prebuilt->fetch_cache[prebuilt->n_fetch_cached],
3225
 
                         prebuilt->mysql_row_len);
3226
3169
 
3227
3170
        if (UNIV_UNLIKELY(!row_sel_store_mysql_rec(
3228
3171
                                  prebuilt->fetch_cache[
3229
3172
                                          prebuilt->n_fetch_cached],
3230
3173
                                  prebuilt, rec, offsets))) {
3231
 
                return(FALSE);
 
3174
                ut_error;
3232
3175
        }
3233
3176
 
3234
3177
        prebuilt->n_fetch_cached++;
3235
 
        return(TRUE);
3236
3178
}
3237
3179
 
3238
3180
/*********************************************************************//**
3260
3202
        ut_ad(dict_index_is_clust(index));
3261
3203
        ut_ad(!prebuilt->templ_contains_blob);
3262
3204
 
3263
 
#ifndef UNIV_SEARCH_DEBUG
3264
3205
        btr_pcur_open_with_no_init(index, search_tuple, PAGE_CUR_GE,
3265
3206
                                   BTR_SEARCH_LEAF, pcur,
 
3207
#ifndef UNIV_SEARCH_DEBUG
3266
3208
                                   RW_S_LATCH,
3267
 
                                   mtr);
3268
 
#else /* UNIV_SEARCH_DEBUG */
3269
 
        btr_pcur_open_with_no_init(index, search_tuple, PAGE_CUR_GE,
3270
 
                                   BTR_SEARCH_LEAF, pcur,
 
3209
#else
3271
3210
                                   0,
 
3211
#endif
3272
3212
                                   mtr);
3273
 
#endif /* UNIV_SEARCH_DEBUG */
3274
3213
        rec = btr_pcur_get_rec(pcur);
3275
3214
 
3276
3215
        if (!page_rec_is_user_rec(rec)) {
3370
3309
        mem_heap_t*     heap                            = NULL;
3371
3310
        ulint           offsets_[REC_OFFS_NORMAL_SIZE];
3372
3311
        ulint*          offsets                         = offsets_;
3373
 
        ibool           table_lock_waited               = FALSE;
3374
3312
 
3375
3313
        rec_offs_init(offsets_);
3376
3314
 
3414
3352
        }
3415
3353
 
3416
3354
#if 0
 
3355
        /* August 19, 2005 by Heikki: temporarily disable this error
 
3356
        print until the cursor lock count is done correctly.
 
3357
        See bugs #12263 and #12456!*/
 
3358
 
 
3359
        if (trx->n_mysql_tables_in_use == 0
 
3360
            && UNIV_UNLIKELY(prebuilt->select_lock_type == LOCK_NONE)) {
 
3361
                /* Note that if MySQL uses an InnoDB temp table that it
 
3362
                created inside LOCK TABLES, then n_mysql_tables_in_use can
 
3363
                be zero; in that case select_lock_type is set to LOCK_X in
 
3364
                ::start_stmt. */
 
3365
 
 
3366
                fputs("InnoDB: Error: MySQL is trying to perform a SELECT\n"
 
3367
                      "InnoDB: but it has not locked"
 
3368
                      " any tables in ::external_lock()!\n",
 
3369
                      stderr);
 
3370
                trx_print(stderr, trx, 600);
 
3371
                fputc('\n', stderr);
 
3372
        }
 
3373
#endif
 
3374
 
 
3375
#if 0
3417
3376
        fprintf(stderr, "Match mode %lu\n search tuple ",
3418
3377
                (ulong) match_mode);
3419
3378
        dtuple_print(search_tuple);
3535
3494
 
3536
3495
                /* Even if the condition is unique, MySQL seems to try to
3537
3496
                retrieve also a second row if a primary key contains more than
3538
 
                1 column.*/
 
3497
                1 column. Return immediately if this is not a HANDLER
 
3498
                command. */
3539
3499
 
3540
 
                if (UNIV_UNLIKELY(direction != 0)) {
 
3500
                if (UNIV_UNLIKELY(direction != 0
 
3501
                                  && !prebuilt->used_in_HANDLER)) {
3541
3502
 
3542
3503
                        err = DB_RECORD_NOT_FOUND;
3543
3504
                        goto func_exit;
3559
3520
            && unique_search
3560
3521
            && dict_index_is_clust(index)
3561
3522
            && !prebuilt->templ_contains_blob
 
3523
            && !prebuilt->used_in_HANDLER
3562
3524
            && (prebuilt->mysql_row_len < UNIV_PAGE_SIZE / 8)) {
3563
3525
 
3564
3526
                mode = PAGE_CUR_GE;
3601
3563
                                row_sel_try_search_shortcut_for_mysql().
3602
3564
                                The latch will not be released until
3603
3565
                                mtr_commit(&mtr). */
3604
 
                                ut_ad(!rec_get_deleted_flag(rec, comp));
3605
3566
 
3606
3567
                                if (!row_sel_store_mysql_rec(buf, prebuilt,
3607
3568
                                                             rec, offsets)) {
3608
 
                                        /* Only fresh inserts may contain
3609
 
                                        incomplete externally stored
3610
 
                                        columns. Pretend that such
3611
 
                                        records do not exist. Such
3612
 
                                        records may only be accessed
3613
 
                                        at the READ UNCOMMITTED
3614
 
                                        isolation level or when
3615
 
                                        rolling back a recovered
3616
 
                                        transaction. Rollback happens
3617
 
                                        at a lower level, not here. */
3618
 
                                        ut_a(trx->isolation_level
3619
 
                                             == TRX_ISO_READ_UNCOMMITTED);
 
3569
                                        err = DB_TOO_BIG_RECORD;
3620
3570
 
3621
 
                                        /* Proceed as in case SEL_RETRY. */
3622
 
                                        break;
 
3571
                                        /* We let the main loop to do the
 
3572
                                        error handling */
 
3573
                                        goto shortcut_fails_too_big_rec;
3623
3574
                                }
3624
3575
 
3625
3576
                                mtr_commit(&mtr);
3659
3610
                        default:
3660
3611
                                ut_ad(0);
3661
3612
                        }
3662
 
 
 
3613
shortcut_fails_too_big_rec:
3663
3614
                        mtr_commit(&mtr);
3664
3615
                        mtr_start(&mtr);
3665
3616
                }
3673
3624
                trx->has_search_latch = FALSE;
3674
3625
        }
3675
3626
 
3676
 
        ut_ad(prebuilt->sql_stat_start || trx->conc_state == TRX_ACTIVE);
3677
 
        ut_ad(trx->conc_state == TRX_NOT_STARTED
3678
 
              || trx->conc_state == TRX_ACTIVE);
3679
 
        ut_ad(prebuilt->sql_stat_start
3680
 
              || prebuilt->select_lock_type != LOCK_NONE
3681
 
              || trx->read_view);
3682
 
 
3683
 
        ut_ad(prebuilt->sql_stat_start || trx->conc_state == TRX_ACTIVE);
3684
 
        ut_ad(trx->conc_state == TRX_NOT_STARTED
3685
 
              || trx->conc_state == TRX_ACTIVE);
3686
 
        ut_ad(prebuilt->sql_stat_start
3687
 
              || prebuilt->select_lock_type != LOCK_NONE
3688
 
              || trx->read_view);
3689
 
 
3690
3627
        trx_start_if_not_started(trx);
3691
3628
 
3692
3629
        if (trx->isolation_level <= TRX_ISO_READ_COMMITTED
3717
3654
 
3718
3655
        clust_index = dict_table_get_first_index(index->table);
3719
3656
 
3720
 
        /* Do some start-of-statement preparations */
3721
 
 
3722
 
        if (!prebuilt->sql_stat_start) {
3723
 
                /* No need to set an intention lock or assign a read view */
3724
 
 
3725
 
                if (trx->read_view == NULL
3726
 
                    && prebuilt->select_lock_type == LOCK_NONE) {
3727
 
 
3728
 
                        fputs("InnoDB: Error: MySQL is trying to"
3729
 
                              " perform a consistent read\n"
3730
 
                              "InnoDB: but the read view is not assigned!\n",
3731
 
                              stderr);
3732
 
                        trx_print(stderr, trx, 600);
3733
 
                        fputc('\n', stderr);
3734
 
                        ut_error;
3735
 
                }
3736
 
        } else if (prebuilt->select_lock_type == LOCK_NONE) {
3737
 
                /* This is a consistent read */
3738
 
                /* Assign a read view for the query */
3739
 
 
3740
 
                trx_assign_read_view(trx);
3741
 
                prebuilt->sql_stat_start = FALSE;
3742
 
        } else {
3743
 
wait_table_again:
3744
 
                err = lock_table(0, index->table,
3745
 
                                 prebuilt->select_lock_type == LOCK_S
3746
 
                                 ? LOCK_IS : LOCK_IX, thr);
3747
 
 
3748
 
                if (err != DB_SUCCESS) {
3749
 
 
3750
 
                        table_lock_waited = TRUE;
3751
 
                        goto lock_table_wait;
3752
 
                }
3753
 
                prebuilt->sql_stat_start = FALSE;
3754
 
        }
3755
 
 
3756
 
        /* Open or restore index cursor position */
3757
 
 
3758
3657
        if (UNIV_LIKELY(direction != 0)) {
3759
3658
                ibool   need_to_process = sel_restore_position_for_mysql(
3760
3659
                        &same_user_rec, BTR_SEARCH_LEAF,
3795
3694
                    && !page_rec_is_supremum(rec)
3796
3695
                    && set_also_gap_locks
3797
3696
                    && !(srv_locks_unsafe_for_binlog
3798
 
                         || trx->isolation_level <= TRX_ISO_READ_COMMITTED)
 
3697
                         || trx->isolation_level == TRX_ISO_READ_COMMITTED)
3799
3698
                    && prebuilt->select_lock_type != LOCK_NONE) {
3800
3699
 
3801
3700
                        /* Try to place a gap lock on the next index record
3809
3708
                                               prebuilt->select_lock_type,
3810
3709
                                               LOCK_GAP, thr);
3811
3710
 
3812
 
                        switch (err) {
3813
 
                        case DB_SUCCESS_LOCKED_REC:
3814
 
                                err = DB_SUCCESS;
3815
 
                        case DB_SUCCESS:
3816
 
                                break;
3817
 
                        default:
 
3711
                        if (err != DB_SUCCESS) {
 
3712
 
3818
3713
                                goto lock_wait_or_error;
3819
3714
                        }
3820
3715
                }
3830
3725
                }
3831
3726
        }
3832
3727
 
 
3728
        if (!prebuilt->sql_stat_start) {
 
3729
                /* No need to set an intention lock or assign a read view */
 
3730
 
 
3731
                if (trx->read_view == NULL
 
3732
                    && prebuilt->select_lock_type == LOCK_NONE) {
 
3733
 
 
3734
                        fputs("InnoDB: Error: MySQL is trying to"
 
3735
                              " perform a consistent read\n"
 
3736
                              "InnoDB: but the read view is not assigned!\n",
 
3737
                              stderr);
 
3738
                        trx_print(stderr, trx, 600);
 
3739
                        fputc('\n', stderr);
 
3740
                        ut_a(0);
 
3741
                }
 
3742
        } else if (prebuilt->select_lock_type == LOCK_NONE) {
 
3743
                /* This is a consistent read */
 
3744
                /* Assign a read view for the query */
 
3745
 
 
3746
                trx_assign_read_view(trx);
 
3747
                prebuilt->sql_stat_start = FALSE;
 
3748
        } else {
 
3749
                ulint   lock_mode;
 
3750
                if (prebuilt->select_lock_type == LOCK_S) {
 
3751
                        lock_mode = LOCK_IS;
 
3752
                } else {
 
3753
                        lock_mode = LOCK_IX;
 
3754
                }
 
3755
                err = lock_table(0, index->table, lock_mode, thr);
 
3756
 
 
3757
                if (err != DB_SUCCESS) {
 
3758
 
 
3759
                        goto lock_wait_or_error;
 
3760
                }
 
3761
                prebuilt->sql_stat_start = FALSE;
 
3762
        }
 
3763
 
3833
3764
rec_loop:
3834
3765
        /*-------------------------------------------------------------*/
3835
3766
        /* PHASE 4: Look for matching records in a loop */
3859
3790
 
3860
3791
                if (set_also_gap_locks
3861
3792
                    && !(srv_locks_unsafe_for_binlog
3862
 
                         || trx->isolation_level <= TRX_ISO_READ_COMMITTED)
 
3793
                         || trx->isolation_level == TRX_ISO_READ_COMMITTED)
3863
3794
                    && prebuilt->select_lock_type != LOCK_NONE) {
3864
3795
 
3865
3796
                        /* Try to place a lock on the index record */
3876
3807
                                               prebuilt->select_lock_type,
3877
3808
                                               LOCK_ORDINARY, thr);
3878
3809
 
3879
 
                        switch (err) {
3880
 
                        case DB_SUCCESS_LOCKED_REC:
3881
 
                                err = DB_SUCCESS;
3882
 
                        case DB_SUCCESS:
3883
 
                                break;
3884
 
                        default:
 
3810
                        if (err != DB_SUCCESS) {
 
3811
 
3885
3812
                                goto lock_wait_or_error;
3886
3813
                        }
3887
3814
                }
3997
3924
                        if (set_also_gap_locks
3998
3925
                            && !(srv_locks_unsafe_for_binlog
3999
3926
                                 || trx->isolation_level
4000
 
                                 <= TRX_ISO_READ_COMMITTED)
 
3927
                                 == TRX_ISO_READ_COMMITTED)
4001
3928
                            && prebuilt->select_lock_type != LOCK_NONE) {
4002
3929
 
4003
3930
                                /* Try to place a gap lock on the index
4011
3938
                                        prebuilt->select_lock_type, LOCK_GAP,
4012
3939
                                        thr);
4013
3940
 
4014
 
                                switch (err) {
4015
 
                                case DB_SUCCESS_LOCKED_REC:
4016
 
                                case DB_SUCCESS:
4017
 
                                        break;
4018
 
                                default:
 
3941
                                if (err != DB_SUCCESS) {
 
3942
 
4019
3943
                                        goto lock_wait_or_error;
4020
3944
                                }
4021
3945
                        }
4036
3960
                        if (set_also_gap_locks
4037
3961
                            && !(srv_locks_unsafe_for_binlog
4038
3962
                                 || trx->isolation_level
4039
 
                                 <= TRX_ISO_READ_COMMITTED)
 
3963
                                 == TRX_ISO_READ_COMMITTED)
4040
3964
                            && prebuilt->select_lock_type != LOCK_NONE) {
4041
3965
 
4042
3966
                                /* Try to place a gap lock on the index
4050
3974
                                        prebuilt->select_lock_type, LOCK_GAP,
4051
3975
                                        thr);
4052
3976
 
4053
 
                                switch (err) {
4054
 
                                case DB_SUCCESS_LOCKED_REC:
4055
 
                                case DB_SUCCESS:
4056
 
                                        break;
4057
 
                                default:
 
3977
                                if (err != DB_SUCCESS) {
 
3978
 
4058
3979
                                        goto lock_wait_or_error;
4059
3980
                                }
4060
3981
                        }
4087
4008
 
4088
4009
                if (!set_also_gap_locks
4089
4010
                    || srv_locks_unsafe_for_binlog
4090
 
                    || trx->isolation_level <= TRX_ISO_READ_COMMITTED
 
4011
                    || trx->isolation_level == TRX_ISO_READ_COMMITTED
4091
4012
                    || (unique_search
4092
4013
                        && !UNIV_UNLIKELY(rec_get_deleted_flag(rec, comp)))) {
4093
4014
 
4124
4045
 
4125
4046
                switch (err) {
4126
4047
                        const rec_t*    old_vers;
4127
 
                case DB_SUCCESS_LOCKED_REC:
 
4048
                case DB_SUCCESS:
4128
4049
                        if (srv_locks_unsafe_for_binlog
4129
 
                            || trx->isolation_level
4130
 
                            <= TRX_ISO_READ_COMMITTED) {
 
4050
                            || trx->isolation_level == TRX_ISO_READ_COMMITTED) {
4131
4051
                                /* Note that a record of
4132
4052
                                prebuilt->index was locked. */
4133
4053
                                prebuilt->new_rec_locks = 1;
4134
4054
                        }
4135
 
                        err = DB_SUCCESS;
4136
 
                case DB_SUCCESS:
4137
4055
                        break;
4138
4056
                case DB_LOCK_WAIT:
4139
 
                        /* Never unlock rows that were part of a conflict. */
4140
 
                        prebuilt->new_rec_locks = 0;
4141
 
 
4142
4057
                        if (UNIV_LIKELY(prebuilt->row_read_type
4143
4058
                                        != ROW_READ_TRY_SEMI_CONSISTENT)
4144
 
                            || unique_search
4145
4059
                            || index != clust_index) {
4146
4060
 
4147
4061
                                goto lock_wait_or_error;
4153
4067
                                clust_index, prebuilt, rec,
4154
4068
                                &offsets, &heap, &old_vers, &mtr);
4155
4069
 
4156
 
                        switch (err) {
4157
 
                        case DB_SUCCESS_LOCKED_REC:
4158
 
                                err = DB_SUCCESS;
4159
 
                        case DB_SUCCESS:
4160
 
                                break;
4161
 
                        default:
 
4070
                        if (err != DB_SUCCESS) {
 
4071
 
4162
4072
                                goto lock_wait_or_error;
4163
4073
                        }
4164
4074
 
4172
4082
                        if (UNIV_LIKELY(trx->wait_lock != NULL)) {
4173
4083
                                lock_cancel_waiting_and_release(
4174
4084
                                        trx->wait_lock);
 
4085
                                prebuilt->new_rec_locks = 0;
4175
4086
                        } else {
4176
4087
                                mutex_exit(&kernel_mutex);
4177
4088
 
4183
4094
                                                          ULINT_UNDEFINED,
4184
4095
                                                          &heap);
4185
4096
                                err = DB_SUCCESS;
 
4097
                                /* Note that a record of
 
4098
                                prebuilt->index was locked. */
 
4099
                                prebuilt->new_rec_locks = 1;
4186
4100
                                break;
4187
4101
                        }
4188
4102
                        mutex_exit(&kernel_mutex);
4228
4142
                                        prebuilt, rec, &offsets, &heap,
4229
4143
                                        &old_vers, &mtr);
4230
4144
 
4231
 
                                switch (err) {
4232
 
                                case DB_SUCCESS_LOCKED_REC:
4233
 
                                case DB_SUCCESS:
4234
 
                                        break;
4235
 
                                default:
 
4145
                                if (err != DB_SUCCESS) {
 
4146
 
4236
4147
                                        goto lock_wait_or_error;
4237
4148
                                }
4238
4149
 
4245
4156
 
4246
4157
                                rec = old_vers;
4247
4158
                        }
4248
 
                } else {
 
4159
                } else if (!lock_sec_rec_cons_read_sees(rec, trx->read_view)) {
4249
4160
                        /* We are looking into a non-clustered index,
4250
4161
                        and to get the right version of the record we
4251
4162
                        have to look also into the clustered index: this
4253
4164
                        information via the clustered index record. */
4254
4165
 
4255
4166
                        ut_ad(index != clust_index);
4256
 
                        ut_ad(!dict_index_is_clust(index));
4257
 
                        if (!lock_sec_rec_cons_read_sees(
4258
 
                                    rec, trx->read_view)) {
4259
 
                                goto requires_clust_rec;
4260
 
                        }
 
4167
                        goto requires_clust_rec;
4261
4168
                }
4262
4169
        }
4263
4170
 
4271
4178
                /* The record is delete-marked: we can skip it */
4272
4179
 
4273
4180
                if ((srv_locks_unsafe_for_binlog
4274
 
                     || trx->isolation_level <= TRX_ISO_READ_COMMITTED)
 
4181
                     || trx->isolation_level == TRX_ISO_READ_COMMITTED)
4275
4182
                    && prebuilt->select_lock_type != LOCK_NONE
4276
4183
                    && !did_semi_consistent_read) {
4277
4184
 
4325
4232
                err = row_sel_get_clust_rec_for_mysql(prebuilt, index, rec,
4326
4233
                                                      thr, &clust_rec,
4327
4234
                                                      &offsets, &heap, &mtr);
4328
 
                switch (err) {
4329
 
                case DB_SUCCESS:
4330
 
                        if (clust_rec == NULL) {
4331
 
                                /* The record did not exist in the read view */
4332
 
                                ut_ad(prebuilt->select_lock_type == LOCK_NONE);
 
4235
                if (err != DB_SUCCESS) {
4333
4236
 
4334
 
                                goto next_rec;
4335
 
                        }
4336
 
                        break;
4337
 
                case DB_SUCCESS_LOCKED_REC:
4338
 
                        ut_a(clust_rec != NULL);
4339
 
                        if (srv_locks_unsafe_for_binlog
4340
 
                             || trx->isolation_level
4341
 
                            <= TRX_ISO_READ_COMMITTED) {
4342
 
                                /* Note that the clustered index record
4343
 
                                was locked. */
4344
 
                                prebuilt->new_rec_locks = 2;
4345
 
                        }
4346
 
                        err = DB_SUCCESS;
4347
 
                        break;
4348
 
                default:
4349
4237
                        goto lock_wait_or_error;
4350
4238
                }
4351
4239
 
 
4240
                if (clust_rec == NULL) {
 
4241
                        /* The record did not exist in the read view */
 
4242
                        ut_ad(prebuilt->select_lock_type == LOCK_NONE);
 
4243
 
 
4244
                        goto next_rec;
 
4245
                }
 
4246
 
 
4247
                if ((srv_locks_unsafe_for_binlog
 
4248
                     || trx->isolation_level == TRX_ISO_READ_COMMITTED)
 
4249
                    && prebuilt->select_lock_type != LOCK_NONE) {
 
4250
                        /* Note that both the secondary index record
 
4251
                        and the clustered index record were locked. */
 
4252
                        ut_ad(prebuilt->new_rec_locks == 1);
 
4253
                        prebuilt->new_rec_locks = 2;
 
4254
                }
 
4255
 
4352
4256
                if (UNIV_UNLIKELY(rec_get_deleted_flag(clust_rec, comp))) {
4353
4257
 
4354
4258
                        /* The record is delete marked: we can skip it */
4355
4259
 
4356
4260
                        if ((srv_locks_unsafe_for_binlog
4357
 
                             || trx->isolation_level <= TRX_ISO_READ_COMMITTED)
 
4261
                             || trx->isolation_level == TRX_ISO_READ_COMMITTED)
4358
4262
                            && prebuilt->select_lock_type != LOCK_NONE) {
4359
4263
 
4360
4264
                                /* No need to keep a lock on a delete-marked
4380
4284
                                                  ULINT_UNDEFINED, &heap);
4381
4285
                        result_rec = rec;
4382
4286
                }
4383
 
 
4384
 
                /* result_rec can legitimately be delete-marked
4385
 
                now that it has been established that it points to a
4386
 
                clustered index record that exists in the read view. */
4387
4287
        } else {
4388
4288
                result_rec = rec;
4389
 
                ut_ad(!rec_get_deleted_flag(rec, comp));
4390
4289
        }
4391
4290
 
4392
4291
        /* We found a qualifying record 'result_rec'. At this point,
4405
4304
            && prebuilt->select_lock_type == LOCK_NONE
4406
4305
            && !prebuilt->templ_contains_blob
4407
4306
            && !prebuilt->clust_index_was_generated
 
4307
            && !prebuilt->used_in_HANDLER
4408
4308
            && prebuilt->template_type
4409
4309
            != ROW_MYSQL_DUMMY_TEMPLATE) {
4410
4310
 
4417
4317
                not cache rows because there the cursor is a scrollable
4418
4318
                cursor. */
4419
4319
 
4420
 
                if (!row_sel_push_cache_row_for_mysql(prebuilt, result_rec,
4421
 
                                                      offsets)) {
4422
 
                        /* Only fresh inserts may contain incomplete
4423
 
                        externally stored columns. Pretend that such
4424
 
                        records do not exist. Such records may only be
4425
 
                        accessed at the READ UNCOMMITTED isolation
4426
 
                        level or when rolling back a recovered
4427
 
                        transaction. Rollback happens at a lower
4428
 
                        level, not here. */
4429
 
                        ut_a(trx->isolation_level == TRX_ISO_READ_UNCOMMITTED);
4430
 
                } else if (prebuilt->n_fetch_cached
4431
 
                           == MYSQL_FETCH_CACHE_SIZE) {
 
4320
                row_sel_push_cache_row_for_mysql(prebuilt, result_rec,
 
4321
                                                 offsets);
 
4322
                if (prebuilt->n_fetch_cached == MYSQL_FETCH_CACHE_SIZE) {
4432
4323
 
4433
4324
                        goto got_row;
4434
4325
                }
4444
4335
                } else {
4445
4336
                        if (!row_sel_store_mysql_rec(buf, prebuilt,
4446
4337
                                                     result_rec, offsets)) {
4447
 
                                /* Only fresh inserts may contain
4448
 
                                incomplete externally stored
4449
 
                                columns. Pretend that such records do
4450
 
                                not exist. Such records may only be
4451
 
                                accessed at the READ UNCOMMITTED
4452
 
                                isolation level or when rolling back a
4453
 
                                recovered transaction. Rollback
4454
 
                                happens at a lower level, not here. */
4455
 
                                ut_a(trx->isolation_level
4456
 
                                     == TRX_ISO_READ_UNCOMMITTED);
4457
 
                                goto next_rec;
 
4338
                                err = DB_TOO_BIG_RECORD;
 
4339
 
 
4340
                                goto lock_wait_or_error;
4458
4341
                        }
4459
4342
                }
4460
4343
 
4480
4363
        even after a unique search. */
4481
4364
 
4482
4365
        if (!unique_search_from_clust_index
4483
 
            || prebuilt->select_lock_type != LOCK_NONE) {
 
4366
            || prebuilt->select_lock_type != LOCK_NONE
 
4367
            || prebuilt->used_in_HANDLER) {
4484
4368
 
4485
4369
                /* Inside an update always store the cursor position */
4486
4370
 
4563
4447
 
4564
4448
        btr_pcur_store_position(pcur, &mtr);
4565
4449
 
4566
 
lock_table_wait:
4567
4450
        mtr_commit(&mtr);
4568
4451
        mtr_has_extra_clust_latch = FALSE;
4569
4452
 
4581
4464
                thr->lock_state = QUE_THR_LOCK_NOLOCK;
4582
4465
                mtr_start(&mtr);
4583
4466
 
4584
 
                /* Table lock waited, go try to obtain table lock
4585
 
                again */
4586
 
                if (table_lock_waited) {
4587
 
                        table_lock_waited = FALSE;
4588
 
 
4589
 
                        goto wait_table_again;
4590
 
                }
4591
 
 
4592
4467
                sel_restore_position_for_mysql(&same_user_rec,
4593
4468
                                               BTR_SEARCH_LEAF, pcur,
4594
4469
                                               moves_up, &mtr);
4595
4470
 
4596
4471
                if ((srv_locks_unsafe_for_binlog
4597
 
                     || trx->isolation_level <= TRX_ISO_READ_COMMITTED)
 
4472
                     || trx->isolation_level == TRX_ISO_READ_COMMITTED)
4598
4473
                    && !same_user_rec) {
4599
4474
 
4600
4475
                        /* Since we were not able to restore the cursor
4707
4582
        IX type locks actually would require ret = FALSE. */
4708
4583
 
4709
4584
        if (UT_LIST_GET_LEN(table->locks) == 0
4710
 
            && trx->id >= table->query_cache_inv_trx_id) {
 
4585
            && ut_dulint_cmp(trx->id,
 
4586
                             table->query_cache_inv_trx_id) >= 0) {
4711
4587
 
4712
4588
                ret = TRUE;
4713
4589
 
4739
4615
        dict_index_t*   index,          /*!< in: index to read from */
4740
4616
        const rec_t*    rec,            /*!< in: current rec */
4741
4617
        ulint           col_no,         /*!< in: column number */
4742
 
        ulint           mtype,          /*!< in: column main type */
4743
4618
        ibool           unsigned_type)  /*!< in: signed or unsigned flag */
4744
4619
{
4745
4620
        ulint           len;
4756
4631
        data = rec_get_nth_field(rec, offsets, col_no, &len);
4757
4632
 
4758
4633
        ut_a(len != UNIV_SQL_NULL);
4759
 
 
4760
 
        switch (mtype) {
4761
 
        case DATA_INT:
4762
 
                ut_a(len <= sizeof value);
4763
 
                value = mach_read_int_type(data, len, unsigned_type);
4764
 
                break;
4765
 
 
4766
 
        case DATA_FLOAT:
4767
 
                ut_a(len == sizeof(float));
4768
 
                value = (ib_uint64_t) mach_float_read(data);
4769
 
                break;
4770
 
 
4771
 
        case DATA_DOUBLE:
4772
 
                ut_a(len == sizeof(double));
4773
 
                value = (ib_uint64_t) mach_double_read(data);
4774
 
                break;
4775
 
 
4776
 
        default:
4777
 
                ut_error;
4778
 
        }
 
4634
        ut_a(len <= sizeof value);
 
4635
 
 
4636
        /* we assume AUTOINC value cannot be negative */
 
4637
        value = mach_read_int_type(data, len, unsigned_type);
4779
4638
 
4780
4639
        if (UNIV_LIKELY_NULL(heap)) {
4781
4640
                mem_heap_free(heap);
4861
4720
                                        dfield->col->prtype & DATA_UNSIGNED);
4862
4721
 
4863
4722
                                *value = row_search_autoinc_read_column(
4864
 
                                        index, rec, i,
4865
 
                                        dfield->col->mtype, unsigned_type);
 
4723
                                        index, rec, i, unsigned_type);
4866
4724
                        }
4867
4725
                }
4868
4726