1
1
/*****************************************************************************
3
Copyright (C) 1997, 2010, Innobase Oy. All Rights Reserved.
4
Copyright (C) 2008, Google Inc.
3
Copyright (c) 1997, 2009, 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));
142
132
NOTE: the comparison is NOT done as a binary comparison, but character
143
133
fields are compared with collation!
144
134
@return TRUE if the secondary record is equal to the corresponding
145
fields in the clustered record, when compared with collation;
146
FALSE if not equal or if the clustered record has been marked for deletion */
135
fields in the clustered record, when compared with collation */
149
138
row_sel_sec_rec_is_for_clust_rec(
214
203
len = dtype_get_at_most_n_mbchars(
215
col->prtype, col->mbminmaxlen,
204
col->prtype, col->mbminlen, col->mbmaxlen,
216
205
ifield->prefix_len, len, (char*) clust_field);
218
207
if (rec_offs_nth_extern(clust_offs, clust_pos)
219
208
&& len < sec_len) {
220
209
if (!row_sel_sec_rec_is_for_blob(
221
210
col->mtype, col->prtype,
211
col->mbminlen, col->mbmaxlen,
223
212
clust_field, clust_len,
224
213
sec_field, sec_len,
225
214
dict_table_zip_size(
356
345
ut_ad(node->is_aggregate);
358
func_node = static_cast<func_node_t *>(node->select_list);
347
func_node = node->select_list;
360
349
while (func_node) {
361
350
eval_node_set_int_val(func_node, 0);
363
func_node = static_cast<func_node_t *>(que_node_get_next(func_node));
352
func_node = que_node_get_next(func_node);
366
355
node->aggregate_already_fetched = FALSE;
435
424
dict_table_zip_size(index->table),
436
425
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
427
ut_a(len != UNIV_SQL_NULL);
451
429
needs_copy = TRUE;
487
469
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)));
471
column->prefetch_buf = mem_alloc(SEL_MAX_N_PREFETCH
472
* sizeof(sel_buf_t));
491
473
for (i = 0; i < SEL_MAX_N_PREFETCH; i++) {
492
474
sel_buf = column->prefetch_buf + i;
566
548
column values to be able to free it later: therefore
567
549
we swap the values for sel_buf and val */
569
sel_buf->data = static_cast<byte *>(dfield_get_data(val));
551
sel_buf->data = dfield_get_data(val);
570
552
sel_buf->len = dfield_get_len(val);
571
553
sel_buf->val_buf_size = que_node_get_val_buf_size(column);
882
864
err = lock_clust_rec_read_check_and_lock(
883
865
0, btr_pcur_get_block(&plan->clust_pcur),
884
866
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);
867
node->row_lock_mode, lock_type, thr);
869
if (err != DB_SUCCESS) {
947
923
when plan->clust_pcur was positioned. The latch will not be
948
924
released until mtr_commit(mtr). */
950
ut_ad(!rec_get_deleted_flag(clust_rec, rec_offs_comp(offsets)));
951
926
row_sel_fetch_columns(index, clust_rec, offsets,
952
927
UT_LIST_GET_FIRST(plan->columns));
953
928
*out_rec = clust_rec;
963
938
/*********************************************************************//**
964
939
Sets a lock on a record.
965
@return DB_SUCCESS, DB_SUCCESS_LOCKED_REC, or error code */
940
@return DB_SUCCESS or error code */
968
943
sel_set_rec_lock(
969
944
/*=============*/
970
945
const buf_block_t* block, /*!< in: buffer block of rec */
991
966
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);
967
err = lock_clust_rec_read_check_and_lock(
968
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);
970
err = lock_sec_rec_read_check_and_lock(
971
0, block, rec, index, offsets, mode, type, thr);
1652
1619
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
1620
offsets = rec_get_offsets(
1661
1621
rec, index, offsets,
1662
1622
ULINT_UNDEFINED, &heap);
2061
2016
while (table_node) {
2062
2017
err = lock_table(0, table_node->table,
2063
static_cast<lock_mode>(i_lock_mode), thr);
2064
2019
if (err != DB_SUCCESS) {
2065
2020
thr_get_trx(thr)->error_state = err;
2070
table_node = static_cast<sym_node_t *>(que_node_get_next(table_node));
2025
table_node = que_node_get_next(table_node);
2217
2170
return((void*)42);
2173
/****************************************************************//**
2174
Callback function for fetch that stores an unsigned 4 byte integer to the
2175
location pointed. The column's type must be DATA_INT, DATA_UNSIGNED, length
2177
@return always returns NULL */
2180
row_fetch_store_uint4(
2181
/*==================*/
2182
void* row, /*!< in: sel_node_t* */
2183
void* user_arg) /*!< in: data pointer */
2185
sel_node_t* node = row;
2186
ib_uint32_t* val = user_arg;
2189
dfield_t* dfield = que_node_get_val(node->select_list);
2190
const dtype_t* type = dfield_get_type(dfield);
2191
ulint len = dfield_get_len(dfield);
2193
ut_a(dtype_get_mtype(type) == DATA_INT);
2194
ut_a(dtype_get_prtype(type) & DATA_UNSIGNED);
2197
tmp = mach_read_from_4(dfield_get_data(dfield));
2198
*val = (ib_uint32_t) tmp;
2220
2203
/***********************************************************//**
2221
2204
Prints a row in a select result.
2222
2205
@return query thread to run next or NULL */
2544
2527
ulint len) /*!< in: length of the data */
2548
2533
ut_ad(len != UNIV_SQL_NULL);
2549
UNIV_MEM_ASSERT_RW(data, len);
2551
2535
switch (templ->type) {
2552
const byte* field_end;
2555
2537
/* Convert integer data from Innobase to a little-endian
2556
2538
format, sign bit restored to normal */
2594
2576
unused end of a >= 5.0.3 true VARCHAR column, just in case
2595
2577
MySQL expects its contents to be deterministic. */
2579
pad_ptr = dest + len;
2599
2581
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 */
2583
/* We handle UCS2 charset strings differently. */
2584
if (templ->mbminlen == 2) {
2585
/* A space char is two bytes, 0x0020 in UCS2 */
2612
if (UNIV_UNLIKELY(len & 1)) {
2613
2588
/* A 0x20 has been stripped from the column.
2614
2589
Pad it back. */
2616
if (pad < field_end) {
2591
if (pad_ptr < field_end) {
2597
/* Pad the rest of the string with 0x0020 */
2599
while (pad_ptr < field_end) {
2606
ut_ad(templ->mbminlen == 1);
2609
memset(pad_ptr, 0x20, field_end - pad_ptr);
2622
row_mysql_pad_col(templ->mbminlen, pad, field_end - pad);
2625
2613
case DATA_BLOB:
2644
2632
|| !(templ->mysql_col_len % templ->mbmaxlen));
2645
2633
ut_ad(len * templ->mbmaxlen >= templ->mysql_col_len);
2647
if (templ->mbminlen == 1 && templ->mbmaxlen != 1) {
2635
if (templ->mbminlen != templ->mbmaxlen) {
2648
2636
/* Pad with spaces. This undoes the stripping
2649
done in row0mysql.c, function
2637
done in row0mysql.ic, function
2650
2638
row_mysql_store_col_in_innobase_format(). */
2652
2640
memset(dest + len, 0x20, templ->mysql_col_len - len);
2677
2665
Note that the template in prebuilt may advise us to copy only a few
2678
2666
columns to mysql_rec, other columns are left blank. All columns may not
2679
2667
be needed in the query.
2680
@return TRUE on success, FALSE if not all columns could be retrieved */
2668
@return TRUE if success, FALSE if could not allocate memory for a BLOB
2669
(though we may also assert in that case) */
2683
__attribute__((warn_unused_result))
2686
2672
row_sel_store_mysql_rec(
2687
2673
/*====================*/
2689
2675
row_prebuilt_t* prebuilt, /*!< in: prebuilt struct */
2690
2676
const rec_t* rec, /*!< in: Innobase record in the index
2691
2677
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
2678
template; must be protected by
2697
2680
const ulint* offsets) /*!< in: array returned by
2698
rec_get_offsets(rec) */
2681
rec_get_offsets() */
2700
mem_heap_t* extern_field_heap = NULL;
2683
mysql_row_templ_t* templ;
2684
mem_heap_t* extern_field_heap = NULL;
2704
2690
ut_ad(prebuilt->mysql_template);
2705
2691
ut_ad(prebuilt->default_rec);
2706
2692
ut_ad(rec_offs_validate(rec, NULL, offsets));
2707
ut_ad(!rec_get_deleted_flag(rec, rec_offs_comp(offsets)));
2709
2694
if (UNIV_LIKELY_NULL(prebuilt->blob_heap)) {
2710
2695
mem_heap_free(prebuilt->blob_heap);
2714
2699
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))) {
2701
templ = prebuilt->mysql_template + i;
2703
if (UNIV_UNLIKELY(rec_offs_nth_extern(offsets,
2704
templ->rec_field_no))) {
2726
2706
/* Copy an externally stored field to the temporary
2749
2729
data = btr_rec_copy_externally_stored_field(
2751
2731
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);
2732
templ->rec_field_no, &len, heap);
2784
2734
ut_a(len != UNIV_SQL_NULL);
2786
2736
/* Field is stored in the row. */
2788
data = rec_get_nth_field(rec, offsets, field_no, &len);
2738
data = rec_get_nth_field(rec, offsets,
2739
templ->rec_field_no, &len);
2790
2741
if (UNIV_UNLIKELY(templ->type == DATA_BLOB)
2791
2742
&& len != UNIV_SQL_NULL) {
2828
2779
/* MySQL assumes that the field for an SQL
2829
2780
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
2782
mysql_rec[templ->mysql_null_byte_offset]
2835
2783
|= (byte) templ->mysql_null_bit_mask;
2836
2784
memcpy(mysql_rec + templ->mysql_col_offset,
2882
2830
Retrieves the clustered index record corresponding to a record in a
2883
2831
non-clustered index. Does the necessary locking. Used in the MySQL
2885
@return DB_SUCCESS, DB_SUCCESS_LOCKED_REC, or error code */
2833
@return DB_SUCCESS or error code */
2888
2836
row_sel_get_clust_rec_for_mysql(
2889
2837
/*============================*/
2890
2838
row_prebuilt_t* prebuilt,/*!< in: prebuilt struct in the handle */
2985
2932
err = lock_clust_rec_read_check_and_lock(
2986
2933
0, btr_pcur_get_block(prebuilt->clust_pcur),
2987
2934
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:
2935
prebuilt->select_lock_type, LOCK_REC_NOT_GAP, thr);
2936
if (err != DB_SUCCESS) {
3011
2954
/* The following call returns 'offsets' associated with
3013
err = static_cast<db_err>(row_sel_build_prev_vers_for_mysql(
2956
err = row_sel_build_prev_vers_for_mysql(
3014
2957
trx->read_view, clust_index, prebuilt,
3015
2958
clust_rec, offsets, offset_heap, &old_vers,
3018
2961
if (err != DB_SUCCESS || old_vers == NULL) {
3162
3103
for (i = 0; i < prebuilt->n_template; i++) {
3163
3104
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
3105
ut_memcpy(buf + templ->mysql_col_offset,
3170
3106
cached_rec + templ->mysql_col_offset,
3171
3107
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
3120
prebuilt->fetch_cache[prebuilt->fetch_cache_first],
3190
3121
prebuilt->mysql_prefix_len);
3200
3131
/********************************************************************//**
3201
Pushes a row for MySQL to the fetch cache.
3202
@return TRUE on success, FALSE if the record contains incomplete BLOBs */
3132
Pushes a row for MySQL to the fetch cache. */
3205
__attribute__((warn_unused_result))
3208
3135
row_sel_push_cache_row_for_mysql(
3209
3136
/*=============================*/
3210
3137
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) */
3138
const rec_t* rec, /*!< in: record to push; must
3139
be protected by a page latch */
3140
const ulint* offsets) /*!<in: rec_get_offsets() */
3223
3145
ut_ad(prebuilt->n_fetch_cached < MYSQL_FETCH_CACHE_SIZE);
3224
3146
ut_ad(rec_offs_validate(rec, NULL, offsets));
3225
ut_ad(!rec_get_deleted_flag(rec, rec_offs_comp(offsets)));
3226
3147
ut_a(!prebuilt->templ_contains_blob);
3228
3149
if (prebuilt->fetch_cache[0] == NULL) {
3247
3168
ut_ad(prebuilt->fetch_cache_first == 0);
3248
UNIV_MEM_INVALID(prebuilt->fetch_cache[prebuilt->n_fetch_cached],
3249
prebuilt->mysql_row_len);
3251
3170
if (UNIV_UNLIKELY(!row_sel_store_mysql_rec(
3252
3171
prebuilt->fetch_cache[
3253
3172
prebuilt->n_fetch_cached],
3254
prebuilt, rec, rec_clust, offsets))) {
3173
prebuilt, rec, offsets))) {
3258
3177
prebuilt->n_fetch_cached++;
3262
3180
/*********************************************************************//**
3284
3202
ut_ad(dict_index_is_clust(index));
3285
3203
ut_ad(!prebuilt->templ_contains_blob);
3287
#ifndef UNIV_SEARCH_DEBUG
3288
3205
btr_pcur_open_with_no_init(index, search_tuple, PAGE_CUR_GE,
3289
3206
BTR_SEARCH_LEAF, pcur,
3207
#ifndef UNIV_SEARCH_DEBUG
3292
#else /* UNIV_SEARCH_DEBUG */
3293
btr_pcur_open_with_no_init(index, search_tuple, PAGE_CUR_GE,
3294
BTR_SEARCH_LEAF, pcur,
3297
#endif /* UNIV_SEARCH_DEBUG */
3298
3213
rec = btr_pcur_get_rec(pcur);
3300
3215
if (!page_rec_is_user_rec(rec)) {
3625
3539
row_sel_try_search_shortcut_for_mysql().
3626
3540
The latch will not be released until
3627
3541
mtr_commit(&mtr). */
3628
ut_ad(!rec_get_deleted_flag(rec, comp));
3630
3543
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);
3545
err = DB_TOO_BIG_RECORD;
3646
/* Proceed as in case SEL_RETRY. */
3547
/* We let the main loop to do the
3549
goto shortcut_fails_too_big_rec;
3650
3552
mtr_commit(&mtr);
3698
3600
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
3603
trx_start_if_not_started(trx);
3717
3605
if (trx->isolation_level <= TRX_ISO_READ_COMMITTED
3743
3631
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
3633
if (UNIV_LIKELY(direction != 0)) {
3784
3634
ibool need_to_process = sel_restore_position_for_mysql(
3785
3635
&same_user_rec, BTR_SEARCH_LEAF,
3820
3670
&& !page_rec_is_supremum(rec)
3821
3671
&& set_also_gap_locks
3822
3672
&& !(srv_locks_unsafe_for_binlog
3823
|| trx->isolation_level <= TRX_ISO_READ_COMMITTED)
3673
|| trx->isolation_level == TRX_ISO_READ_COMMITTED)
3824
3674
&& prebuilt->select_lock_type != LOCK_NONE) {
3826
3676
/* Try to place a gap lock on the next index record
3704
if (!prebuilt->sql_stat_start) {
3705
/* No need to set an intention lock or assign a read view */
3707
if (trx->read_view == NULL
3708
&& prebuilt->select_lock_type == LOCK_NONE) {
3710
fputs("InnoDB: Error: MySQL is trying to"
3711
" perform a consistent read\n"
3712
"InnoDB: but the read view is not assigned!\n",
3714
trx_print(stderr, trx, 600);
3715
fputc('\n', stderr);
3718
} else if (prebuilt->select_lock_type == LOCK_NONE) {
3719
/* This is a consistent read */
3720
/* Assign a read view for the query */
3722
trx_assign_read_view(trx);
3723
prebuilt->sql_stat_start = FALSE;
3726
if (prebuilt->select_lock_type == LOCK_S) {
3727
lock_mode = LOCK_IS;
3729
lock_mode = LOCK_IX;
3731
err = lock_table(0, index->table, lock_mode, thr);
3733
if (err != DB_SUCCESS) {
3735
goto lock_wait_or_error;
3737
prebuilt->sql_stat_start = FALSE;
3859
3741
/*-------------------------------------------------------------*/
3860
3742
/* PHASE 4: Look for matching records in a loop */
4151
4023
const rec_t* old_vers;
4152
case DB_SUCCESS_LOCKED_REC:
4153
4025
if (srv_locks_unsafe_for_binlog
4154
|| trx->isolation_level
4155
<= TRX_ISO_READ_COMMITTED) {
4026
|| trx->isolation_level == TRX_ISO_READ_COMMITTED) {
4156
4027
/* Note that a record of
4157
4028
prebuilt->index was locked. */
4158
4029
prebuilt->new_rec_locks = 1;
4163
4032
case DB_LOCK_WAIT:
4164
/* Never unlock rows that were part of a conflict. */
4165
prebuilt->new_rec_locks = 0;
4167
4033
if (UNIV_LIKELY(prebuilt->row_read_type
4168
4034
!= ROW_READ_TRY_SEMI_CONSISTENT)
4170
4035
|| index != clust_index) {
4172
4037
goto lock_wait_or_error;
4178
4043
clust_index, prebuilt, rec,
4179
4044
&offsets, &heap, &old_vers, &mtr);
4182
case DB_SUCCESS_LOCKED_REC:
4046
if (err != DB_SUCCESS) {
4187
4048
goto lock_wait_or_error;
4271
4133
rec = old_vers;
4135
} else if (!lock_sec_rec_cons_read_sees(rec, trx->read_view)) {
4274
4136
/* We are looking into a non-clustered index,
4275
4137
and to get the right version of the record we
4276
4138
have to look also into the clustered index: this
4277
4139
is necessary, because we can only get the undo
4278
4140
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;
4142
ut_ad(index != clust_index);
4143
goto requires_clust_rec;
4295
4154
/* The record is delete-marked: we can skip it */
4297
4156
if ((srv_locks_unsafe_for_binlog
4298
|| trx->isolation_level <= TRX_ISO_READ_COMMITTED)
4157
|| trx->isolation_level == TRX_ISO_READ_COMMITTED)
4299
4158
&& prebuilt->select_lock_type != LOCK_NONE
4300
4159
&& !did_semi_consistent_read) {
4349
4208
err = row_sel_get_clust_rec_for_mysql(prebuilt, index, rec,
4350
4209
thr, &clust_rec,
4351
4210
&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);
4211
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
4213
goto lock_wait_or_error;
4216
if (clust_rec == NULL) {
4217
/* The record did not exist in the read view */
4218
ut_ad(prebuilt->select_lock_type == LOCK_NONE);
4223
if ((srv_locks_unsafe_for_binlog
4224
|| trx->isolation_level == TRX_ISO_READ_COMMITTED)
4225
&& prebuilt->select_lock_type != LOCK_NONE) {
4226
/* Note that both the secondary index record
4227
and the clustered index record were locked. */
4228
ut_ad(prebuilt->new_rec_locks == 1);
4229
prebuilt->new_rec_locks = 2;
4376
4232
if (UNIV_UNLIKELY(rec_get_deleted_flag(clust_rec, comp))) {
4378
4234
/* The record is delete marked: we can skip it */
4380
4236
if ((srv_locks_unsafe_for_binlog
4381
|| trx->isolation_level <= TRX_ISO_READ_COMMITTED)
4237
|| trx->isolation_level == TRX_ISO_READ_COMMITTED)
4382
4238
&& prebuilt->select_lock_type != LOCK_NONE) {
4384
4240
/* No need to keep a lock on a delete-marked
4394
result_rec = clust_rec;
4395
ut_ad(rec_offs_validate(result_rec, clust_index, offsets));
4250
if (prebuilt->need_to_access_clustered) {
4252
result_rec = clust_rec;
4254
ut_ad(rec_offs_validate(result_rec, clust_index,
4257
/* We used 'offsets' for the clust rec, recalculate
4259
offsets = rec_get_offsets(rec, index, offsets,
4260
ULINT_UNDEFINED, &heap);
4397
4264
result_rec = rec;
4403
4270
ut_ad(rec_offs_validate(result_rec,
4404
4271
result_rec != rec ? clust_index : index,
4406
ut_ad(!rec_get_deleted_flag(result_rec, comp));
4408
4274
/* At this point, the clustered index record is protected
4409
4275
by a page latch that was acquired when pcur was positioned.
4426
4292
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) {
4295
row_sel_push_cache_row_for_mysql(prebuilt, result_rec,
4297
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,
4304
if (prebuilt->template_type == ROW_MYSQL_DUMMY_TEMPLATE) {
4462
4305
memcpy(buf + 4, result_rec
4463
4306
- rec_offs_extra_size(offsets),
4464
4307
rec_offs_size(offsets));
4465
4308
mach_write_to_4(buf,
4466
4309
rec_offs_extra_size(offsets) + 4);
4468
/* Returning a row to MySQL */
4311
if (!row_sel_store_mysql_rec(buf, prebuilt,
4312
result_rec, offsets)) {
4313
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);
4315
goto lock_wait_or_error;
4607
4438
thr->lock_state = QUE_THR_LOCK_NOLOCK;
4608
4439
mtr_start(&mtr);
4610
/* Table lock waited, go try to obtain table lock
4612
if (table_lock_waited) {
4613
table_lock_waited = FALSE;
4615
goto wait_table_again;
4618
4441
sel_restore_position_for_mysql(&same_user_rec,
4619
4442
BTR_SEARCH_LEAF, pcur,
4620
4443
moves_up, &mtr);
4622
4445
if ((srv_locks_unsafe_for_binlog
4623
|| trx->isolation_level <= TRX_ISO_READ_COMMITTED)
4446
|| trx->isolation_level == TRX_ISO_READ_COMMITTED)
4624
4447
&& !same_user_rec) {
4626
4449
/* Since we were not able to restore the cursor
4733
4556
IX type locks actually would require ret = FALSE. */
4735
4558
if (UT_LIST_GET_LEN(table->locks) == 0
4736
&& trx->id >= table->query_cache_inv_trx_id) {
4559
&& ut_dulint_cmp(trx->id,
4560
table->query_cache_inv_trx_id) >= 0) {
4765
4589
dict_index_t* index, /*!< in: index to read from */
4766
4590
const rec_t* rec, /*!< in: current rec */
4767
4591
ulint col_no, /*!< in: column number */
4768
ulint mtype, /*!< in: column main type */
4769
4592
ibool unsigned_type) /*!< in: signed or unsigned flag */
4782
4605
data = rec_get_nth_field(rec, offsets, col_no, &len);
4784
4607
ut_a(len != UNIV_SQL_NULL);
4788
ut_a(len <= sizeof value);
4789
value = mach_read_int_type(data, len, unsigned_type);
4793
ut_a(len == sizeof(float));
4794
value = (ib_uint64_t) mach_float_read(data);
4798
ut_a(len == sizeof(double));
4799
value = (ib_uint64_t) mach_double_read(data);
4608
ut_a(len <= sizeof value);
4610
/* we assume AUTOINC value cannot be negative */
4611
value = mach_read_int_type(data, len, unsigned_type);
4806
4613
if (UNIV_LIKELY_NULL(heap)) {
4807
4614
mem_heap_free(heap);
4887
4694
dfield->col->prtype & DATA_UNSIGNED);
4889
4696
*value = row_search_autoinc_read_column(
4891
dfield->col->mtype, unsigned_type);
4697
index, rec, i, unsigned_type);