~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-26 22:50:54 UTC
  • mfrom: (1953.1.6 build)
  • Revision ID: mordred@inaugust.com-20101126225054-sg90svw8579t5p3i
Stewart - InnoDB 1.1.1
Monty - Fixed some autoconf tests which were returning false positives.

Show diffs side-by-side

added added

removed removed

Lines of Context:
416
416
                                                              field_no))) {
417
417
 
418
418
                                /* Copy an externally stored field to the
419
 
                                temporary heap */
 
419
                                temporary heap, if possible. */
420
420
 
421
421
                                heap = mem_heap_create(1);
422
422
 
425
425
                                        dict_table_zip_size(index->table),
426
426
                                        field_no, &len, heap);
427
427
 
 
428
                                /* data == NULL means that the
 
429
                                externally stored field was not
 
430
                                written yet. This record
 
431
                                should only be seen by
 
432
                                recv_recovery_rollback_active() or any
 
433
                                TRX_ISO_READ_UNCOMMITTED
 
434
                                transactions. The InnoDB SQL parser
 
435
                                (the sole caller of this function)
 
436
                                does not implement READ UNCOMMITTED,
 
437
                                and it is not involved during rollback. */
 
438
                                ut_a(data);
428
439
                                ut_a(len != UNIV_SQL_NULL);
429
440
 
430
441
                                needs_copy = TRUE;
863
874
                        clust_rec, index, offsets,
864
875
                        node->row_lock_mode, lock_type, thr);
865
876
 
866
 
                if (err != DB_SUCCESS) {
867
 
 
 
877
                switch (err) {
 
878
                case DB_SUCCESS:
 
879
                case DB_SUCCESS_LOCKED_REC:
 
880
                        /* Declare the variable uninitialized in Valgrind.
 
881
                        It should be set to DB_SUCCESS at func_exit. */
 
882
                        UNIV_MEM_INVALID(&err, sizeof err);
 
883
                        break;
 
884
                default:
868
885
                        goto err_exit;
869
886
                }
870
887
        } else {
920
937
        when plan->clust_pcur was positioned.  The latch will not be
921
938
        released until mtr_commit(mtr). */
922
939
 
 
940
        ut_ad(!rec_get_deleted_flag(clust_rec, rec_offs_comp(offsets)));
923
941
        row_sel_fetch_columns(index, clust_rec, offsets,
924
942
                              UT_LIST_GET_FIRST(plan->columns));
925
943
        *out_rec = clust_rec;
934
952
 
935
953
/*********************************************************************//**
936
954
Sets a lock on a record.
937
 
@return DB_SUCCESS or error code */
 
955
@return DB_SUCCESS, DB_SUCCESS_LOCKED_REC, or error code */
938
956
UNIV_INLINE
939
 
ulint
 
957
enum db_err
940
958
sel_set_rec_lock(
941
959
/*=============*/
942
960
        const buf_block_t*      block,  /*!< in: buffer block of rec */
948
966
                                        LOC_REC_NOT_GAP */
949
967
        que_thr_t*              thr)    /*!< in: query thread */
950
968
{
951
 
        trx_t*  trx;
952
 
        ulint   err;
 
969
        trx_t*          trx;
 
970
        enum db_err     err;
953
971
 
954
972
        trx = thr_get_trx(thr);
955
973
 
1482
1500
                                               node->row_lock_mode,
1483
1501
                                               lock_type, thr);
1484
1502
 
1485
 
                        if (err != DB_SUCCESS) {
 
1503
                        switch (err) {
 
1504
                        case DB_SUCCESS_LOCKED_REC:
 
1505
                                err = DB_SUCCESS;
 
1506
                        case DB_SUCCESS:
 
1507
                                break;
 
1508
                        default:
1486
1509
                                /* Note that in this case we will store in pcur
1487
1510
                                the PREDECESSOR of the record we are waiting
1488
1511
                                the lock for */
1489
 
 
1490
1512
                                goto lock_wait_or_error;
1491
1513
                        }
1492
1514
                }
1538
1560
                                       rec, index, offsets,
1539
1561
                                       node->row_lock_mode, lock_type, thr);
1540
1562
 
1541
 
                if (err != DB_SUCCESS) {
1542
 
 
 
1563
                switch (err) {
 
1564
                case DB_SUCCESS_LOCKED_REC:
 
1565
                        err = DB_SUCCESS;
 
1566
                case DB_SUCCESS:
 
1567
                        break;
 
1568
                default:
1543
1569
                        goto lock_wait_or_error;
1544
1570
                }
1545
1571
        }
1614
1640
                                }
1615
1641
 
1616
1642
                                if (old_vers == NULL) {
 
1643
                                        /* The record does not exist
 
1644
                                        in our read view. Skip it, but
 
1645
                                        first attempt to determine
 
1646
                                        whether the index segment we
 
1647
                                        are searching through has been
 
1648
                                        exhausted. */
 
1649
 
1617
1650
                                        offsets = rec_get_offsets(
1618
1651
                                                rec, index, offsets,
1619
1652
                                                ULINT_UNDEFINED, &heap);
2498
2531
        byte*   pad_ptr;
2499
2532
 
2500
2533
        ut_ad(len != UNIV_SQL_NULL);
 
2534
        UNIV_MEM_ASSERT_RW(data, len);
2501
2535
 
2502
2536
        switch (templ->type) {
2503
2537
        case DATA_INT:
2632
2666
Note that the template in prebuilt may advise us to copy only a few
2633
2667
columns to mysql_rec, other columns are left blank. All columns may not
2634
2668
be needed in the query.
2635
 
@return TRUE if success, FALSE if could not allocate memory for a BLOB
2636
 
(though we may also assert in that case) */
 
2669
@return TRUE on success, FALSE if not all columns could be retrieved */
2637
2670
static
 
2671
#ifdef __GNUC__
 
2672
 __attribute__((warn_unused_result))
 
2673
#endif
2638
2674
ibool
2639
2675
row_sel_store_mysql_rec(
2640
2676
/*====================*/
2657
2693
        ut_ad(prebuilt->mysql_template);
2658
2694
        ut_ad(prebuilt->default_rec);
2659
2695
        ut_ad(rec_offs_validate(rec, NULL, offsets));
 
2696
        ut_ad(!rec_get_deleted_flag(rec, rec_offs_comp(offsets)));
2660
2697
 
2661
2698
        if (UNIV_LIKELY_NULL(prebuilt->blob_heap)) {
2662
2699
                mem_heap_free(prebuilt->blob_heap);
2663
2700
                prebuilt->blob_heap = NULL;
2664
2701
        }
2665
2702
 
 
2703
        /* init null bytes with default values as they might be
 
2704
        left uninitialized in some cases and these uninited bytes
 
2705
        might be copied into mysql record buffer that leads to
 
2706
        valgrind warnings */
 
2707
        memcpy(mysql_rec, prebuilt->default_rec, prebuilt->null_bitmap_len);
 
2708
 
2666
2709
        for (i = 0; i < prebuilt->n_template ; i++) {
2667
2710
 
2668
2711
                templ = prebuilt->mysql_template + i;
2698
2741
                                dict_table_zip_size(prebuilt->table),
2699
2742
                                templ->rec_field_no, &len, heap);
2700
2743
 
 
2744
                        if (UNIV_UNLIKELY(!data)) {
 
2745
                                /* The externally stored field
 
2746
                                was not written yet. This
 
2747
                                record should only be seen by
 
2748
                                recv_recovery_rollback_active()
 
2749
                                or any TRX_ISO_READ_UNCOMMITTED
 
2750
                                transactions. */
 
2751
 
 
2752
                                if (extern_field_heap) {
 
2753
                                        mem_heap_free(extern_field_heap);
 
2754
                                }
 
2755
 
 
2756
                                return(FALSE);
 
2757
                        }
 
2758
 
2701
2759
                        ut_a(len != UNIV_SQL_NULL);
2702
2760
                } else {
2703
2761
                        /* Field is stored in the row. */
2746
2804
                        /* MySQL assumes that the field for an SQL
2747
2805
                        NULL value is set to the default value. */
2748
2806
 
 
2807
                        UNIV_MEM_ASSERT_RW(prebuilt->default_rec
 
2808
                                           + templ->mysql_col_offset,
 
2809
                                           templ->mysql_col_len);
2749
2810
                        mysql_rec[templ->mysql_null_byte_offset]
2750
2811
                                |= (byte) templ->mysql_null_bit_mask;
2751
2812
                        memcpy(mysql_rec + templ->mysql_col_offset,
2797
2858
Retrieves the clustered index record corresponding to a record in a
2798
2859
non-clustered index. Does the necessary locking. Used in the MySQL
2799
2860
interface.
2800
 
@return DB_SUCCESS or error code */
 
2861
@return DB_SUCCESS, DB_SUCCESS_LOCKED_REC, or error code */
2801
2862
static
2802
 
ulint
 
2863
enum db_err
2803
2864
row_sel_get_clust_rec_for_mysql(
2804
2865
/*============================*/
2805
2866
        row_prebuilt_t* prebuilt,/*!< in: prebuilt struct in the handle */
2826
2887
        dict_index_t*   clust_index;
2827
2888
        const rec_t*    clust_rec;
2828
2889
        rec_t*          old_vers;
2829
 
        ulint           err;
 
2890
        enum db_err     err;
2830
2891
        trx_t*          trx;
2831
2892
 
2832
2893
        *out_rec = NULL;
2885
2946
 
2886
2947
                clust_rec = NULL;
2887
2948
 
 
2949
                err = DB_SUCCESS;
2888
2950
                goto func_exit;
2889
2951
        }
2890
2952
 
2900
2962
                        0, btr_pcur_get_block(prebuilt->clust_pcur),
2901
2963
                        clust_rec, clust_index, *offsets,
2902
2964
                        prebuilt->select_lock_type, LOCK_REC_NOT_GAP, thr);
2903
 
                if (err != DB_SUCCESS) {
2904
 
 
 
2965
                switch (err) {
 
2966
                case DB_SUCCESS:
 
2967
                case DB_SUCCESS_LOCKED_REC:
 
2968
                        break;
 
2969
                default:
2905
2970
                        goto err_exit;
2906
2971
                }
2907
2972
        } else {
2961
3026
                                     rec, sec_index, clust_rec, clust_index));
2962
3027
#endif
2963
3028
                }
 
3029
 
 
3030
                err = DB_SUCCESS;
2964
3031
        }
2965
3032
 
2966
3033
func_exit:
2973
3040
                btr_pcur_store_position(prebuilt->clust_pcur, mtr);
2974
3041
        }
2975
3042
 
2976
 
        err = DB_SUCCESS;
2977
3043
err_exit:
2978
3044
        return(err);
2979
3045
}
3070
3136
 
3071
3137
                for (i = 0; i < prebuilt->n_template; i++) {
3072
3138
                        templ = prebuilt->mysql_template + i;
 
3139
#if 0 /* Some of the cached_rec may legitimately be uninitialized. */
 
3140
                        UNIV_MEM_ASSERT_RW(cached_rec
 
3141
                                           + templ->mysql_col_offset,
 
3142
                                           templ->mysql_col_len);
 
3143
#endif
3073
3144
                        ut_memcpy(buf + templ->mysql_col_offset,
3074
3145
                                  cached_rec + templ->mysql_col_offset,
3075
3146
                                  templ->mysql_col_len);
3084
3155
                }
3085
3156
        }
3086
3157
        else {
 
3158
#if 0 /* Some of the cached_rec may legitimately be uninitialized. */
 
3159
                UNIV_MEM_ASSERT_RW(prebuilt->fetch_cache
 
3160
                                   [prebuilt->fetch_cache_first],
 
3161
                                   prebuilt->mysql_prefix_len);
 
3162
#endif
3087
3163
                ut_memcpy(buf,
3088
3164
                          prebuilt->fetch_cache[prebuilt->fetch_cache_first],
3089
3165
                          prebuilt->mysql_prefix_len);
3097
3173
}
3098
3174
 
3099
3175
/********************************************************************//**
3100
 
Pushes a row for MySQL to the fetch cache. */
 
3176
Pushes a row for MySQL to the fetch cache.
 
3177
@return TRUE on success, FALSE if the record contains incomplete BLOBs */
3101
3178
UNIV_INLINE
3102
 
void
 
3179
#ifdef __GNUC__
 
3180
__attribute__((warn_unused_result))
 
3181
#endif
 
3182
ibool
3103
3183
row_sel_push_cache_row_for_mysql(
3104
3184
/*=============================*/
3105
3185
        row_prebuilt_t* prebuilt,       /*!< in: prebuilt struct */
3134
3214
        }
3135
3215
 
3136
3216
        ut_ad(prebuilt->fetch_cache_first == 0);
 
3217
        UNIV_MEM_INVALID(prebuilt->fetch_cache[prebuilt->n_fetch_cached],
 
3218
                         prebuilt->mysql_row_len);
3137
3219
 
3138
3220
        if (UNIV_UNLIKELY(!row_sel_store_mysql_rec(
3139
3221
                                  prebuilt->fetch_cache[
3140
3222
                                          prebuilt->n_fetch_cached],
3141
3223
                                  prebuilt, rec, offsets))) {
3142
 
                ut_error;
 
3224
                return(FALSE);
3143
3225
        }
3144
3226
 
3145
3227
        prebuilt->n_fetch_cached++;
 
3228
        return(TRUE);
3146
3229
}
3147
3230
 
3148
3231
/*********************************************************************//**
3513
3596
 
3514
3597
                                if (!row_sel_store_mysql_rec(buf, prebuilt,
3515
3598
                                                             rec, offsets)) {
3516
 
                                        err = DB_TOO_BIG_RECORD;
 
3599
                                        /* Only fresh inserts may contain
 
3600
                                        incomplete externally stored
 
3601
                                        columns. Pretend that such
 
3602
                                        records do not exist. Such
 
3603
                                        records may only be accessed
 
3604
                                        at the READ UNCOMMITTED
 
3605
                                        isolation level or when
 
3606
                                        rolling back a recovered
 
3607
                                        transaction. Rollback happens
 
3608
                                        at a lower level, not here. */
 
3609
                                        ut_a(trx->isolation_level
 
3610
                                             == TRX_ISO_READ_UNCOMMITTED);
3517
3611
 
3518
 
                                        /* We let the main loop to do the
3519
 
                                        error handling */
3520
 
                                        goto shortcut_fails_too_big_rec;
 
3612
                                        /* Proceed as in case SEL_RETRY. */
 
3613
                                        break;
3521
3614
                                }
3522
3615
 
3523
3616
                                mtr_commit(&mtr);
3557
3650
                        default:
3558
3651
                                ut_ad(0);
3559
3652
                        }
3560
 
shortcut_fails_too_big_rec:
 
3653
 
3561
3654
                        mtr_commit(&mtr);
3562
3655
                        mtr_start(&mtr);
3563
3656
                }
3571
3664
                trx->has_search_latch = FALSE;
3572
3665
        }
3573
3666
 
 
3667
        ut_ad(prebuilt->sql_stat_start || trx->conc_state == TRX_ACTIVE);
 
3668
        ut_ad(trx->conc_state == TRX_NOT_STARTED
 
3669
              || trx->conc_state == TRX_ACTIVE);
 
3670
        ut_ad(prebuilt->sql_stat_start
 
3671
              || prebuilt->select_lock_type != LOCK_NONE
 
3672
              || trx->read_view);
 
3673
 
 
3674
        ut_ad(prebuilt->sql_stat_start || trx->conc_state == TRX_ACTIVE);
 
3675
        ut_ad(trx->conc_state == TRX_NOT_STARTED
 
3676
              || trx->conc_state == TRX_ACTIVE);
 
3677
        ut_ad(prebuilt->sql_stat_start
 
3678
              || prebuilt->select_lock_type != LOCK_NONE
 
3679
              || trx->read_view);
 
3680
 
3574
3681
        trx_start_if_not_started(trx);
3575
3682
 
3576
3683
        if (trx->isolation_level <= TRX_ISO_READ_COMMITTED
3655
3762
                                               prebuilt->select_lock_type,
3656
3763
                                               LOCK_GAP, thr);
3657
3764
 
3658
 
                        if (err != DB_SUCCESS) {
3659
 
 
 
3765
                        switch (err) {
 
3766
                        case DB_SUCCESS_LOCKED_REC:
 
3767
                                err = DB_SUCCESS;
 
3768
                        case DB_SUCCESS:
 
3769
                                break;
 
3770
                        default:
3660
3771
                                goto lock_wait_or_error;
3661
3772
                        }
3662
3773
                }
3754
3865
                                               prebuilt->select_lock_type,
3755
3866
                                               LOCK_ORDINARY, thr);
3756
3867
 
3757
 
                        if (err != DB_SUCCESS) {
3758
 
 
 
3868
                        switch (err) {
 
3869
                        case DB_SUCCESS_LOCKED_REC:
 
3870
                                err = DB_SUCCESS;
 
3871
                        case DB_SUCCESS:
 
3872
                                break;
 
3873
                        default:
3759
3874
                                goto lock_wait_or_error;
3760
3875
                        }
3761
3876
                }
3885
4000
                                        prebuilt->select_lock_type, LOCK_GAP,
3886
4001
                                        thr);
3887
4002
 
3888
 
                                if (err != DB_SUCCESS) {
3889
 
 
 
4003
                                switch (err) {
 
4004
                                case DB_SUCCESS_LOCKED_REC:
 
4005
                                case DB_SUCCESS:
 
4006
                                        break;
 
4007
                                default:
3890
4008
                                        goto lock_wait_or_error;
3891
4009
                                }
3892
4010
                        }
3921
4039
                                        prebuilt->select_lock_type, LOCK_GAP,
3922
4040
                                        thr);
3923
4041
 
3924
 
                                if (err != DB_SUCCESS) {
3925
 
 
 
4042
                                switch (err) {
 
4043
                                case DB_SUCCESS_LOCKED_REC:
 
4044
                                case DB_SUCCESS:
 
4045
                                        break;
 
4046
                                default:
3926
4047
                                        goto lock_wait_or_error;
3927
4048
                                }
3928
4049
                        }
3992
4113
 
3993
4114
                switch (err) {
3994
4115
                        const rec_t*    old_vers;
3995
 
                case DB_SUCCESS:
 
4116
                case DB_SUCCESS_LOCKED_REC:
3996
4117
                        if (srv_locks_unsafe_for_binlog
3997
 
                            || trx->isolation_level <= TRX_ISO_READ_COMMITTED) {
 
4118
                            || trx->isolation_level
 
4119
                            <= TRX_ISO_READ_COMMITTED) {
3998
4120
                                /* Note that a record of
3999
4121
                                prebuilt->index was locked. */
4000
4122
                                prebuilt->new_rec_locks = 1;
4001
4123
                        }
 
4124
                        err = DB_SUCCESS;
 
4125
                case DB_SUCCESS:
4002
4126
                        break;
4003
4127
                case DB_LOCK_WAIT:
 
4128
                        /* Never unlock rows that were part of a conflict. */
 
4129
                        prebuilt->new_rec_locks = 0;
 
4130
 
4004
4131
                        if (UNIV_LIKELY(prebuilt->row_read_type
4005
4132
                                        != ROW_READ_TRY_SEMI_CONSISTENT)
4006
4133
                            || unique_search
4030
4157
                        if (UNIV_LIKELY(trx->wait_lock != NULL)) {
4031
4158
                                lock_cancel_waiting_and_release(
4032
4159
                                        trx->wait_lock);
4033
 
                                prebuilt->new_rec_locks = 0;
4034
4160
                        } else {
4035
4161
                                mutex_exit(&kernel_mutex);
4036
4162
 
4042
4168
                                                          ULINT_UNDEFINED,
4043
4169
                                                          &heap);
4044
4170
                                err = DB_SUCCESS;
4045
 
                                /* Note that a record of
4046
 
                                prebuilt->index was locked. */
4047
 
                                prebuilt->new_rec_locks = 1;
4048
4171
                                break;
4049
4172
                        }
4050
4173
                        mutex_exit(&kernel_mutex);
4180
4303
                err = row_sel_get_clust_rec_for_mysql(prebuilt, index, rec,
4181
4304
                                                      thr, &clust_rec,
4182
4305
                                                      &offsets, &heap, &mtr);
4183
 
                if (err != DB_SUCCESS) {
 
4306
                switch (err) {
 
4307
                case DB_SUCCESS:
 
4308
                        if (clust_rec == NULL) {
 
4309
                                /* The record did not exist in the read view */
 
4310
                                ut_ad(prebuilt->select_lock_type == LOCK_NONE);
4184
4311
 
 
4312
                                goto next_rec;
 
4313
                        }
 
4314
                        break;
 
4315
                case DB_SUCCESS_LOCKED_REC:
 
4316
                        ut_a(clust_rec != NULL);
 
4317
                        if (srv_locks_unsafe_for_binlog
 
4318
                             || trx->isolation_level
 
4319
                            <= TRX_ISO_READ_COMMITTED) {
 
4320
                                /* Note that the clustered index record
 
4321
                                was locked. */
 
4322
                                prebuilt->new_rec_locks = 2;
 
4323
                        }
 
4324
                        err = DB_SUCCESS;
 
4325
                        break;
 
4326
                default:
4185
4327
                        goto lock_wait_or_error;
4186
4328
                }
4187
4329
 
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
 
 
4204
4330
                if (UNIV_UNLIKELY(rec_get_deleted_flag(clust_rec, comp))) {
4205
4331
 
4206
4332
                        /* The record is delete marked: we can skip it */
4264
4390
                not cache rows because there the cursor is a scrollable
4265
4391
                cursor. */
4266
4392
 
4267
 
                row_sel_push_cache_row_for_mysql(prebuilt, result_rec,
4268
 
                                                 offsets);
4269
 
                if (prebuilt->n_fetch_cached == MYSQL_FETCH_CACHE_SIZE) {
 
4393
                if (!row_sel_push_cache_row_for_mysql(prebuilt, result_rec,
 
4394
                                                      offsets)) {
 
4395
                        /* Only fresh inserts may contain incomplete
 
4396
                        externally stored columns. Pretend that such
 
4397
                        records do not exist. Such records may only be
 
4398
                        accessed at the READ UNCOMMITTED isolation
 
4399
                        level or when rolling back a recovered
 
4400
                        transaction. Rollback happens at a lower
 
4401
                        level, not here. */
 
4402
                        ut_a(trx->isolation_level == TRX_ISO_READ_UNCOMMITTED);
 
4403
                } else if (prebuilt->n_fetch_cached
 
4404
                           == MYSQL_FETCH_CACHE_SIZE) {
4270
4405
 
4271
4406
                        goto got_row;
4272
4407
                }
4282
4417
                } else {
4283
4418
                        if (!row_sel_store_mysql_rec(buf, prebuilt,
4284
4419
                                                     result_rec, offsets)) {
4285
 
                                err = DB_TOO_BIG_RECORD;
4286
 
 
4287
 
                                goto lock_wait_or_error;
 
4420
                                /* Only fresh inserts may contain
 
4421
                                incomplete externally stored
 
4422
                                columns. Pretend that such records do
 
4423
                                not exist. Such records may only be
 
4424
                                accessed at the READ UNCOMMITTED
 
4425
                                isolation level or when rolling back a
 
4426
                                recovered transaction. Rollback
 
4427
                                happens at a lower level, not here. */
 
4428
                                ut_a(trx->isolation_level
 
4429
                                     == TRX_ISO_READ_UNCOMMITTED);
 
4430
                                goto next_rec;
4288
4431
                        }
4289
4432
                }
4290
4433