~drizzle-trunk/drizzle/development

« back to all changes in this revision

Viewing changes to plugin/innobase/row/row0sel.c

  • Committer: Eric Day
  • Date: 2009-10-31 21:53:33 UTC
  • mfrom: (1200 staging)
  • mto: This revision was merged to the branch mainline in revision 1202.
  • Revision ID: eday@oddments.org-20091031215333-j94bjoanwmi68p6f
Merged trunk.

Show diffs side-by-side

added added

removed removed

Lines of Context:
23
23
 
24
24
*****************************************************************************/
25
25
 
26
 
/*******************************************************
 
26
/***************************************************//**
 
27
@file row/row0sel.c
27
28
Select
28
29
 
29
30
Created 12/19/1997 Heikki Tuuri
74
75
#define SEL_EXHAUSTED   1
75
76
#define SEL_RETRY       2
76
77
 
77
 
/************************************************************************
 
78
/********************************************************************//**
78
79
Returns TRUE if the user-defined column in a secondary index record
79
80
is alphabetically the same as the corresponding BLOB column in the clustered
80
81
index record.
81
82
NOTE: the comparison is NOT done as a binary comparison, but character
82
 
fields are compared with collation! */
 
83
fields are compared with collation!
 
84
@return TRUE if the columns are equal */
83
85
static
84
86
ibool
85
87
row_sel_sec_rec_is_for_blob(
86
88
/*========================*/
87
 
                                        /* out: TRUE if the columns
88
 
                                        are equal */
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
 
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 */
105
105
{
106
106
        ulint   len;
107
107
        byte    buf[DICT_MAX_INDEX_COL_LEN];
125
125
        return(!cmp_data_data(mtype, prtype, buf, len, sec_field, sec_len));
126
126
}
127
127
 
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
131
131
index record.
132
132
NOTE: the comparison is NOT done as a binary comparison, but character
133
 
fields are compared with collation! */
 
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 */
134
136
static
135
137
ibool
136
138
row_sel_sec_rec_is_for_clust_rec(
137
139
/*=============================*/
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;
 
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;
145
143
                                        must be protected by a lock or
146
144
                                        a page latch against deletion
147
145
                                        in rollback or purge */
148
 
        dict_index_t*   clust_index)    /* in: clustered index */
 
146
        dict_index_t*   clust_index)    /*!< in: clustered index */
149
147
{
150
148
        const byte*     sec_field;
151
149
        ulint           sec_len;
238
236
        return(is_equal);
239
237
}
240
238
 
241
 
/*************************************************************************
242
 
Creates a select node struct. */
 
239
/*********************************************************************//**
 
240
Creates a select node struct.
 
241
@return own: select node struct */
243
242
UNIV_INTERN
244
243
sel_node_t*
245
244
sel_node_create(
246
245
/*============*/
247
 
                                /* out, own: select node struct */
248
 
        mem_heap_t*     heap)   /* in: memory heap where created */
 
246
        mem_heap_t*     heap)   /*!< in: memory heap where created */
249
247
{
250
248
        sel_node_t*     node;
251
249
 
258
256
        return(node);
259
257
}
260
258
 
261
 
/*************************************************************************
 
259
/*********************************************************************//**
262
260
Frees the memory private to a select node when a query graph is freed,
263
261
does not free the heap where the node was originally created. */
264
262
UNIV_INTERN
265
263
void
266
264
sel_node_free_private(
267
265
/*==================*/
268
 
        sel_node_t*     node)   /* in: select node struct */
 
266
        sel_node_t*     node)   /*!< in: select node struct */
269
267
{
270
268
        ulint   i;
271
269
        plan_t* plan;
284
282
        }
285
283
}
286
284
 
287
 
/*************************************************************************
 
285
/*********************************************************************//**
288
286
Evaluates the values in a select list. If there are aggregate functions,
289
287
their argument value is added to the aggregate total. */
290
288
UNIV_INLINE
291
289
void
292
290
sel_eval_select_list(
293
291
/*=================*/
294
 
        sel_node_t*     node)   /* in: select node */
 
292
        sel_node_t*     node)   /*!< in: select node */
295
293
{
296
294
        que_node_t*     exp;
297
295
 
304
302
        }
305
303
}
306
304
 
307
 
/*************************************************************************
 
305
/*********************************************************************//**
308
306
Assigns the values in the select list to the possible into-variables in
309
307
SELECT ... INTO ... */
310
308
UNIV_INLINE
311
309
void
312
310
sel_assign_into_var_values(
313
311
/*=======================*/
314
 
        sym_node_t*     var,    /* in: first variable in a list of variables */
315
 
        sel_node_t*     node)   /* in: select node */
 
312
        sym_node_t*     var,    /*!< in: first variable in a list of variables */
 
313
        sel_node_t*     node)   /*!< in: select node */
316
314
{
317
315
        que_node_t*     exp;
318
316
 
333
331
        }
334
332
}
335
333
 
336
 
/*************************************************************************
 
334
/*********************************************************************//**
337
335
Resets the aggregate value totals in the select list of an aggregate type
338
336
query. */
339
337
UNIV_INLINE
340
338
void
341
339
sel_reset_aggregate_vals(
342
340
/*=====================*/
343
 
        sel_node_t*     node)   /* in: select node */
 
341
        sel_node_t*     node)   /*!< in: select node */
344
342
{
345
343
        func_node_t*    func_node;
346
344
 
357
355
        node->aggregate_already_fetched = FALSE;
358
356
}
359
357
 
360
 
/*************************************************************************
 
358
/*********************************************************************//**
361
359
Copies the input variable values when an explicit cursor is opened. */
362
360
UNIV_INLINE
363
361
void
364
362
row_sel_copy_input_variable_vals(
365
363
/*=============================*/
366
 
        sel_node_t*     node)   /* in: select node */
 
364
        sel_node_t*     node)   /*!< in: select node */
367
365
{
368
366
        sym_node_t*     var;
369
367
 
378
376
        }
379
377
}
380
378
 
381
 
/*************************************************************************
 
379
/*********************************************************************//**
382
380
Fetches the column values from a record. */
383
381
static
384
382
void
385
383
row_sel_fetch_columns(
386
384
/*==================*/
387
 
        dict_index_t*   index,  /* in: record index */
388
 
        const rec_t*    rec,    /* in: record in a clustered or non-clustered
 
385
        dict_index_t*   index,  /*!< in: record index */
 
386
        const rec_t*    rec,    /*!< in: record in a clustered or non-clustered
389
387
                                index; must be protected by a page latch */
390
 
        const ulint*    offsets,/* in: rec_get_offsets(rec, index) */
391
 
        sym_node_t*     column) /* in: first column in a column list, or
 
388
        const ulint*    offsets,/*!< in: rec_get_offsets(rec, index) */
 
389
        sym_node_t*     column) /*!< in: first column in a column list, or
392
390
                                NULL */
393
391
{
394
392
        dfield_t*       val;
457
455
        }
458
456
}
459
457
 
460
 
/*************************************************************************
 
458
/*********************************************************************//**
461
459
Allocates a prefetch buffer for a column when prefetch is first time done. */
462
460
static
463
461
void
464
462
sel_col_prefetch_buf_alloc(
465
463
/*=======================*/
466
 
        sym_node_t*     column) /* in: symbol table node for a column */
 
464
        sym_node_t*     column) /*!< in: symbol table node for a column */
467
465
{
468
466
        sel_buf_t*      sel_buf;
469
467
        ulint           i;
481
479
        }
482
480
}
483
481
 
484
 
/*************************************************************************
 
482
/*********************************************************************//**
485
483
Frees a prefetch buffer for a column, including the dynamically allocated
486
484
memory for data stored there. */
487
485
UNIV_INTERN
488
486
void
489
487
sel_col_prefetch_buf_free(
490
488
/*======================*/
491
 
        sel_buf_t*      prefetch_buf)   /* in, own: prefetch buffer */
 
489
        sel_buf_t*      prefetch_buf)   /*!< in, own: prefetch buffer */
492
490
{
493
491
        sel_buf_t*      sel_buf;
494
492
        ulint           i;
503
501
        }
504
502
}
505
503
 
506
 
/*************************************************************************
 
504
/*********************************************************************//**
507
505
Pops the column values for a prefetched, cached row from the column prefetch
508
506
buffers and places them to the val fields in the column nodes. */
509
507
static
510
508
void
511
509
sel_pop_prefetched_row(
512
510
/*===================*/
513
 
        plan_t* plan)   /* in: plan node for a table */
 
511
        plan_t* plan)   /*!< in: plan node for a table */
514
512
{
515
513
        sym_node_t*     column;
516
514
        sel_buf_t*      sel_buf;
565
563
        plan->first_prefetched++;
566
564
}
567
565
 
568
 
/*************************************************************************
 
566
/*********************************************************************//**
569
567
Pushes the column values for a prefetched, cached row to the column prefetch
570
568
buffers from the val fields in the column nodes. */
571
569
UNIV_INLINE
572
570
void
573
571
sel_push_prefetched_row(
574
572
/*====================*/
575
 
        plan_t* plan)   /* in: plan node for a table */
 
573
        plan_t* plan)   /*!< in: plan node for a table */
576
574
{
577
575
        sym_node_t*     column;
578
576
        sel_buf_t*      sel_buf;
637
635
        }
638
636
}
639
637
 
640
 
/*************************************************************************
641
 
Builds a previous version of a clustered index record for a consistent read */
 
638
/*********************************************************************//**
 
639
Builds a previous version of a clustered index record for a consistent read
 
640
@return DB_SUCCESS or error code */
642
641
static
643
642
ulint
644
643
row_sel_build_prev_vers(
645
644
/*====================*/
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
 
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
651
649
                                        rec_get_offsets(rec, plan->index) */
652
 
        mem_heap_t**    offset_heap,    /* in/out: memory heap from which
 
650
        mem_heap_t**    offset_heap,    /*!< in/out: memory heap from which
653
651
                                        the offsets are allocated */
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
 
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
656
654
                                        record does not exist in the view:
657
655
                                        i.e., it was freshly inserted
658
656
                                        afterwards */
659
 
        mtr_t*          mtr)            /* in: mtr */
 
657
        mtr_t*          mtr)            /*!< in: mtr */
660
658
{
661
659
        ulint   err;
662
660
 
672
670
        return(err);
673
671
}
674
672
 
675
 
/*************************************************************************
 
673
/*********************************************************************//**
676
674
Builds the last committed version of a clustered index record for a
677
 
semi-consistent read. */
 
675
semi-consistent read.
 
676
@return DB_SUCCESS or error code */
678
677
static
679
678
ulint
680
679
row_sel_build_committed_vers_for_mysql(
681
680
/*===================================*/
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
 
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
687
685
                                        rec_get_offsets(rec, clust_index) */
688
 
        mem_heap_t**    offset_heap,    /* in/out: memory heap from which
 
686
        mem_heap_t**    offset_heap,    /*!< in/out: memory heap from which
689
687
                                        the offsets are allocated */
690
 
        const rec_t**   old_vers,       /* out: old version, or NULL if the
 
688
        const rec_t**   old_vers,       /*!< out: old version, or NULL if the
691
689
                                        record does not exist in the view:
692
690
                                        i.e., it was freshly inserted
693
691
                                        afterwards */
694
 
        mtr_t*          mtr)            /* in: mtr */
 
692
        mtr_t*          mtr)            /*!< in: mtr */
695
693
{
696
694
        ulint   err;
697
695
 
707
705
        return(err);
708
706
}
709
707
 
710
 
/*************************************************************************
 
708
/*********************************************************************//**
711
709
Tests the conditions which determine when the index segment we are searching
712
 
through has been exhausted. */
 
710
through has been exhausted.
 
711
@return TRUE if row passed the tests */
713
712
UNIV_INLINE
714
713
ibool
715
714
row_sel_test_end_conds(
716
715
/*===================*/
717
 
                        /* out: TRUE if row passed the tests */
718
 
        plan_t* plan)   /* in: plan for the table; the column values must
 
716
        plan_t* plan)   /*!< in: plan for the table; the column values must
719
717
                        already have been retrieved and the right sides of
720
718
                        comparisons evaluated */
721
719
{
745
743
        return(TRUE);
746
744
}
747
745
 
748
 
/*************************************************************************
749
 
Tests the other conditions. */
 
746
/*********************************************************************//**
 
747
Tests the other conditions.
 
748
@return TRUE if row passed the tests */
750
749
UNIV_INLINE
751
750
ibool
752
751
row_sel_test_other_conds(
753
752
/*=====================*/
754
 
                        /* out: TRUE if row passed the tests */
755
 
        plan_t* plan)   /* in: plan for the table; the column values must
 
753
        plan_t* plan)   /*!< in: plan for the table; the column values must
756
754
                        already have been retrieved */
757
755
{
758
756
        func_node_t*    cond;
773
771
        return(TRUE);
774
772
}
775
773
 
776
 
/*************************************************************************
 
774
/*********************************************************************//**
777
775
Retrieves the clustered index record corresponding to a record in a
778
 
non-clustered index. Does the necessary locking. */
 
776
non-clustered index. Does the necessary locking.
 
777
@return DB_SUCCESS or error code */
779
778
static
780
779
ulint
781
780
row_sel_get_clust_rec(
782
781
/*==================*/
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
 
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
789
787
                                it, NULL if the old version did not exist
790
788
                                in the read view, i.e., it was a fresh
791
789
                                inserted version */
792
 
        mtr_t*          mtr)    /* in: mtr used to get access to the
 
790
        mtr_t*          mtr)    /*!< in: mtr used to get access to the
793
791
                                non-clustered record; the same mtr is used to
794
792
                                access the clustered index */
795
793
{
937
935
        return(err);
938
936
}
939
937
 
940
 
/*************************************************************************
941
 
Sets a lock on a record. */
 
938
/*********************************************************************//**
 
939
Sets a lock on a record.
 
940
@return DB_SUCCESS or error code */
942
941
UNIV_INLINE
943
942
ulint
944
943
sel_set_rec_lock(
945
944
/*=============*/
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
 
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
953
951
                                        LOC_REC_NOT_GAP */
954
 
        que_thr_t*              thr)    /* in: query thread */
 
952
        que_thr_t*              thr)    /*!< in: query thread */
955
953
{
956
954
        trx_t*  trx;
957
955
        ulint   err;
976
974
        return(err);
977
975
}
978
976
 
979
 
/*************************************************************************
 
977
/*********************************************************************//**
980
978
Opens a pcur to a table index. */
981
979
static
982
980
void
983
981
row_sel_open_pcur(
984
982
/*==============*/
985
 
        plan_t*         plan,           /* in: table plan */
 
983
        plan_t*         plan,           /*!< in: table plan */
986
984
        ibool           search_latch_locked,
987
 
                                        /* in: TRUE if the thread currently
 
985
                                        /*!< in: TRUE if the thread currently
988
986
                                        has the search latch locked in
989
987
                                        s-mode */
990
 
        mtr_t*          mtr)            /* in: mtr */
 
988
        mtr_t*          mtr)            /*!< in: mtr */
991
989
{
992
990
        dict_index_t*   index;
993
991
        func_node_t*    cond;
1051
1049
        plan->pcur_is_open = TRUE;
1052
1050
}
1053
1051
 
1054
 
/*************************************************************************
1055
 
Restores a stored pcur position to a table index. */
 
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
 
1057
record */
1056
1058
static
1057
1059
ibool
1058
1060
row_sel_restore_pcur_pos(
1059
1061
/*=====================*/
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 */
 
1062
        plan_t*         plan,   /*!< in: table plan */
 
1063
        mtr_t*          mtr)    /*!< in: mtr */
1067
1064
{
1068
1065
        ibool   equal_position;
1069
1066
        ulint   relative_position;
1147
1144
        return(TRUE);
1148
1145
}
1149
1146
 
1150
 
/*************************************************************************
 
1147
/*********************************************************************//**
1151
1148
Resets a plan cursor to a closed state. */
1152
1149
UNIV_INLINE
1153
1150
void
1154
1151
plan_reset_cursor(
1155
1152
/*==============*/
1156
 
        plan_t* plan)   /* in: plan */
 
1153
        plan_t* plan)   /*!< in: plan */
1157
1154
{
1158
1155
        plan->pcur_is_open = FALSE;
1159
1156
        plan->cursor_at_end = FALSE;
1161
1158
        plan->n_rows_prefetched = 0;
1162
1159
}
1163
1160
 
1164
 
/*************************************************************************
 
1161
/*********************************************************************//**
1165
1162
Tries to do a shortcut to fetch a clustered index record with a unique key,
1166
 
using the hash index if possible (not always). */
 
1163
using the hash index if possible (not always).
 
1164
@return SEL_FOUND, SEL_EXHAUSTED, SEL_RETRY */
1167
1165
static
1168
1166
ulint
1169
1167
row_sel_try_search_shortcut(
1170
1168
/*========================*/
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
 
1169
        sel_node_t*     node,   /*!< in: select node for a consistent read */
 
1170
        plan_t*         plan,   /*!< in: plan for a unique search in clustered
1174
1171
                                index */
1175
 
        mtr_t*          mtr)    /* in: mtr */
 
1172
        mtr_t*          mtr)    /*!< in: mtr */
1176
1173
{
1177
1174
        dict_index_t*   index;
1178
1175
        rec_t*          rec;
1263
1260
        return(ret);
1264
1261
}
1265
1262
 
1266
 
/*************************************************************************
1267
 
Performs a select step. */
 
1263
/*********************************************************************//**
 
1264
Performs a select step.
 
1265
@return DB_SUCCESS or error code */
1268
1266
static
1269
1267
ulint
1270
1268
row_sel(
1271
1269
/*====*/
1272
 
                                /* out: DB_SUCCESS or error code */
1273
 
        sel_node_t*     node,   /* in: select node */
1274
 
        que_thr_t*      thr)    /* in: query thread */
 
1270
        sel_node_t*     node,   /*!< in: select node */
 
1271
        que_thr_t*      thr)    /*!< in: query thread */
1275
1272
{
1276
1273
        dict_index_t*   index;
1277
1274
        plan_t*         plan;
1692
1689
                goto next_rec;
1693
1690
        }
1694
1691
 
1695
 
 
1696
1692
        /* PHASE 5: Get the clustered index record, if needed and if we did
1697
1693
        not do the search using the clustered index */
1698
1694
 
1965
1961
        return(err);
1966
1962
}
1967
1963
 
1968
 
/**************************************************************************
 
1964
/**********************************************************************//**
1969
1965
Performs a select step. This is a high-level function used in SQL execution
1970
 
graphs. */
 
1966
graphs.
 
1967
@return query thread to run next or NULL */
1971
1968
UNIV_INTERN
1972
1969
que_thr_t*
1973
1970
row_sel_step(
1974
1971
/*=========*/
1975
 
                                /* out: query thread to run next or NULL */
1976
 
        que_thr_t*      thr)    /* in: query thread */
 
1972
        que_thr_t*      thr)    /*!< in: query thread */
1977
1973
{
1978
1974
        ulint           i_lock_mode;
1979
1975
        sym_node_t*     table_node;
2067
2063
        return(thr);
2068
2064
}
2069
2065
 
2070
 
/**************************************************************************
2071
 
Performs a fetch for a cursor. */
 
2066
/**********************************************************************//**
 
2067
Performs a fetch for a cursor.
 
2068
@return query thread to run next or NULL */
2072
2069
UNIV_INTERN
2073
2070
que_thr_t*
2074
2071
fetch_step(
2075
2072
/*=======*/
2076
 
                                /* out: query thread to run next or NULL */
2077
 
        que_thr_t*      thr)    /* in: query thread */
 
2073
        que_thr_t*      thr)    /*!< in: query thread */
2078
2074
{
2079
2075
        sel_node_t*     sel_node;
2080
2076
        fetch_node_t*   node;
2130
2126
        return(thr);
2131
2127
}
2132
2128
 
2133
 
/********************************************************************
2134
 
Sample callback function for fetch that prints each row.*/
 
2129
/****************************************************************//**
 
2130
Sample callback function for fetch that prints each row.
 
2131
@return always returns non-NULL */
2135
2132
UNIV_INTERN
2136
2133
void*
2137
2134
row_fetch_print(
2138
2135
/*============*/
2139
 
                                /* out: always returns non-NULL */
2140
 
        void*   row,            /* in:  sel_node_t* */
2141
 
        void*   user_arg)       /* in:  not used */
 
2136
        void*   row,            /*!< in:  sel_node_t* */
 
2137
        void*   user_arg)       /*!< in:  not used */
2142
2138
{
2143
2139
        sel_node_t*     node = row;
2144
2140
        que_node_t*     exp;
2174
2170
        return((void*)42);
2175
2171
}
2176
2172
 
2177
 
/********************************************************************
 
2173
/****************************************************************//**
2178
2174
Callback function for fetch that stores an unsigned 4 byte integer to the
2179
2175
location pointed. The column's type must be DATA_INT, DATA_UNSIGNED, length
2180
 
= 4. */
 
2176
= 4.
 
2177
@return always returns NULL */
2181
2178
UNIV_INTERN
2182
2179
void*
2183
2180
row_fetch_store_uint4(
2184
2181
/*==================*/
2185
 
                                /* out: always returns NULL */
2186
 
        void*   row,            /* in:  sel_node_t* */
2187
 
        void*   user_arg)       /* in:  data pointer */
 
2182
        void*   row,            /*!< in:  sel_node_t* */
 
2183
        void*   user_arg)       /*!< in:  data pointer */
2188
2184
{
2189
2185
        sel_node_t*     node = row;
2190
2186
        ib_uint32_t*    val = user_arg;
2204
2200
        return(NULL);
2205
2201
}
2206
2202
 
2207
 
/***************************************************************
2208
 
Prints a row in a select result. */
 
2203
/***********************************************************//**
 
2204
Prints a row in a select result.
 
2205
@return query thread to run next or NULL */
2209
2206
UNIV_INTERN
2210
2207
que_thr_t*
2211
2208
row_printf_step(
2212
2209
/*============*/
2213
 
                                /* out: query thread to run next or NULL */
2214
 
        que_thr_t*      thr)    /* in: query thread */
 
2210
        que_thr_t*      thr)    /*!< in: query thread */
2215
2211
{
2216
2212
        row_printf_node_t*      node;
2217
2213
        sel_node_t*             sel_node;
2267
2263
        return(thr);
2268
2264
}
2269
2265
 
2270
 
/********************************************************************
 
2266
/****************************************************************//**
2271
2267
Converts a key value stored in MySQL format to an Innobase dtuple. The last
2272
2268
field of the key value may be just a prefix of a fixed length field: hence
2273
2269
the parameter key_len. But currently we do not allow search keys where the
2278
2274
void
2279
2275
row_sel_convert_mysql_key_to_innobase(
2280
2276
/*==================================*/
2281
 
        dtuple_t*       tuple,          /* in/out: tuple where to build;
 
2277
        dtuple_t*       tuple,          /*!< in/out: tuple where to build;
2282
2278
                                        NOTE: we assume that the type info
2283
2279
                                        in the tuple is already according
2284
2280
                                        to index! */
2285
 
        byte*           buf,            /* in: buffer to use in field
 
2281
        byte*           buf,            /*!< in: buffer to use in field
2286
2282
                                        conversions */
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 */
 
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 */
2292
2288
{
2293
2289
        byte*           original_buf    = buf;
2294
2290
        const byte*     original_key_ptr = key_ptr;
2471
2467
        dtuple_set_n_fields(tuple, n_fields);
2472
2468
}
2473
2469
 
2474
 
/******************************************************************
 
2470
/**************************************************************//**
2475
2471
Stores the row id to the prebuilt struct. */
2476
2472
static
2477
2473
void
2478
2474
row_sel_store_row_id_to_prebuilt(
2479
2475
/*=============================*/
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
 
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
2484
2480
                                                (index_rec, index) */
2485
2481
{
2486
2482
        const byte*     data;
2509
2505
        ut_memcpy(prebuilt->row_id, data, len);
2510
2506
}
2511
2507
 
2512
 
/******************************************************************
 
2508
/**************************************************************//**
2513
2509
Stores a non-SQL-NULL field in the MySQL format. The counterpart of this
2514
2510
function is row_mysql_store_col_in_innobase_format() in row0mysql.c. */
2515
2511
static
2516
2512
void
2517
2513
row_sel_field_store_in_mysql_format(
2518
2514
/*================================*/
2519
 
        byte*           dest,   /* in/out: buffer where to store; NOTE
 
2515
        byte*           dest,   /*!< in/out: buffer where to store; NOTE
2520
2516
                                that BLOBs are not in themselves
2521
2517
                                stored here: the caller must allocate
2522
2518
                                and copy the BLOB into buffer before,
2523
2519
                                and pass the pointer to the BLOB in
2524
2520
                                'data' */
2525
2521
        const mysql_row_templ_t* templ,
2526
 
                                /* in: MySQL column template.
 
2522
                                /*!< in: MySQL column template.
2527
2523
                                Its following fields are referenced:
2528
2524
                                type, is_unsigned, mysql_col_len,
2529
2525
                                mbminlen, mbmaxlen */
2530
 
        const byte*     data,   /* in: data to store */
2531
 
        ulint           len)    /* in: length of the data */
 
2526
        const byte*     data,   /*!< in: data to store */
 
2527
        ulint           len)    /*!< in: length of the data */
2532
2528
{
2533
2529
        byte*   ptr;
2534
2530
        byte*   field_end;
2664
2660
        }
2665
2661
}
2666
2662
 
2667
 
/******************************************************************
 
2663
/**************************************************************//**
2668
2664
Convert a row in the Innobase format to a row in the MySQL format.
2669
2665
Note that the template in prebuilt may advise us to copy only a few
2670
2666
columns to mysql_rec, other columns are left blank. All columns may not
2671
 
be needed in the query. */
 
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) */
2672
2670
static
2673
2671
ibool
2674
2672
row_sel_store_mysql_rec(
2675
2673
/*====================*/
2676
 
                                        /* out: TRUE if success, FALSE if
2677
 
                                        could not allocate memory for a BLOB
2678
 
                                        (though we may also assert in that
2679
 
                                        case) */
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
 
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
2683
2677
                                        which was described in prebuilt's
2684
2678
                                        template; must be protected by
2685
2679
                                        a page latch */
2686
 
        const ulint*    offsets,        /* in: array returned by
 
2680
        const ulint*    offsets)        /*!< in: array returned by
2687
2681
                                        rec_get_offsets() */
2688
 
        ulint start_field_no,
2689
 
        ulint end_field_no)
2690
2682
{
2691
2683
        mysql_row_templ_t*      templ;
2692
2684
        mem_heap_t*             extern_field_heap       = NULL;
2704
2696
                prebuilt->blob_heap = NULL;
2705
2697
        }
2706
2698
 
2707
 
        memset(mysql_rec, 0xff, prebuilt->null_bitmap_len);
2708
 
        for (i = start_field_no; i < end_field_no /* prebuilt->n_template */; i++) {
 
2699
        for (i = 0; i < prebuilt->n_template ; i++) {
2709
2700
 
2710
2701
                templ = prebuilt->mysql_template + i;
2711
2702
 
2791
2782
                        mysql_rec[templ->mysql_null_byte_offset]
2792
2783
                                |= (byte) templ->mysql_null_bit_mask;
2793
2784
                        memcpy(mysql_rec + templ->mysql_col_offset,
2794
 
                               prebuilt->default_rec + templ->mysql_col_offset,
 
2785
                               (const byte*) prebuilt->default_rec
 
2786
                               + templ->mysql_col_offset,
2795
2787
                               templ->mysql_col_len);
2796
2788
                }
2797
2789
        }
2799
2791
        return(TRUE);
2800
2792
}
2801
2793
 
2802
 
/*************************************************************************
2803
 
Builds a previous version of a clustered index record for a consistent read */
 
2794
/*********************************************************************//**
 
2795
Builds a previous version of a clustered index record for a consistent read
 
2796
@return DB_SUCCESS or error code */
2804
2797
static
2805
2798
ulint
2806
2799
row_sel_build_prev_vers_for_mysql(
2807
2800
/*==============================*/
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
 
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
2814
2806
                                        rec_get_offsets(rec, clust_index) */
2815
 
        mem_heap_t**    offset_heap,    /* in/out: memory heap from which
 
2807
        mem_heap_t**    offset_heap,    /*!< in/out: memory heap from which
2816
2808
                                        the offsets are allocated */
2817
 
        rec_t**         old_vers,       /* out: old version, or NULL if the
 
2809
        rec_t**         old_vers,       /*!< out: old version, or NULL if the
2818
2810
                                        record does not exist in the view:
2819
2811
                                        i.e., it was freshly inserted
2820
2812
                                        afterwards */
2821
 
        mtr_t*          mtr)            /* in: mtr */
 
2813
        mtr_t*          mtr)            /*!< in: mtr */
2822
2814
{
2823
2815
        ulint   err;
2824
2816
 
2834
2826
        return(err);
2835
2827
}
2836
2828
 
2837
 
/*************************************************************************
 
2829
/*********************************************************************//**
2838
2830
Retrieves the clustered index record corresponding to a record in a
2839
2831
non-clustered index. Does the necessary locking. Used in the MySQL
2840
 
interface. */
 
2832
interface.
 
2833
@return DB_SUCCESS or error code */
2841
2834
static
2842
2835
ulint
2843
2836
row_sel_get_clust_rec_for_mysql(
2844
2837
/*============================*/
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
 
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
2849
2841
                                this is a locking read, then rec is not
2850
2842
                                allowed to be delete-marked, and that would
2851
2843
                                not make sense either */
2852
 
        que_thr_t*      thr,    /* in: query thread */
2853
 
        const rec_t**   out_rec,/* out: clustered record or an old version of
 
2844
        que_thr_t*      thr,    /*!< in: query thread */
 
2845
        const rec_t**   out_rec,/*!< out: clustered record or an old version of
2854
2846
                                it, NULL if the old version did not exist
2855
2847
                                in the read view, i.e., it was a fresh
2856
2848
                                inserted version */
2857
 
        ulint**         offsets,/* in: offsets returned by
 
2849
        ulint**         offsets,/*!< in: offsets returned by
2858
2850
                                rec_get_offsets(rec, sec_index);
2859
2851
                                out: offsets returned by
2860
2852
                                rec_get_offsets(out_rec, clust_index) */
2861
 
        mem_heap_t**    offset_heap,/* in/out: memory heap from which
 
2853
        mem_heap_t**    offset_heap,/*!< in/out: memory heap from which
2862
2854
                                the offsets are allocated */
2863
 
        mtr_t*          mtr)    /* in: mtr used to get access to the
 
2855
        mtr_t*          mtr)    /*!< in: mtr used to get access to the
2864
2856
                                non-clustered record; the same mtr is used to
2865
2857
                                access the clustered index */
2866
2858
{
3006
2998
func_exit:
3007
2999
        *out_rec = clust_rec;
3008
3000
 
3009
 
        if (prebuilt->select_lock_type == LOCK_X) {
3010
 
                /* We may use the cursor in update: store its position */
 
3001
        if (prebuilt->select_lock_type != LOCK_NONE) {
 
3002
                /* We may use the cursor in update or in unlock_row():
 
3003
                store its position */
3011
3004
 
3012
3005
                btr_pcur_store_position(prebuilt->clust_pcur, mtr);
3013
3006
        }
3017
3010
        return(err);
3018
3011
}
3019
3012
 
3020
 
/************************************************************************
 
3013
/********************************************************************//**
3021
3014
Restores cursor position after it has been stored. We have to take into
3022
3015
account that the record cursor was positioned on may have been deleted.
3023
 
Then we may have to move the cursor one step up or down. */
 
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) */
3024
3019
static
3025
3020
ibool
3026
3021
sel_restore_position_for_mysql(
3027
3022
/*===========================*/
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
 
3023
        ibool*          same_user_rec,  /*!< out: TRUE if we were able to restore
3033
3024
                                        the cursor on a user record with the
3034
3025
                                        same ordering prefix in in the
3035
3026
                                        B-tree index */
3036
 
        ulint           latch_mode,     /* in: latch mode wished in
 
3027
        ulint           latch_mode,     /*!< in: latch mode wished in
3037
3028
                                        restoration */
3038
 
        btr_pcur_t*     pcur,           /* in: cursor whose position
 
3029
        btr_pcur_t*     pcur,           /*!< in: cursor whose position
3039
3030
                                        has been stored */
3040
 
        ibool           moves_up,       /* in: TRUE if the cursor moves up
 
3031
        ibool           moves_up,       /*!< in: TRUE if the cursor moves up
3041
3032
                                        in the index */
3042
 
        mtr_t*          mtr)            /* in: mtr; CAUTION: may commit
 
3033
        mtr_t*          mtr)            /*!< in: mtr; CAUTION: may commit
3043
3034
                                        mtr temporarily! */
3044
3035
{
3045
3036
        ibool   success;
3087
3078
        return(TRUE);
3088
3079
}
3089
3080
 
3090
 
/************************************************************************
 
3081
/********************************************************************//**
3091
3082
Pops a cached row for MySQL from the fetch cache. */
3092
3083
UNIV_INLINE
3093
3084
void
3094
3085
row_sel_pop_cached_row_for_mysql(
3095
3086
/*=============================*/
3096
 
        byte*           buf,            /* in/out: buffer where to copy the
 
3087
        byte*           buf,            /*!< in/out: buffer where to copy the
3097
3088
                                        row */
3098
 
        row_prebuilt_t* prebuilt)       /* in: prebuilt struct */
 
3089
        row_prebuilt_t* prebuilt)       /*!< in: prebuilt struct */
3099
3090
{
3100
3091
        ulint                   i;
3101
3092
        mysql_row_templ_t*      templ;
3137
3128
        }
3138
3129
}
3139
3130
 
3140
 
/************************************************************************
 
3131
/********************************************************************//**
3141
3132
Pushes a row for MySQL to the fetch cache. */
3142
3133
UNIV_INLINE
3143
3134
void
3144
3135
row_sel_push_cache_row_for_mysql(
3145
3136
/*=============================*/
3146
 
        row_prebuilt_t* prebuilt,       /* in: prebuilt struct */
3147
 
        const rec_t*    rec,            /* in: record to push; must
 
3137
        row_prebuilt_t* prebuilt,       /*!< in: prebuilt struct */
 
3138
        const rec_t*    rec,            /*!< in: record to push; must
3148
3139
                                        be protected by a page latch */
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
3152
 
                                           prev fields */
 
3140
        const ulint*    offsets)        /*!<in: rec_get_offsets() */
3153
3141
{
3154
3142
        byte*   buf;
3155
3143
        ulint   i;
3182
3170
        if (UNIV_UNLIKELY(!row_sel_store_mysql_rec(
3183
3171
                                  prebuilt->fetch_cache[
3184
3172
                                          prebuilt->n_fetch_cached],
3185
 
                                  prebuilt, rec, offsets, start_field_no,
3186
 
                                  prebuilt->n_template))) {
 
3173
                                  prebuilt, rec, offsets))) {
3187
3174
                ut_error;
3188
3175
        }
3189
3176
 
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;
3195
 
 
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);
3201
 
              else
3202
 
                *(prebuilt->fetch_cache[prebuilt->n_fetch_cached] + offs) &= 
3203
 
                  ~templ->mysql_null_bit_mask;
3204
 
 
3205
 
            }
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);
3210
 
          }
3211
 
        }
3212
 
 
3213
 
 
3214
3177
        prebuilt->n_fetch_cached++;
3215
3178
}
3216
3179
 
3217
 
/*************************************************************************
 
3180
/*********************************************************************//**
3218
3181
Tries to do a shortcut to fetch a clustered index record with a unique key,
3219
3182
using the hash index if possible (not always). We assume that the search
3220
3183
mode is PAGE_CUR_GE, it is a consistent read, there is a read view in trx,
3221
 
btr search latch has been locked in S-mode. */
 
3184
btr search latch has been locked in S-mode.
 
3185
@return SEL_FOUND, SEL_EXHAUSTED, SEL_RETRY */
3222
3186
static
3223
3187
ulint
3224
3188
row_sel_try_search_shortcut_for_mysql(
3225
3189
/*==================================*/
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 */
 
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 */
3232
3195
{
3233
3196
        dict_index_t*   index           = prebuilt->index;
3234
3197
        const dtuple_t* search_tuple    = prebuilt->search_tuple;
3285
3248
        return(SEL_FOUND);
3286
3249
}
3287
3250
 
3288
 
/************************************************************************
 
3251
/********************************************************************//**
3289
3252
Searches for rows in the database. This is used in the interface to
3290
3253
MySQL. This function opens a cursor, and also implements fetch next
3291
3254
and fetch prev. NOTE that if we do a search with a full key value
3292
3255
from a unique index (ROW_SEL_EXACT), then we will not store the cursor
3293
 
position and fetch next or fetch prev must not be tried to 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 */
3294
3259
UNIV_INTERN
3295
3260
ulint
3296
3261
row_search_for_mysql(
3297
3262
/*=================*/
3298
 
                                        /* out: DB_SUCCESS,
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
 
3263
        byte*           buf,            /*!< in/out: buffer for the fetched
3304
3264
                                        row in the MySQL format */
3305
 
        ulint           mode,           /* in: search mode PAGE_CUR_L, ... */
3306
 
        row_prebuilt_t* prebuilt,       /* in: prebuilt struct for the
 
3265
        ulint           mode,           /*!< in: search mode PAGE_CUR_L, ... */
 
3266
        row_prebuilt_t* prebuilt,       /*!< in: prebuilt struct for the
3307
3267
                                        table handle; this contains the info
3308
3268
                                        of search_tuple, index; if search
3309
3269
                                        tuple contains 0 fields then we
3310
3270
                                        position the cursor at the start or
3311
3271
                                        the end of the index, depending on
3312
3272
                                        'mode' */
3313
 
        ulint           match_mode,     /* in: 0 or ROW_SEL_EXACT or
 
3273
        ulint           match_mode,     /*!< in: 0 or ROW_SEL_EXACT or
3314
3274
                                        ROW_SEL_EXACT_PREFIX */
3315
 
        ulint           direction)      /* in: 0 or ROW_SEL_NEXT or
 
3275
        ulint           direction)      /*!< in: 0 or ROW_SEL_NEXT or
3316
3276
                                        ROW_SEL_PREV; NOTE: if this is != 0,
3317
3277
                                        then prebuilt must have a pcur
3318
3278
                                        with stored position! In opening of a
3349
3309
        mem_heap_t*     heap                            = NULL;
3350
3310
        ulint           offsets_[REC_OFFS_NORMAL_SIZE];
3351
3311
        ulint*          offsets                         = offsets_;
3352
 
        ibool           some_fields_in_buffer;
3353
 
        ibool           get_clust_rec= 0;
3354
3312
 
3355
3313
        rec_offs_init(offsets_);
3356
3314
 
3368
3326
                        "InnoDB: the MySQL datadir, or have you used"
3369
3327
                        " DISCARD TABLESPACE?\n"
3370
3328
                        "InnoDB: Look from\n"
3371
 
                        "InnoDB: http://dev.mysql.com/doc/refman/5.1/en/"
3372
 
                        "innodb-troubleshooting.html\n"
 
3329
                        "InnoDB: " REFMAN "innodb-troubleshooting.html\n"
3373
3330
                        "InnoDB: how you can resolve the problem.\n",
3374
3331
                        prebuilt->table->name);
3375
3332
 
3376
3333
                return(DB_ERROR);
3377
3334
        }
3378
3335
 
 
3336
        if (UNIV_UNLIKELY(!prebuilt->index_usable)) {
 
3337
 
 
3338
                return(DB_MISSING_HISTORY);
 
3339
        }
 
3340
 
3379
3341
        if (UNIV_UNLIKELY(prebuilt->magic_n != ROW_PREBUILT_ALLOCATED)) {
3380
3342
                fprintf(stderr,
3381
3343
                        "InnoDB: Error: trying to free a corrupt\n"
3439
3401
        is set or session is using a READ COMMITED isolation level. Then
3440
3402
        we are able to remove the record locks set here on an individual
3441
3403
        row. */
3442
 
 
3443
 
        if ((srv_locks_unsafe_for_binlog
3444
 
             || trx->isolation_level == TRX_ISO_READ_COMMITTED)
3445
 
            && prebuilt->select_lock_type != LOCK_NONE) {
3446
 
 
3447
 
                trx_reset_new_rec_lock_info(trx);
3448
 
        }
 
3404
        prebuilt->new_rec_locks = 0;
3449
3405
 
3450
3406
        /*-------------------------------------------------------------*/
3451
3407
        /* PHASE 1: Try to pop the row from the prefetch cache */
3609
3565
                                mtr_commit(&mtr). */
3610
3566
 
3611
3567
                                if (!row_sel_store_mysql_rec(buf, prebuilt,
3612
 
                                                             rec, offsets, 0,
3613
 
                                                             prebuilt->n_template)) {
 
3568
                                                             rec, offsets)) {
3614
3569
                                        err = DB_TOO_BIG_RECORD;
3615
3570
 
3616
3571
                                        /* We let the main loop to do the
4091
4046
                switch (err) {
4092
4047
                        const rec_t*    old_vers;
4093
4048
                case DB_SUCCESS:
 
4049
                        if (srv_locks_unsafe_for_binlog
 
4050
                            || trx->isolation_level == TRX_ISO_READ_COMMITTED) {
 
4051
                                /* Note that a record of
 
4052
                                prebuilt->index was locked. */
 
4053
                                prebuilt->new_rec_locks = 1;
 
4054
                        }
4094
4055
                        break;
4095
4056
                case DB_LOCK_WAIT:
4096
4057
                        if (UNIV_LIKELY(prebuilt->row_read_type
4121
4082
                        if (UNIV_LIKELY(trx->wait_lock != NULL)) {
4122
4083
                                lock_cancel_waiting_and_release(
4123
4084
                                        trx->wait_lock);
4124
 
                                trx_reset_new_rec_lock_info(trx);
 
4085
                                prebuilt->new_rec_locks = 0;
4125
4086
                        } else {
4126
4087
                                mutex_exit(&kernel_mutex);
4127
4088
 
4133
4094
                                                          ULINT_UNDEFINED,
4134
4095
                                                          &heap);
4135
4096
                                err = DB_SUCCESS;
 
4097
                                /* Note that a record of
 
4098
                                prebuilt->index was locked. */
 
4099
                                prebuilt->new_rec_locks = 1;
4136
4100
                                break;
4137
4101
                        }
4138
4102
                        mutex_exit(&kernel_mutex);
4200
4164
                        information via the clustered index record. */
4201
4165
 
4202
4166
                        ut_ad(index != clust_index);
4203
 
                        get_clust_rec= TRUE;
4204
 
                        goto idx_cond_check;
 
4167
                        goto requires_clust_rec;
4205
4168
                }
4206
4169
        }
4207
4170
 
4245
4208
                goto next_rec;
4246
4209
        }
4247
4210
 
4248
 
idx_cond_check:
4249
 
        if (prebuilt->idx_cond_func)
4250
 
        {
4251
 
          int res;
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);
4257
 
          if (res == 0)
4258
 
            goto next_rec;
4259
 
          if (res == 2)
4260
 
          {
4261
 
            err = DB_RECORD_NOT_FOUND;
4262
 
            goto idx_cond_failed;
4263
 
          }
4264
 
        }
4265
 
 
4266
4211
        /* Get the clustered index record if needed, if we did not do the
4267
4212
        search using the clustered index. */
4268
4213
 
4269
 
        if (get_clust_rec || (index != clust_index &&
4270
 
            prebuilt->need_to_access_clustered)) {
 
4214
        if (index != clust_index && prebuilt->need_to_access_clustered) {
4271
4215
 
 
4216
requires_clust_rec:
4272
4217
                /* We use a 'goto' to the preceding label if a consistent
4273
4218
                read of a secondary index record requires us to look up old
4274
4219
                versions of the associated clustered index record. */
4299
4244
                        goto next_rec;
4300
4245
                }
4301
4246
 
 
4247
                if ((srv_locks_unsafe_for_binlog
 
4248
                     || trx->isolation_level == TRX_ISO_READ_COMMITTED)
 
4249
                    && prebuilt->select_lock_type != LOCK_NONE) {
 
4250
                        /* Note that both the secondary index record
 
4251
                        and the clustered index record were locked. */
 
4252
                        ut_ad(prebuilt->new_rec_locks == 1);
 
4253
                        prebuilt->new_rec_locks = 2;
 
4254
                }
 
4255
 
4302
4256
                if (UNIV_UNLIKELY(rec_get_deleted_flag(clust_rec, comp))) {
4303
4257
 
4304
4258
                        /* The record is delete marked: we can skip it */
4362
4316
                are BLOBs in the fields to be fetched. In HANDLER we do
4363
4317
                not cache rows because there the cursor is a scrollable
4364
4318
                cursor. */
4365
 
                some_fields_in_buffer= (index != clust_index &&
4366
 
                                        prebuilt->idx_cond_func);
4367
4319
 
4368
4320
                row_sel_push_cache_row_for_mysql(prebuilt, result_rec,
4369
 
                                                 offsets,
4370
 
                                                 some_fields_in_buffer?
4371
 
                                                 prebuilt->n_index_fields: 0,
4372
 
                                                 buf);
 
4321
                                                 offsets);
4373
4322
                if (prebuilt->n_fetch_cached == MYSQL_FETCH_CACHE_SIZE) {
4374
4323
 
4375
4324
                        goto got_row;
4385
4334
                                        rec_offs_extra_size(offsets) + 4);
4386
4335
                } else {
4387
4336
                        if (!row_sel_store_mysql_rec(buf, prebuilt,
4388
 
                                                     result_rec, offsets,
4389
 
                                                     prebuilt->idx_cond_func?
4390
 
                                                     prebuilt->n_index_fields: 0,
4391
 
                                                     prebuilt->n_template)) {
 
4337
                                                     result_rec, offsets)) {
4392
4338
                                err = DB_TOO_BIG_RECORD;
4393
4339
 
4394
4340
                                goto lock_wait_or_error;
4416
4362
        HANDLER command where the user can move the cursor with PREV or NEXT
4417
4363
        even after a unique search. */
4418
4364
 
4419
 
idx_cond_failed:
4420
4365
        if (!unique_search_from_clust_index
4421
4366
            || prebuilt->select_lock_type != LOCK_NONE
4422
4367
            || prebuilt->used_in_HANDLER) {
4437
4382
                prebuilt->row_read_type = ROW_READ_TRY_SEMI_CONSISTENT;
4438
4383
        }
4439
4384
        did_semi_consistent_read = FALSE;
4440
 
 
4441
 
        if (UNIV_UNLIKELY(srv_locks_unsafe_for_binlog
4442
 
                          || trx->isolation_level == TRX_ISO_READ_COMMITTED)
4443
 
            && prebuilt->select_lock_type != LOCK_NONE) {
4444
 
 
4445
 
                trx_reset_new_rec_lock_info(trx);
4446
 
        }
 
4385
        prebuilt->new_rec_locks = 0;
4447
4386
 
4448
4387
        /*-------------------------------------------------------------*/
4449
4388
        /* PHASE 5: Move the cursor to the next index record */
4549
4488
                        rec_loop we will again try to set a lock, and
4550
4489
                        new_rec_lock_info in trx will be right at the end. */
4551
4490
 
4552
 
                        trx_reset_new_rec_lock_info(trx);
 
4491
                        prebuilt->new_rec_locks = 0;
4553
4492
                }
4554
4493
 
4555
4494
                mode = pcur->search_mode;
4609
4548
        return(err);
4610
4549
}
4611
4550
 
4612
 
/***********************************************************************
 
4551
/*******************************************************************//**
4613
4552
Checks if MySQL at the moment is allowed for this table to retrieve a
4614
 
consistent read result, or store it to the query cache. */
 
4553
consistent read result, or store it to the query cache.
 
4554
@return TRUE if storing or retrieving from the query cache is permitted */
4615
4555
UNIV_INTERN
4616
4556
ibool
4617
4557
row_search_check_if_query_cache_permitted(
4618
4558
/*======================================*/
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,
 
4559
        trx_t*          trx,            /*!< in: transaction object */
 
4560
        const char*     norm_name)      /*!< in: concatenation of database name,
4623
4561
                                        '/' char, table name */
4624
4562
{
4625
4563
        dict_table_t*   table;
4666
4604
        return(ret);
4667
4605
}
4668
4606
 
4669
 
/***********************************************************************
 
4607
/*******************************************************************//**
4670
4608
Read the AUTOINC column from the current row. If the value is less than
4671
 
0 and the type is not unsigned then we reset the value to 0. */
 
4609
0 and the type is not unsigned then we reset the value to 0.
 
4610
@return value read from the column */
4672
4611
static
4673
4612
ib_uint64_t
4674
4613
row_search_autoinc_read_column(
4675
4614
/*===========================*/
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 */
 
4615
        dict_index_t*   index,          /*!< in: index to read from */
 
4616
        const rec_t*    rec,            /*!< in: current rec */
 
4617
        ulint           col_no,         /*!< in: column number */
 
4618
        ibool           unsigned_type)  /*!< in: signed or unsigned flag */
4681
4619
{
4682
4620
        ulint           len;
4683
4621
        const byte*     data;
4709
4647
        return(value);
4710
4648
}
4711
4649
 
4712
 
/***********************************************************************
4713
 
Get the last row. */
 
4650
/*******************************************************************//**
 
4651
Get the last row.
 
4652
@return current rec or NULL */
4714
4653
static
4715
4654
const rec_t*
4716
4655
row_search_autoinc_get_rec(
4717
4656
/*=======================*/
4718
 
                                        /* out: current rec or NULL */
4719
 
        btr_pcur_t*     pcur,           /* in: the current cursor */
4720
 
        mtr_t*          mtr)            /* in: mini transaction */
 
4657
        btr_pcur_t*     pcur,           /*!< in: the current cursor */
 
4658
        mtr_t*          mtr)            /*!< in: mini transaction */
4721
4659
{
4722
4660
        do {
4723
4661
                const rec_t* rec = btr_pcur_get_rec(pcur);
4730
4668
        return(NULL);
4731
4669
}
4732
4670
 
4733
 
/***********************************************************************
4734
 
Read the max AUTOINC value from an index. */
 
4671
/*******************************************************************//**
 
4672
Read the max AUTOINC value from an index.
 
4673
@return DB_SUCCESS if all OK else error code, DB_RECORD_NOT_FOUND if
 
4674
column name can't be found in index */
4735
4675
UNIV_INTERN
4736
4676
ulint
4737
4677
row_search_max_autoinc(
4738
4678
/*===================*/
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 */
 
4679
        dict_index_t*   index,          /*!< in: index to search */
 
4680
        const char*     col_name,       /*!< in: name of autoinc column */
 
4681
        ib_uint64_t*    value)          /*!< out: AUTOINC value read */
4745
4682
{
4746
4683
        ulint           i;
4747
4684
        ulint           n_cols;