1
/*****************************************************************************
3
Copyright (C) 1997, 2010, Innobase Oy. All Rights Reserved.
4
Copyright (C) 2008, Google Inc.
6
Portions of this file contain modifications contributed and copyrighted by
7
Google, Inc. Those modifications are gratefully acknowledged and are described
8
briefly in the InnoDB documentation. The contributions by Google are
9
incorporated with their permission, and subject to the conditions contained in
10
the file COPYING.Google.
12
This program is free software; you can redistribute it and/or modify it under
13
the terms of the GNU General Public License as published by the Free Software
14
Foundation; version 2 of the License.
16
This program is distributed in the hope that it will be useful, but WITHOUT
17
ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
18
FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.
20
You should have received a copy of the GNU General Public License along with
21
this program; if not, write to the Free Software Foundation, Inc., 51 Franklin
22
St, Fifth Floor, Boston, MA 02110-1301 USA
24
*****************************************************************************/
26
/***************************************************//**
1
/*******************************************************
30
6
Created 12/19/1997 Heikki Tuuri
31
7
*******************************************************/
75
51
#define SEL_EXHAUSTED 1
76
52
#define SEL_RETRY 2
78
/********************************************************************//**
54
/************************************************************************
79
55
Returns TRUE if the user-defined column in a secondary index record
80
56
is alphabetically the same as the corresponding BLOB column in the clustered
82
58
NOTE: the comparison is NOT done as a binary comparison, but character
83
fields are compared with collation!
84
@return TRUE if the columns are equal */
59
fields are compared with collation! */
87
62
row_sel_sec_rec_is_for_blob(
88
63
/*========================*/
89
ulint mtype, /*!< in: main type */
90
ulint prtype, /*!< in: precise type */
91
ulint mbminmaxlen, /*!< in: minimum and maximum length of
92
a multi-byte character */
93
const byte* clust_field, /*!< in: the locally stored part of
64
/* out: TRUE if the columns
66
ulint mtype, /* in: main type */
67
ulint prtype, /* in: precise type */
68
ulint mbminlen, /* in: minimum length of a
69
multi-byte character */
70
ulint mbmaxlen, /* in: maximum length of a
71
multi-byte character */
72
const byte* clust_field, /* in: the locally stored part of
94
73
the clustered index column, including
95
74
the BLOB pointer; the clustered
96
75
index record must be covered by
97
76
a lock or a page latch to protect it
98
77
against deletion (rollback or purge) */
99
ulint clust_len, /*!< in: length of clust_field */
100
const byte* sec_field, /*!< in: column in secondary index */
101
ulint sec_len, /*!< in: length of sec_field */
102
ulint zip_size) /*!< in: compressed page size, or 0 */
78
ulint clust_len, /* in: length of clust_field */
79
const byte* sec_field, /* in: column in secondary index */
80
ulint sec_len, /* in: length of sec_field */
81
ulint zip_size) /* in: compressed page size, or 0 */
105
84
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
86
len = btr_copy_externally_stored_field_prefix(buf, sizeof buf,
121
88
clust_field, clust_len);
132
len = dtype_get_at_most_n_mbchars(prtype, mbminmaxlen,
99
len = dtype_get_at_most_n_mbchars(prtype, mbminlen, mbmaxlen,
133
100
sec_len, len, (const char*) buf);
135
102
return(!cmp_data_data(mtype, prtype, buf, len, sec_field, sec_len));
138
/********************************************************************//**
105
/************************************************************************
139
106
Returns TRUE if the user-defined column values in a secondary index record
140
107
are alphabetically the same as the corresponding columns in the clustered
142
109
NOTE: the comparison is NOT done as a binary comparison, but character
143
fields are compared with collation!
144
@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 */
110
fields are compared with collation! */
149
113
row_sel_sec_rec_is_for_clust_rec(
150
114
/*=============================*/
151
const rec_t* sec_rec, /*!< in: secondary index record */
152
dict_index_t* sec_index, /*!< in: secondary index */
153
const rec_t* clust_rec, /*!< in: clustered index record;
115
/* out: TRUE if the secondary
116
record is equal to the corresponding
117
fields in the clustered record,
118
when compared with collation */
119
const rec_t* sec_rec, /* in: secondary index record */
120
dict_index_t* sec_index, /* in: secondary index */
121
const rec_t* clust_rec, /* in: clustered index record;
154
122
must be protected by a lock or
155
123
a page latch against deletion
156
124
in rollback or purge */
157
dict_index_t* clust_index) /*!< in: clustered index */
125
dict_index_t* clust_index) /* in: clustered index */
159
127
const byte* sec_field;
214
182
len = dtype_get_at_most_n_mbchars(
215
col->prtype, col->mbminmaxlen,
183
col->prtype, col->mbminlen, col->mbmaxlen,
216
184
ifield->prefix_len, len, (char*) clust_field);
218
186
if (rec_offs_nth_extern(clust_offs, clust_pos)
219
187
&& len < sec_len) {
220
188
if (!row_sel_sec_rec_is_for_blob(
221
189
col->mtype, col->prtype,
190
col->mbminlen, col->mbmaxlen,
223
191
clust_field, clust_len,
224
192
sec_field, sec_len,
225
193
dict_table_zip_size(
247
215
return(is_equal);
250
/*********************************************************************//**
251
Creates a select node struct.
252
@return own: select node struct */
218
/*************************************************************************
219
Creates a select node struct. */
257
mem_heap_t* heap) /*!< in: memory heap where created */
224
/* out, own: select node struct */
225
mem_heap_t* heap) /* in: memory heap where created */
259
227
sel_node_t* node;
261
node = static_cast<sel_node_t *>(mem_heap_alloc(heap, sizeof(sel_node_t)));
229
node = mem_heap_alloc(heap, sizeof(sel_node_t));
262
230
node->common.type = QUE_NODE_SELECT;
263
231
node->state = SEL_NODE_OPEN;
233
node->select_will_do_update = FALSE;
234
node->latch_mode = BTR_SEARCH_LEAF;
265
236
node->plans = NULL;
270
/*********************************************************************//**
241
/*************************************************************************
271
242
Frees the memory private to a select node when a query graph is freed,
272
243
does not free the heap where the node was originally created. */
275
246
sel_node_free_private(
276
247
/*==================*/
277
sel_node_t* node) /*!< in: select node struct */
248
sel_node_t* node) /* in: select node struct */
338
309
eval_node_copy_val(var->alias, exp);
340
311
exp = que_node_get_next(exp);
341
var = static_cast<sym_node_t *>(que_node_get_next(var));
312
var = que_node_get_next(var);
345
/*********************************************************************//**
316
/*************************************************************************
346
317
Resets the aggregate value totals in the select list of an aggregate type
350
321
sel_reset_aggregate_vals(
351
322
/*=====================*/
352
sel_node_t* node) /*!< in: select node */
323
sel_node_t* node) /* in: select node */
354
325
func_node_t* func_node;
356
327
ut_ad(node->is_aggregate);
358
func_node = static_cast<func_node_t *>(node->select_list);
329
func_node = node->select_list;
360
331
while (func_node) {
361
332
eval_node_set_int_val(func_node, 0);
363
func_node = static_cast<func_node_t *>(que_node_get_next(func_node));
334
func_node = que_node_get_next(func_node);
366
337
node->aggregate_already_fetched = FALSE;
369
/*********************************************************************//**
340
/*************************************************************************
370
341
Copies the input variable values when an explicit cursor is opened. */
373
344
row_sel_copy_input_variable_vals(
374
345
/*=============================*/
375
sel_node_t* node) /*!< in: select node */
346
sel_node_t* node) /* in: select node */
390
/*********************************************************************//**
361
/*************************************************************************
391
362
Fetches the column values from a record. */
394
365
row_sel_fetch_columns(
395
366
/*==================*/
396
dict_index_t* index, /*!< in: record index */
397
const rec_t* rec, /*!< in: record in a clustered or non-clustered
367
dict_index_t* index, /* in: record index */
368
const rec_t* rec, /* in: record in a clustered or non-clustered
398
369
index; must be protected by a page latch */
399
const ulint* offsets,/*!< in: rec_get_offsets(rec, index) */
400
sym_node_t* column) /*!< in: first column in a column list, or
370
const ulint* offsets,/* in: rec_get_offsets(rec, index) */
371
sym_node_t* column) /* in: first column in a column list, or
476
/*********************************************************************//**
440
/*************************************************************************
477
441
Allocates a prefetch buffer for a column when prefetch is first time done. */
480
444
sel_col_prefetch_buf_alloc(
481
445
/*=======================*/
482
sym_node_t* column) /*!< in: symbol table node for a column */
446
sym_node_t* column) /* in: symbol table node for a column */
484
448
sel_buf_t* sel_buf;
487
451
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)));
453
column->prefetch_buf = mem_alloc(SEL_MAX_N_PREFETCH
454
* sizeof(sel_buf_t));
491
455
for (i = 0; i < SEL_MAX_N_PREFETCH; i++) {
492
456
sel_buf = column->prefetch_buf + i;
656
/*********************************************************************//**
657
Builds a previous version of a clustered index record for a consistent read
658
@return DB_SUCCESS or error code */
620
/*************************************************************************
621
Builds a previous version of a clustered index record for a consistent read */
661
624
row_sel_build_prev_vers(
662
625
/*====================*/
663
read_view_t* read_view, /*!< in: read view */
664
dict_index_t* index, /*!< in: plan node for table */
665
rec_t* rec, /*!< in: record in a clustered index */
666
ulint** offsets, /*!< in/out: offsets returned by
626
/* out: DB_SUCCESS or error code */
627
read_view_t* read_view, /* in: read view */
628
dict_index_t* index, /* in: plan node for table */
629
rec_t* rec, /* in: record in a clustered index */
630
ulint** offsets, /* in/out: offsets returned by
667
631
rec_get_offsets(rec, plan->index) */
668
mem_heap_t** offset_heap, /*!< in/out: memory heap from which
632
mem_heap_t** offset_heap, /* in/out: memory heap from which
669
633
the offsets are allocated */
670
mem_heap_t** old_vers_heap, /*!< out: old version heap to use */
671
rec_t** old_vers, /*!< out: old version, or NULL if the
634
mem_heap_t** old_vers_heap, /* out: old version heap to use */
635
rec_t** old_vers, /* out: old version, or NULL if the
672
636
record does not exist in the view:
673
637
i.e., it was freshly inserted
675
mtr_t* mtr) /*!< in: mtr */
639
mtr_t* mtr) /* in: mtr */
691
/*********************************************************************//**
655
/*************************************************************************
692
656
Builds the last committed version of a clustered index record for a
693
semi-consistent read.
694
@return DB_SUCCESS or error code */
657
semi-consistent read. */
697
660
row_sel_build_committed_vers_for_mysql(
698
661
/*===================================*/
699
dict_index_t* clust_index, /*!< in: clustered index */
700
row_prebuilt_t* prebuilt, /*!< in: prebuilt struct */
701
const rec_t* rec, /*!< in: record in a clustered index */
702
ulint** offsets, /*!< in/out: offsets returned by
662
/* out: DB_SUCCESS or error code */
663
dict_index_t* clust_index, /* in: clustered index */
664
row_prebuilt_t* prebuilt, /* in: prebuilt struct */
665
const rec_t* rec, /* in: record in a clustered index */
666
ulint** offsets, /* in/out: offsets returned by
703
667
rec_get_offsets(rec, clust_index) */
704
mem_heap_t** offset_heap, /*!< in/out: memory heap from which
668
mem_heap_t** offset_heap, /* in/out: memory heap from which
705
669
the offsets are allocated */
706
const rec_t** old_vers, /*!< out: old version, or NULL if the
670
const rec_t** old_vers, /* out: old version, or NULL if the
707
671
record does not exist in the view:
708
672
i.e., it was freshly inserted
710
mtr_t* mtr) /*!< in: mtr */
674
mtr_t* mtr) /* in: mtr */
764
/*********************************************************************//**
765
Tests the other conditions.
766
@return TRUE if row passed the tests */
728
/*************************************************************************
729
Tests the other conditions. */
769
732
row_sel_test_other_conds(
770
733
/*=====================*/
771
plan_t* plan) /*!< in: plan for the table; the column values must
734
/* out: TRUE if row passed the tests */
735
plan_t* plan) /* in: plan for the table; the column values must
772
736
already have been retrieved */
774
738
func_node_t* cond;
792
/*********************************************************************//**
756
/*************************************************************************
793
757
Retrieves the clustered index record corresponding to a record in a
794
non-clustered index. Does the necessary locking.
795
@return DB_SUCCESS or error code */
758
non-clustered index. Does the necessary locking. */
798
761
row_sel_get_clust_rec(
799
762
/*==================*/
800
sel_node_t* node, /*!< in: select_node */
801
plan_t* plan, /*!< in: plan node for table */
802
rec_t* rec, /*!< in: record in a non-clustered index */
803
que_thr_t* thr, /*!< in: query thread */
804
rec_t** out_rec,/*!< out: clustered record or an old version of
763
/* out: DB_SUCCESS or error code */
764
sel_node_t* node, /* in: select_node */
765
plan_t* plan, /* in: plan node for table */
766
rec_t* rec, /* in: record in a non-clustered index */
767
que_thr_t* thr, /* in: query thread */
768
rec_t** out_rec,/* out: clustered record or an old version of
805
769
it, NULL if the old version did not exist
806
770
in the read view, i.e., it was a fresh
807
771
inserted version */
808
mtr_t* mtr) /*!< in: mtr used to get access to the
772
mtr_t* mtr) /* in: mtr used to get access to the
809
773
non-clustered record; the same mtr is used to
810
774
access the clustered index */
882
846
err = lock_clust_rec_read_check_and_lock(
883
847
0, btr_pcur_get_block(&plan->clust_pcur),
884
848
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);
849
node->row_lock_mode, lock_type, thr);
851
if (err != DB_SUCCESS) {
963
/*********************************************************************//**
964
Sets a lock on a record.
965
@return DB_SUCCESS, DB_SUCCESS_LOCKED_REC, or error code */
920
/*************************************************************************
921
Sets a lock on a record. */
968
924
sel_set_rec_lock(
969
925
/*=============*/
970
const buf_block_t* block, /*!< in: buffer block of rec */
971
const rec_t* rec, /*!< in: record */
972
dict_index_t* index, /*!< in: index */
973
const ulint* offsets,/*!< in: rec_get_offsets(rec, index) */
974
ulint mode, /*!< in: lock mode */
975
ulint type, /*!< in: LOCK_ORDINARY, LOCK_GAP, or
926
/* out: DB_SUCCESS or error code */
927
const buf_block_t* block, /* in: buffer block of rec */
928
const rec_t* rec, /* in: record */
929
dict_index_t* index, /* in: index */
930
const ulint* offsets,/* in: rec_get_offsets(rec, index) */
931
ulint mode, /* in: lock mode */
932
ulint type, /* in: LOCK_ORDINARY, LOCK_GAP, or
976
933
LOC_REC_NOT_GAP */
977
que_thr_t* thr) /*!< in: query thread */
934
que_thr_t* thr) /* in: query thread */
982
939
trx = thr_get_trx(thr);
991
948
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);
949
err = lock_clust_rec_read_check_and_lock(
950
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);
952
err = lock_sec_rec_read_check_and_lock(
953
0, block, rec, index, offsets, mode, type, thr);
1002
/*********************************************************************//**
959
/*************************************************************************
1003
960
Opens a pcur to a table index. */
1006
963
row_sel_open_pcur(
1007
964
/*==============*/
1008
plan_t* plan, /*!< in: table plan */
965
sel_node_t* node, /* in: select node */
966
plan_t* plan, /* in: table plan */
1009
967
ibool search_latch_locked,
1010
/*!< in: TRUE if the thread currently
968
/* in: TRUE if the thread currently
1011
969
has the search latch locked in
1013
mtr_t* mtr) /*!< in: mtr */
971
mtr_t* mtr) /* in: mtr */
1015
973
dict_index_t* index;
1016
974
func_node_t* cond;
1057
1015
/* Open pcur to the index */
1059
1017
btr_pcur_open_with_no_init(index, plan->tuple, plan->mode,
1060
BTR_SEARCH_LEAF, &plan->pcur,
1018
node->latch_mode, &(plan->pcur),
1061
1019
has_search_latch, mtr);
1063
1021
/* Open the cursor to the start or the end of the index
1064
1022
(FALSE: no init) */
1066
btr_pcur_open_at_index_side(plan->asc, index, BTR_SEARCH_LEAF,
1024
btr_pcur_open_at_index_side(plan->asc, index, node->latch_mode,
1067
1025
&(plan->pcur), FALSE, mtr);
1074
1032
plan->pcur_is_open = TRUE;
1077
/*********************************************************************//**
1078
Restores a stored pcur position to a table index.
1079
@return TRUE if the cursor should be moved to the next record after we
1080
return from this function (moved to the previous, in the case of a
1081
descending cursor) without processing again the current cursor
1035
/*************************************************************************
1036
Restores a stored pcur position to a table index. */
1085
1039
row_sel_restore_pcur_pos(
1086
1040
/*=====================*/
1087
plan_t* plan, /*!< in: table plan */
1088
mtr_t* mtr) /*!< in: mtr */
1041
/* out: TRUE if the cursor should be moved to
1042
the next record after we return from this
1043
function (moved to the previous, in the case
1044
of a descending cursor) without processing
1045
again the current cursor record */
1046
sel_node_t* node, /* in: select node */
1047
plan_t* plan, /* in: table plan */
1048
mtr_t* mtr) /* in: mtr */
1090
1050
ibool equal_position;
1091
1051
ulint relative_position;
1183
1143
plan->n_rows_prefetched = 0;
1186
/*********************************************************************//**
1146
/*************************************************************************
1187
1147
Tries to do a shortcut to fetch a clustered index record with a unique key,
1188
using the hash index if possible (not always).
1189
@return SEL_FOUND, SEL_EXHAUSTED, SEL_RETRY */
1148
using the hash index if possible (not always). */
1192
1151
row_sel_try_search_shortcut(
1193
1152
/*========================*/
1194
sel_node_t* node, /*!< in: select node for a consistent read */
1195
plan_t* plan, /*!< in: plan for a unique search in clustered
1153
/* out: SEL_FOUND, SEL_EXHAUSTED, SEL_RETRY */
1154
sel_node_t* node, /* in: select node for a consistent read */
1155
plan_t* plan, /* in: plan for a unique search in clustered
1197
mtr_t* mtr) /*!< in: mtr */
1157
mtr_t* mtr) /* in: mtr */
1199
1159
dict_index_t* index;
1794
1744
plan->n_rows_fetched++;
1796
ut_ad(plan->pcur.latch_mode == BTR_SEARCH_LEAF);
1746
ut_ad(plan->pcur.latch_mode == node->latch_mode);
1748
if (node->select_will_do_update) {
1749
/* This is a searched update and we can do the update in-place,
1752
row_upd_in_place_in_select(node, thr, &mtr);
1754
leaf_contains_updates = TRUE;
1756
/* When the database is in the online backup mode, the number
1757
of log records for a single mtr should be small: increment the
1758
cost counter to ensure it */
1760
cost_counter += 1 + (SEL_COST_LIMIT / 8);
1762
if (plan->unique_search) {
1764
goto table_exhausted;
1798
1770
if ((plan->n_rows_fetched <= SEL_PREFETCH_LIMIT)
1799
1771
|| plan->unique_search || plan->no_prefetch
2113
/**********************************************************************//**
2114
Performs a fetch for a cursor.
2115
@return query thread to run next or NULL */
2098
/**************************************************************************
2099
Performs a fetch for a cursor. */
2120
que_thr_t* thr) /*!< in: query thread */
2104
/* out: query thread to run next or NULL */
2105
que_thr_t* thr) /* in: query thread */
2122
2107
sel_node_t* sel_node;
2123
2108
fetch_node_t* node;
2127
node = static_cast<fetch_node_t *>(thr->run_node);
2112
node = thr->run_node;
2128
2113
sel_node = node->cursor_def;
2130
2115
ut_ad(que_node_get_type(node) == QUE_NODE_FETCH);
2176
/****************************************************************//**
2177
Sample callback function for fetch that prints each row.
2178
@return always returns non-NULL */
2161
/********************************************************************
2162
Sample callback function for fetch that prints each row.*/
2181
2165
row_fetch_print(
2182
2166
/*============*/
2183
void* row, /*!< in: sel_node_t* */
2184
void* user_arg) /*!< in: not used */
2167
/* out: always returns non-NULL */
2168
void* row, /* in: sel_node_t* */
2169
void* user_arg) /* in: not used */
2186
sel_node_t *node = static_cast<sel_node_t *>(row);
2171
sel_node_t* node = row;
2187
2172
que_node_t* exp;
2217
2202
return((void*)42);
2220
/***********************************************************//**
2221
Prints a row in a select result.
2222
@return query thread to run next or NULL */
2205
/********************************************************************
2206
Callback function for fetch that stores an unsigned 4 byte integer to the
2207
location pointed. The column's type must be DATA_INT, DATA_UNSIGNED, length
2211
row_fetch_store_uint4(
2212
/*==================*/
2213
/* out: always returns NULL */
2214
void* row, /* in: sel_node_t* */
2215
void* user_arg) /* in: data pointer */
2217
sel_node_t* node = row;
2218
ib_uint32_t* val = user_arg;
2221
dfield_t* dfield = que_node_get_val(node->select_list);
2222
const dtype_t* type = dfield_get_type(dfield);
2223
ulint len = dfield_get_len(dfield);
2225
ut_a(dtype_get_mtype(type) == DATA_INT);
2226
ut_a(dtype_get_prtype(type) & DATA_UNSIGNED);
2229
tmp = mach_read_from_4(dfield_get_data(dfield));
2230
*val = (ib_uint32_t) tmp;
2235
/***************************************************************
2236
Prints a row in a select result. */
2225
2239
row_printf_step(
2226
2240
/*============*/
2227
que_thr_t* thr) /*!< in: query thread */
2241
/* out: query thread to run next or NULL */
2242
que_thr_t* thr) /* in: query thread */
2229
2244
row_printf_node_t* node;
2230
2245
sel_node_t* sel_node;
2292
2307
row_sel_convert_mysql_key_to_innobase(
2293
2308
/*==================================*/
2294
dtuple_t* tuple, /*!< in/out: tuple where to build;
2309
dtuple_t* tuple, /* in/out: tuple where to build;
2295
2310
NOTE: we assume that the type info
2296
2311
in the tuple is already according
2298
byte* buf, /*!< in: buffer to use in field
2313
byte* buf, /* in: buffer to use in field
2300
ulint buf_len, /*!< in: buffer length */
2301
dict_index_t* index, /*!< in: index of the key value */
2302
const byte* key_ptr, /*!< in: MySQL key value */
2303
ulint key_len, /*!< in: MySQL key value length */
2304
trx_t* trx) /*!< in: transaction */
2315
ulint buf_len, /* in: buffer length */
2316
dict_index_t* index, /* in: index of the key value */
2317
const byte* key_ptr, /* in: MySQL key value */
2318
ulint key_len, /* in: MySQL key value length */
2319
trx_t* trx) /* in: transaction */
2306
2321
byte* original_buf = buf;
2307
2322
const byte* original_key_ptr = key_ptr;
2484
2499
dtuple_set_n_fields(tuple, n_fields);
2487
/**************************************************************//**
2502
/******************************************************************
2488
2503
Stores the row id to the prebuilt struct. */
2491
2506
row_sel_store_row_id_to_prebuilt(
2492
2507
/*=============================*/
2493
row_prebuilt_t* prebuilt, /*!< in/out: prebuilt */
2494
const rec_t* index_rec, /*!< in: record */
2495
const dict_index_t* index, /*!< in: index of the record */
2496
const ulint* offsets) /*!< in: rec_get_offsets
2508
row_prebuilt_t* prebuilt, /* in/out: prebuilt */
2509
const rec_t* index_rec, /* in: record */
2510
const dict_index_t* index, /* in: index of the record */
2511
const ulint* offsets) /* in: rec_get_offsets
2497
2512
(index_rec, index) */
2499
2514
const byte* data;
2522
2537
ut_memcpy(prebuilt->row_id, data, len);
2525
/**************************************************************//**
2540
/******************************************************************
2526
2541
Stores a non-SQL-NULL field in the MySQL format. The counterpart of this
2527
2542
function is row_mysql_store_col_in_innobase_format() in row0mysql.c. */
2530
2545
row_sel_field_store_in_mysql_format(
2531
2546
/*================================*/
2532
byte* dest, /*!< in/out: buffer where to store; NOTE
2547
byte* dest, /* in/out: buffer where to store; NOTE
2533
2548
that BLOBs are not in themselves
2534
2549
stored here: the caller must allocate
2535
2550
and copy the BLOB into buffer before,
2536
2551
and pass the pointer to the BLOB in
2538
2553
const mysql_row_templ_t* templ,
2539
/*!< in: MySQL column template.
2554
/* in: MySQL column template.
2540
2555
Its following fields are referenced:
2541
2556
type, is_unsigned, mysql_col_len,
2542
2557
mbminlen, mbmaxlen */
2543
const byte* data, /*!< in: data to store */
2544
ulint len) /*!< in: length of the data */
2558
const byte* data, /* in: data to store */
2559
ulint len) /* in: length of the data */
2548
2565
ut_ad(len != UNIV_SQL_NULL);
2549
UNIV_MEM_ASSERT_RW(data, len);
2551
2567
switch (templ->type) {
2552
const byte* field_end;
2555
2569
/* Convert integer data from Innobase to a little-endian
2556
2570
format, sign bit restored to normal */
2594
2608
unused end of a >= 5.0.3 true VARCHAR column, just in case
2595
2609
MySQL expects its contents to be deterministic. */
2611
pad_ptr = dest + len;
2599
2613
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 */
2615
/* We handle UCS2 charset strings differently. */
2616
if (templ->mbminlen == 2) {
2617
/* A space char is two bytes, 0x0020 in UCS2 */
2612
if (UNIV_UNLIKELY(len & 1)) {
2613
2620
/* A 0x20 has been stripped from the column.
2614
2621
Pad it back. */
2616
if (pad < field_end) {
2623
if (pad_ptr < field_end) {
2629
/* Pad the rest of the string with 0x0020 */
2631
while (pad_ptr < field_end) {
2638
ut_ad(templ->mbminlen == 1);
2641
memset(pad_ptr, 0x20, field_end - pad_ptr);
2622
row_mysql_pad_col(templ->mbminlen, pad, field_end - pad);
2625
2645
case DATA_BLOB:
2675
/**************************************************************//**
2695
/******************************************************************
2676
2696
Convert a row in the Innobase format to a row in the MySQL format.
2677
2697
Note that the template in prebuilt may advise us to copy only a few
2678
2698
columns to mysql_rec, other columns are left blank. All columns may not
2679
be needed in the query.
2680
@return TRUE on success, FALSE if not all columns could be retrieved */
2699
be needed in the query. */
2683
__attribute__((warn_unused_result))
2686
2702
row_sel_store_mysql_rec(
2687
2703
/*====================*/
2688
byte* mysql_rec, /*!< out: row in the MySQL format */
2689
row_prebuilt_t* prebuilt, /*!< in: prebuilt struct */
2690
const rec_t* rec, /*!< in: Innobase record in the index
2704
/* out: TRUE if success, FALSE if
2705
could not allocate memory for a BLOB
2706
(though we may also assert in that
2708
byte* mysql_rec, /* out: row in the MySQL format */
2709
row_prebuilt_t* prebuilt, /* in: prebuilt struct */
2710
const rec_t* rec, /* in: Innobase record in the index
2691
2711
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
2697
const ulint* offsets) /*!< in: array returned by
2698
rec_get_offsets(rec) */
2712
template; must be protected by
2714
const ulint* offsets, /* in: array returned by
2715
rec_get_offsets() */
2716
ulint start_field_no,
2700
mem_heap_t* extern_field_heap = NULL;
2719
mysql_row_templ_t* templ;
2720
mem_heap_t* extern_field_heap = NULL;
2704
2726
ut_ad(prebuilt->mysql_template);
2705
ut_ad(prebuilt->default_rec);
2706
2727
ut_ad(rec_offs_validate(rec, NULL, offsets));
2707
ut_ad(!rec_get_deleted_flag(rec, rec_offs_comp(offsets)));
2709
2729
if (UNIV_LIKELY_NULL(prebuilt->blob_heap)) {
2710
2730
mem_heap_free(prebuilt->blob_heap);
2711
2731
prebuilt->blob_heap = NULL;
2714
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))) {
2734
memset(mysql_rec, 0xff, prebuilt->null_bitmap_len);
2735
for (i = start_field_no; i < end_field_no /* prebuilt->n_template */; i++) {
2737
templ = prebuilt->mysql_template + i;
2739
if (UNIV_UNLIKELY(rec_offs_nth_extern(offsets,
2740
templ->rec_field_no))) {
2726
2742
/* Copy an externally stored field to the temporary
2749
2765
data = btr_rec_copy_externally_stored_field(
2751
2767
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);
2768
templ->rec_field_no, &len, heap);
2784
2770
ut_a(len != UNIV_SQL_NULL);
2786
2772
/* Field is stored in the row. */
2788
data = rec_get_nth_field(rec, offsets, field_no, &len);
2774
data = rec_get_nth_field(rec, offsets,
2775
templ->rec_field_no, &len);
2790
2777
if (UNIV_UNLIKELY(templ->type == DATA_BLOB)
2791
2778
&& len != UNIV_SQL_NULL) {
2825
2812
&= ~(byte) templ->mysql_null_bit_mask;
2828
/* MySQL assumes that the field for an SQL
2829
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
mysql_rec[templ->mysql_null_byte_offset]
2835
|= (byte) templ->mysql_null_bit_mask;
2836
memcpy(mysql_rec + templ->mysql_col_offset,
2837
(const byte*) prebuilt->default_rec
2838
+ templ->mysql_col_offset,
2839
templ->mysql_col_len);
2815
/* MySQL seems to assume the field for an SQL NULL
2816
value is set to zero or space. Not taking this into
2817
account caused seg faults with NULL BLOB fields, and
2818
bug number 154 in the MySQL bug database: GROUP BY
2819
and DISTINCT could treat NULL values inequal. */
2822
/* We already set all NULL bits by default above,
2823
so don't need to do it here. */
2825
switch (templ->type) {
2829
if (templ->mysql_type
2830
== DATA_MYSQL_TRUE_VARCHAR) {
2831
/* This is a >= 5.0.3 type
2832
true VARCHAR. Zero the field. */
2838
case DATA_FIXBINARY:
2840
/* MySQL pads all string types (except
2841
BLOB, TEXT and true VARCHAR) with space. */
2842
if (UNIV_UNLIKELY(templ->mbminlen == 2)) {
2843
/* Treat UCS2 as a special case. */
2845
+ templ->mysql_col_offset;
2846
len = templ->mysql_col_len;
2847
/* There are two UCS2 bytes per char,
2848
so the length has to be even. */
2850
/* Pad with 0x0020. */
2865
ut_ad(!pad_char || templ->mbminlen == 1);
2866
memset(mysql_rec + templ->mysql_col_offset,
2867
pad_char, templ->mysql_col_len);
2846
/*********************************************************************//**
2847
Builds a previous version of a clustered index record for a consistent read
2848
@return DB_SUCCESS or error code */
2874
/*************************************************************************
2875
Builds a previous version of a clustered index record for a consistent read */
2851
2878
row_sel_build_prev_vers_for_mysql(
2852
2879
/*==============================*/
2853
read_view_t* read_view, /*!< in: read view */
2854
dict_index_t* clust_index, /*!< in: clustered index */
2855
row_prebuilt_t* prebuilt, /*!< in: prebuilt struct */
2856
const rec_t* rec, /*!< in: record in a clustered index */
2857
ulint** offsets, /*!< in/out: offsets returned by
2880
/* out: DB_SUCCESS or error code */
2881
read_view_t* read_view, /* in: read view */
2882
dict_index_t* clust_index, /* in: clustered index */
2883
row_prebuilt_t* prebuilt, /* in: prebuilt struct */
2884
const rec_t* rec, /* in: record in a clustered index */
2885
ulint** offsets, /* in/out: offsets returned by
2858
2886
rec_get_offsets(rec, clust_index) */
2859
mem_heap_t** offset_heap, /*!< in/out: memory heap from which
2887
mem_heap_t** offset_heap, /* in/out: memory heap from which
2860
2888
the offsets are allocated */
2861
rec_t** old_vers, /*!< out: old version, or NULL if the
2889
rec_t** old_vers, /* out: old version, or NULL if the
2862
2890
record does not exist in the view:
2863
2891
i.e., it was freshly inserted
2865
mtr_t* mtr) /*!< in: mtr */
2893
mtr_t* mtr) /* in: mtr */
2881
/*********************************************************************//**
2909
/*************************************************************************
2882
2910
Retrieves the clustered index record corresponding to a record in a
2883
2911
non-clustered index. Does the necessary locking. Used in the MySQL
2885
@return DB_SUCCESS, DB_SUCCESS_LOCKED_REC, or error code */
2888
2915
row_sel_get_clust_rec_for_mysql(
2889
2916
/*============================*/
2890
row_prebuilt_t* prebuilt,/*!< in: prebuilt struct in the handle */
2891
dict_index_t* sec_index,/*!< in: secondary index where rec resides */
2892
const rec_t* rec, /*!< in: record in a non-clustered index; if
2917
/* out: DB_SUCCESS or error code */
2918
row_prebuilt_t* prebuilt,/* in: prebuilt struct in the handle */
2919
dict_index_t* sec_index,/* in: secondary index where rec resides */
2920
const rec_t* rec, /* in: record in a non-clustered index; if
2893
2921
this is a locking read, then rec is not
2894
2922
allowed to be delete-marked, and that would
2895
2923
not make sense either */
2896
que_thr_t* thr, /*!< in: query thread */
2897
const rec_t** out_rec,/*!< out: clustered record or an old version of
2924
que_thr_t* thr, /* in: query thread */
2925
const rec_t** out_rec,/* out: clustered record or an old version of
2898
2926
it, NULL if the old version did not exist
2899
2927
in the read view, i.e., it was a fresh
2900
2928
inserted version */
2901
ulint** offsets,/*!< in: offsets returned by
2929
ulint** offsets,/* in: offsets returned by
2902
2930
rec_get_offsets(rec, sec_index);
2903
2931
out: offsets returned by
2904
2932
rec_get_offsets(out_rec, clust_index) */
2905
mem_heap_t** offset_heap,/*!< in/out: memory heap from which
2933
mem_heap_t** offset_heap,/* in/out: memory heap from which
2906
2934
the offsets are allocated */
2907
mtr_t* mtr) /*!< in: mtr used to get access to the
2935
mtr_t* mtr) /* in: mtr used to get access to the
2908
2936
non-clustered record; the same mtr is used to
2909
2937
access the clustered index */
2911
2939
dict_index_t* clust_index;
2912
2940
const rec_t* clust_rec;
2913
2941
rec_t* old_vers;
2917
2945
*out_rec = NULL;
3051
3073
rec, sec_index, clust_rec, clust_index));
3059
3079
*out_rec = clust_rec;
3061
if (prebuilt->select_lock_type != LOCK_NONE) {
3062
/* We may use the cursor in update or in unlock_row():
3063
store its position */
3081
if (prebuilt->select_lock_type == LOCK_X) {
3082
/* We may use the cursor in update: store its position */
3065
3084
btr_pcur_store_position(prebuilt->clust_pcur, mtr);
3072
/********************************************************************//**
3092
/************************************************************************
3073
3093
Restores cursor position after it has been stored. We have to take into
3074
3094
account that the record cursor was positioned on may have been deleted.
3075
Then we may have to move the cursor one step up or down.
3076
@return TRUE if we may need to process the record the cursor is now
3077
positioned on (i.e. we should not go to the next record yet) */
3095
Then we may have to move the cursor one step up or down. */
3080
3098
sel_restore_position_for_mysql(
3081
3099
/*===========================*/
3082
ibool* same_user_rec, /*!< out: TRUE if we were able to restore
3100
/* out: TRUE if we may need to
3101
process the record the cursor is
3102
now positioned on (i.e. we should
3103
not go to the next record yet) */
3104
ibool* same_user_rec, /* out: TRUE if we were able to restore
3083
3105
the cursor on a user record with the
3084
3106
same ordering prefix in in the
3085
3107
B-tree index */
3086
ulint latch_mode, /*!< in: latch mode wished in
3108
ulint latch_mode, /* in: latch mode wished in
3088
btr_pcur_t* pcur, /*!< in: cursor whose position
3110
btr_pcur_t* pcur, /* in: cursor whose position
3089
3111
has been stored */
3090
ibool moves_up, /*!< in: TRUE if the cursor moves up
3112
ibool moves_up, /* in: TRUE if the cursor moves up
3091
3113
in the index */
3092
mtr_t* mtr) /*!< in: mtr; CAUTION: may commit
3114
mtr_t* mtr) /* in: mtr; CAUTION: may commit
3093
3115
mtr temporarily! */
3140
/********************************************************************//**
3162
/************************************************************************
3141
3163
Pops a cached row for MySQL from the fetch cache. */
3144
3166
row_sel_pop_cached_row_for_mysql(
3145
3167
/*=============================*/
3146
byte* buf, /*!< in/out: buffer where to copy the
3168
byte* buf, /* in/out: buffer where to copy the
3148
row_prebuilt_t* prebuilt) /*!< in: prebuilt struct */
3170
row_prebuilt_t* prebuilt) /* in: prebuilt struct */
3151
const mysql_row_templ_t*templ;
3173
mysql_row_templ_t* templ;
3152
3174
byte* cached_rec;
3153
3175
ut_ad(prebuilt->n_fetch_cached > 0);
3154
3176
ut_ad(prebuilt->mysql_prefix_len <= prebuilt->mysql_row_len);
3200
/********************************************************************//**
3201
Pushes a row for MySQL to the fetch cache.
3202
@return TRUE on success, FALSE if the record contains incomplete BLOBs */
3212
/************************************************************************
3213
Pushes a row for MySQL to the fetch cache. */
3205
__attribute__((warn_unused_result))
3208
3216
row_sel_push_cache_row_for_mysql(
3209
3217
/*=============================*/
3210
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) */
3218
row_prebuilt_t* prebuilt, /* in: prebuilt struct */
3219
const rec_t* rec, /* in: record to push; must
3220
be protected by a page latch */
3221
const ulint* offsets, /* in: rec_get_offsets() */
3222
ulint start_field_no, /* psergy: start from this field */
3223
byte* remainder_buf) /* if above !=0 -> where to take
3223
3229
ut_ad(prebuilt->n_fetch_cached < MYSQL_FETCH_CACHE_SIZE);
3224
3230
ut_ad(rec_offs_validate(rec, NULL, offsets));
3225
ut_ad(!rec_get_deleted_flag(rec, rec_offs_comp(offsets)));
3226
3231
ut_a(!prebuilt->templ_contains_blob);
3228
3233
if (prebuilt->fetch_cache[0] == NULL) {
3247
3252
ut_ad(prebuilt->fetch_cache_first == 0);
3248
UNIV_MEM_INVALID(prebuilt->fetch_cache[prebuilt->n_fetch_cached],
3249
prebuilt->mysql_row_len);
3251
3254
if (UNIV_UNLIKELY(!row_sel_store_mysql_rec(
3252
3255
prebuilt->fetch_cache[
3253
3256
prebuilt->n_fetch_cached],
3254
prebuilt, rec, rec_clust, offsets))) {
3257
prebuilt, rec, offsets, start_field_no,
3258
prebuilt->n_template))) {
3262
if (start_field_no) {
3263
for (i=0; i < start_field_no; i++) {
3264
register ulint offs;
3265
mysql_row_templ_t* templ;
3266
templ = prebuilt->mysql_template + i;
3268
if (templ->mysql_null_bit_mask) {
3269
offs= templ->mysql_null_byte_offset;
3270
if (*(remainder_buf + offs) & templ->mysql_null_bit_mask)
3271
*(prebuilt->fetch_cache[prebuilt->n_fetch_cached] + offs) |=
3272
/* (*(remainder_buf + offs) &*/( templ->mysql_null_bit_mask);
3274
*(prebuilt->fetch_cache[prebuilt->n_fetch_cached] + offs) &=
3275
~templ->mysql_null_bit_mask;
3278
offs= templ->mysql_col_offset;
3279
memcpy(prebuilt->fetch_cache[prebuilt->n_fetch_cached] + offs,
3280
remainder_buf + offs,
3281
templ->mysql_col_len);
3258
3286
prebuilt->n_fetch_cached++;
3262
/*********************************************************************//**
3289
/*************************************************************************
3263
3290
Tries to do a shortcut to fetch a clustered index record with a unique key,
3264
3291
using the hash index if possible (not always). We assume that the search
3265
3292
mode is PAGE_CUR_GE, it is a consistent read, there is a read view in trx,
3266
btr search latch has been locked in S-mode.
3267
@return SEL_FOUND, SEL_EXHAUSTED, SEL_RETRY */
3293
btr search latch has been locked in S-mode. */
3270
3296
row_sel_try_search_shortcut_for_mysql(
3271
3297
/*==================================*/
3272
const rec_t** out_rec,/*!< out: record if found */
3273
row_prebuilt_t* prebuilt,/*!< in: prebuilt struct */
3274
ulint** offsets,/*!< in/out: for rec_get_offsets(*out_rec) */
3275
mem_heap_t** heap, /*!< in/out: heap for rec_get_offsets() */
3276
mtr_t* mtr) /*!< in: started mtr */
3298
/* out: SEL_FOUND, SEL_EXHAUSTED, SEL_RETRY */
3299
const rec_t** out_rec,/* out: record if found */
3300
row_prebuilt_t* prebuilt,/* in: prebuilt struct */
3301
ulint** offsets,/* in/out: for rec_get_offsets(*out_rec) */
3302
mem_heap_t** heap, /* in/out: heap for rec_get_offsets() */
3303
mtr_t* mtr) /* in: started mtr */
3278
3305
dict_index_t* index = prebuilt->index;
3279
3306
const dtuple_t* search_tuple = prebuilt->search_tuple;
3284
3311
ut_ad(dict_index_is_clust(index));
3285
3312
ut_ad(!prebuilt->templ_contains_blob);
3287
#ifndef UNIV_SEARCH_DEBUG
3288
3314
btr_pcur_open_with_no_init(index, search_tuple, PAGE_CUR_GE,
3289
3315
BTR_SEARCH_LEAF, pcur,
3316
#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
3322
rec = btr_pcur_get_rec(pcur);
3300
3324
if (!page_rec_is_user_rec(rec)) {
3333
3357
return(SEL_FOUND);
3336
/********************************************************************//**
3360
/************************************************************************
3337
3361
Searches for rows in the database. This is used in the interface to
3338
3362
MySQL. This function opens a cursor, and also implements fetch next
3339
3363
and fetch prev. NOTE that if we do a search with a full key value
3340
3364
from a unique index (ROW_SEL_EXACT), then we will not store the cursor
3341
position and fetch next or fetch prev must not be tried to the cursor!
3342
@return DB_SUCCESS, DB_RECORD_NOT_FOUND, DB_END_OF_INDEX, DB_DEADLOCK,
3343
DB_LOCK_TABLE_FULL, DB_CORRUPTION, or DB_TOO_BIG_RECORD */
3365
position and fetch next or fetch prev must not be tried to the cursor! */
3346
3368
row_search_for_mysql(
3347
3369
/*=================*/
3348
byte* buf, /*!< in/out: buffer for the fetched
3371
DB_RECORD_NOT_FOUND,
3372
DB_END_OF_INDEX, DB_DEADLOCK,
3373
DB_LOCK_TABLE_FULL, DB_CORRUPTION,
3374
or DB_TOO_BIG_RECORD */
3375
byte* buf, /* in/out: buffer for the fetched
3349
3376
row in the MySQL format */
3350
ulint mode, /*!< in: search mode PAGE_CUR_L, ... */
3351
row_prebuilt_t* prebuilt, /*!< in: prebuilt struct for the
3377
ulint mode, /* in: search mode PAGE_CUR_L, ... */
3378
row_prebuilt_t* prebuilt, /* in: prebuilt struct for the
3352
3379
table handle; this contains the info
3353
3380
of search_tuple, index; if search
3354
3381
tuple contains 0 fields then we
3355
3382
position the cursor at the start or
3356
3383
the end of the index, depending on
3358
ulint match_mode, /*!< in: 0 or ROW_SEL_EXACT or
3385
ulint match_mode, /* in: 0 or ROW_SEL_EXACT or
3359
3386
ROW_SEL_EXACT_PREFIX */
3360
ulint direction) /*!< in: 0 or ROW_SEL_NEXT or
3387
ulint direction) /* in: 0 or ROW_SEL_NEXT or
3361
3388
ROW_SEL_PREV; NOTE: if this is != 0,
3362
3389
then prebuilt must have a pcur
3363
3390
with stored position! In opening of a
3465
/* August 19, 2005 by Heikki: temporarily disable this error
3466
print until the cursor lock count is done correctly.
3467
See bugs #12263 and #12456!*/
3469
if (trx->n_mysql_tables_in_use == 0
3470
&& UNIV_UNLIKELY(prebuilt->select_lock_type == LOCK_NONE)) {
3471
/* Note that if MySQL uses an InnoDB temp table that it
3472
created inside LOCK TABLES, then n_mysql_tables_in_use can
3473
be zero; in that case select_lock_type is set to LOCK_X in
3476
fputs("InnoDB: Error: MySQL is trying to perform a SELECT\n"
3477
"InnoDB: but it has not locked"
3478
" any tables in ::external_lock()!\n",
3480
trx_print(stderr, trx, 600);
3481
fputc('\n', stderr);
3441
3486
fprintf(stderr, "Match mode %lu\n search tuple ",
3442
3487
(ulong) match_mode);
3443
3488
dtuple_print(search_tuple);
3625
3679
row_sel_try_search_shortcut_for_mysql().
3626
3680
The latch will not be released until
3627
3681
mtr_commit(&mtr). */
3628
ut_ad(!rec_get_deleted_flag(rec, comp));
3630
3683
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);
3685
prebuilt->n_template)) {
3686
err = DB_TOO_BIG_RECORD;
3646
/* Proceed as in case SEL_RETRY. */
3688
/* We let the main loop to do the
3690
goto shortcut_fails_too_big_rec;
3650
3693
mtr_commit(&mtr);
3698
3741
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
3744
trx_start_if_not_started(trx);
3717
3746
if (trx->isolation_level <= TRX_ISO_READ_COMMITTED
3743
3772
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
3774
if (UNIV_LIKELY(direction != 0)) {
3784
3775
ibool need_to_process = sel_restore_position_for_mysql(
3785
3776
&same_user_rec, BTR_SEARCH_LEAF,
3845
if (!prebuilt->sql_stat_start) {
3846
/* No need to set an intention lock or assign a read view */
3848
if (trx->read_view == NULL
3849
&& prebuilt->select_lock_type == LOCK_NONE) {
3851
fputs("InnoDB: Error: MySQL is trying to"
3852
" perform a consistent read\n"
3853
"InnoDB: but the read view is not assigned!\n",
3855
trx_print(stderr, trx, 600);
3856
fputc('\n', stderr);
3859
} else if (prebuilt->select_lock_type == LOCK_NONE) {
3860
/* This is a consistent read */
3861
/* Assign a read view for the query */
3863
trx_assign_read_view(trx);
3864
prebuilt->sql_stat_start = FALSE;
3867
if (prebuilt->select_lock_type == LOCK_S) {
3868
lock_mode = LOCK_IS;
3870
lock_mode = LOCK_IX;
3872
err = lock_table(0, index->table, lock_mode, thr);
3874
if (err != DB_SUCCESS) {
3876
goto lock_wait_or_error;
3878
prebuilt->sql_stat_start = FALSE;
3859
3882
/*-------------------------------------------------------------*/
3860
3883
/* PHASE 4: Look for matching records in a loop */
4321
if (prebuilt->idx_cond_func)
4324
ut_ad(prebuilt->template_type != ROW_DRIZZLE_DUMMY_TEMPLATE);
4325
offsets = rec_get_offsets(rec, index, offsets, ULINT_UNDEFINED, &heap);
4326
row_sel_store_mysql_rec(buf, prebuilt, rec,
4327
offsets, 0, prebuilt->n_index_fields);
4328
res= prebuilt->idx_cond_func(prebuilt->idx_cond_func_arg);
4333
err = DB_RECORD_NOT_FOUND;
4334
goto idx_cond_failed;
4328
4338
/* Get the clustered index record if needed, if we did not do the
4329
4339
search using the clustered index. */
4331
if (index != clust_index && prebuilt->need_to_access_clustered) {
4341
if (get_clust_rec || (index != clust_index &&
4342
prebuilt->need_to_access_clustered)) {
4334
4344
/* We use a 'goto' to the preceding label if a consistent
4335
4345
read of a secondary index record requires us to look up old
4336
4346
versions of the associated clustered index record. */
4349
4359
err = row_sel_get_clust_rec_for_mysql(prebuilt, index, rec,
4350
4360
thr, &clust_rec,
4351
4361
&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);
4362
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
4364
goto lock_wait_or_error;
4367
if (clust_rec == NULL) {
4368
/* The record did not exist in the read view */
4369
ut_ad(prebuilt->select_lock_type == LOCK_NONE);
4376
4374
if (UNIV_UNLIKELY(rec_get_deleted_flag(clust_rec, comp))) {
4378
4376
/* The record is delete marked: we can skip it */
4380
4378
if ((srv_locks_unsafe_for_binlog
4381
|| trx->isolation_level <= TRX_ISO_READ_COMMITTED)
4379
|| trx->isolation_level == TRX_ISO_READ_COMMITTED)
4382
4380
&& prebuilt->select_lock_type != LOCK_NONE) {
4384
4382
/* No need to keep a lock on a delete-marked
4425
4434
are BLOBs in the fields to be fetched. In HANDLER we do
4426
4435
not cache rows because there the cursor is a scrollable
4437
some_fields_in_buffer= (index != clust_index &&
4438
prebuilt->idx_cond_func);
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) {
4440
row_sel_push_cache_row_for_mysql(prebuilt, result_rec,
4442
some_fields_in_buffer?
4443
prebuilt->n_index_fields: 0,
4445
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,
4452
if (prebuilt->template_type == ROW_MYSQL_DUMMY_TEMPLATE) {
4462
4453
memcpy(buf + 4, result_rec
4463
4454
- rec_offs_extra_size(offsets),
4464
4455
rec_offs_size(offsets));
4465
4456
mach_write_to_4(buf,
4466
4457
rec_offs_extra_size(offsets) + 4);
4468
/* Returning a row to MySQL */
4459
if (!row_sel_store_mysql_rec(buf, prebuilt,
4460
result_rec, offsets,
4461
prebuilt->idx_cond_func?
4462
prebuilt->n_index_fields: 0,
4463
prebuilt->n_template)) {
4464
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);
4466
goto lock_wait_or_error;
4702
/*******************************************************************//**
4684
/***********************************************************************
4703
4685
Checks if MySQL at the moment is allowed for this table to retrieve a
4704
consistent read result, or store it to the query cache.
4705
@return TRUE if storing or retrieving from the query cache is permitted */
4686
consistent read result, or store it to the query cache. */
4708
4689
row_search_check_if_query_cache_permitted(
4709
4690
/*======================================*/
4710
trx_t* trx, /*!< in: transaction object */
4711
const char* norm_name) /*!< in: concatenation of database name,
4691
/* out: TRUE if storing or retrieving
4692
from the query cache is permitted */
4693
trx_t* trx, /* in: transaction object */
4694
const char* norm_name) /* in: concatenation of database name,
4712
4695
'/' char, table name */
4714
4697
dict_table_t* table;
4757
/*******************************************************************//**
4741
/***********************************************************************
4758
4742
Read the AUTOINC column from the current row. If the value is less than
4759
0 and the type is not unsigned then we reset the value to 0.
4760
@return value read from the column */
4743
0 and the type is not unsigned then we reset the value to 0. */
4763
4746
row_search_autoinc_read_column(
4764
4747
/*===========================*/
4765
dict_index_t* index, /*!< in: index to read from */
4766
const rec_t* rec, /*!< in: current rec */
4767
ulint col_no, /*!< in: column number */
4768
ulint mtype, /*!< in: column main type */
4769
ibool unsigned_type) /*!< in: signed or unsigned flag */
4748
/* out: value read from the column */
4749
dict_index_t* index, /* in: index to read from */
4750
const rec_t* rec, /* in: current rec */
4751
ulint col_no, /* in: column number */
4752
ibool unsigned_type) /* in: signed or unsigned flag */
4772
4755
const byte* data;
4782
4765
data = rec_get_nth_field(rec, offsets, col_no, &len);
4784
4767
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);
4768
ut_a(len <= sizeof value);
4770
/* we assume AUTOINC value cannot be negative */
4771
value = mach_read_int_type(data, len, unsigned_type);
4806
4773
if (UNIV_LIKELY_NULL(heap)) {
4807
4774
mem_heap_free(heap);
4817
/*******************************************************************//**
4819
@return current rec or NULL */
4784
/***********************************************************************
4785
Get the last row. */
4822
4788
row_search_autoinc_get_rec(
4823
4789
/*=======================*/
4824
btr_pcur_t* pcur, /*!< in: the current cursor */
4825
mtr_t* mtr) /*!< in: mini transaction */
4790
/* out: current rec or NULL */
4791
btr_pcur_t* pcur, /* in: the current cursor */
4792
mtr_t* mtr) /* in: mini transaction */
4828
4795
const rec_t* rec = btr_pcur_get_rec(pcur);
4838
/*******************************************************************//**
4839
Read the max AUTOINC value from an index.
4840
@return DB_SUCCESS if all OK else error code, DB_RECORD_NOT_FOUND if
4841
column name can't be found in index */
4805
/***********************************************************************
4806
Read the max AUTOINC value from an index. */
4844
4809
row_search_max_autoinc(
4845
4810
/*===================*/
4846
dict_index_t* index, /*!< in: index to search */
4847
const char* col_name, /*!< in: name of autoinc column */
4848
ib_uint64_t* value) /*!< out: AUTOINC value read */
4811
/* out: DB_SUCCESS if all OK else
4812
error code, DB_RECORD_NOT_FOUND if
4813
column name can't be found in index */
4814
dict_index_t* index, /* in: index to search */
4815
const char* col_name, /* in: name of autoinc column */
4816
ib_uint64_t* value) /* out: AUTOINC value read */