~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-25 01:53:19 UTC
  • mto: (1953.1.2 build)
  • mto: This revision was merged to the branch mainline in revision 1955.
  • Revision ID: mordred@inaugust.com-20101125015319-ia85msn25uemopgc
Re-enabled -Wformat and then cleaned up the carnage.

Show diffs side-by-side

added added

removed removed

Lines of Context:
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));
200
202
                        }
201
203
 
202
204
                        len = dtype_get_at_most_n_mbchars(
203
 
                                col->prtype, col->mbminmaxlen,
 
205
                                col->prtype, col->mbminlen, col->mbmaxlen,
204
206
                                ifield->prefix_len, len, (char*) clust_field);
205
207
 
206
208
                        if (rec_offs_nth_extern(clust_offs, clust_pos)
207
209
                            && len < sec_len) {
208
210
                                if (!row_sel_sec_rec_is_for_blob(
209
211
                                            col->mtype, col->prtype,
210
 
                                            col->mbminmaxlen,
 
212
                                            col->mbminlen, col->mbmaxlen,
211
213
                                            clust_field, clust_len,
212
214
                                            sec_field, sec_len,
213
215
                                            dict_table_zip_size(
414
416
                                                              field_no))) {
415
417
 
416
418
                                /* Copy an externally stored field to the
417
 
                                temporary heap, if possible. */
 
419
                                temporary heap */
418
420
 
419
421
                                heap = mem_heap_create(1);
420
422
 
423
425
                                        dict_table_zip_size(index->table),
424
426
                                        field_no, &len, heap);
425
427
 
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
428
                                ut_a(len != UNIV_SQL_NULL);
438
429
 
439
430
                                needs_copy = TRUE;
872
863
                        clust_rec, index, offsets,
873
864
                        node->row_lock_mode, lock_type, thr);
874
865
 
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:
 
866
                if (err != DB_SUCCESS) {
 
867
 
883
868
                        goto err_exit;
884
869
                }
885
870
        } else {
935
920
        when plan->clust_pcur was positioned.  The latch will not be
936
921
        released until mtr_commit(mtr). */
937
922
 
938
 
        ut_ad(!rec_get_deleted_flag(clust_rec, rec_offs_comp(offsets)));
939
923
        row_sel_fetch_columns(index, clust_rec, offsets,
940
924
                              UT_LIST_GET_FIRST(plan->columns));
941
925
        *out_rec = clust_rec;
950
934
 
951
935
/*********************************************************************//**
952
936
Sets a lock on a record.
953
 
@return DB_SUCCESS, DB_SUCCESS_LOCKED_REC, or error code */
 
937
@return DB_SUCCESS or error code */
954
938
UNIV_INLINE
955
 
enum db_err
 
939
ulint
956
940
sel_set_rec_lock(
957
941
/*=============*/
958
942
        const buf_block_t*      block,  /*!< in: buffer block of rec */
964
948
                                        LOC_REC_NOT_GAP */
965
949
        que_thr_t*              thr)    /*!< in: query thread */
966
950
{
967
 
        trx_t*          trx;
968
 
        enum db_err     err;
 
951
        trx_t*  trx;
 
952
        ulint   err;
969
953
 
970
954
        trx = thr_get_trx(thr);
971
955
 
1498
1482
                                               node->row_lock_mode,
1499
1483
                                               lock_type, thr);
1500
1484
 
1501
 
                        switch (err) {
1502
 
                        case DB_SUCCESS_LOCKED_REC:
1503
 
                                err = DB_SUCCESS;
1504
 
                        case DB_SUCCESS:
1505
 
                                break;
1506
 
                        default:
 
1485
                        if (err != DB_SUCCESS) {
1507
1486
                                /* Note that in this case we will store in pcur
1508
1487
                                the PREDECESSOR of the record we are waiting
1509
1488
                                the lock for */
 
1489
 
1510
1490
                                goto lock_wait_or_error;
1511
1491
                        }
1512
1492
                }
1558
1538
                                       rec, index, offsets,
1559
1539
                                       node->row_lock_mode, lock_type, thr);
1560
1540
 
1561
 
                switch (err) {
1562
 
                case DB_SUCCESS_LOCKED_REC:
1563
 
                        err = DB_SUCCESS;
1564
 
                case DB_SUCCESS:
1565
 
                        break;
1566
 
                default:
 
1541
                if (err != DB_SUCCESS) {
 
1542
 
1567
1543
                        goto lock_wait_or_error;
1568
1544
                }
1569
1545
        }
1638
1614
                                }
1639
1615
 
1640
1616
                                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
1617
                                        offsets = rec_get_offsets(
1649
1618
                                                rec, index, offsets,
1650
1619
                                                ULINT_UNDEFINED, &heap);
1729
1698
                                            &mtr);
1730
1699
                mtr_has_extra_clust_latch = TRUE;
1731
1700
 
1732
 
                switch (err) {
1733
 
                case DB_SUCCESS_LOCKED_REC:
1734
 
                        err = DB_SUCCESS;
1735
 
                case DB_SUCCESS:
1736
 
                        break;
1737
 
                default:
 
1701
                if (err != DB_SUCCESS) {
 
1702
 
1738
1703
                        goto lock_wait_or_error;
1739
1704
                }
1740
1705
 
1919
1884
                        thr->run_node = que_node_get_parent(node);
1920
1885
                }
1921
1886
 
1922
 
                err = DB_SUCCESS;
1923
1887
                goto func_exit;
1924
1888
        }
1925
1889
 
2077
2041
                        /* Reset the aggregate total values */
2078
2042
                        sel_reset_aggregate_vals(node);
2079
2043
                }
2080
 
 
2081
 
                err = DB_SUCCESS;
2082
2044
        }
2083
2045
 
2084
2046
        err = row_sel(node, thr);
2532
2494
        ulint           len)    /*!< in: length of the data */
2533
2495
{
2534
2496
        byte*   ptr;
 
2497
        byte*   field_end;
 
2498
        byte*   pad_ptr;
2535
2499
 
2536
2500
        ut_ad(len != UNIV_SQL_NULL);
2537
 
        UNIV_MEM_ASSERT_RW(data, len);
2538
2501
 
2539
2502
        switch (templ->type) {
2540
 
                const byte*     field_end;
2541
 
                byte*           pad;
2542
2503
        case DATA_INT:
2543
2504
                /* Convert integer data from Innobase to a little-endian
2544
2505
                format, sign bit restored to normal */
2582
2543
                unused end of a >= 5.0.3 true VARCHAR column, just in case
2583
2544
                MySQL expects its contents to be deterministic. */
2584
2545
 
2585
 
                pad = dest + len;
 
2546
                pad_ptr = dest + len;
2586
2547
 
2587
2548
                ut_ad(templ->mbminlen <= templ->mbmaxlen);
2588
2549
 
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 */
 
2550
                /* We handle UCS2 charset strings differently. */
 
2551
                if (templ->mbminlen == 2) {
 
2552
                        /* A space char is two bytes, 0x0020 in UCS2 */
2599
2553
 
2600
 
                        if (UNIV_UNLIKELY(len & 1)) {
 
2554
                        if (len & 1) {
2601
2555
                                /* A 0x20 has been stripped from the column.
2602
2556
                                Pad it back. */
2603
2557
 
2604
 
                                if (pad < field_end) {
2605
 
                                        *pad++ = 0x20;
 
2558
                                if (pad_ptr < field_end) {
 
2559
                                        *pad_ptr = 0x20;
 
2560
                                        pad_ptr++;
2606
2561
                                }
2607
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);
2608
2577
                }
2609
 
 
2610
 
                row_mysql_pad_col(templ->mbminlen, pad, field_end - pad);
2611
2578
                break;
2612
2579
 
2613
2580
        case DATA_BLOB:
2632
2599
                      || !(templ->mysql_col_len % templ->mbmaxlen));
2633
2600
                ut_ad(len * templ->mbmaxlen >= templ->mysql_col_len);
2634
2601
 
2635
 
                if (templ->mbminlen == 1 && templ->mbmaxlen != 1) {
 
2602
                if (templ->mbminlen != templ->mbmaxlen) {
2636
2603
                        /* Pad with spaces. This undoes the stripping
2637
 
                        done in row0mysql.c, function
 
2604
                        done in row0mysql.ic, function
2638
2605
                        row_mysql_store_col_in_innobase_format(). */
2639
2606
 
2640
2607
                        memset(dest + len, 0x20, templ->mysql_col_len - len);
2665
2632
Note that the template in prebuilt may advise us to copy only a few
2666
2633
columns to mysql_rec, other columns are left blank. All columns may not
2667
2634
be needed in the query.
2668
 
@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) */
2669
2637
static
2670
 
#ifdef __GNUC__
2671
 
 __attribute__((warn_unused_result))
2672
 
#endif
2673
2638
ibool
2674
2639
row_sel_store_mysql_rec(
2675
2640
/*====================*/
2733
2698
                                dict_table_zip_size(prebuilt->table),
2734
2699
                                templ->rec_field_no, &len, heap);
2735
2700
 
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
2701
                        ut_a(len != UNIV_SQL_NULL);
2767
2702
                } else {
2768
2703
                        /* Field is stored in the row. */
2811
2746
                        /* MySQL assumes that the field for an SQL
2812
2747
                        NULL value is set to the default value. */
2813
2748
 
2814
 
                        UNIV_MEM_ASSERT_RW(prebuilt->default_rec
2815
 
                                           + templ->mysql_col_offset,
2816
 
                                           templ->mysql_col_len);
2817
2749
                        mysql_rec[templ->mysql_null_byte_offset]
2818
2750
                                |= (byte) templ->mysql_null_bit_mask;
2819
2751
                        memcpy(mysql_rec + templ->mysql_col_offset,
2865
2797
Retrieves the clustered index record corresponding to a record in a
2866
2798
non-clustered index. Does the necessary locking. Used in the MySQL
2867
2799
interface.
2868
 
@return DB_SUCCESS, DB_SUCCESS_LOCKED_REC, or error code */
 
2800
@return DB_SUCCESS or error code */
2869
2801
static
2870
 
enum db_err
 
2802
ulint
2871
2803
row_sel_get_clust_rec_for_mysql(
2872
2804
/*============================*/
2873
2805
        row_prebuilt_t* prebuilt,/*!< in: prebuilt struct in the handle */
2894
2826
        dict_index_t*   clust_index;
2895
2827
        const rec_t*    clust_rec;
2896
2828
        rec_t*          old_vers;
2897
 
        enum db_err     err;
 
2829
        ulint           err;
2898
2830
        trx_t*          trx;
2899
2831
 
2900
2832
        *out_rec = NULL;
2953
2885
 
2954
2886
                clust_rec = NULL;
2955
2887
 
2956
 
                err = DB_SUCCESS;
2957
2888
                goto func_exit;
2958
2889
        }
2959
2890
 
2969
2900
                        0, btr_pcur_get_block(prebuilt->clust_pcur),
2970
2901
                        clust_rec, clust_index, *offsets,
2971
2902
                        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:
 
2903
                if (err != DB_SUCCESS) {
 
2904
 
2977
2905
                        goto err_exit;
2978
2906
                }
2979
2907
        } else {
3033
2961
                                     rec, sec_index, clust_rec, clust_index));
3034
2962
#endif
3035
2963
                }
3036
 
 
3037
 
                err = DB_SUCCESS;
3038
2964
        }
3039
2965
 
3040
2966
func_exit:
3047
2973
                btr_pcur_store_position(prebuilt->clust_pcur, mtr);
3048
2974
        }
3049
2975
 
 
2976
        err = DB_SUCCESS;
3050
2977
err_exit:
3051
2978
        return(err);
3052
2979
}
3143
3070
 
3144
3071
                for (i = 0; i < prebuilt->n_template; i++) {
3145
3072
                        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
3073
                        ut_memcpy(buf + templ->mysql_col_offset,
3152
3074
                                  cached_rec + templ->mysql_col_offset,
3153
3075
                                  templ->mysql_col_len);
3162
3084
                }
3163
3085
        }
3164
3086
        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
3087
                ut_memcpy(buf,
3171
3088
                          prebuilt->fetch_cache[prebuilt->fetch_cache_first],
3172
3089
                          prebuilt->mysql_prefix_len);
3180
3097
}
3181
3098
 
3182
3099
/********************************************************************//**
3183
 
Pushes a row for MySQL to the fetch cache.
3184
 
@return TRUE on success, FALSE if the record contains incomplete BLOBs */
 
3100
Pushes a row for MySQL to the fetch cache. */
3185
3101
UNIV_INLINE
3186
 
#ifdef __GNUC__
3187
 
__attribute__((warn_unused_result))
3188
 
#endif
3189
 
ibool
 
3102
void
3190
3103
row_sel_push_cache_row_for_mysql(
3191
3104
/*=============================*/
3192
3105
        row_prebuilt_t* prebuilt,       /*!< in: prebuilt struct */
3221
3134
        }
3222
3135
 
3223
3136
        ut_ad(prebuilt->fetch_cache_first == 0);
3224
 
        UNIV_MEM_INVALID(prebuilt->fetch_cache[prebuilt->n_fetch_cached],
3225
 
                         prebuilt->mysql_row_len);
3226
3137
 
3227
3138
        if (UNIV_UNLIKELY(!row_sel_store_mysql_rec(
3228
3139
                                  prebuilt->fetch_cache[
3229
3140
                                          prebuilt->n_fetch_cached],
3230
3141
                                  prebuilt, rec, offsets))) {
3231
 
                return(FALSE);
 
3142
                ut_error;
3232
3143
        }
3233
3144
 
3234
3145
        prebuilt->n_fetch_cached++;
3235
 
        return(TRUE);
3236
3146
}
3237
3147
 
3238
3148
/*********************************************************************//**
3370
3280
        mem_heap_t*     heap                            = NULL;
3371
3281
        ulint           offsets_[REC_OFFS_NORMAL_SIZE];
3372
3282
        ulint*          offsets                         = offsets_;
3373
 
        ibool           table_lock_waited               = FALSE;
3374
3283
 
3375
3284
        rec_offs_init(offsets_);
3376
3285
 
3601
3510
                                row_sel_try_search_shortcut_for_mysql().
3602
3511
                                The latch will not be released until
3603
3512
                                mtr_commit(&mtr). */
3604
 
                                ut_ad(!rec_get_deleted_flag(rec, comp));
3605
3513
 
3606
3514
                                if (!row_sel_store_mysql_rec(buf, prebuilt,
3607
3515
                                                             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);
 
3516
                                        err = DB_TOO_BIG_RECORD;
3620
3517
 
3621
 
                                        /* Proceed as in case SEL_RETRY. */
3622
 
                                        break;
 
3518
                                        /* We let the main loop to do the
 
3519
                                        error handling */
 
3520
                                        goto shortcut_fails_too_big_rec;
3623
3521
                                }
3624
3522
 
3625
3523
                                mtr_commit(&mtr);
3659
3557
                        default:
3660
3558
                                ut_ad(0);
3661
3559
                        }
3662
 
 
 
3560
shortcut_fails_too_big_rec:
3663
3561
                        mtr_commit(&mtr);
3664
3562
                        mtr_start(&mtr);
3665
3563
                }
3673
3571
                trx->has_search_latch = FALSE;
3674
3572
        }
3675
3573
 
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
3574
        trx_start_if_not_started(trx);
3691
3575
 
3692
3576
        if (trx->isolation_level <= TRX_ISO_READ_COMMITTED
3717
3601
 
3718
3602
        clust_index = dict_table_get_first_index(index->table);
3719
3603
 
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
3604
        if (UNIV_LIKELY(direction != 0)) {
3759
3605
                ibool   need_to_process = sel_restore_position_for_mysql(
3760
3606
                        &same_user_rec, BTR_SEARCH_LEAF,
3809
3655
                                               prebuilt->select_lock_type,
3810
3656
                                               LOCK_GAP, thr);
3811
3657
 
3812
 
                        switch (err) {
3813
 
                        case DB_SUCCESS_LOCKED_REC:
3814
 
                                err = DB_SUCCESS;
3815
 
                        case DB_SUCCESS:
3816
 
                                break;
3817
 
                        default:
 
3658
                        if (err != DB_SUCCESS) {
 
3659
 
3818
3660
                                goto lock_wait_or_error;
3819
3661
                        }
3820
3662
                }
3830
3672
                }
3831
3673
        }
3832
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
 
3833
3711
rec_loop:
3834
3712
        /*-------------------------------------------------------------*/
3835
3713
        /* PHASE 4: Look for matching records in a loop */
3876
3754
                                               prebuilt->select_lock_type,
3877
3755
                                               LOCK_ORDINARY, thr);
3878
3756
 
3879
 
                        switch (err) {
3880
 
                        case DB_SUCCESS_LOCKED_REC:
3881
 
                                err = DB_SUCCESS;
3882
 
                        case DB_SUCCESS:
3883
 
                                break;
3884
 
                        default:
 
3757
                        if (err != DB_SUCCESS) {
 
3758
 
3885
3759
                                goto lock_wait_or_error;
3886
3760
                        }
3887
3761
                }
4011
3885
                                        prebuilt->select_lock_type, LOCK_GAP,
4012
3886
                                        thr);
4013
3887
 
4014
 
                                switch (err) {
4015
 
                                case DB_SUCCESS_LOCKED_REC:
4016
 
                                case DB_SUCCESS:
4017
 
                                        break;
4018
 
                                default:
 
3888
                                if (err != DB_SUCCESS) {
 
3889
 
4019
3890
                                        goto lock_wait_or_error;
4020
3891
                                }
4021
3892
                        }
4050
3921
                                        prebuilt->select_lock_type, LOCK_GAP,
4051
3922
                                        thr);
4052
3923
 
4053
 
                                switch (err) {
4054
 
                                case DB_SUCCESS_LOCKED_REC:
4055
 
                                case DB_SUCCESS:
4056
 
                                        break;
4057
 
                                default:
 
3924
                                if (err != DB_SUCCESS) {
 
3925
 
4058
3926
                                        goto lock_wait_or_error;
4059
3927
                                }
4060
3928
                        }
4124
3992
 
4125
3993
                switch (err) {
4126
3994
                        const rec_t*    old_vers;
4127
 
                case DB_SUCCESS_LOCKED_REC:
 
3995
                case DB_SUCCESS:
4128
3996
                        if (srv_locks_unsafe_for_binlog
4129
 
                            || trx->isolation_level
4130
 
                            <= TRX_ISO_READ_COMMITTED) {
 
3997
                            || trx->isolation_level <= TRX_ISO_READ_COMMITTED) {
4131
3998
                                /* Note that a record of
4132
3999
                                prebuilt->index was locked. */
4133
4000
                                prebuilt->new_rec_locks = 1;
4134
4001
                        }
4135
 
                        err = DB_SUCCESS;
4136
 
                case DB_SUCCESS:
4137
4002
                        break;
4138
4003
                case DB_LOCK_WAIT:
4139
 
                        /* Never unlock rows that were part of a conflict. */
4140
 
                        prebuilt->new_rec_locks = 0;
4141
 
 
4142
4004
                        if (UNIV_LIKELY(prebuilt->row_read_type
4143
4005
                                        != ROW_READ_TRY_SEMI_CONSISTENT)
4144
4006
                            || unique_search
4153
4015
                                clust_index, prebuilt, rec,
4154
4016
                                &offsets, &heap, &old_vers, &mtr);
4155
4017
 
4156
 
                        switch (err) {
4157
 
                        case DB_SUCCESS_LOCKED_REC:
4158
 
                                err = DB_SUCCESS;
4159
 
                        case DB_SUCCESS:
4160
 
                                break;
4161
 
                        default:
 
4018
                        if (err != DB_SUCCESS) {
 
4019
 
4162
4020
                                goto lock_wait_or_error;
4163
4021
                        }
4164
4022
 
4172
4030
                        if (UNIV_LIKELY(trx->wait_lock != NULL)) {
4173
4031
                                lock_cancel_waiting_and_release(
4174
4032
                                        trx->wait_lock);
 
4033
                                prebuilt->new_rec_locks = 0;
4175
4034
                        } else {
4176
4035
                                mutex_exit(&kernel_mutex);
4177
4036
 
4183
4042
                                                          ULINT_UNDEFINED,
4184
4043
                                                          &heap);
4185
4044
                                err = DB_SUCCESS;
 
4045
                                /* Note that a record of
 
4046
                                prebuilt->index was locked. */
 
4047
                                prebuilt->new_rec_locks = 1;
4186
4048
                                break;
4187
4049
                        }
4188
4050
                        mutex_exit(&kernel_mutex);
4228
4090
                                        prebuilt, rec, &offsets, &heap,
4229
4091
                                        &old_vers, &mtr);
4230
4092
 
4231
 
                                switch (err) {
4232
 
                                case DB_SUCCESS_LOCKED_REC:
4233
 
                                case DB_SUCCESS:
4234
 
                                        break;
4235
 
                                default:
 
4093
                                if (err != DB_SUCCESS) {
 
4094
 
4236
4095
                                        goto lock_wait_or_error;
4237
4096
                                }
4238
4097
 
4245
4104
 
4246
4105
                                rec = old_vers;
4247
4106
                        }
4248
 
                } else {
 
4107
                } else if (!lock_sec_rec_cons_read_sees(rec, trx->read_view)) {
4249
4108
                        /* We are looking into a non-clustered index,
4250
4109
                        and to get the right version of the record we
4251
4110
                        have to look also into the clustered index: this
4253
4112
                        information via the clustered index record. */
4254
4113
 
4255
4114
                        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
 
                        }
 
4115
                        goto requires_clust_rec;
4261
4116
                }
4262
4117
        }
4263
4118
 
4325
4180
                err = row_sel_get_clust_rec_for_mysql(prebuilt, index, rec,
4326
4181
                                                      thr, &clust_rec,
4327
4182
                                                      &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);
 
4183
                if (err != DB_SUCCESS) {
4333
4184
 
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
4185
                        goto lock_wait_or_error;
4350
4186
                }
4351
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
 
4352
4204
                if (UNIV_UNLIKELY(rec_get_deleted_flag(clust_rec, comp))) {
4353
4205
 
4354
4206
                        /* The record is delete marked: we can skip it */
4380
4232
                                                  ULINT_UNDEFINED, &heap);
4381
4233
                        result_rec = rec;
4382
4234
                }
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
4235
        } else {
4388
4236
                result_rec = rec;
4389
 
                ut_ad(!rec_get_deleted_flag(rec, comp));
4390
4237
        }
4391
4238
 
4392
4239
        /* We found a qualifying record 'result_rec'. At this point,
4417
4264
                not cache rows because there the cursor is a scrollable
4418
4265
                cursor. */
4419
4266
 
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) {
 
4267
                row_sel_push_cache_row_for_mysql(prebuilt, result_rec,
 
4268
                                                 offsets);
 
4269
                if (prebuilt->n_fetch_cached == MYSQL_FETCH_CACHE_SIZE) {
4432
4270
 
4433
4271
                        goto got_row;
4434
4272
                }
4444
4282
                } else {
4445
4283
                        if (!row_sel_store_mysql_rec(buf, prebuilt,
4446
4284
                                                     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;
 
4285
                                err = DB_TOO_BIG_RECORD;
 
4286
 
 
4287
                                goto lock_wait_or_error;
4458
4288
                        }
4459
4289
                }
4460
4290
 
4563
4393
 
4564
4394
        btr_pcur_store_position(pcur, &mtr);
4565
4395
 
4566
 
lock_table_wait:
4567
4396
        mtr_commit(&mtr);
4568
4397
        mtr_has_extra_clust_latch = FALSE;
4569
4398
 
4581
4410
                thr->lock_state = QUE_THR_LOCK_NOLOCK;
4582
4411
                mtr_start(&mtr);
4583
4412
 
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
4413
                sel_restore_position_for_mysql(&same_user_rec,
4593
4414
                                               BTR_SEARCH_LEAF, pcur,
4594
4415
                                               moves_up, &mtr);
4707
4528
        IX type locks actually would require ret = FALSE. */
4708
4529
 
4709
4530
        if (UT_LIST_GET_LEN(table->locks) == 0
4710
 
            && trx->id >= table->query_cache_inv_trx_id) {
 
4531
            && ut_dulint_cmp(trx->id,
 
4532
                             table->query_cache_inv_trx_id) >= 0) {
4711
4533
 
4712
4534
                ret = TRUE;
4713
4535