75
74
#define SEL_EXHAUSTED 1
76
75
#define SEL_RETRY 2
78
/********************************************************************//**
77
/************************************************************************
79
78
Returns TRUE if the user-defined column in a secondary index record
80
79
is alphabetically the same as the corresponding BLOB column in the clustered
82
81
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 */
82
fields are compared with collation! */
87
85
row_sel_sec_rec_is_for_blob(
88
86
/*========================*/
89
ulint mtype, /*!< in: main type */
90
ulint prtype, /*!< in: precise type */
91
ulint mbminlen, /*!< in: minimum length of a
92
multi-byte character */
93
ulint mbmaxlen, /*!< in: maximum length of a
94
multi-byte character */
95
const byte* clust_field, /*!< in: the locally stored part of
87
/* out: TRUE if the columns
89
ulint mtype, /* in: main type */
90
ulint prtype, /* in: precise type */
91
ulint mbminlen, /* in: minimum length of a
92
multi-byte character */
93
ulint mbmaxlen, /* in: maximum length of a
94
multi-byte character */
95
const byte* clust_field, /* in: the locally stored part of
96
96
the clustered index column, including
97
97
the BLOB pointer; the clustered
98
98
index record must be covered by
99
99
a lock or a page latch to protect it
100
100
against deletion (rollback or purge) */
101
ulint clust_len, /*!< in: length of clust_field */
102
const byte* sec_field, /*!< in: column in secondary index */
103
ulint sec_len, /*!< in: length of sec_field */
104
ulint zip_size) /*!< in: compressed page size, or 0 */
101
ulint clust_len, /* in: length of clust_field */
102
const byte* sec_field, /* in: column in secondary index */
103
ulint sec_len, /* in: length of sec_field */
104
ulint zip_size) /* in: compressed page size, or 0 */
107
107
byte buf[DICT_MAX_INDEX_COL_LEN];
125
125
return(!cmp_data_data(mtype, prtype, buf, len, sec_field, sec_len));
128
/********************************************************************//**
128
/************************************************************************
129
129
Returns TRUE if the user-defined column values in a secondary index record
130
130
are alphabetically the same as the corresponding columns in the clustered
132
132
NOTE: the comparison is NOT done as a binary comparison, but character
133
fields are compared with collation!
134
@return TRUE if the secondary record is equal to the corresponding
135
fields in the clustered record, when compared with collation */
133
fields are compared with collation! */
138
136
row_sel_sec_rec_is_for_clust_rec(
139
137
/*=============================*/
140
const rec_t* sec_rec, /*!< in: secondary index record */
141
dict_index_t* sec_index, /*!< in: secondary index */
142
const rec_t* clust_rec, /*!< in: clustered index record;
138
/* out: TRUE if the secondary
139
record is equal to the corresponding
140
fields in the clustered record,
141
when compared with collation */
142
const rec_t* sec_rec, /* in: secondary index record */
143
dict_index_t* sec_index, /* in: secondary index */
144
const rec_t* clust_rec, /* in: clustered index record;
143
145
must be protected by a lock or
144
146
a page latch against deletion
145
147
in rollback or purge */
146
dict_index_t* clust_index) /*!< in: clustered index */
148
dict_index_t* clust_index) /* in: clustered index */
148
150
const byte* sec_field;
236
238
return(is_equal);
239
/*********************************************************************//**
240
Creates a select node struct.
241
@return own: select node struct */
241
/*************************************************************************
242
Creates a select node struct. */
246
mem_heap_t* heap) /*!< in: memory heap where created */
247
/* out, own: select node struct */
248
mem_heap_t* heap) /* in: memory heap where created */
248
250
sel_node_t* node;
305
/*********************************************************************//**
307
/*************************************************************************
306
308
Assigns the values in the select list to the possible into-variables in
307
309
SELECT ... INTO ... */
310
312
sel_assign_into_var_values(
311
313
/*=======================*/
312
sym_node_t* var, /*!< in: first variable in a list of variables */
313
sel_node_t* node) /*!< in: select node */
314
sym_node_t* var, /* in: first variable in a list of variables */
315
sel_node_t* node) /* in: select node */
334
/*********************************************************************//**
336
/*************************************************************************
335
337
Resets the aggregate value totals in the select list of an aggregate type
339
341
sel_reset_aggregate_vals(
340
342
/*=====================*/
341
sel_node_t* node) /*!< in: select node */
343
sel_node_t* node) /* in: select node */
343
345
func_node_t* func_node;
355
357
node->aggregate_already_fetched = FALSE;
358
/*********************************************************************//**
360
/*************************************************************************
359
361
Copies the input variable values when an explicit cursor is opened. */
362
364
row_sel_copy_input_variable_vals(
363
365
/*=============================*/
364
sel_node_t* node) /*!< in: select node */
366
sel_node_t* node) /* in: select node */
379
/*********************************************************************//**
381
/*************************************************************************
380
382
Fetches the column values from a record. */
383
385
row_sel_fetch_columns(
384
386
/*==================*/
385
dict_index_t* index, /*!< in: record index */
386
const rec_t* rec, /*!< in: record in a clustered or non-clustered
387
dict_index_t* index, /* in: record index */
388
const rec_t* rec, /* in: record in a clustered or non-clustered
387
389
index; must be protected by a page latch */
388
const ulint* offsets,/*!< in: rec_get_offsets(rec, index) */
389
sym_node_t* column) /*!< in: first column in a column list, or
390
const ulint* offsets,/* in: rec_get_offsets(rec, index) */
391
sym_node_t* column) /* in: first column in a column list, or
458
/*********************************************************************//**
460
/*************************************************************************
459
461
Allocates a prefetch buffer for a column when prefetch is first time done. */
462
464
sel_col_prefetch_buf_alloc(
463
465
/*=======================*/
464
sym_node_t* column) /*!< in: symbol table node for a column */
466
sym_node_t* column) /* in: symbol table node for a column */
466
468
sel_buf_t* sel_buf;
482
/*********************************************************************//**
484
/*************************************************************************
483
485
Frees a prefetch buffer for a column, including the dynamically allocated
484
486
memory for data stored there. */
487
489
sel_col_prefetch_buf_free(
488
490
/*======================*/
489
sel_buf_t* prefetch_buf) /*!< in, own: prefetch buffer */
491
sel_buf_t* prefetch_buf) /* in, own: prefetch buffer */
491
493
sel_buf_t* sel_buf;
563
565
plan->first_prefetched++;
566
/*********************************************************************//**
568
/*************************************************************************
567
569
Pushes the column values for a prefetched, cached row to the column prefetch
568
570
buffers from the val fields in the column nodes. */
571
573
sel_push_prefetched_row(
572
574
/*====================*/
573
plan_t* plan) /*!< in: plan node for a table */
575
plan_t* plan) /* in: plan node for a table */
575
577
sym_node_t* column;
576
578
sel_buf_t* sel_buf;
638
/*********************************************************************//**
639
Builds a previous version of a clustered index record for a consistent read
640
@return DB_SUCCESS or error code */
640
/*************************************************************************
641
Builds a previous version of a clustered index record for a consistent read */
643
644
row_sel_build_prev_vers(
644
645
/*====================*/
645
read_view_t* read_view, /*!< in: read view */
646
dict_index_t* index, /*!< in: plan node for table */
647
rec_t* rec, /*!< in: record in a clustered index */
648
ulint** offsets, /*!< in/out: offsets returned by
646
/* out: DB_SUCCESS or error code */
647
read_view_t* read_view, /* in: read view */
648
dict_index_t* index, /* in: plan node for table */
649
rec_t* rec, /* in: record in a clustered index */
650
ulint** offsets, /* in/out: offsets returned by
649
651
rec_get_offsets(rec, plan->index) */
650
mem_heap_t** offset_heap, /*!< in/out: memory heap from which
652
mem_heap_t** offset_heap, /* in/out: memory heap from which
651
653
the offsets are allocated */
652
mem_heap_t** old_vers_heap, /*!< out: old version heap to use */
653
rec_t** old_vers, /*!< out: old version, or NULL if the
654
mem_heap_t** old_vers_heap, /* out: old version heap to use */
655
rec_t** old_vers, /* out: old version, or NULL if the
654
656
record does not exist in the view:
655
657
i.e., it was freshly inserted
657
mtr_t* mtr) /*!< in: mtr */
659
mtr_t* mtr) /* in: mtr */
673
/*********************************************************************//**
675
/*************************************************************************
674
676
Builds the last committed version of a clustered index record for a
675
semi-consistent read.
676
@return DB_SUCCESS or error code */
677
semi-consistent read. */
679
680
row_sel_build_committed_vers_for_mysql(
680
681
/*===================================*/
681
dict_index_t* clust_index, /*!< in: clustered index */
682
row_prebuilt_t* prebuilt, /*!< in: prebuilt struct */
683
const rec_t* rec, /*!< in: record in a clustered index */
684
ulint** offsets, /*!< in/out: offsets returned by
682
/* out: DB_SUCCESS or error code */
683
dict_index_t* clust_index, /* in: clustered index */
684
row_prebuilt_t* prebuilt, /* in: prebuilt struct */
685
const rec_t* rec, /* in: record in a clustered index */
686
ulint** offsets, /* in/out: offsets returned by
685
687
rec_get_offsets(rec, clust_index) */
686
mem_heap_t** offset_heap, /*!< in/out: memory heap from which
688
mem_heap_t** offset_heap, /* in/out: memory heap from which
687
689
the offsets are allocated */
688
const rec_t** old_vers, /*!< out: old version, or NULL if the
690
const rec_t** old_vers, /* out: old version, or NULL if the
689
691
record does not exist in the view:
690
692
i.e., it was freshly inserted
692
mtr_t* mtr) /*!< in: mtr */
694
mtr_t* mtr) /* in: mtr */
708
/*********************************************************************//**
710
/*************************************************************************
709
711
Tests the conditions which determine when the index segment we are searching
710
through has been exhausted.
711
@return TRUE if row passed the tests */
712
through has been exhausted. */
714
715
row_sel_test_end_conds(
715
716
/*===================*/
716
plan_t* plan) /*!< in: plan for the table; the column values must
717
/* out: TRUE if row passed the tests */
718
plan_t* plan) /* in: plan for the table; the column values must
717
719
already have been retrieved and the right sides of
718
720
comparisons evaluated */
746
/*********************************************************************//**
747
Tests the other conditions.
748
@return TRUE if row passed the tests */
748
/*************************************************************************
749
Tests the other conditions. */
751
752
row_sel_test_other_conds(
752
753
/*=====================*/
753
plan_t* plan) /*!< in: plan for the table; the column values must
754
/* out: TRUE if row passed the tests */
755
plan_t* plan) /* in: plan for the table; the column values must
754
756
already have been retrieved */
756
758
func_node_t* cond;
774
/*********************************************************************//**
776
/*************************************************************************
775
777
Retrieves the clustered index record corresponding to a record in a
776
non-clustered index. Does the necessary locking.
777
@return DB_SUCCESS or error code */
778
non-clustered index. Does the necessary locking. */
780
781
row_sel_get_clust_rec(
781
782
/*==================*/
782
sel_node_t* node, /*!< in: select_node */
783
plan_t* plan, /*!< in: plan node for table */
784
rec_t* rec, /*!< in: record in a non-clustered index */
785
que_thr_t* thr, /*!< in: query thread */
786
rec_t** out_rec,/*!< out: clustered record or an old version of
783
/* out: DB_SUCCESS or error code */
784
sel_node_t* node, /* in: select_node */
785
plan_t* plan, /* in: plan node for table */
786
rec_t* rec, /* in: record in a non-clustered index */
787
que_thr_t* thr, /* in: query thread */
788
rec_t** out_rec,/* out: clustered record or an old version of
787
789
it, NULL if the old version did not exist
788
790
in the read view, i.e., it was a fresh
789
791
inserted version */
790
mtr_t* mtr) /*!< in: mtr used to get access to the
792
mtr_t* mtr) /* in: mtr used to get access to the
791
793
non-clustered record; the same mtr is used to
792
794
access the clustered index */
938
/*********************************************************************//**
939
Sets a lock on a record.
940
@return DB_SUCCESS or error code */
940
/*************************************************************************
941
Sets a lock on a record. */
943
944
sel_set_rec_lock(
944
945
/*=============*/
945
const buf_block_t* block, /*!< in: buffer block of rec */
946
const rec_t* rec, /*!< in: record */
947
dict_index_t* index, /*!< in: index */
948
const ulint* offsets,/*!< in: rec_get_offsets(rec, index) */
949
ulint mode, /*!< in: lock mode */
950
ulint type, /*!< in: LOCK_ORDINARY, LOCK_GAP, or
946
/* out: DB_SUCCESS or error code */
947
const buf_block_t* block, /* in: buffer block of rec */
948
const rec_t* rec, /* in: record */
949
dict_index_t* index, /* in: index */
950
const ulint* offsets,/* in: rec_get_offsets(rec, index) */
951
ulint mode, /* in: lock mode */
952
ulint type, /* in: LOCK_ORDINARY, LOCK_GAP, or
951
953
LOC_REC_NOT_GAP */
952
que_thr_t* thr) /*!< in: query thread */
954
que_thr_t* thr) /* in: query thread */
977
/*********************************************************************//**
979
/*************************************************************************
978
980
Opens a pcur to a table index. */
981
983
row_sel_open_pcur(
982
984
/*==============*/
983
plan_t* plan, /*!< in: table plan */
985
plan_t* plan, /* in: table plan */
984
986
ibool search_latch_locked,
985
/*!< in: TRUE if the thread currently
987
/* in: TRUE if the thread currently
986
988
has the search latch locked in
988
mtr_t* mtr) /*!< in: mtr */
990
mtr_t* mtr) /* in: mtr */
990
992
dict_index_t* index;
991
993
func_node_t* cond;
1049
1051
plan->pcur_is_open = TRUE;
1052
/*********************************************************************//**
1053
Restores a stored pcur position to a table index.
1054
@return TRUE if the cursor should be moved to the next record after we
1055
return from this function (moved to the previous, in the case of a
1056
descending cursor) without processing again the current cursor
1054
/*************************************************************************
1055
Restores a stored pcur position to a table index. */
1060
1058
row_sel_restore_pcur_pos(
1061
1059
/*=====================*/
1062
plan_t* plan, /*!< in: table plan */
1063
mtr_t* mtr) /*!< in: mtr */
1060
/* out: TRUE if the cursor should be moved to
1061
the next record after we return from this
1062
function (moved to the previous, in the case
1063
of a descending cursor) without processing
1064
again the current cursor record */
1065
plan_t* plan, /* in: table plan */
1066
mtr_t* mtr) /* in: mtr */
1065
1068
ibool equal_position;
1066
1069
ulint relative_position;
1158
1161
plan->n_rows_prefetched = 0;
1161
/*********************************************************************//**
1164
/*************************************************************************
1162
1165
Tries to do a shortcut to fetch a clustered index record with a unique key,
1163
using the hash index if possible (not always).
1164
@return SEL_FOUND, SEL_EXHAUSTED, SEL_RETRY */
1166
using the hash index if possible (not always). */
1167
1169
row_sel_try_search_shortcut(
1168
1170
/*========================*/
1169
sel_node_t* node, /*!< in: select node for a consistent read */
1170
plan_t* plan, /*!< in: plan for a unique search in clustered
1171
/* out: SEL_FOUND, SEL_EXHAUSTED, SEL_RETRY */
1172
sel_node_t* node, /* in: select node for a consistent read */
1173
plan_t* plan, /* in: plan for a unique search in clustered
1172
mtr_t* mtr) /*!< in: mtr */
1175
mtr_t* mtr) /* in: mtr */
1174
1177
dict_index_t* index;
1263
/*********************************************************************//**
1264
Performs a select step.
1265
@return DB_SUCCESS or error code */
1266
/*************************************************************************
1267
Performs a select step. */
1270
sel_node_t* node, /*!< in: select node */
1271
que_thr_t* thr) /*!< in: query thread */
1272
/* out: DB_SUCCESS or error code */
1273
sel_node_t* node, /* in: select node */
1274
que_thr_t* thr) /* in: query thread */
1273
1276
dict_index_t* index;
1964
/**********************************************************************//**
1968
/**************************************************************************
1965
1969
Performs a select step. This is a high-level function used in SQL execution
1967
@return query thread to run next or NULL */
1972
que_thr_t* thr) /*!< in: query thread */
1975
/* out: query thread to run next or NULL */
1976
que_thr_t* thr) /* in: query thread */
1974
1978
ulint i_lock_mode;
1975
1979
sym_node_t* table_node;
2066
/**********************************************************************//**
2067
Performs a fetch for a cursor.
2068
@return query thread to run next or NULL */
2070
/**************************************************************************
2071
Performs a fetch for a cursor. */
2073
que_thr_t* thr) /*!< in: query thread */
2076
/* out: query thread to run next or NULL */
2077
que_thr_t* thr) /* in: query thread */
2075
2079
sel_node_t* sel_node;
2076
2080
fetch_node_t* node;
2129
/****************************************************************//**
2130
Sample callback function for fetch that prints each row.
2131
@return always returns non-NULL */
2133
/********************************************************************
2134
Sample callback function for fetch that prints each row.*/
2134
2137
row_fetch_print(
2135
2138
/*============*/
2136
void* row, /*!< in: sel_node_t* */
2137
void* user_arg) /*!< in: not used */
2139
/* out: always returns non-NULL */
2140
void* row, /* in: sel_node_t* */
2141
void* user_arg) /* in: not used */
2139
2143
sel_node_t* node = row;
2140
2144
que_node_t* exp;
2170
2174
return((void*)42);
2173
/****************************************************************//**
2177
/********************************************************************
2174
2178
Callback function for fetch that stores an unsigned 4 byte integer to the
2175
2179
location pointed. The column's type must be DATA_INT, DATA_UNSIGNED, length
2177
@return always returns NULL */
2180
2183
row_fetch_store_uint4(
2181
2184
/*==================*/
2182
void* row, /*!< in: sel_node_t* */
2183
void* user_arg) /*!< in: data pointer */
2185
/* out: always returns NULL */
2186
void* row, /* in: sel_node_t* */
2187
void* user_arg) /* in: data pointer */
2185
2189
sel_node_t* node = row;
2186
2190
ib_uint32_t* val = user_arg;
2203
/***********************************************************//**
2204
Prints a row in a select result.
2205
@return query thread to run next or NULL */
2207
/***************************************************************
2208
Prints a row in a select result. */
2208
2211
row_printf_step(
2209
2212
/*============*/
2210
que_thr_t* thr) /*!< in: query thread */
2213
/* out: query thread to run next or NULL */
2214
que_thr_t* thr) /* in: query thread */
2212
2216
row_printf_node_t* node;
2213
2217
sel_node_t* sel_node;
2275
2279
row_sel_convert_mysql_key_to_innobase(
2276
2280
/*==================================*/
2277
dtuple_t* tuple, /*!< in/out: tuple where to build;
2281
dtuple_t* tuple, /* in/out: tuple where to build;
2278
2282
NOTE: we assume that the type info
2279
2283
in the tuple is already according
2281
byte* buf, /*!< in: buffer to use in field
2285
byte* buf, /* in: buffer to use in field
2283
ulint buf_len, /*!< in: buffer length */
2284
dict_index_t* index, /*!< in: index of the key value */
2285
const byte* key_ptr, /*!< in: MySQL key value */
2286
ulint key_len, /*!< in: MySQL key value length */
2287
trx_t* trx) /*!< in: transaction */
2287
ulint buf_len, /* in: buffer length */
2288
dict_index_t* index, /* in: index of the key value */
2289
const byte* key_ptr, /* in: MySQL key value */
2290
ulint key_len, /* in: MySQL key value length */
2291
trx_t* trx) /* in: transaction */
2289
2293
byte* original_buf = buf;
2290
2294
const byte* original_key_ptr = key_ptr;
2467
2471
dtuple_set_n_fields(tuple, n_fields);
2470
/**************************************************************//**
2474
/******************************************************************
2471
2475
Stores the row id to the prebuilt struct. */
2474
2478
row_sel_store_row_id_to_prebuilt(
2475
2479
/*=============================*/
2476
row_prebuilt_t* prebuilt, /*!< in/out: prebuilt */
2477
const rec_t* index_rec, /*!< in: record */
2478
const dict_index_t* index, /*!< in: index of the record */
2479
const ulint* offsets) /*!< in: rec_get_offsets
2480
row_prebuilt_t* prebuilt, /* in/out: prebuilt */
2481
const rec_t* index_rec, /* in: record */
2482
const dict_index_t* index, /* in: index of the record */
2483
const ulint* offsets) /* in: rec_get_offsets
2480
2484
(index_rec, index) */
2482
2486
const byte* data;
2505
2509
ut_memcpy(prebuilt->row_id, data, len);
2508
/**************************************************************//**
2512
/******************************************************************
2509
2513
Stores a non-SQL-NULL field in the MySQL format. The counterpart of this
2510
2514
function is row_mysql_store_col_in_innobase_format() in row0mysql.c. */
2513
2517
row_sel_field_store_in_mysql_format(
2514
2518
/*================================*/
2515
byte* dest, /*!< in/out: buffer where to store; NOTE
2519
byte* dest, /* in/out: buffer where to store; NOTE
2516
2520
that BLOBs are not in themselves
2517
2521
stored here: the caller must allocate
2518
2522
and copy the BLOB into buffer before,
2519
2523
and pass the pointer to the BLOB in
2521
2525
const mysql_row_templ_t* templ,
2522
/*!< in: MySQL column template.
2526
/* in: MySQL column template.
2523
2527
Its following fields are referenced:
2524
2528
type, is_unsigned, mysql_col_len,
2525
2529
mbminlen, mbmaxlen */
2526
const byte* data, /*!< in: data to store */
2527
ulint len) /*!< in: length of the data */
2530
const byte* data, /* in: data to store */
2531
ulint len) /* in: length of the data */
2530
2534
byte* field_end;
2663
/**************************************************************//**
2667
/******************************************************************
2664
2668
Convert a row in the Innobase format to a row in the MySQL format.
2665
2669
Note that the template in prebuilt may advise us to copy only a few
2666
2670
columns to mysql_rec, other columns are left blank. All columns may not
2667
be needed in the query.
2668
@return TRUE if success, FALSE if could not allocate memory for a BLOB
2669
(though we may also assert in that case) */
2671
be needed in the query. */
2672
2674
row_sel_store_mysql_rec(
2673
2675
/*====================*/
2674
byte* mysql_rec, /*!< out: row in the MySQL format */
2675
row_prebuilt_t* prebuilt, /*!< in: prebuilt struct */
2676
const rec_t* rec, /*!< in: Innobase record in the index
2676
/* out: TRUE if success, FALSE if
2677
could not allocate memory for a BLOB
2678
(though we may also assert in that
2680
byte* mysql_rec, /* out: row in the MySQL format */
2681
row_prebuilt_t* prebuilt, /* in: prebuilt struct */
2682
const rec_t* rec, /* in: Innobase record in the index
2677
2683
which was described in prebuilt's
2678
2684
template; must be protected by
2679
2685
a page latch */
2680
const ulint* offsets) /*!< in: array returned by
2686
const ulint* offsets, /* in: array returned by
2681
2687
rec_get_offsets() */
2688
ulint start_field_no,
2683
2691
mysql_row_templ_t* templ;
2684
2692
mem_heap_t* extern_field_heap = NULL;
2782
2791
mysql_rec[templ->mysql_null_byte_offset]
2783
2792
|= (byte) templ->mysql_null_bit_mask;
2784
2793
memcpy(mysql_rec + templ->mysql_col_offset,
2785
(const byte*) prebuilt->default_rec
2786
+ templ->mysql_col_offset,
2794
prebuilt->default_rec + templ->mysql_col_offset,
2787
2795
templ->mysql_col_len);
2794
/*********************************************************************//**
2795
Builds a previous version of a clustered index record for a consistent read
2796
@return DB_SUCCESS or error code */
2802
/*************************************************************************
2803
Builds a previous version of a clustered index record for a consistent read */
2799
2806
row_sel_build_prev_vers_for_mysql(
2800
2807
/*==============================*/
2801
read_view_t* read_view, /*!< in: read view */
2802
dict_index_t* clust_index, /*!< in: clustered index */
2803
row_prebuilt_t* prebuilt, /*!< in: prebuilt struct */
2804
const rec_t* rec, /*!< in: record in a clustered index */
2805
ulint** offsets, /*!< in/out: offsets returned by
2808
/* out: DB_SUCCESS or error code */
2809
read_view_t* read_view, /* in: read view */
2810
dict_index_t* clust_index, /* in: clustered index */
2811
row_prebuilt_t* prebuilt, /* in: prebuilt struct */
2812
const rec_t* rec, /* in: record in a clustered index */
2813
ulint** offsets, /* in/out: offsets returned by
2806
2814
rec_get_offsets(rec, clust_index) */
2807
mem_heap_t** offset_heap, /*!< in/out: memory heap from which
2815
mem_heap_t** offset_heap, /* in/out: memory heap from which
2808
2816
the offsets are allocated */
2809
rec_t** old_vers, /*!< out: old version, or NULL if the
2817
rec_t** old_vers, /* out: old version, or NULL if the
2810
2818
record does not exist in the view:
2811
2819
i.e., it was freshly inserted
2813
mtr_t* mtr) /*!< in: mtr */
2821
mtr_t* mtr) /* in: mtr */
2829
/*********************************************************************//**
2837
/*************************************************************************
2830
2838
Retrieves the clustered index record corresponding to a record in a
2831
2839
non-clustered index. Does the necessary locking. Used in the MySQL
2833
@return DB_SUCCESS or error code */
2836
2843
row_sel_get_clust_rec_for_mysql(
2837
2844
/*============================*/
2838
row_prebuilt_t* prebuilt,/*!< in: prebuilt struct in the handle */
2839
dict_index_t* sec_index,/*!< in: secondary index where rec resides */
2840
const rec_t* rec, /*!< in: record in a non-clustered index; if
2845
/* out: DB_SUCCESS or error code */
2846
row_prebuilt_t* prebuilt,/* in: prebuilt struct in the handle */
2847
dict_index_t* sec_index,/* in: secondary index where rec resides */
2848
const rec_t* rec, /* in: record in a non-clustered index; if
2841
2849
this is a locking read, then rec is not
2842
2850
allowed to be delete-marked, and that would
2843
2851
not make sense either */
2844
que_thr_t* thr, /*!< in: query thread */
2845
const rec_t** out_rec,/*!< out: clustered record or an old version of
2852
que_thr_t* thr, /* in: query thread */
2853
const rec_t** out_rec,/* out: clustered record or an old version of
2846
2854
it, NULL if the old version did not exist
2847
2855
in the read view, i.e., it was a fresh
2848
2856
inserted version */
2849
ulint** offsets,/*!< in: offsets returned by
2857
ulint** offsets,/* in: offsets returned by
2850
2858
rec_get_offsets(rec, sec_index);
2851
2859
out: offsets returned by
2852
2860
rec_get_offsets(out_rec, clust_index) */
2853
mem_heap_t** offset_heap,/*!< in/out: memory heap from which
2861
mem_heap_t** offset_heap,/* in/out: memory heap from which
2854
2862
the offsets are allocated */
2855
mtr_t* mtr) /*!< in: mtr used to get access to the
2863
mtr_t* mtr) /* in: mtr used to get access to the
2856
2864
non-clustered record; the same mtr is used to
2857
2865
access the clustered index */
3013
/********************************************************************//**
3020
/************************************************************************
3014
3021
Restores cursor position after it has been stored. We have to take into
3015
3022
account that the record cursor was positioned on may have been deleted.
3016
Then we may have to move the cursor one step up or down.
3017
@return TRUE if we may need to process the record the cursor is now
3018
positioned on (i.e. we should not go to the next record yet) */
3023
Then we may have to move the cursor one step up or down. */
3021
3026
sel_restore_position_for_mysql(
3022
3027
/*===========================*/
3023
ibool* same_user_rec, /*!< out: TRUE if we were able to restore
3028
/* out: TRUE if we may need to
3029
process the record the cursor is
3030
now positioned on (i.e. we should
3031
not go to the next record yet) */
3032
ibool* same_user_rec, /* out: TRUE if we were able to restore
3024
3033
the cursor on a user record with the
3025
3034
same ordering prefix in in the
3026
3035
B-tree index */
3027
ulint latch_mode, /*!< in: latch mode wished in
3036
ulint latch_mode, /* in: latch mode wished in
3029
btr_pcur_t* pcur, /*!< in: cursor whose position
3038
btr_pcur_t* pcur, /* in: cursor whose position
3030
3039
has been stored */
3031
ibool moves_up, /*!< in: TRUE if the cursor moves up
3040
ibool moves_up, /* in: TRUE if the cursor moves up
3032
3041
in the index */
3033
mtr_t* mtr) /*!< in: mtr; CAUTION: may commit
3042
mtr_t* mtr) /* in: mtr; CAUTION: may commit
3034
3043
mtr temporarily! */
3081
/********************************************************************//**
3090
/************************************************************************
3082
3091
Pops a cached row for MySQL from the fetch cache. */
3085
3094
row_sel_pop_cached_row_for_mysql(
3086
3095
/*=============================*/
3087
byte* buf, /*!< in/out: buffer where to copy the
3096
byte* buf, /* in/out: buffer where to copy the
3089
row_prebuilt_t* prebuilt) /*!< in: prebuilt struct */
3098
row_prebuilt_t* prebuilt) /* in: prebuilt struct */
3092
3101
mysql_row_templ_t* templ;
3131
/********************************************************************//**
3140
/************************************************************************
3132
3141
Pushes a row for MySQL to the fetch cache. */
3135
3144
row_sel_push_cache_row_for_mysql(
3136
3145
/*=============================*/
3137
row_prebuilt_t* prebuilt, /*!< in: prebuilt struct */
3138
const rec_t* rec, /*!< in: record to push; must
3146
row_prebuilt_t* prebuilt, /* in: prebuilt struct */
3147
const rec_t* rec, /* in: record to push; must
3139
3148
be protected by a page latch */
3140
const ulint* offsets) /*!<in: rec_get_offsets() */
3149
const ulint* offsets, /* in: rec_get_offsets() */
3150
ulint start_field_no, /* psergy: start from this field */
3151
byte* remainder_buf) /* if above !=0 -> where to take
3170
3182
if (UNIV_UNLIKELY(!row_sel_store_mysql_rec(
3171
3183
prebuilt->fetch_cache[
3172
3184
prebuilt->n_fetch_cached],
3173
prebuilt, rec, offsets))) {
3185
prebuilt, rec, offsets, start_field_no,
3186
prebuilt->n_template))) {
3190
if (start_field_no) {
3191
for (i=0; i < start_field_no; i++) {
3192
register ulint offs;
3193
mysql_row_templ_t* templ;
3194
templ = prebuilt->mysql_template + i;
3196
if (templ->mysql_null_bit_mask) {
3197
offs= templ->mysql_null_byte_offset;
3198
if (*(remainder_buf + offs) & templ->mysql_null_bit_mask)
3199
*(prebuilt->fetch_cache[prebuilt->n_fetch_cached] + offs) |=
3200
/* (*(remainder_buf + offs) &*/( templ->mysql_null_bit_mask);
3202
*(prebuilt->fetch_cache[prebuilt->n_fetch_cached] + offs) &=
3203
~templ->mysql_null_bit_mask;
3206
offs= templ->mysql_col_offset;
3207
memcpy(prebuilt->fetch_cache[prebuilt->n_fetch_cached] + offs,
3208
remainder_buf + offs,
3209
templ->mysql_col_len);
3177
3214
prebuilt->n_fetch_cached++;
3180
/*********************************************************************//**
3217
/*************************************************************************
3181
3218
Tries to do a shortcut to fetch a clustered index record with a unique key,
3182
3219
using the hash index if possible (not always). We assume that the search
3183
3220
mode is PAGE_CUR_GE, it is a consistent read, there is a read view in trx,
3184
btr search latch has been locked in S-mode.
3185
@return SEL_FOUND, SEL_EXHAUSTED, SEL_RETRY */
3221
btr search latch has been locked in S-mode. */
3188
3224
row_sel_try_search_shortcut_for_mysql(
3189
3225
/*==================================*/
3190
const rec_t** out_rec,/*!< out: record if found */
3191
row_prebuilt_t* prebuilt,/*!< in: prebuilt struct */
3192
ulint** offsets,/*!< in/out: for rec_get_offsets(*out_rec) */
3193
mem_heap_t** heap, /*!< in/out: heap for rec_get_offsets() */
3194
mtr_t* mtr) /*!< in: started mtr */
3226
/* out: SEL_FOUND, SEL_EXHAUSTED, SEL_RETRY */
3227
const rec_t** out_rec,/* out: record if found */
3228
row_prebuilt_t* prebuilt,/* in: prebuilt struct */
3229
ulint** offsets,/* in/out: for rec_get_offsets(*out_rec) */
3230
mem_heap_t** heap, /* in/out: heap for rec_get_offsets() */
3231
mtr_t* mtr) /* in: started mtr */
3196
3233
dict_index_t* index = prebuilt->index;
3197
3234
const dtuple_t* search_tuple = prebuilt->search_tuple;
3248
3285
return(SEL_FOUND);
3251
/********************************************************************//**
3288
/************************************************************************
3252
3289
Searches for rows in the database. This is used in the interface to
3253
3290
MySQL. This function opens a cursor, and also implements fetch next
3254
3291
and fetch prev. NOTE that if we do a search with a full key value
3255
3292
from a unique index (ROW_SEL_EXACT), then we will not store the cursor
3256
position and fetch next or fetch prev must not be tried to the cursor!
3257
@return DB_SUCCESS, DB_RECORD_NOT_FOUND, DB_END_OF_INDEX, DB_DEADLOCK,
3258
DB_LOCK_TABLE_FULL, DB_CORRUPTION, or DB_TOO_BIG_RECORD */
3293
position and fetch next or fetch prev must not be tried to the cursor! */
3261
3296
row_search_for_mysql(
3262
3297
/*=================*/
3263
byte* buf, /*!< in/out: buffer for the fetched
3299
DB_RECORD_NOT_FOUND,
3300
DB_END_OF_INDEX, DB_DEADLOCK,
3301
DB_LOCK_TABLE_FULL, DB_CORRUPTION,
3302
or DB_TOO_BIG_RECORD */
3303
byte* buf, /* in/out: buffer for the fetched
3264
3304
row in the MySQL format */
3265
ulint mode, /*!< in: search mode PAGE_CUR_L, ... */
3266
row_prebuilt_t* prebuilt, /*!< in: prebuilt struct for the
3305
ulint mode, /* in: search mode PAGE_CUR_L, ... */
3306
row_prebuilt_t* prebuilt, /* in: prebuilt struct for the
3267
3307
table handle; this contains the info
3268
3308
of search_tuple, index; if search
3269
3309
tuple contains 0 fields then we
3270
3310
position the cursor at the start or
3271
3311
the end of the index, depending on
3273
ulint match_mode, /*!< in: 0 or ROW_SEL_EXACT or
3313
ulint match_mode, /* in: 0 or ROW_SEL_EXACT or
3274
3314
ROW_SEL_EXACT_PREFIX */
3275
ulint direction) /*!< in: 0 or ROW_SEL_NEXT or
3315
ulint direction) /* in: 0 or ROW_SEL_NEXT or
3276
3316
ROW_SEL_PREV; NOTE: if this is != 0,
3277
3317
then prebuilt must have a pcur
3278
3318
with stored position! In opening of a
3326
3368
"InnoDB: the MySQL datadir, or have you used"
3327
3369
" DISCARD TABLESPACE?\n"
3328
3370
"InnoDB: Look from\n"
3329
"InnoDB: " REFMAN "innodb-troubleshooting.html\n"
3371
"InnoDB: http://dev.mysql.com/doc/refman/5.1/en/"
3372
"innodb-troubleshooting.html\n"
3330
3373
"InnoDB: how you can resolve the problem.\n",
3331
3374
prebuilt->table->name);
3333
3376
return(DB_ERROR);
3336
if (UNIV_UNLIKELY(!prebuilt->index_usable)) {
3338
return(DB_MISSING_HISTORY);
3341
3379
if (UNIV_UNLIKELY(prebuilt->magic_n != ROW_PREBUILT_ALLOCATED)) {
3342
3380
fprintf(stderr,
3343
3381
"InnoDB: Error: trying to free a corrupt\n"
3393
/* August 19, 2005 by Heikki: temporarily disable this error
3394
print until the cursor lock count is done correctly.
3395
See bugs #12263 and #12456!*/
3397
if (trx->n_mysql_tables_in_use == 0
3398
&& UNIV_UNLIKELY(prebuilt->select_lock_type == LOCK_NONE)) {
3399
/* Note that if MySQL uses an InnoDB temp table that it
3400
created inside LOCK TABLES, then n_mysql_tables_in_use can
3401
be zero; in that case select_lock_type is set to LOCK_X in
3404
fputs("InnoDB: Error: MySQL is trying to perform a SELECT\n"
3405
"InnoDB: but it has not locked"
3406
" any tables in ::external_lock()!\n",
3408
trx_print(stderr, trx, 600);
3409
fputc('\n', stderr);
3355
3414
fprintf(stderr, "Match mode %lu\n search tuple ",
3356
3415
(ulong) match_mode);
3357
3416
dtuple_print(search_tuple);
3380
3439
is set or session is using a READ COMMITED isolation level. Then
3381
3440
we are able to remove the record locks set here on an individual
3383
prebuilt->new_rec_locks = 0;
3443
if ((srv_locks_unsafe_for_binlog
3444
|| trx->isolation_level == TRX_ISO_READ_COMMITTED)
3445
&& prebuilt->select_lock_type != LOCK_NONE) {
3447
trx_reset_new_rec_lock_info(trx);
3385
3450
/*-------------------------------------------------------------*/
3386
3451
/* PHASE 1: Try to pop the row from the prefetch cache */
3474
3539
/* Even if the condition is unique, MySQL seems to try to
3475
3540
retrieve also a second row if a primary key contains more than
3541
1 column. Return immediately if this is not a HANDLER
3478
if (UNIV_UNLIKELY(direction != 0)) {
3544
if (UNIV_UNLIKELY(direction != 0
3545
&& !prebuilt->used_in_HANDLER)) {
3480
3547
err = DB_RECORD_NOT_FOUND;
3481
3548
goto func_exit;
4249
if (prebuilt->idx_cond_func)
4252
ut_ad(prebuilt->template_type != ROW_DRIZZLE_DUMMY_TEMPLATE);
4253
offsets = rec_get_offsets(rec, index, offsets, ULINT_UNDEFINED, &heap);
4254
row_sel_store_mysql_rec(buf, prebuilt, rec,
4255
offsets, 0, prebuilt->n_index_fields);
4256
res= prebuilt->idx_cond_func(prebuilt->idx_cond_func_arg);
4261
err = DB_RECORD_NOT_FOUND;
4262
goto idx_cond_failed;
4187
4266
/* Get the clustered index record if needed, if we did not do the
4188
4267
search using the clustered index. */
4190
if (index != clust_index && prebuilt->need_to_access_clustered) {
4269
if (get_clust_rec || (index != clust_index &&
4270
prebuilt->need_to_access_clustered)) {
4193
4272
/* We use a 'goto' to the preceding label if a consistent
4194
4273
read of a secondary index record requires us to look up old
4195
4274
versions of the associated clustered index record. */
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;
4232
4302
if (UNIV_UNLIKELY(rec_get_deleted_flag(clust_rec, comp))) {
4234
4304
/* The record is delete marked: we can skip it */
4291
4362
are BLOBs in the fields to be fetched. In HANDLER we do
4292
4363
not cache rows because there the cursor is a scrollable
4365
some_fields_in_buffer= (index != clust_index &&
4366
prebuilt->idx_cond_func);
4295
4368
row_sel_push_cache_row_for_mysql(prebuilt, result_rec,
4370
some_fields_in_buffer?
4371
prebuilt->n_index_fields: 0,
4297
4373
if (prebuilt->n_fetch_cached == MYSQL_FETCH_CACHE_SIZE) {
4356
4437
prebuilt->row_read_type = ROW_READ_TRY_SEMI_CONSISTENT;
4358
4439
did_semi_consistent_read = FALSE;
4359
prebuilt->new_rec_locks = 0;
4441
if (UNIV_UNLIKELY(srv_locks_unsafe_for_binlog
4442
|| trx->isolation_level == TRX_ISO_READ_COMMITTED)
4443
&& prebuilt->select_lock_type != LOCK_NONE) {
4445
trx_reset_new_rec_lock_info(trx);
4361
4448
/*-------------------------------------------------------------*/
4362
4449
/* PHASE 5: Move the cursor to the next index record */
4525
/*******************************************************************//**
4612
/***********************************************************************
4526
4613
Checks if MySQL at the moment is allowed for this table to retrieve a
4527
consistent read result, or store it to the query cache.
4528
@return TRUE if storing or retrieving from the query cache is permitted */
4614
consistent read result, or store it to the query cache. */
4531
4617
row_search_check_if_query_cache_permitted(
4532
4618
/*======================================*/
4533
trx_t* trx, /*!< in: transaction object */
4534
const char* norm_name) /*!< in: concatenation of database name,
4619
/* out: TRUE if storing or retrieving
4620
from the query cache is permitted */
4621
trx_t* trx, /* in: transaction object */
4622
const char* norm_name) /* in: concatenation of database name,
4535
4623
'/' char, table name */
4537
4625
dict_table_t* table;
4581
/*******************************************************************//**
4669
/***********************************************************************
4582
4670
Read the AUTOINC column from the current row. If the value is less than
4583
0 and the type is not unsigned then we reset the value to 0.
4584
@return value read from the column */
4671
0 and the type is not unsigned then we reset the value to 0. */
4587
4674
row_search_autoinc_read_column(
4588
4675
/*===========================*/
4589
dict_index_t* index, /*!< in: index to read from */
4590
const rec_t* rec, /*!< in: current rec */
4591
ulint col_no, /*!< in: column number */
4592
ibool unsigned_type) /*!< in: signed or unsigned flag */
4676
/* out: value read from the column */
4677
dict_index_t* index, /* in: index to read from */
4678
const rec_t* rec, /* in: current rec */
4679
ulint col_no, /* in: column number */
4680
ibool unsigned_type) /* in: signed or unsigned flag */
4595
4683
const byte* data;
4624
/*******************************************************************//**
4626
@return current rec or NULL */
4712
/***********************************************************************
4713
Get the last row. */
4629
4716
row_search_autoinc_get_rec(
4630
4717
/*=======================*/
4631
btr_pcur_t* pcur, /*!< in: the current cursor */
4632
mtr_t* mtr) /*!< in: mini transaction */
4718
/* out: current rec or NULL */
4719
btr_pcur_t* pcur, /* in: the current cursor */
4720
mtr_t* mtr) /* in: mini transaction */
4635
4723
const rec_t* rec = btr_pcur_get_rec(pcur);
4645
/*******************************************************************//**
4646
Read the max AUTOINC value from an index.
4647
@return DB_SUCCESS if all OK else error code, DB_RECORD_NOT_FOUND if
4648
column name can't be found in index */
4733
/***********************************************************************
4734
Read the max AUTOINC value from an index. */
4651
4737
row_search_max_autoinc(
4652
4738
/*===================*/
4653
dict_index_t* index, /*!< in: index to search */
4654
const char* col_name, /*!< in: name of autoinc column */
4655
ib_uint64_t* value) /*!< out: AUTOINC value read */
4739
/* out: DB_SUCCESS if all OK else
4740
error code, DB_RECORD_NOT_FOUND if
4741
column name can't be found in index */
4742
dict_index_t* index, /* in: index to search */
4743
const char* col_name, /* in: name of autoinc column */
4744
ib_uint64_t* value) /* out: AUTOINC value read */