1
1
/*****************************************************************************
3
Copyright (C) 1997, 2010, Innobase Oy. All Rights Reserved.
4
Copyright (C) 2008, Google Inc.
3
Copyright (c) 1997, 2010, Innobase Oy. All Rights Reserved.
4
Copyright (c) 2008, Google Inc.
6
6
Portions of this file contain modifications contributed and copyrighted by
7
7
Google, Inc. Those modifications are gratefully acknowledged and are described
88
88
/*========================*/
89
89
ulint mtype, /*!< in: main type */
90
90
ulint prtype, /*!< in: precise type */
91
ulint mbminmaxlen, /*!< in: minimum and maximum length of
92
a multi-byte character */
91
ulint mbminlen, /*!< in: minimum length of a
92
multi-byte character */
93
ulint mbmaxlen, /*!< in: maximum length of a
94
multi-byte character */
93
95
const byte* clust_field, /*!< in: the locally stored part of
94
96
the clustered index column, including
95
97
the BLOB pointer; the clustered
105
107
byte buf[DICT_MAX_INDEX_COL_LEN];
107
ut_a(clust_len >= BTR_EXTERN_FIELD_REF_SIZE);
110
(!memcmp(clust_field + clust_len - BTR_EXTERN_FIELD_REF_SIZE,
111
field_ref_zero, BTR_EXTERN_FIELD_REF_SIZE))) {
112
/* The externally stored field was not written yet.
113
This record should only be seen by
114
recv_recovery_rollback_active() or any
115
TRX_ISO_READ_UNCOMMITTED transactions. */
119
109
len = btr_copy_externally_stored_field_prefix(buf, sizeof buf,
121
111
clust_field, clust_len);
132
len = dtype_get_at_most_n_mbchars(prtype, mbminmaxlen,
122
len = dtype_get_at_most_n_mbchars(prtype, mbminlen, mbmaxlen,
133
123
sec_len, len, (const char*) buf);
135
125
return(!cmp_data_data(mtype, prtype, buf, len, sec_field, sec_len));
214
204
len = dtype_get_at_most_n_mbchars(
215
col->prtype, col->mbminmaxlen,
205
col->prtype, col->mbminlen, col->mbmaxlen,
216
206
ifield->prefix_len, len, (char*) clust_field);
218
208
if (rec_offs_nth_extern(clust_offs, clust_pos)
219
209
&& len < sec_len) {
220
210
if (!row_sel_sec_rec_is_for_blob(
221
211
col->mtype, col->prtype,
212
col->mbminlen, col->mbmaxlen,
223
213
clust_field, clust_len,
224
214
sec_field, sec_len,
225
215
dict_table_zip_size(
356
346
ut_ad(node->is_aggregate);
358
func_node = static_cast<func_node_t *>(node->select_list);
348
func_node = node->select_list;
360
350
while (func_node) {
361
351
eval_node_set_int_val(func_node, 0);
363
func_node = static_cast<func_node_t *>(que_node_get_next(func_node));
353
func_node = que_node_get_next(func_node);
366
356
node->aggregate_already_fetched = FALSE;
435
425
dict_table_zip_size(index->table),
436
426
field_no, &len, heap);
438
/* data == NULL means that the
439
externally stored field was not
440
written yet. This record
441
should only be seen by
442
recv_recovery_rollback_active() or any
443
TRX_ISO_READ_UNCOMMITTED
444
transactions. The InnoDB SQL parser
445
(the sole caller of this function)
446
does not implement READ UNCOMMITTED,
447
and it is not involved during rollback. */
449
428
ut_a(len != UNIV_SQL_NULL);
451
430
needs_copy = TRUE;
487
466
ut_ad(que_node_get_type(column) == QUE_NODE_SYMBOL);
489
column->prefetch_buf = static_cast<sel_buf_t *>(mem_alloc(SEL_MAX_N_PREFETCH
490
* sizeof(sel_buf_t)));
468
column->prefetch_buf = mem_alloc(SEL_MAX_N_PREFETCH
469
* sizeof(sel_buf_t));
491
470
for (i = 0; i < SEL_MAX_N_PREFETCH; i++) {
492
471
sel_buf = column->prefetch_buf + i;
566
545
column values to be able to free it later: therefore
567
546
we swap the values for sel_buf and val */
569
sel_buf->data = static_cast<byte *>(dfield_get_data(val));
548
sel_buf->data = dfield_get_data(val);
570
549
sel_buf->len = dfield_get_len(val);
571
550
sel_buf->val_buf_size = que_node_get_val_buf_size(column);
882
861
err = lock_clust_rec_read_check_and_lock(
883
862
0, btr_pcur_get_block(&plan->clust_pcur),
884
863
clust_rec, index, offsets,
885
static_cast<lock_mode>(node->row_lock_mode), lock_type, thr);
889
case DB_SUCCESS_LOCKED_REC:
890
/* Declare the variable uninitialized in Valgrind.
891
It should be set to DB_SUCCESS at func_exit. */
892
UNIV_MEM_INVALID(&err, sizeof err);
864
node->row_lock_mode, lock_type, thr);
866
if (err != DB_SUCCESS) {
947
920
when plan->clust_pcur was positioned. The latch will not be
948
921
released until mtr_commit(mtr). */
950
ut_ad(!rec_get_deleted_flag(clust_rec, rec_offs_comp(offsets)));
951
923
row_sel_fetch_columns(index, clust_rec, offsets,
952
924
UT_LIST_GET_FIRST(plan->columns));
953
925
*out_rec = clust_rec;
963
935
/*********************************************************************//**
964
936
Sets a lock on a record.
965
@return DB_SUCCESS, DB_SUCCESS_LOCKED_REC, or error code */
937
@return DB_SUCCESS or error code */
968
940
sel_set_rec_lock(
969
941
/*=============*/
970
942
const buf_block_t* block, /*!< in: buffer block of rec */
991
963
if (dict_index_is_clust(index)) {
992
err = lock_clust_rec_read_check_and_lock(0, block, rec, index,
993
offsets, static_cast<lock_mode>(mode), type, thr);
964
err = lock_clust_rec_read_check_and_lock(
965
0, block, rec, index, offsets, mode, type, thr);
995
err = lock_sec_rec_read_check_and_lock(0, block, rec, index,
996
offsets, static_cast<lock_mode>(mode), type, thr);
967
err = lock_sec_rec_read_check_and_lock(
968
0, block, rec, index, offsets, mode, type, thr);
1652
1616
if (old_vers == NULL) {
1653
/* The record does not exist
1654
in our read view. Skip it, but
1655
first attempt to determine
1656
whether the index segment we
1657
are searching through has been
1660
1617
offsets = rec_get_offsets(
1661
1618
rec, index, offsets,
1662
1619
ULINT_UNDEFINED, &heap);
2061
2013
while (table_node) {
2062
2014
err = lock_table(0, table_node->table,
2063
static_cast<lock_mode>(i_lock_mode), thr);
2064
2016
if (err != DB_SUCCESS) {
2065
2017
thr_get_trx(thr)->error_state = err;
2070
table_node = static_cast<sym_node_t *>(que_node_get_next(table_node));
2022
table_node = que_node_get_next(table_node);
2544
2494
ulint len) /*!< in: length of the data */
2548
2500
ut_ad(len != UNIV_SQL_NULL);
2549
UNIV_MEM_ASSERT_RW(data, len);
2551
2502
switch (templ->type) {
2552
const byte* field_end;
2555
2504
/* Convert integer data from Innobase to a little-endian
2556
2505
format, sign bit restored to normal */
2594
2543
unused end of a >= 5.0.3 true VARCHAR column, just in case
2595
2544
MySQL expects its contents to be deterministic. */
2546
pad_ptr = dest + len;
2599
2548
ut_ad(templ->mbminlen <= templ->mbmaxlen);
2601
/* We treat some Unicode charset strings specially. */
2602
switch (templ->mbminlen) {
2604
/* InnoDB should never have stripped partial
2605
UTF-32 characters. */
2609
/* A space char is two bytes,
2610
0x0020 in UCS2 and UTF-16 */
2550
/* We handle UCS2 charset strings differently. */
2551
if (templ->mbminlen == 2) {
2552
/* A space char is two bytes, 0x0020 in UCS2 */
2612
if (UNIV_UNLIKELY(len & 1)) {
2613
2555
/* A 0x20 has been stripped from the column.
2614
2556
Pad it back. */
2616
if (pad < field_end) {
2558
if (pad_ptr < field_end) {
2564
/* Pad the rest of the string with 0x0020 */
2566
while (pad_ptr < field_end) {
2573
ut_ad(templ->mbminlen == 1);
2576
memset(pad_ptr, 0x20, field_end - pad_ptr);
2622
row_mysql_pad_col(templ->mbminlen, pad, field_end - pad);
2625
2580
case DATA_BLOB:
2644
2599
|| !(templ->mysql_col_len % templ->mbmaxlen));
2645
2600
ut_ad(len * templ->mbmaxlen >= templ->mysql_col_len);
2647
if (templ->mbminlen == 1 && templ->mbmaxlen != 1) {
2602
if (templ->mbminlen != templ->mbmaxlen) {
2648
2603
/* Pad with spaces. This undoes the stripping
2649
done in row0mysql.c, function
2604
done in row0mysql.ic, function
2650
2605
row_mysql_store_col_in_innobase_format(). */
2652
2607
memset(dest + len, 0x20, templ->mysql_col_len - len);
2677
2632
Note that the template in prebuilt may advise us to copy only a few
2678
2633
columns to mysql_rec, other columns are left blank. All columns may not
2679
2634
be needed in the query.
2680
@return TRUE on success, FALSE if not all columns could be retrieved */
2635
@return TRUE if success, FALSE if could not allocate memory for a BLOB
2636
(though we may also assert in that case) */
2683
__attribute__((warn_unused_result))
2686
2639
row_sel_store_mysql_rec(
2687
2640
/*====================*/
2689
2642
row_prebuilt_t* prebuilt, /*!< in: prebuilt struct */
2690
2643
const rec_t* rec, /*!< in: Innobase record in the index
2691
2644
which was described in prebuilt's
2692
template, or in the clustered index;
2693
must be protected by a page latch */
2694
ibool rec_clust, /*!< in: TRUE if rec is in the
2695
clustered index instead of
2645
template; must be protected by
2697
2647
const ulint* offsets) /*!< in: array returned by
2698
rec_get_offsets(rec) */
2648
rec_get_offsets() */
2700
mem_heap_t* extern_field_heap = NULL;
2650
mysql_row_templ_t* templ;
2651
mem_heap_t* extern_field_heap = NULL;
2704
2657
ut_ad(prebuilt->mysql_template);
2705
2658
ut_ad(prebuilt->default_rec);
2706
2659
ut_ad(rec_offs_validate(rec, NULL, offsets));
2707
ut_ad(!rec_get_deleted_flag(rec, rec_offs_comp(offsets)));
2709
2661
if (UNIV_LIKELY_NULL(prebuilt->blob_heap)) {
2710
2662
mem_heap_free(prebuilt->blob_heap);
2714
2666
for (i = 0; i < prebuilt->n_template ; i++) {
2716
const mysql_row_templ_t*templ = prebuilt->mysql_template + i;
2721
field_no = rec_clust
2722
? templ->clust_rec_field_no : templ->rec_field_no;
2724
if (UNIV_UNLIKELY(rec_offs_nth_extern(offsets, field_no))) {
2668
templ = prebuilt->mysql_template + i;
2670
if (UNIV_UNLIKELY(rec_offs_nth_extern(offsets,
2671
templ->rec_field_no))) {
2726
2673
/* Copy an externally stored field to the temporary
2749
2696
data = btr_rec_copy_externally_stored_field(
2751
2698
dict_table_zip_size(prebuilt->table),
2752
field_no, &len, heap);
2754
if (UNIV_UNLIKELY(!data)) {
2755
/* The externally stored field
2756
was not written yet. This
2757
record should only be seen by
2758
recv_recovery_rollback_active()
2759
or any TRX_ISO_READ_UNCOMMITTED
2762
if (extern_field_heap) {
2763
mem_heap_free(extern_field_heap);
2769
if (UNIV_UNLIKELY(!data)) {
2770
/* The externally stored field
2771
was not written yet. This
2772
record should only be seen by
2773
recv_recovery_rollback_active()
2774
or any TRX_ISO_READ_UNCOMMITTED
2777
if (extern_field_heap) {
2778
mem_heap_free(extern_field_heap);
2699
templ->rec_field_no, &len, heap);
2784
2701
ut_a(len != UNIV_SQL_NULL);
2786
2703
/* Field is stored in the row. */
2788
data = rec_get_nth_field(rec, offsets, field_no, &len);
2705
data = rec_get_nth_field(rec, offsets,
2706
templ->rec_field_no, &len);
2790
2708
if (UNIV_UNLIKELY(templ->type == DATA_BLOB)
2791
2709
&& len != UNIV_SQL_NULL) {
2828
2746
/* MySQL assumes that the field for an SQL
2829
2747
NULL value is set to the default value. */
2831
UNIV_MEM_ASSERT_RW(prebuilt->default_rec
2832
+ templ->mysql_col_offset,
2833
templ->mysql_col_len);
2834
2749
mysql_rec[templ->mysql_null_byte_offset]
2835
2750
|= (byte) templ->mysql_null_bit_mask;
2836
2751
memcpy(mysql_rec + templ->mysql_col_offset,
2882
2797
Retrieves the clustered index record corresponding to a record in a
2883
2798
non-clustered index. Does the necessary locking. Used in the MySQL
2885
@return DB_SUCCESS, DB_SUCCESS_LOCKED_REC, or error code */
2800
@return DB_SUCCESS or error code */
2888
2803
row_sel_get_clust_rec_for_mysql(
2889
2804
/*============================*/
2890
2805
row_prebuilt_t* prebuilt,/*!< in: prebuilt struct in the handle */
2985
2899
err = lock_clust_rec_read_check_and_lock(
2986
2900
0, btr_pcur_get_block(prebuilt->clust_pcur),
2987
2901
clust_rec, clust_index, *offsets,
2988
static_cast<lock_mode>(prebuilt->select_lock_type),
2989
LOCK_REC_NOT_GAP, thr);
2992
case DB_SUCCESS_LOCKED_REC:
2902
prebuilt->select_lock_type, LOCK_REC_NOT_GAP, thr);
2903
if (err != DB_SUCCESS) {
3011
2921
/* The following call returns 'offsets' associated with
3013
err = static_cast<db_err>(row_sel_build_prev_vers_for_mysql(
2923
err = row_sel_build_prev_vers_for_mysql(
3014
2924
trx->read_view, clust_index, prebuilt,
3015
2925
clust_rec, offsets, offset_heap, &old_vers,
3018
2928
if (err != DB_SUCCESS || old_vers == NULL) {
3162
3071
for (i = 0; i < prebuilt->n_template; i++) {
3163
3072
templ = prebuilt->mysql_template + i;
3164
#if 0 /* Some of the cached_rec may legitimately be uninitialized. */
3165
UNIV_MEM_ASSERT_RW(cached_rec
3166
+ templ->mysql_col_offset,
3167
templ->mysql_col_len);
3169
3073
ut_memcpy(buf + templ->mysql_col_offset,
3170
3074
cached_rec + templ->mysql_col_offset,
3171
3075
templ->mysql_col_len);
3183
#if 0 /* Some of the cached_rec may legitimately be uninitialized. */
3184
UNIV_MEM_ASSERT_RW(prebuilt->fetch_cache
3185
[prebuilt->fetch_cache_first],
3186
prebuilt->mysql_prefix_len);
3189
3088
prebuilt->fetch_cache[prebuilt->fetch_cache_first],
3190
3089
prebuilt->mysql_prefix_len);
3200
3099
/********************************************************************//**
3201
Pushes a row for MySQL to the fetch cache.
3202
@return TRUE on success, FALSE if the record contains incomplete BLOBs */
3100
Pushes a row for MySQL to the fetch cache. */
3205
__attribute__((warn_unused_result))
3208
3103
row_sel_push_cache_row_for_mysql(
3209
3104
/*=============================*/
3210
3105
row_prebuilt_t* prebuilt, /*!< in: prebuilt struct */
3211
const rec_t* rec, /*!< in: record to push, in the index
3212
which was described in prebuilt's
3213
template, or in the clustered index;
3214
must be protected by a page latch */
3215
ibool rec_clust, /*!< in: TRUE if rec is in the
3216
clustered index instead of
3218
const ulint* offsets) /*!< in: rec_get_offsets(rec) */
3106
const rec_t* rec, /*!< in: record to push; must
3107
be protected by a page latch */
3108
const ulint* offsets) /*!<in: rec_get_offsets() */
3223
3113
ut_ad(prebuilt->n_fetch_cached < MYSQL_FETCH_CACHE_SIZE);
3224
3114
ut_ad(rec_offs_validate(rec, NULL, offsets));
3225
ut_ad(!rec_get_deleted_flag(rec, rec_offs_comp(offsets)));
3226
3115
ut_a(!prebuilt->templ_contains_blob);
3228
3117
if (prebuilt->fetch_cache[0] == NULL) {
3247
3136
ut_ad(prebuilt->fetch_cache_first == 0);
3248
UNIV_MEM_INVALID(prebuilt->fetch_cache[prebuilt->n_fetch_cached],
3249
prebuilt->mysql_row_len);
3251
3138
if (UNIV_UNLIKELY(!row_sel_store_mysql_rec(
3252
3139
prebuilt->fetch_cache[
3253
3140
prebuilt->n_fetch_cached],
3254
prebuilt, rec, rec_clust, offsets))) {
3141
prebuilt, rec, offsets))) {
3258
3145
prebuilt->n_fetch_cached++;
3262
3148
/*********************************************************************//**
3625
3510
row_sel_try_search_shortcut_for_mysql().
3626
3511
The latch will not be released until
3627
3512
mtr_commit(&mtr). */
3628
ut_ad(!rec_get_deleted_flag(rec, comp));
3630
3514
if (!row_sel_store_mysql_rec(buf, prebuilt,
3633
/* Only fresh inserts may contain
3634
incomplete externally stored
3635
columns. Pretend that such
3636
records do not exist. Such
3637
records may only be accessed
3638
at the READ UNCOMMITTED
3639
isolation level or when
3640
rolling back a recovered
3641
transaction. Rollback happens
3642
at a lower level, not here. */
3643
ut_a(trx->isolation_level
3644
== TRX_ISO_READ_UNCOMMITTED);
3516
err = DB_TOO_BIG_RECORD;
3646
/* Proceed as in case SEL_RETRY. */
3518
/* We let the main loop to do the
3520
goto shortcut_fails_too_big_rec;
3650
3523
mtr_commit(&mtr);
3698
3571
trx->has_search_latch = FALSE;
3701
ut_ad(prebuilt->sql_stat_start || trx->conc_state == TRX_ACTIVE);
3702
ut_ad(trx->conc_state == TRX_NOT_STARTED
3703
|| trx->conc_state == TRX_ACTIVE);
3704
ut_ad(prebuilt->sql_stat_start
3705
|| prebuilt->select_lock_type != LOCK_NONE
3708
ut_ad(prebuilt->sql_stat_start || trx->conc_state == TRX_ACTIVE);
3709
ut_ad(trx->conc_state == TRX_NOT_STARTED
3710
|| trx->conc_state == TRX_ACTIVE);
3711
ut_ad(prebuilt->sql_stat_start
3712
|| prebuilt->select_lock_type != LOCK_NONE
3715
3574
trx_start_if_not_started(trx);
3717
3576
if (trx->isolation_level <= TRX_ISO_READ_COMMITTED
3743
3602
clust_index = dict_table_get_first_index(index->table);
3745
/* Do some start-of-statement preparations */
3747
if (!prebuilt->sql_stat_start) {
3748
/* No need to set an intention lock or assign a read view */
3750
if (trx->read_view == NULL
3751
&& prebuilt->select_lock_type == LOCK_NONE) {
3753
fputs("InnoDB: Error: MySQL is trying to"
3754
" perform a consistent read\n"
3755
"InnoDB: but the read view is not assigned!\n",
3757
trx_print(stderr, trx, 600);
3758
fputc('\n', stderr);
3761
} else if (prebuilt->select_lock_type == LOCK_NONE) {
3762
/* This is a consistent read */
3763
/* Assign a read view for the query */
3765
trx_assign_read_view(trx);
3766
prebuilt->sql_stat_start = FALSE;
3769
err = lock_table(0, index->table,
3770
prebuilt->select_lock_type == LOCK_S
3771
? LOCK_IS : LOCK_IX, thr);
3773
if (err != DB_SUCCESS) {
3775
table_lock_waited = TRUE;
3776
goto lock_table_wait;
3778
prebuilt->sql_stat_start = FALSE;
3781
/* Open or restore index cursor position */
3783
3604
if (UNIV_LIKELY(direction != 0)) {
3784
3605
ibool need_to_process = sel_restore_position_for_mysql(
3785
3606
&same_user_rec, BTR_SEARCH_LEAF,
3675
if (!prebuilt->sql_stat_start) {
3676
/* No need to set an intention lock or assign a read view */
3678
if (trx->read_view == NULL
3679
&& prebuilt->select_lock_type == LOCK_NONE) {
3681
fputs("InnoDB: Error: MySQL is trying to"
3682
" perform a consistent read\n"
3683
"InnoDB: but the read view is not assigned!\n",
3685
trx_print(stderr, trx, 600);
3686
fputc('\n', stderr);
3689
} else if (prebuilt->select_lock_type == LOCK_NONE) {
3690
/* This is a consistent read */
3691
/* Assign a read view for the query */
3693
trx_assign_read_view(trx);
3694
prebuilt->sql_stat_start = FALSE;
3697
if (prebuilt->select_lock_type == LOCK_S) {
3698
lock_mode = LOCK_IS;
3700
lock_mode = LOCK_IX;
3702
err = lock_table(0, index->table, lock_mode, thr);
3704
if (err != DB_SUCCESS) {
3706
goto lock_wait_or_error;
3708
prebuilt->sql_stat_start = FALSE;
3859
3712
/*-------------------------------------------------------------*/
3860
3713
/* PHASE 4: Look for matching records in a loop */
4151
3994
const rec_t* old_vers;
4152
case DB_SUCCESS_LOCKED_REC:
4153
3996
if (srv_locks_unsafe_for_binlog
4154
|| trx->isolation_level
4155
<= TRX_ISO_READ_COMMITTED) {
3997
|| trx->isolation_level <= TRX_ISO_READ_COMMITTED) {
4156
3998
/* Note that a record of
4157
3999
prebuilt->index was locked. */
4158
4000
prebuilt->new_rec_locks = 1;
4163
4003
case DB_LOCK_WAIT:
4164
/* Never unlock rows that were part of a conflict. */
4165
prebuilt->new_rec_locks = 0;
4167
4004
if (UNIV_LIKELY(prebuilt->row_read_type
4168
4005
!= ROW_READ_TRY_SEMI_CONSISTENT)
4169
4006
|| unique_search
4178
4015
clust_index, prebuilt, rec,
4179
4016
&offsets, &heap, &old_vers, &mtr);
4182
case DB_SUCCESS_LOCKED_REC:
4018
if (err != DB_SUCCESS) {
4187
4020
goto lock_wait_or_error;
4271
4105
rec = old_vers;
4107
} else if (!lock_sec_rec_cons_read_sees(rec, trx->read_view)) {
4274
4108
/* We are looking into a non-clustered index,
4275
4109
and to get the right version of the record we
4276
4110
have to look also into the clustered index: this
4277
4111
is necessary, because we can only get the undo
4278
4112
information via the clustered index record. */
4280
ut_ad(!dict_index_is_clust(index));
4281
if (!lock_sec_rec_cons_read_sees(
4282
rec, trx->read_view)) {
4283
goto requires_clust_rec;
4114
ut_ad(index != clust_index);
4115
goto requires_clust_rec;
4349
4180
err = row_sel_get_clust_rec_for_mysql(prebuilt, index, rec,
4350
4181
thr, &clust_rec,
4351
4182
&offsets, &heap, &mtr);
4354
if (clust_rec == NULL) {
4355
/* The record did not exist in the read view */
4356
ut_ad(prebuilt->select_lock_type == LOCK_NONE);
4183
if (err != DB_SUCCESS) {
4361
case DB_SUCCESS_LOCKED_REC:
4362
ut_a(clust_rec != NULL);
4363
if (srv_locks_unsafe_for_binlog
4364
|| trx->isolation_level
4365
<= TRX_ISO_READ_COMMITTED) {
4366
/* Note that the clustered index record
4368
prebuilt->new_rec_locks = 2;
4373
4185
goto lock_wait_or_error;
4188
if (clust_rec == NULL) {
4189
/* The record did not exist in the read view */
4190
ut_ad(prebuilt->select_lock_type == LOCK_NONE);
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;
4376
4204
if (UNIV_UNLIKELY(rec_get_deleted_flag(clust_rec, comp))) {
4378
4206
/* The record is delete marked: we can skip it */
4394
result_rec = clust_rec;
4395
ut_ad(rec_offs_validate(result_rec, clust_index, offsets));
4222
if (prebuilt->need_to_access_clustered) {
4224
result_rec = clust_rec;
4226
ut_ad(rec_offs_validate(result_rec, clust_index,
4229
/* We used 'offsets' for the clust rec, recalculate
4231
offsets = rec_get_offsets(rec, index, offsets,
4232
ULINT_UNDEFINED, &heap);
4397
4236
result_rec = rec;
4403
4242
ut_ad(rec_offs_validate(result_rec,
4404
4243
result_rec != rec ? clust_index : index,
4406
ut_ad(!rec_get_deleted_flag(result_rec, comp));
4408
4246
/* At this point, the clustered index record is protected
4409
4247
by a page latch that was acquired when pcur was positioned.
4426
4264
not cache rows because there the cursor is a scrollable
4429
if (!row_sel_push_cache_row_for_mysql(prebuilt, result_rec,
4432
/* Only fresh inserts may contain incomplete
4433
externally stored columns. Pretend that such
4434
records do not exist. Such records may only be
4435
accessed at the READ UNCOMMITTED isolation
4436
level or when rolling back a recovered
4437
transaction. Rollback happens at a lower
4439
ut_a(trx->isolation_level == TRX_ISO_READ_UNCOMMITTED);
4440
} else if (prebuilt->n_fetch_cached
4441
== MYSQL_FETCH_CACHE_SIZE) {
4267
row_sel_push_cache_row_for_mysql(prebuilt, result_rec,
4269
if (prebuilt->n_fetch_cached == MYSQL_FETCH_CACHE_SIZE) {
4449
(prebuilt->template_type == ROW_MYSQL_DUMMY_TEMPLATE)) {
4450
/* CHECK TABLE: fetch the row */
4452
if (result_rec != rec
4453
&& !prebuilt->need_to_access_clustered) {
4454
/* We used 'offsets' for the clust
4455
rec, recalculate them for 'rec' */
4456
offsets = rec_get_offsets(rec, index, offsets,
4276
if (prebuilt->template_type == ROW_MYSQL_DUMMY_TEMPLATE) {
4462
4277
memcpy(buf + 4, result_rec
4463
4278
- rec_offs_extra_size(offsets),
4464
4279
rec_offs_size(offsets));
4465
4280
mach_write_to_4(buf,
4466
4281
rec_offs_extra_size(offsets) + 4);
4468
/* Returning a row to MySQL */
4283
if (!row_sel_store_mysql_rec(buf, prebuilt,
4284
result_rec, offsets)) {
4285
err = DB_TOO_BIG_RECORD;
4470
if (!row_sel_store_mysql_rec(buf, prebuilt, result_rec,
4473
/* Only fresh inserts may contain
4474
incomplete externally stored
4475
columns. Pretend that such records do
4476
not exist. Such records may only be
4477
accessed at the READ UNCOMMITTED
4478
isolation level or when rolling back a
4479
recovered transaction. Rollback
4480
happens at a lower level, not here. */
4481
ut_a(trx->isolation_level
4482
== TRX_ISO_READ_UNCOMMITTED);
4287
goto lock_wait_or_error;
4733
4528
IX type locks actually would require ret = FALSE. */
4735
4530
if (UT_LIST_GET_LEN(table->locks) == 0
4736
&& trx->id >= table->query_cache_inv_trx_id) {
4531
&& ut_dulint_cmp(trx->id,
4532
table->query_cache_inv_trx_id) >= 0) {