~drizzle-trunk/drizzle/development

« back to all changes in this revision

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

  • Committer: Mark Atwood
  • Date: 2009-03-04 01:02:00 UTC
  • mto: (968.2.20 mordred)
  • mto: This revision was merged to the branch mainline in revision 971.
  • Revision ID: me@mark.atwood.name-20090304010200-t1n4xxdoil2yae9a
add gearman logging plugin

Show diffs side-by-side

added added

removed removed

Lines of Context:
1
 
/*****************************************************************************
2
 
 
3
 
Copyright (C) 1997, 2010, Innobase Oy. All Rights Reserved.
4
 
Copyright (C) 2008, Google Inc.
5
 
 
6
 
Portions of this file contain modifications contributed and copyrighted by
7
 
Google, Inc. Those modifications are gratefully acknowledged and are described
8
 
briefly in the InnoDB documentation. The contributions by Google are
9
 
incorporated with their permission, and subject to the conditions contained in
10
 
the file COPYING.Google.
11
 
 
12
 
This program is free software; you can redistribute it and/or modify it under
13
 
the terms of the GNU General Public License as published by the Free Software
14
 
Foundation; version 2 of the License.
15
 
 
16
 
This program is distributed in the hope that it will be useful, but WITHOUT
17
 
ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
18
 
FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.
19
 
 
20
 
You should have received a copy of the GNU General Public License along with
21
 
this program; if not, write to the Free Software Foundation, Inc., 51 Franklin
22
 
St, Fifth Floor, Boston, MA 02110-1301 USA
23
 
 
24
 
*****************************************************************************/
25
 
 
26
 
/***************************************************//**
27
 
@file row/row0sel.c
 
1
/*******************************************************
28
2
Select
29
3
 
 
4
(c) 1997 Innobase Oy
 
5
 
30
6
Created 12/19/1997 Heikki Tuuri
31
7
*******************************************************/
32
8
 
75
51
#define SEL_EXHAUSTED   1
76
52
#define SEL_RETRY       2
77
53
 
78
 
/********************************************************************//**
 
54
/************************************************************************
79
55
Returns TRUE if the user-defined column in a secondary index record
80
56
is alphabetically the same as the corresponding BLOB column in the clustered
81
57
index record.
82
58
NOTE: the comparison is NOT done as a binary comparison, but character
83
 
fields are compared with collation!
84
 
@return TRUE if the columns are equal */
 
59
fields are compared with collation! */
85
60
static
86
61
ibool
87
62
row_sel_sec_rec_is_for_blob(
88
63
/*========================*/
89
 
        ulint           mtype,          /*!< in: main type */
90
 
        ulint           prtype,         /*!< in: precise type */
91
 
        ulint           mbminmaxlen,    /*!< in: minimum and maximum length of
92
 
                                        a multi-byte character */
93
 
        const byte*     clust_field,    /*!< in: the locally stored part of
 
64
                                        /* out: TRUE if the columns
 
65
                                        are equal */
 
66
        ulint           mtype,          /* in: main type */
 
67
        ulint           prtype,         /* in: precise type */
 
68
        ulint           mbminlen,       /* in: minimum length of a
 
69
                                        multi-byte character */
 
70
        ulint           mbmaxlen,       /* in: maximum length of a
 
71
                                        multi-byte character */
 
72
        const byte*     clust_field,    /* in: the locally stored part of
94
73
                                        the clustered index column, including
95
74
                                        the BLOB pointer; the clustered
96
75
                                        index record must be covered by
97
76
                                        a lock or a page latch to protect it
98
77
                                        against deletion (rollback or purge) */
99
 
        ulint           clust_len,      /*!< in: length of clust_field */
100
 
        const byte*     sec_field,      /*!< in: column in secondary index */
101
 
        ulint           sec_len,        /*!< in: length of sec_field */
102
 
        ulint           zip_size)       /*!< in: compressed page size, or 0 */
 
78
        ulint           clust_len,      /* in: length of clust_field */
 
79
        const byte*     sec_field,      /* in: column in secondary index */
 
80
        ulint           sec_len,        /* in: length of sec_field */
 
81
        ulint           zip_size)       /* in: compressed page size, or 0 */
103
82
{
104
83
        ulint   len;
105
84
        byte    buf[DICT_MAX_INDEX_COL_LEN];
106
85
 
107
 
        ut_a(clust_len >= BTR_EXTERN_FIELD_REF_SIZE);
108
 
 
109
 
        if (UNIV_UNLIKELY
110
 
            (!memcmp(clust_field + clust_len - BTR_EXTERN_FIELD_REF_SIZE,
111
 
                     field_ref_zero, BTR_EXTERN_FIELD_REF_SIZE))) {
112
 
                /* The externally stored field was not written yet.
113
 
                This record should only be seen by
114
 
                recv_recovery_rollback_active() or any
115
 
                TRX_ISO_READ_UNCOMMITTED transactions. */
116
 
                return(FALSE);
117
 
        }
118
 
 
119
86
        len = btr_copy_externally_stored_field_prefix(buf, sizeof buf,
120
87
                                                      zip_size,
121
88
                                                      clust_field, clust_len);
129
96
                return(FALSE);
130
97
        }
131
98
 
132
 
        len = dtype_get_at_most_n_mbchars(prtype, mbminmaxlen,
 
99
        len = dtype_get_at_most_n_mbchars(prtype, mbminlen, mbmaxlen,
133
100
                                          sec_len, len, (const char*) buf);
134
101
 
135
102
        return(!cmp_data_data(mtype, prtype, buf, len, sec_field, sec_len));
136
103
}
137
104
 
138
 
/********************************************************************//**
 
105
/************************************************************************
139
106
Returns TRUE if the user-defined column values in a secondary index record
140
107
are alphabetically the same as the corresponding columns in the clustered
141
108
index record.
142
109
NOTE: the comparison is NOT done as a binary comparison, but character
143
 
fields are compared with collation!
144
 
@return TRUE if the secondary record is equal to the corresponding
145
 
fields in the clustered record, when compared with collation;
146
 
FALSE if not equal or if the clustered record has been marked for deletion */
 
110
fields are compared with collation! */
147
111
static
148
112
ibool
149
113
row_sel_sec_rec_is_for_clust_rec(
150
114
/*=============================*/
151
 
        const rec_t*    sec_rec,        /*!< in: secondary index record */
152
 
        dict_index_t*   sec_index,      /*!< in: secondary index */
153
 
        const rec_t*    clust_rec,      /*!< in: clustered index record;
 
115
                                        /* out: TRUE if the secondary
 
116
                                        record is equal to the corresponding
 
117
                                        fields in the clustered record,
 
118
                                        when compared with collation */
 
119
        const rec_t*    sec_rec,        /* in: secondary index record */
 
120
        dict_index_t*   sec_index,      /* in: secondary index */
 
121
        const rec_t*    clust_rec,      /* in: clustered index record;
154
122
                                        must be protected by a lock or
155
123
                                        a page latch against deletion
156
124
                                        in rollback or purge */
157
 
        dict_index_t*   clust_index)    /*!< in: clustered index */
 
125
        dict_index_t*   clust_index)    /* in: clustered index */
158
126
{
159
127
        const byte*     sec_field;
160
128
        ulint           sec_len;
212
180
                        }
213
181
 
214
182
                        len = dtype_get_at_most_n_mbchars(
215
 
                                col->prtype, col->mbminmaxlen,
 
183
                                col->prtype, col->mbminlen, col->mbmaxlen,
216
184
                                ifield->prefix_len, len, (char*) clust_field);
217
185
 
218
186
                        if (rec_offs_nth_extern(clust_offs, clust_pos)
219
187
                            && len < sec_len) {
220
188
                                if (!row_sel_sec_rec_is_for_blob(
221
189
                                            col->mtype, col->prtype,
222
 
                                            col->mbminmaxlen,
 
190
                                            col->mbminlen, col->mbmaxlen,
223
191
                                            clust_field, clust_len,
224
192
                                            sec_field, sec_len,
225
193
                                            dict_table_zip_size(
247
215
        return(is_equal);
248
216
}
249
217
 
250
 
/*********************************************************************//**
251
 
Creates a select node struct.
252
 
@return own: select node struct */
 
218
/*************************************************************************
 
219
Creates a select node struct. */
253
220
UNIV_INTERN
254
221
sel_node_t*
255
222
sel_node_create(
256
223
/*============*/
257
 
        mem_heap_t*     heap)   /*!< in: memory heap where created */
 
224
                                /* out, own: select node struct */
 
225
        mem_heap_t*     heap)   /* in: memory heap where created */
258
226
{
259
227
        sel_node_t*     node;
260
228
 
261
 
        node = static_cast<sel_node_t *>(mem_heap_alloc(heap, sizeof(sel_node_t)));
 
229
        node = mem_heap_alloc(heap, sizeof(sel_node_t));
262
230
        node->common.type = QUE_NODE_SELECT;
263
231
        node->state = SEL_NODE_OPEN;
264
232
 
 
233
        node->select_will_do_update = FALSE;
 
234
        node->latch_mode = BTR_SEARCH_LEAF;
 
235
 
265
236
        node->plans = NULL;
266
237
 
267
238
        return(node);
268
239
}
269
240
 
270
 
/*********************************************************************//**
 
241
/*************************************************************************
271
242
Frees the memory private to a select node when a query graph is freed,
272
243
does not free the heap where the node was originally created. */
273
244
UNIV_INTERN
274
245
void
275
246
sel_node_free_private(
276
247
/*==================*/
277
 
        sel_node_t*     node)   /*!< in: select node struct */
 
248
        sel_node_t*     node)   /* in: select node struct */
278
249
{
279
250
        ulint   i;
280
251
        plan_t* plan;
293
264
        }
294
265
}
295
266
 
296
 
/*********************************************************************//**
 
267
/*************************************************************************
297
268
Evaluates the values in a select list. If there are aggregate functions,
298
269
their argument value is added to the aggregate total. */
299
270
UNIV_INLINE
300
271
void
301
272
sel_eval_select_list(
302
273
/*=================*/
303
 
        sel_node_t*     node)   /*!< in: select node */
 
274
        sel_node_t*     node)   /* in: select node */
304
275
{
305
276
        que_node_t*     exp;
306
277
 
313
284
        }
314
285
}
315
286
 
316
 
/*********************************************************************//**
 
287
/*************************************************************************
317
288
Assigns the values in the select list to the possible into-variables in
318
289
SELECT ... INTO ... */
319
290
UNIV_INLINE
320
291
void
321
292
sel_assign_into_var_values(
322
293
/*=======================*/
323
 
        sym_node_t*     var,    /*!< in: first variable in a list of variables */
324
 
        sel_node_t*     node)   /*!< in: select node */
 
294
        sym_node_t*     var,    /* in: first variable in a list of variables */
 
295
        sel_node_t*     node)   /* in: select node */
325
296
{
326
297
        que_node_t*     exp;
327
298
 
338
309
                eval_node_copy_val(var->alias, exp);
339
310
 
340
311
                exp = que_node_get_next(exp);
341
 
                var = static_cast<sym_node_t *>(que_node_get_next(var));
 
312
                var = que_node_get_next(var);
342
313
        }
343
314
}
344
315
 
345
 
/*********************************************************************//**
 
316
/*************************************************************************
346
317
Resets the aggregate value totals in the select list of an aggregate type
347
318
query. */
348
319
UNIV_INLINE
349
320
void
350
321
sel_reset_aggregate_vals(
351
322
/*=====================*/
352
 
        sel_node_t*     node)   /*!< in: select node */
 
323
        sel_node_t*     node)   /* in: select node */
353
324
{
354
325
        func_node_t*    func_node;
355
326
 
356
327
        ut_ad(node->is_aggregate);
357
328
 
358
 
        func_node = static_cast<func_node_t *>(node->select_list);
 
329
        func_node = node->select_list;
359
330
 
360
331
        while (func_node) {
361
332
                eval_node_set_int_val(func_node, 0);
362
333
 
363
 
                func_node = static_cast<func_node_t *>(que_node_get_next(func_node));
 
334
                func_node = que_node_get_next(func_node);
364
335
        }
365
336
 
366
337
        node->aggregate_already_fetched = FALSE;
367
338
}
368
339
 
369
 
/*********************************************************************//**
 
340
/*************************************************************************
370
341
Copies the input variable values when an explicit cursor is opened. */
371
342
UNIV_INLINE
372
343
void
373
344
row_sel_copy_input_variable_vals(
374
345
/*=============================*/
375
 
        sel_node_t*     node)   /*!< in: select node */
 
346
        sel_node_t*     node)   /* in: select node */
376
347
{
377
348
        sym_node_t*     var;
378
349
 
387
358
        }
388
359
}
389
360
 
390
 
/*********************************************************************//**
 
361
/*************************************************************************
391
362
Fetches the column values from a record. */
392
363
static
393
364
void
394
365
row_sel_fetch_columns(
395
366
/*==================*/
396
 
        dict_index_t*   index,  /*!< in: record index */
397
 
        const rec_t*    rec,    /*!< in: record in a clustered or non-clustered
 
367
        dict_index_t*   index,  /* in: record index */
 
368
        const rec_t*    rec,    /* in: record in a clustered or non-clustered
398
369
                                index; must be protected by a page latch */
399
 
        const ulint*    offsets,/*!< in: rec_get_offsets(rec, index) */
400
 
        sym_node_t*     column) /*!< in: first column in a column list, or
 
370
        const ulint*    offsets,/* in: rec_get_offsets(rec, index) */
 
371
        sym_node_t*     column) /* in: first column in a column list, or
401
372
                                NULL */
402
373
{
403
374
        dfield_t*       val;
426
397
                                                              field_no))) {
427
398
 
428
399
                                /* Copy an externally stored field to the
429
 
                                temporary heap, if possible. */
 
400
                                temporary heap */
430
401
 
431
402
                                heap = mem_heap_create(1);
432
403
 
435
406
                                        dict_table_zip_size(index->table),
436
407
                                        field_no, &len, heap);
437
408
 
438
 
                                /* data == NULL means that the
439
 
                                externally stored field was not
440
 
                                written yet. This record
441
 
                                should only be seen by
442
 
                                recv_recovery_rollback_active() or any
443
 
                                TRX_ISO_READ_UNCOMMITTED
444
 
                                transactions. The InnoDB SQL parser
445
 
                                (the sole caller of this function)
446
 
                                does not implement READ UNCOMMITTED,
447
 
                                and it is not involved during rollback. */
448
 
                                ut_a(data);
449
409
                                ut_a(len != UNIV_SQL_NULL);
450
410
 
451
411
                                needs_copy = TRUE;
453
413
                                data = rec_get_nth_field(rec, offsets,
454
414
                                                         field_no, &len);
455
415
 
 
416
                                if (len == UNIV_SQL_NULL) {
 
417
                                        len = UNIV_SQL_NULL;
 
418
                                }
 
419
 
456
420
                                needs_copy = column->copy_val;
457
421
                        }
458
422
 
473
437
        }
474
438
}
475
439
 
476
 
/*********************************************************************//**
 
440
/*************************************************************************
477
441
Allocates a prefetch buffer for a column when prefetch is first time done. */
478
442
static
479
443
void
480
444
sel_col_prefetch_buf_alloc(
481
445
/*=======================*/
482
 
        sym_node_t*     column) /*!< in: symbol table node for a column */
 
446
        sym_node_t*     column) /* in: symbol table node for a column */
483
447
{
484
448
        sel_buf_t*      sel_buf;
485
449
        ulint           i;
486
450
 
487
451
        ut_ad(que_node_get_type(column) == QUE_NODE_SYMBOL);
488
452
 
489
 
        column->prefetch_buf = static_cast<sel_buf_t *>(mem_alloc(SEL_MAX_N_PREFETCH
490
 
                                                                  * sizeof(sel_buf_t)));
 
453
        column->prefetch_buf = mem_alloc(SEL_MAX_N_PREFETCH
 
454
                                         * sizeof(sel_buf_t));
491
455
        for (i = 0; i < SEL_MAX_N_PREFETCH; i++) {
492
456
                sel_buf = column->prefetch_buf + i;
493
457
 
497
461
        }
498
462
}
499
463
 
500
 
/*********************************************************************//**
 
464
/*************************************************************************
501
465
Frees a prefetch buffer for a column, including the dynamically allocated
502
466
memory for data stored there. */
503
467
UNIV_INTERN
504
468
void
505
469
sel_col_prefetch_buf_free(
506
470
/*======================*/
507
 
        sel_buf_t*      prefetch_buf)   /*!< in, own: prefetch buffer */
 
471
        sel_buf_t*      prefetch_buf)   /* in, own: prefetch buffer */
508
472
{
509
473
        sel_buf_t*      sel_buf;
510
474
        ulint           i;
519
483
        }
520
484
}
521
485
 
522
 
/*********************************************************************//**
 
486
/*************************************************************************
523
487
Pops the column values for a prefetched, cached row from the column prefetch
524
488
buffers and places them to the val fields in the column nodes. */
525
489
static
526
490
void
527
491
sel_pop_prefetched_row(
528
492
/*===================*/
529
 
        plan_t* plan)   /*!< in: plan node for a table */
 
493
        plan_t* plan)   /* in: plan node for a table */
530
494
{
531
495
        sym_node_t*     column;
532
496
        sel_buf_t*      sel_buf;
566
530
                column values to be able to free it later: therefore
567
531
                we swap the values for sel_buf and val */
568
532
 
569
 
                sel_buf->data = static_cast<byte *>(dfield_get_data(val));
 
533
                sel_buf->data = dfield_get_data(val);
570
534
                sel_buf->len = dfield_get_len(val);
571
535
                sel_buf->val_buf_size = que_node_get_val_buf_size(column);
572
536
 
581
545
        plan->first_prefetched++;
582
546
}
583
547
 
584
 
/*********************************************************************//**
 
548
/*************************************************************************
585
549
Pushes the column values for a prefetched, cached row to the column prefetch
586
550
buffers from the val fields in the column nodes. */
587
551
UNIV_INLINE
588
552
void
589
553
sel_push_prefetched_row(
590
554
/*====================*/
591
 
        plan_t* plan)   /*!< in: plan node for a table */
 
555
        plan_t* plan)   /* in: plan node for a table */
592
556
{
593
557
        sym_node_t*     column;
594
558
        sel_buf_t*      sel_buf;
634
598
 
635
599
                val = que_node_get_val(column);
636
600
 
637
 
                data = static_cast<byte *>(dfield_get_data(val));
 
601
                data = dfield_get_data(val);
638
602
                len = dfield_get_len(val);
639
603
                val_buf_size = que_node_get_val_buf_size(column);
640
604
 
653
617
        }
654
618
}
655
619
 
656
 
/*********************************************************************//**
657
 
Builds a previous version of a clustered index record for a consistent read
658
 
@return DB_SUCCESS or error code */
 
620
/*************************************************************************
 
621
Builds a previous version of a clustered index record for a consistent read */
659
622
static
660
623
ulint
661
624
row_sel_build_prev_vers(
662
625
/*====================*/
663
 
        read_view_t*    read_view,      /*!< in: read view */
664
 
        dict_index_t*   index,          /*!< in: plan node for table */
665
 
        rec_t*          rec,            /*!< in: record in a clustered index */
666
 
        ulint**         offsets,        /*!< in/out: offsets returned by
 
626
                                        /* out: DB_SUCCESS or error code */
 
627
        read_view_t*    read_view,      /* in: read view */
 
628
        dict_index_t*   index,          /* in: plan node for table */
 
629
        rec_t*          rec,            /* in: record in a clustered index */
 
630
        ulint**         offsets,        /* in/out: offsets returned by
667
631
                                        rec_get_offsets(rec, plan->index) */
668
 
        mem_heap_t**    offset_heap,    /*!< in/out: memory heap from which
 
632
        mem_heap_t**    offset_heap,    /* in/out: memory heap from which
669
633
                                        the offsets are allocated */
670
 
        mem_heap_t**    old_vers_heap,  /*!< out: old version heap to use */
671
 
        rec_t**         old_vers,       /*!< out: old version, or NULL if the
 
634
        mem_heap_t**    old_vers_heap,  /* out: old version heap to use */
 
635
        rec_t**         old_vers,       /* out: old version, or NULL if the
672
636
                                        record does not exist in the view:
673
637
                                        i.e., it was freshly inserted
674
638
                                        afterwards */
675
 
        mtr_t*          mtr)            /*!< in: mtr */
 
639
        mtr_t*          mtr)            /* in: mtr */
676
640
{
677
641
        ulint   err;
678
642
 
688
652
        return(err);
689
653
}
690
654
 
691
 
/*********************************************************************//**
 
655
/*************************************************************************
692
656
Builds the last committed version of a clustered index record for a
693
 
semi-consistent read.
694
 
@return DB_SUCCESS or error code */
 
657
semi-consistent read. */
695
658
static
696
659
ulint
697
660
row_sel_build_committed_vers_for_mysql(
698
661
/*===================================*/
699
 
        dict_index_t*   clust_index,    /*!< in: clustered index */
700
 
        row_prebuilt_t* prebuilt,       /*!< in: prebuilt struct */
701
 
        const rec_t*    rec,            /*!< in: record in a clustered index */
702
 
        ulint**         offsets,        /*!< in/out: offsets returned by
 
662
                                        /* out: DB_SUCCESS or error code */
 
663
        dict_index_t*   clust_index,    /* in: clustered index */
 
664
        row_prebuilt_t* prebuilt,       /* in: prebuilt struct */
 
665
        const rec_t*    rec,            /* in: record in a clustered index */
 
666
        ulint**         offsets,        /* in/out: offsets returned by
703
667
                                        rec_get_offsets(rec, clust_index) */
704
 
        mem_heap_t**    offset_heap,    /*!< in/out: memory heap from which
 
668
        mem_heap_t**    offset_heap,    /* in/out: memory heap from which
705
669
                                        the offsets are allocated */
706
 
        const rec_t**   old_vers,       /*!< out: old version, or NULL if the
 
670
        const rec_t**   old_vers,       /* out: old version, or NULL if the
707
671
                                        record does not exist in the view:
708
672
                                        i.e., it was freshly inserted
709
673
                                        afterwards */
710
 
        mtr_t*          mtr)            /*!< in: mtr */
 
674
        mtr_t*          mtr)            /* in: mtr */
711
675
{
712
676
        ulint   err;
713
677
 
723
687
        return(err);
724
688
}
725
689
 
726
 
/*********************************************************************//**
 
690
/*************************************************************************
727
691
Tests the conditions which determine when the index segment we are searching
728
 
through has been exhausted.
729
 
@return TRUE if row passed the tests */
 
692
through has been exhausted. */
730
693
UNIV_INLINE
731
694
ibool
732
695
row_sel_test_end_conds(
733
696
/*===================*/
734
 
        plan_t* plan)   /*!< in: plan for the table; the column values must
 
697
                        /* out: TRUE if row passed the tests */
 
698
        plan_t* plan)   /* in: plan for the table; the column values must
735
699
                        already have been retrieved and the right sides of
736
700
                        comparisons evaluated */
737
701
{
746
710
                /* Evaluate the left side of the comparison, i.e., get the
747
711
                column value if there is an indirection */
748
712
 
749
 
          eval_sym(static_cast<sym_node_t *>(cond->args));
 
713
                eval_sym(cond->args);
750
714
 
751
715
                /* Do the comparison */
752
716
 
761
725
        return(TRUE);
762
726
}
763
727
 
764
 
/*********************************************************************//**
765
 
Tests the other conditions.
766
 
@return TRUE if row passed the tests */
 
728
/*************************************************************************
 
729
Tests the other conditions. */
767
730
UNIV_INLINE
768
731
ibool
769
732
row_sel_test_other_conds(
770
733
/*=====================*/
771
 
        plan_t* plan)   /*!< in: plan for the table; the column values must
 
734
                        /* out: TRUE if row passed the tests */
 
735
        plan_t* plan)   /* in: plan for the table; the column values must
772
736
                        already have been retrieved */
773
737
{
774
738
        func_node_t*    cond;
789
753
        return(TRUE);
790
754
}
791
755
 
792
 
/*********************************************************************//**
 
756
/*************************************************************************
793
757
Retrieves the clustered index record corresponding to a record in a
794
 
non-clustered index. Does the necessary locking.
795
 
@return DB_SUCCESS or error code */
 
758
non-clustered index. Does the necessary locking. */
796
759
static
797
760
ulint
798
761
row_sel_get_clust_rec(
799
762
/*==================*/
800
 
        sel_node_t*     node,   /*!< in: select_node */
801
 
        plan_t*         plan,   /*!< in: plan node for table */
802
 
        rec_t*          rec,    /*!< in: record in a non-clustered index */
803
 
        que_thr_t*      thr,    /*!< in: query thread */
804
 
        rec_t**         out_rec,/*!< out: clustered record or an old version of
 
763
                                /* out: DB_SUCCESS or error code */
 
764
        sel_node_t*     node,   /* in: select_node */
 
765
        plan_t*         plan,   /* in: plan node for table */
 
766
        rec_t*          rec,    /* in: record in a non-clustered index */
 
767
        que_thr_t*      thr,    /* in: query thread */
 
768
        rec_t**         out_rec,/* out: clustered record or an old version of
805
769
                                it, NULL if the old version did not exist
806
770
                                in the read view, i.e., it was a fresh
807
771
                                inserted version */
808
 
        mtr_t*          mtr)    /*!< in: mtr used to get access to the
 
772
        mtr_t*          mtr)    /* in: mtr used to get access to the
809
773
                                non-clustered record; the same mtr is used to
810
774
                                access the clustered index */
811
775
{
829
793
        index = dict_table_get_first_index(plan->table);
830
794
 
831
795
        btr_pcur_open_with_no_init(index, plan->clust_ref, PAGE_CUR_LE,
832
 
                                   BTR_SEARCH_LEAF, &plan->clust_pcur,
 
796
                                   node->latch_mode, &(plan->clust_pcur),
833
797
                                   0, mtr);
834
798
 
835
799
        clust_rec = btr_pcur_get_rec(&(plan->clust_pcur));
873
837
                trx = thr_get_trx(thr);
874
838
 
875
839
                if (srv_locks_unsafe_for_binlog
876
 
                    || trx->isolation_level <= TRX_ISO_READ_COMMITTED) {
 
840
                    || trx->isolation_level == TRX_ISO_READ_COMMITTED) {
877
841
                        lock_type = LOCK_REC_NOT_GAP;
878
842
                } else {
879
843
                        lock_type = LOCK_ORDINARY;
882
846
                err = lock_clust_rec_read_check_and_lock(
883
847
                        0, btr_pcur_get_block(&plan->clust_pcur),
884
848
                        clust_rec, index, offsets,
885
 
                        static_cast<lock_mode>(node->row_lock_mode), lock_type, thr);
886
 
 
887
 
                switch (err) {
888
 
                case DB_SUCCESS:
889
 
                case DB_SUCCESS_LOCKED_REC:
890
 
                        /* Declare the variable uninitialized in Valgrind.
891
 
                        It should be set to DB_SUCCESS at func_exit. */
892
 
                        UNIV_MEM_INVALID(&err, sizeof err);
893
 
                        break;
894
 
                default:
 
849
                        node->row_lock_mode, lock_type, thr);
 
850
 
 
851
                if (err != DB_SUCCESS) {
 
852
 
895
853
                        goto err_exit;
896
854
                }
897
855
        } else {
947
905
        when plan->clust_pcur was positioned.  The latch will not be
948
906
        released until mtr_commit(mtr). */
949
907
 
950
 
        ut_ad(!rec_get_deleted_flag(clust_rec, rec_offs_comp(offsets)));
951
908
        row_sel_fetch_columns(index, clust_rec, offsets,
952
909
                              UT_LIST_GET_FIRST(plan->columns));
953
910
        *out_rec = clust_rec;
960
917
        return(err);
961
918
}
962
919
 
963
 
/*********************************************************************//**
964
 
Sets a lock on a record.
965
 
@return DB_SUCCESS, DB_SUCCESS_LOCKED_REC, or error code */
 
920
/*************************************************************************
 
921
Sets a lock on a record. */
966
922
UNIV_INLINE
967
 
enum db_err
 
923
ulint
968
924
sel_set_rec_lock(
969
925
/*=============*/
970
 
        const buf_block_t*      block,  /*!< in: buffer block of rec */
971
 
        const rec_t*            rec,    /*!< in: record */
972
 
        dict_index_t*           index,  /*!< in: index */
973
 
        const ulint*            offsets,/*!< in: rec_get_offsets(rec, index) */
974
 
        ulint                   mode,   /*!< in: lock mode */
975
 
        ulint                   type,   /*!< in: LOCK_ORDINARY, LOCK_GAP, or
 
926
                                        /* out: DB_SUCCESS or error code */
 
927
        const buf_block_t*      block,  /* in: buffer block of rec */
 
928
        const rec_t*            rec,    /* in: record */
 
929
        dict_index_t*           index,  /* in: index */
 
930
        const ulint*            offsets,/* in: rec_get_offsets(rec, index) */
 
931
        ulint                   mode,   /* in: lock mode */
 
932
        ulint                   type,   /* in: LOCK_ORDINARY, LOCK_GAP, or
976
933
                                        LOC_REC_NOT_GAP */
977
 
        que_thr_t*              thr)    /*!< in: query thread */
 
934
        que_thr_t*              thr)    /* in: query thread */
978
935
{
979
 
        trx_t*          trx;
980
 
        enum db_err     err;
 
936
        trx_t*  trx;
 
937
        ulint   err;
981
938
 
982
939
        trx = thr_get_trx(thr);
983
940
 
989
946
        }
990
947
 
991
948
        if (dict_index_is_clust(index)) {
992
 
                err = lock_clust_rec_read_check_and_lock(0, block, rec, index,
993
 
                                                         offsets, static_cast<lock_mode>(mode), type, thr);
 
949
                err = lock_clust_rec_read_check_and_lock(
 
950
                        0, block, rec, index, offsets, mode, type, thr);
994
951
        } else {
995
 
                err = lock_sec_rec_read_check_and_lock(0, block, rec, index,
996
 
                                                       offsets, static_cast<lock_mode>(mode), type, thr);
 
952
                err = lock_sec_rec_read_check_and_lock(
 
953
                        0, block, rec, index, offsets, mode, type, thr);
997
954
        }
998
955
 
999
956
        return(err);
1000
957
}
1001
958
 
1002
 
/*********************************************************************//**
 
959
/*************************************************************************
1003
960
Opens a pcur to a table index. */
1004
961
static
1005
962
void
1006
963
row_sel_open_pcur(
1007
964
/*==============*/
1008
 
        plan_t*         plan,           /*!< in: table plan */
 
965
        sel_node_t*     node,           /* in: select node */
 
966
        plan_t*         plan,           /* in: table plan */
1009
967
        ibool           search_latch_locked,
1010
 
                                        /*!< in: TRUE if the thread currently
 
968
                                        /* in: TRUE if the thread currently
1011
969
                                        has the search latch locked in
1012
970
                                        s-mode */
1013
 
        mtr_t*          mtr)            /*!< in: mtr */
 
971
        mtr_t*          mtr)            /* in: mtr */
1014
972
{
1015
973
        dict_index_t*   index;
1016
974
        func_node_t*    cond;
1057
1015
                /* Open pcur to the index */
1058
1016
 
1059
1017
                btr_pcur_open_with_no_init(index, plan->tuple, plan->mode,
1060
 
                                           BTR_SEARCH_LEAF, &plan->pcur,
 
1018
                                           node->latch_mode, &(plan->pcur),
1061
1019
                                           has_search_latch, mtr);
1062
1020
        } else {
1063
1021
                /* Open the cursor to the start or the end of the index
1064
1022
                (FALSE: no init) */
1065
1023
 
1066
 
                btr_pcur_open_at_index_side(plan->asc, index, BTR_SEARCH_LEAF,
 
1024
                btr_pcur_open_at_index_side(plan->asc, index, node->latch_mode,
1067
1025
                                            &(plan->pcur), FALSE, mtr);
1068
1026
        }
1069
1027
 
1074
1032
        plan->pcur_is_open = TRUE;
1075
1033
}
1076
1034
 
1077
 
/*********************************************************************//**
1078
 
Restores a stored pcur position to a table index.
1079
 
@return TRUE if the cursor should be moved to the next record after we
1080
 
return from this function (moved to the previous, in the case of a
1081
 
descending cursor) without processing again the current cursor
1082
 
record */
 
1035
/*************************************************************************
 
1036
Restores a stored pcur position to a table index. */
1083
1037
static
1084
1038
ibool
1085
1039
row_sel_restore_pcur_pos(
1086
1040
/*=====================*/
1087
 
        plan_t*         plan,   /*!< in: table plan */
1088
 
        mtr_t*          mtr)    /*!< in: mtr */
 
1041
                                /* out: TRUE if the cursor should be moved to
 
1042
                                the next record after we return from this
 
1043
                                function (moved to the previous, in the case
 
1044
                                of a descending cursor) without processing
 
1045
                                again the current cursor record */
 
1046
        sel_node_t*     node,   /* in: select node */
 
1047
        plan_t*         plan,   /* in: table plan */
 
1048
        mtr_t*          mtr)    /* in: mtr */
1089
1049
{
1090
1050
        ibool   equal_position;
1091
1051
        ulint   relative_position;
1094
1054
 
1095
1055
        relative_position = btr_pcur_get_rel_pos(&(plan->pcur));
1096
1056
 
1097
 
        equal_position = btr_pcur_restore_position(BTR_SEARCH_LEAF,
 
1057
        equal_position = btr_pcur_restore_position(node->latch_mode,
1098
1058
                                                   &(plan->pcur), mtr);
1099
1059
 
1100
1060
        /* If the cursor is traveling upwards, and relative_position is
1169
1129
        return(TRUE);
1170
1130
}
1171
1131
 
1172
 
/*********************************************************************//**
 
1132
/*************************************************************************
1173
1133
Resets a plan cursor to a closed state. */
1174
1134
UNIV_INLINE
1175
1135
void
1176
1136
plan_reset_cursor(
1177
1137
/*==============*/
1178
 
        plan_t* plan)   /*!< in: plan */
 
1138
        plan_t* plan)   /* in: plan */
1179
1139
{
1180
1140
        plan->pcur_is_open = FALSE;
1181
1141
        plan->cursor_at_end = FALSE;
1183
1143
        plan->n_rows_prefetched = 0;
1184
1144
}
1185
1145
 
1186
 
/*********************************************************************//**
 
1146
/*************************************************************************
1187
1147
Tries to do a shortcut to fetch a clustered index record with a unique key,
1188
 
using the hash index if possible (not always).
1189
 
@return SEL_FOUND, SEL_EXHAUSTED, SEL_RETRY */
 
1148
using the hash index if possible (not always). */
1190
1149
static
1191
1150
ulint
1192
1151
row_sel_try_search_shortcut(
1193
1152
/*========================*/
1194
 
        sel_node_t*     node,   /*!< in: select node for a consistent read */
1195
 
        plan_t*         plan,   /*!< in: plan for a unique search in clustered
 
1153
                                /* out: SEL_FOUND, SEL_EXHAUSTED, SEL_RETRY */
 
1154
        sel_node_t*     node,   /* in: select node for a consistent read */
 
1155
        plan_t*         plan,   /* in: plan for a unique search in clustered
1196
1156
                                index */
1197
 
        mtr_t*          mtr)    /*!< in: mtr */
 
1157
        mtr_t*          mtr)    /* in: mtr */
1198
1158
{
1199
1159
        dict_index_t*   index;
1200
1160
        rec_t*          rec;
1213
1173
        ut_ad(rw_lock_own(&btr_search_latch, RW_LOCK_SHARED));
1214
1174
#endif /* UNIV_SYNC_DEBUG */
1215
1175
 
1216
 
        row_sel_open_pcur(plan, TRUE, mtr);
 
1176
        row_sel_open_pcur(node, plan, TRUE, mtr);
1217
1177
 
1218
1178
        rec = btr_pcur_get_rec(&(plan->pcur));
1219
1179
 
1274
1234
                goto func_exit;
1275
1235
        }
1276
1236
 
1277
 
        ut_ad(plan->pcur.latch_mode == BTR_SEARCH_LEAF);
 
1237
        ut_ad(plan->pcur.latch_mode == node->latch_mode);
1278
1238
 
1279
1239
        plan->n_rows_fetched++;
1280
1240
        ret = SEL_FOUND;
1285
1245
        return(ret);
1286
1246
}
1287
1247
 
1288
 
/*********************************************************************//**
1289
 
Performs a select step.
1290
 
@return DB_SUCCESS or error code */
 
1248
/*************************************************************************
 
1249
Performs a select step. */
1291
1250
static
1292
1251
ulint
1293
1252
row_sel(
1294
1253
/*====*/
1295
 
        sel_node_t*     node,   /*!< in: select node */
1296
 
        que_thr_t*      thr)    /*!< in: query thread */
 
1254
                                /* out: DB_SUCCESS or error code */
 
1255
        sel_node_t*     node,   /* in: select node */
 
1256
        que_thr_t*      thr)    /* in: query thread */
1297
1257
{
1298
1258
        dict_index_t*   index;
1299
1259
        plan_t*         plan;
1314
1274
        ulint           cost_counter                    = 0;
1315
1275
        ibool           cursor_just_opened;
1316
1276
        ibool           must_go_to_next;
 
1277
        ibool           leaf_contains_updates           = FALSE;
 
1278
        /* TRUE if select_will_do_update is
 
1279
        TRUE and the current clustered index
 
1280
        leaf page has been updated during
 
1281
        the current mtr: mtr must be committed
 
1282
        at the same time as the leaf x-latch
 
1283
        is released */
1317
1284
        ibool           mtr_has_extra_clust_latch       = FALSE;
1318
1285
        /* TRUE if the search was made using
1319
1286
        a non-clustered index, and we had to
1352
1319
        node->fetch_table changes, and after adding a row to aggregate totals
1353
1320
        and, of course, when this function is called. */
1354
1321
 
 
1322
        ut_ad(leaf_contains_updates == FALSE);
1355
1323
        ut_ad(mtr_has_extra_clust_latch == FALSE);
1356
1324
 
1357
1325
        plan = sel_node_get_nth_plan(node, node->fetch_table);
1384
1352
                        rw_lock_s_lock(&btr_search_latch);
1385
1353
 
1386
1354
                        search_latch_locked = TRUE;
1387
 
                } else if (rw_lock_get_writer(&btr_search_latch) == RW_LOCK_WAIT_EX) {
 
1355
                } else if (btr_search_latch.writer_is_wait_ex) {
1388
1356
 
1389
1357
                        /* There is an x-latch request waiting: release the
1390
1358
                        s-latch for a moment; as an s-latch here is often
1426
1394
                /* Evaluate the expressions to build the search tuple and
1427
1395
                open the cursor */
1428
1396
 
1429
 
                row_sel_open_pcur(plan, search_latch_locked, &mtr);
 
1397
                row_sel_open_pcur(node, plan, search_latch_locked, &mtr);
1430
1398
 
1431
1399
                cursor_just_opened = TRUE;
1432
1400
 
1435
1403
        } else {
1436
1404
                /* Restore pcur position to the index */
1437
1405
 
1438
 
                must_go_to_next = row_sel_restore_pcur_pos(plan, &mtr);
 
1406
                must_go_to_next = row_sel_restore_pcur_pos(node, plan, &mtr);
1439
1407
 
1440
1408
                cursor_just_opened = FALSE;
1441
1409
 
1493
1461
 
1494
1462
                        if (srv_locks_unsafe_for_binlog
1495
1463
                            || trx->isolation_level
1496
 
                            <= TRX_ISO_READ_COMMITTED) {
 
1464
                            == TRX_ISO_READ_COMMITTED) {
1497
1465
 
1498
1466
                                if (page_rec_is_supremum(next_rec)) {
1499
1467
 
1510
1478
                                               node->row_lock_mode,
1511
1479
                                               lock_type, thr);
1512
1480
 
1513
 
                        switch (err) {
1514
 
                        case DB_SUCCESS_LOCKED_REC:
1515
 
                                err = DB_SUCCESS;
1516
 
                        case DB_SUCCESS:
1517
 
                                break;
1518
 
                        default:
 
1481
                        if (err != DB_SUCCESS) {
1519
1482
                                /* Note that in this case we will store in pcur
1520
1483
                                the PREDECESSOR of the record we are waiting
1521
1484
                                the lock for */
 
1485
 
1522
1486
                                goto lock_wait_or_error;
1523
1487
                        }
1524
1488
                }
1554
1518
                trx = thr_get_trx(thr);
1555
1519
 
1556
1520
                if (srv_locks_unsafe_for_binlog
1557
 
                    || trx->isolation_level <= TRX_ISO_READ_COMMITTED) {
 
1521
                    || trx->isolation_level == TRX_ISO_READ_COMMITTED) {
1558
1522
 
1559
1523
                        if (page_rec_is_supremum(rec)) {
1560
1524
 
1570
1534
                                       rec, index, offsets,
1571
1535
                                       node->row_lock_mode, lock_type, thr);
1572
1536
 
1573
 
                switch (err) {
1574
 
                case DB_SUCCESS_LOCKED_REC:
1575
 
                        err = DB_SUCCESS;
1576
 
                case DB_SUCCESS:
1577
 
                        break;
1578
 
                default:
 
1537
                if (err != DB_SUCCESS) {
 
1538
 
1579
1539
                        goto lock_wait_or_error;
1580
1540
                }
1581
1541
        }
1650
1610
                                }
1651
1611
 
1652
1612
                                if (old_vers == NULL) {
1653
 
                                        /* The record does not exist
1654
 
                                        in our read view. Skip it, but
1655
 
                                        first attempt to determine
1656
 
                                        whether the index segment we
1657
 
                                        are searching through has been
1658
 
                                        exhausted. */
1659
 
 
1660
1613
                                        offsets = rec_get_offsets(
1661
1614
                                                rec, index, offsets,
1662
1615
                                                ULINT_UNDEFINED, &heap);
1729
1682
                goto next_rec;
1730
1683
        }
1731
1684
 
 
1685
 
1732
1686
        /* PHASE 5: Get the clustered index record, if needed and if we did
1733
1687
        not do the search using the clustered index */
1734
1688
 
1741
1695
                                            &mtr);
1742
1696
                mtr_has_extra_clust_latch = TRUE;
1743
1697
 
1744
 
                switch (err) {
1745
 
                case DB_SUCCESS_LOCKED_REC:
1746
 
                        err = DB_SUCCESS;
1747
 
                case DB_SUCCESS:
1748
 
                        break;
1749
 
                default:
 
1698
                if (err != DB_SUCCESS) {
 
1699
 
1750
1700
                        goto lock_wait_or_error;
1751
1701
                }
1752
1702
 
1793
1743
 
1794
1744
        plan->n_rows_fetched++;
1795
1745
 
1796
 
        ut_ad(plan->pcur.latch_mode == BTR_SEARCH_LEAF);
 
1746
        ut_ad(plan->pcur.latch_mode == node->latch_mode);
 
1747
 
 
1748
        if (node->select_will_do_update) {
 
1749
                /* This is a searched update and we can do the update in-place,
 
1750
                saving CPU time */
 
1751
 
 
1752
                row_upd_in_place_in_select(node, thr, &mtr);
 
1753
 
 
1754
                leaf_contains_updates = TRUE;
 
1755
 
 
1756
                /* When the database is in the online backup mode, the number
 
1757
                of log records for a single mtr should be small: increment the
 
1758
                cost counter to ensure it */
 
1759
 
 
1760
                cost_counter += 1 + (SEL_COST_LIMIT / 8);
 
1761
 
 
1762
                if (plan->unique_search) {
 
1763
 
 
1764
                        goto table_exhausted;
 
1765
                }
 
1766
 
 
1767
                goto next_rec;
 
1768
        }
1797
1769
 
1798
1770
        if ((plan->n_rows_fetched <= SEL_PREFETCH_LIMIT)
1799
1771
            || plan->unique_search || plan->no_prefetch
1828
1800
                goto commit_mtr_for_a_while;
1829
1801
        }
1830
1802
 
 
1803
        if (leaf_contains_updates
 
1804
            && btr_pcur_is_after_last_on_page(&plan->pcur)) {
 
1805
 
 
1806
                /* We must commit &mtr if we are moving to a different page,
 
1807
                because we have done updates to the x-latched leaf page, and
 
1808
                the latch would be released in btr_pcur_move_to_next, without
 
1809
                &mtr getting committed there */
 
1810
 
 
1811
                ut_ad(node->asc);
 
1812
 
 
1813
                goto commit_mtr_for_a_while;
 
1814
        }
 
1815
 
1831
1816
        if (node->asc) {
1832
1817
                moved = btr_pcur_move_to_next(&(plan->pcur), &mtr);
1833
1818
        } else {
1864
1849
 
1865
1850
        mtr_commit(&mtr);
1866
1851
 
 
1852
        leaf_contains_updates = FALSE;
1867
1853
        mtr_has_extra_clust_latch = FALSE;
1868
1854
 
1869
1855
next_table_no_mtr:
1904
1890
 
1905
1891
        mtr_commit(&mtr);
1906
1892
 
 
1893
        leaf_contains_updates = FALSE;
1907
1894
        mtr_has_extra_clust_latch = FALSE;
1908
1895
 
1909
1896
        if (plan->n_rows_prefetched > 0) {
1931
1918
                        thr->run_node = que_node_get_parent(node);
1932
1919
                }
1933
1920
 
1934
 
                err = DB_SUCCESS;
1935
1921
                goto func_exit;
1936
1922
        }
1937
1923
 
1973
1959
 
1974
1960
        mtr_commit(&mtr);
1975
1961
 
 
1962
        leaf_contains_updates = FALSE;
1976
1963
        mtr_has_extra_clust_latch = FALSE;
1977
1964
 
1978
1965
#ifdef UNIV_SYNC_DEBUG
2006
1993
        return(err);
2007
1994
}
2008
1995
 
2009
 
/**********************************************************************//**
 
1996
/**************************************************************************
2010
1997
Performs a select step. This is a high-level function used in SQL execution
2011
 
graphs.
2012
 
@return query thread to run next or NULL */
 
1998
graphs. */
2013
1999
UNIV_INTERN
2014
2000
que_thr_t*
2015
2001
row_sel_step(
2016
2002
/*=========*/
2017
 
        que_thr_t*      thr)    /*!< in: query thread */
 
2003
                                /* out: query thread to run next or NULL */
 
2004
        que_thr_t*      thr)    /* in: query thread */
2018
2005
{
2019
2006
        ulint           i_lock_mode;
2020
2007
        sym_node_t*     table_node;
2023
2010
 
2024
2011
        ut_ad(thr);
2025
2012
 
2026
 
        node = static_cast<sel_node_t *>(thr->run_node);
 
2013
        node = thr->run_node;
2027
2014
 
2028
2015
        ut_ad(que_node_get_type(node) == QUE_NODE_SELECT);
2029
2016
 
2060
2047
 
2061
2048
                        while (table_node) {
2062
2049
                                err = lock_table(0, table_node->table,
2063
 
                                                 static_cast<lock_mode>(i_lock_mode), thr);
 
2050
                                                 i_lock_mode, thr);
2064
2051
                                if (err != DB_SUCCESS) {
2065
2052
                                        thr_get_trx(thr)->error_state = err;
2066
2053
 
2067
2054
                                        return(NULL);
2068
2055
                                }
2069
2056
 
2070
 
                                table_node = static_cast<sym_node_t *>(que_node_get_next(table_node));
 
2057
                                table_node = que_node_get_next(table_node);
2071
2058
                        }
2072
2059
                }
2073
2060
 
2089
2076
                        /* Reset the aggregate total values */
2090
2077
                        sel_reset_aggregate_vals(node);
2091
2078
                }
2092
 
 
2093
 
                err = DB_SUCCESS;
2094
2079
        }
2095
2080
 
2096
2081
        err = row_sel(node, thr);
2110
2095
        return(thr);
2111
2096
}
2112
2097
 
2113
 
/**********************************************************************//**
2114
 
Performs a fetch for a cursor.
2115
 
@return query thread to run next or NULL */
 
2098
/**************************************************************************
 
2099
Performs a fetch for a cursor. */
2116
2100
UNIV_INTERN
2117
2101
que_thr_t*
2118
2102
fetch_step(
2119
2103
/*=======*/
2120
 
        que_thr_t*      thr)    /*!< in: query thread */
 
2104
                                /* out: query thread to run next or NULL */
 
2105
        que_thr_t*      thr)    /* in: query thread */
2121
2106
{
2122
2107
        sel_node_t*     sel_node;
2123
2108
        fetch_node_t*   node;
2124
2109
 
2125
2110
        ut_ad(thr);
2126
2111
 
2127
 
        node = static_cast<fetch_node_t *>(thr->run_node);
 
2112
        node = thr->run_node;
2128
2113
        sel_node = node->cursor_def;
2129
2114
 
2130
2115
        ut_ad(que_node_get_type(node) == QUE_NODE_FETCH);
2173
2158
        return(thr);
2174
2159
}
2175
2160
 
2176
 
/****************************************************************//**
2177
 
Sample callback function for fetch that prints each row.
2178
 
@return always returns non-NULL */
 
2161
/********************************************************************
 
2162
Sample callback function for fetch that prints each row.*/
2179
2163
UNIV_INTERN
2180
2164
void*
2181
2165
row_fetch_print(
2182
2166
/*============*/
2183
 
        void*   row,            /*!< in:  sel_node_t* */
2184
 
        void*   user_arg)       /*!< in:  not used */
 
2167
                                /* out: always returns non-NULL */
 
2168
        void*   row,            /* in:  sel_node_t* */
 
2169
        void*   user_arg)       /* in:  not used */
2185
2170
{
2186
 
        sel_node_t *node = static_cast<sel_node_t *>(row);
 
2171
        sel_node_t*     node = row;
2187
2172
        que_node_t*     exp;
2188
2173
        ulint           i = 0;
2189
2174
 
2217
2202
        return((void*)42);
2218
2203
}
2219
2204
 
2220
 
/***********************************************************//**
2221
 
Prints a row in a select result.
2222
 
@return query thread to run next or NULL */
 
2205
/********************************************************************
 
2206
Callback function for fetch that stores an unsigned 4 byte integer to the
 
2207
location pointed. The column's type must be DATA_INT, DATA_UNSIGNED, length
 
2208
= 4. */
 
2209
UNIV_INTERN
 
2210
void*
 
2211
row_fetch_store_uint4(
 
2212
/*==================*/
 
2213
                                /* out: always returns NULL */
 
2214
        void*   row,            /* in:  sel_node_t* */
 
2215
        void*   user_arg)       /* in:  data pointer */
 
2216
{
 
2217
        sel_node_t*     node = row;
 
2218
        ib_uint32_t*    val = user_arg;
 
2219
        ulint           tmp;
 
2220
 
 
2221
        dfield_t*       dfield = que_node_get_val(node->select_list);
 
2222
        const dtype_t*  type = dfield_get_type(dfield);
 
2223
        ulint           len = dfield_get_len(dfield);
 
2224
 
 
2225
        ut_a(dtype_get_mtype(type) == DATA_INT);
 
2226
        ut_a(dtype_get_prtype(type) & DATA_UNSIGNED);
 
2227
        ut_a(len == 4);
 
2228
 
 
2229
        tmp = mach_read_from_4(dfield_get_data(dfield));
 
2230
        *val = (ib_uint32_t) tmp;
 
2231
 
 
2232
        return(NULL);
 
2233
}
 
2234
 
 
2235
/***************************************************************
 
2236
Prints a row in a select result. */
2223
2237
UNIV_INTERN
2224
2238
que_thr_t*
2225
2239
row_printf_step(
2226
2240
/*============*/
2227
 
        que_thr_t*      thr)    /*!< in: query thread */
 
2241
                                /* out: query thread to run next or NULL */
 
2242
        que_thr_t*      thr)    /* in: query thread */
2228
2243
{
2229
2244
        row_printf_node_t*      node;
2230
2245
        sel_node_t*             sel_node;
2232
2247
 
2233
2248
        ut_ad(thr);
2234
2249
 
2235
 
        node = static_cast<row_printf_node_t *>(thr->run_node);
 
2250
        node = thr->run_node;
2236
2251
 
2237
2252
        sel_node = node->sel_node;
2238
2253
 
2280
2295
        return(thr);
2281
2296
}
2282
2297
 
2283
 
/****************************************************************//**
 
2298
/********************************************************************
2284
2299
Converts a key value stored in MySQL format to an Innobase dtuple. The last
2285
2300
field of the key value may be just a prefix of a fixed length field: hence
2286
2301
the parameter key_len. But currently we do not allow search keys where the
2291
2306
void
2292
2307
row_sel_convert_mysql_key_to_innobase(
2293
2308
/*==================================*/
2294
 
        dtuple_t*       tuple,          /*!< in/out: tuple where to build;
 
2309
        dtuple_t*       tuple,          /* in/out: tuple where to build;
2295
2310
                                        NOTE: we assume that the type info
2296
2311
                                        in the tuple is already according
2297
2312
                                        to index! */
2298
 
        byte*           buf,            /*!< in: buffer to use in field
 
2313
        byte*           buf,            /* in: buffer to use in field
2299
2314
                                        conversions */
2300
 
        ulint           buf_len,        /*!< in: buffer length */
2301
 
        dict_index_t*   index,          /*!< in: index of the key value */
2302
 
        const byte*     key_ptr,        /*!< in: MySQL key value */
2303
 
        ulint           key_len,        /*!< in: MySQL key value length */
2304
 
        trx_t*          trx)            /*!< in: transaction */
 
2315
        ulint           buf_len,        /* in: buffer length */
 
2316
        dict_index_t*   index,          /* in: index of the key value */
 
2317
        const byte*     key_ptr,        /* in: MySQL key value */
 
2318
        ulint           key_len,        /* in: MySQL key value length */
 
2319
        trx_t*          trx)            /* in: transaction */
2305
2320
{
2306
2321
        byte*           original_buf    = buf;
2307
2322
        const byte*     original_key_ptr = key_ptr;
2484
2499
        dtuple_set_n_fields(tuple, n_fields);
2485
2500
}
2486
2501
 
2487
 
/**************************************************************//**
 
2502
/******************************************************************
2488
2503
Stores the row id to the prebuilt struct. */
2489
2504
static
2490
2505
void
2491
2506
row_sel_store_row_id_to_prebuilt(
2492
2507
/*=============================*/
2493
 
        row_prebuilt_t*         prebuilt,       /*!< in/out: prebuilt */
2494
 
        const rec_t*            index_rec,      /*!< in: record */
2495
 
        const dict_index_t*     index,          /*!< in: index of the record */
2496
 
        const ulint*            offsets)        /*!< in: rec_get_offsets
 
2508
        row_prebuilt_t*         prebuilt,       /* in/out: prebuilt */
 
2509
        const rec_t*            index_rec,      /* in: record */
 
2510
        const dict_index_t*     index,          /* in: index of the record */
 
2511
        const ulint*            offsets)        /* in: rec_get_offsets
2497
2512
                                                (index_rec, index) */
2498
2513
{
2499
2514
        const byte*     data;
2522
2537
        ut_memcpy(prebuilt->row_id, data, len);
2523
2538
}
2524
2539
 
2525
 
/**************************************************************//**
 
2540
/******************************************************************
2526
2541
Stores a non-SQL-NULL field in the MySQL format. The counterpart of this
2527
2542
function is row_mysql_store_col_in_innobase_format() in row0mysql.c. */
2528
2543
static
2529
2544
void
2530
2545
row_sel_field_store_in_mysql_format(
2531
2546
/*================================*/
2532
 
        byte*           dest,   /*!< in/out: buffer where to store; NOTE
 
2547
        byte*           dest,   /* in/out: buffer where to store; NOTE
2533
2548
                                that BLOBs are not in themselves
2534
2549
                                stored here: the caller must allocate
2535
2550
                                and copy the BLOB into buffer before,
2536
2551
                                and pass the pointer to the BLOB in
2537
2552
                                'data' */
2538
2553
        const mysql_row_templ_t* templ,
2539
 
                                /*!< in: MySQL column template.
 
2554
                                /* in: MySQL column template.
2540
2555
                                Its following fields are referenced:
2541
2556
                                type, is_unsigned, mysql_col_len,
2542
2557
                                mbminlen, mbmaxlen */
2543
 
        const byte*     data,   /*!< in: data to store */
2544
 
        ulint           len)    /*!< in: length of the data */
 
2558
        const byte*     data,   /* in: data to store */
 
2559
        ulint           len)    /* in: length of the data */
2545
2560
{
2546
2561
        byte*   ptr;
 
2562
        byte*   field_end;
 
2563
        byte*   pad_ptr;
2547
2564
 
2548
2565
        ut_ad(len != UNIV_SQL_NULL);
2549
 
        UNIV_MEM_ASSERT_RW(data, len);
2550
2566
 
2551
2567
        switch (templ->type) {
2552
 
                const byte*     field_end;
2553
 
                byte*           pad;
2554
2568
        case DATA_INT:
2555
2569
                /* Convert integer data from Innobase to a little-endian
2556
2570
                format, sign bit restored to normal */
2594
2608
                unused end of a >= 5.0.3 true VARCHAR column, just in case
2595
2609
                MySQL expects its contents to be deterministic. */
2596
2610
 
2597
 
                pad = dest + len;
 
2611
                pad_ptr = dest + len;
2598
2612
 
2599
2613
                ut_ad(templ->mbminlen <= templ->mbmaxlen);
2600
2614
 
2601
 
                /* We treat some Unicode charset strings specially. */
2602
 
                switch (templ->mbminlen) {
2603
 
                case 4:
2604
 
                        /* InnoDB should never have stripped partial
2605
 
                        UTF-32 characters. */
2606
 
                        ut_a(!(len & 3));
2607
 
                        break;
2608
 
                case 2:
2609
 
                        /* A space char is two bytes,
2610
 
                        0x0020 in UCS2 and UTF-16 */
 
2615
                /* We handle UCS2 charset strings differently. */
 
2616
                if (templ->mbminlen == 2) {
 
2617
                        /* A space char is two bytes, 0x0020 in UCS2 */
2611
2618
 
2612
 
                        if (UNIV_UNLIKELY(len & 1)) {
 
2619
                        if (len & 1) {
2613
2620
                                /* A 0x20 has been stripped from the column.
2614
2621
                                Pad it back. */
2615
2622
 
2616
 
                                if (pad < field_end) {
2617
 
                                        *pad++ = 0x20;
 
2623
                                if (pad_ptr < field_end) {
 
2624
                                        *pad_ptr = 0x20;
 
2625
                                        pad_ptr++;
2618
2626
                                }
2619
2627
                        }
 
2628
 
 
2629
                        /* Pad the rest of the string with 0x0020 */
 
2630
 
 
2631
                        while (pad_ptr < field_end) {
 
2632
                                *pad_ptr = 0x00;
 
2633
                                pad_ptr++;
 
2634
                                *pad_ptr = 0x20;
 
2635
                                pad_ptr++;
 
2636
                        }
 
2637
                } else {
 
2638
                        ut_ad(templ->mbminlen == 1);
 
2639
                        /* space=0x20 */
 
2640
 
 
2641
                        memset(pad_ptr, 0x20, field_end - pad_ptr);
2620
2642
                }
2621
 
 
2622
 
                row_mysql_pad_col(templ->mbminlen, pad, field_end - pad);
2623
2643
                break;
2624
2644
 
2625
2645
        case DATA_BLOB:
2644
2664
                      || !(templ->mysql_col_len % templ->mbmaxlen));
2645
2665
                ut_ad(len * templ->mbmaxlen >= templ->mysql_col_len);
2646
2666
 
2647
 
                if (templ->mbminlen == 1 && templ->mbmaxlen != 1) {
 
2667
                if (templ->mbminlen != templ->mbmaxlen) {
2648
2668
                        /* Pad with spaces. This undoes the stripping
2649
 
                        done in row0mysql.c, function
 
2669
                        done in row0mysql.ic, function
2650
2670
                        row_mysql_store_col_in_innobase_format(). */
2651
2671
 
2652
2672
                        memset(dest + len, 0x20, templ->mysql_col_len - len);
2672
2692
        }
2673
2693
}
2674
2694
 
2675
 
/**************************************************************//**
 
2695
/******************************************************************
2676
2696
Convert a row in the Innobase format to a row in the MySQL format.
2677
2697
Note that the template in prebuilt may advise us to copy only a few
2678
2698
columns to mysql_rec, other columns are left blank. All columns may not
2679
 
be needed in the query.
2680
 
@return TRUE on success, FALSE if not all columns could be retrieved */
 
2699
be needed in the query. */
2681
2700
static
2682
 
#ifdef __GNUC__
2683
 
 __attribute__((warn_unused_result))
2684
 
#endif
2685
2701
ibool
2686
2702
row_sel_store_mysql_rec(
2687
2703
/*====================*/
2688
 
        byte*           mysql_rec,      /*!< out: row in the MySQL format */
2689
 
        row_prebuilt_t* prebuilt,       /*!< in: prebuilt struct */
2690
 
        const rec_t*    rec,            /*!< in: Innobase record in the index
 
2704
                                        /* out: TRUE if success, FALSE if
 
2705
                                        could not allocate memory for a BLOB
 
2706
                                        (though we may also assert in that
 
2707
                                        case) */
 
2708
        byte*           mysql_rec,      /* out: row in the MySQL format */
 
2709
        row_prebuilt_t* prebuilt,       /* in: prebuilt struct */
 
2710
        const rec_t*    rec,            /* in: Innobase record in the index
2691
2711
                                        which was described in prebuilt's
2692
 
                                        template, or in the clustered index;
2693
 
                                        must be protected by a page latch */
2694
 
        ibool           rec_clust,      /*!< in: TRUE if rec is in the
2695
 
                                        clustered index instead of
2696
 
                                        prebuilt->index */
2697
 
        const ulint*    offsets)        /*!< in: array returned by
2698
 
                                        rec_get_offsets(rec) */
 
2712
                                        template; must be protected by
 
2713
                                        a page latch */
 
2714
        const ulint*    offsets,        /* in: array returned by
 
2715
                                        rec_get_offsets() */
 
2716
        ulint start_field_no,
 
2717
        ulint end_field_no)
2699
2718
{
2700
 
        mem_heap_t*     extern_field_heap       = NULL;
2701
 
        mem_heap_t*     heap;
2702
 
        ulint           i;
 
2719
        mysql_row_templ_t*      templ;
 
2720
        mem_heap_t*             extern_field_heap       = NULL;
 
2721
        mem_heap_t*             heap;
 
2722
        const byte*             data;
 
2723
        ulint                   len;
 
2724
        ulint                   i;
2703
2725
 
2704
2726
        ut_ad(prebuilt->mysql_template);
2705
 
        ut_ad(prebuilt->default_rec);
2706
2727
        ut_ad(rec_offs_validate(rec, NULL, offsets));
2707
 
        ut_ad(!rec_get_deleted_flag(rec, rec_offs_comp(offsets)));
2708
2728
 
2709
2729
        if (UNIV_LIKELY_NULL(prebuilt->blob_heap)) {
2710
2730
                mem_heap_free(prebuilt->blob_heap);
2711
2731
                prebuilt->blob_heap = NULL;
2712
2732
        }
2713
2733
 
2714
 
        for (i = 0; i < prebuilt->n_template ; i++) {
2715
 
 
2716
 
                const mysql_row_templ_t*templ = prebuilt->mysql_template + i;
2717
 
                const byte*             data;
2718
 
                ulint                   len;
2719
 
                ulint                   field_no;
2720
 
 
2721
 
                field_no = rec_clust
2722
 
                        ? templ->clust_rec_field_no : templ->rec_field_no;
2723
 
 
2724
 
                if (UNIV_UNLIKELY(rec_offs_nth_extern(offsets, field_no))) {
 
2734
        memset(mysql_rec, 0xff, prebuilt->null_bitmap_len);
 
2735
        for (i = start_field_no; i < end_field_no /* prebuilt->n_template */; i++) {
 
2736
 
 
2737
                templ = prebuilt->mysql_template + i;
 
2738
 
 
2739
                if (UNIV_UNLIKELY(rec_offs_nth_extern(offsets,
 
2740
                                                      templ->rec_field_no))) {
2725
2741
 
2726
2742
                        /* Copy an externally stored field to the temporary
2727
2743
                        heap */
2749
2765
                        data = btr_rec_copy_externally_stored_field(
2750
2766
                                rec, offsets,
2751
2767
                                dict_table_zip_size(prebuilt->table),
2752
 
                                field_no, &len, heap);
2753
 
 
2754
 
                        if (UNIV_UNLIKELY(!data)) {
2755
 
                                /* The externally stored field
2756
 
                                was not written yet. This
2757
 
                                record should only be seen by
2758
 
                                recv_recovery_rollback_active()
2759
 
                                or any TRX_ISO_READ_UNCOMMITTED
2760
 
                                transactions. */
2761
 
 
2762
 
                                if (extern_field_heap) {
2763
 
                                        mem_heap_free(extern_field_heap);
2764
 
                                }
2765
 
 
2766
 
                                return(FALSE);
2767
 
                        }
2768
 
 
2769
 
                        if (UNIV_UNLIKELY(!data)) {
2770
 
                                /* The externally stored field
2771
 
                                was not written yet. This
2772
 
                                record should only be seen by
2773
 
                                recv_recovery_rollback_active()
2774
 
                                or any TRX_ISO_READ_UNCOMMITTED
2775
 
                                transactions. */
2776
 
 
2777
 
                                if (extern_field_heap) {
2778
 
                                        mem_heap_free(extern_field_heap);
2779
 
                                }
2780
 
 
2781
 
                                return(FALSE);
2782
 
                        }
 
2768
                                templ->rec_field_no, &len, heap);
2783
2769
 
2784
2770
                        ut_a(len != UNIV_SQL_NULL);
2785
2771
                } else {
2786
2772
                        /* Field is stored in the row. */
2787
2773
 
2788
 
                        data = rec_get_nth_field(rec, offsets, field_no, &len);
 
2774
                        data = rec_get_nth_field(rec, offsets,
 
2775
                                                 templ->rec_field_no, &len);
2789
2776
 
2790
2777
                        if (UNIV_UNLIKELY(templ->type == DATA_BLOB)
2791
2778
                            && len != UNIV_SQL_NULL) {
2801
2788
                                                UNIV_PAGE_SIZE);
2802
2789
                                }
2803
2790
 
2804
 
                                data = static_cast<byte *>(memcpy(mem_heap_alloc(
 
2791
                                data = memcpy(mem_heap_alloc(
2805
2792
                                                prebuilt->blob_heap, len),
2806
 
                                                                  data, len));
 
2793
                                                data, len);
2807
2794
                        }
2808
2795
                }
2809
2796
 
2825
2812
                                        &= ~(byte) templ->mysql_null_bit_mask;
2826
2813
                        }
2827
2814
                } else {
2828
 
                        /* MySQL assumes that the field for an SQL
2829
 
                        NULL value is set to the default value. */
2830
 
 
2831
 
                        UNIV_MEM_ASSERT_RW(prebuilt->default_rec
2832
 
                                           + templ->mysql_col_offset,
2833
 
                                           templ->mysql_col_len);
2834
 
                        mysql_rec[templ->mysql_null_byte_offset]
2835
 
                                |= (byte) templ->mysql_null_bit_mask;
2836
 
                        memcpy(mysql_rec + templ->mysql_col_offset,
2837
 
                               (const byte*) prebuilt->default_rec
2838
 
                               + templ->mysql_col_offset,
2839
 
                               templ->mysql_col_len);
 
2815
                        /* MySQL seems to assume the field for an SQL NULL
 
2816
                        value is set to zero or space. Not taking this into
 
2817
                        account caused seg faults with NULL BLOB fields, and
 
2818
                        bug number 154 in the MySQL bug database: GROUP BY
 
2819
                        and DISTINCT could treat NULL values inequal. */
 
2820
                        int     pad_char;
 
2821
 
 
2822
                        /* We already set all NULL bits by default above,
 
2823
                        so don't need to do it here. */
 
2824
 
 
2825
                        switch (templ->type) {
 
2826
                        case DATA_VARCHAR:
 
2827
                        case DATA_BINARY:
 
2828
                        case DATA_VARMYSQL:
 
2829
                                if (templ->mysql_type
 
2830
                                    == DATA_MYSQL_TRUE_VARCHAR) {
 
2831
                                        /* This is a >= 5.0.3 type
 
2832
                                        true VARCHAR.  Zero the field. */
 
2833
                                        pad_char = 0x00;
 
2834
                                        break;
 
2835
                                }
 
2836
                                /* Fall through */
 
2837
                        case DATA_CHAR:
 
2838
                        case DATA_FIXBINARY:
 
2839
                        case DATA_MYSQL:
 
2840
                                /* MySQL pads all string types (except
 
2841
                                BLOB, TEXT and true VARCHAR) with space. */
 
2842
                                if (UNIV_UNLIKELY(templ->mbminlen == 2)) {
 
2843
                                        /* Treat UCS2 as a special case. */
 
2844
                                        byte* d = mysql_rec
 
2845
                                                + templ->mysql_col_offset;
 
2846
                                        len = templ->mysql_col_len;
 
2847
                                        /* There are two UCS2 bytes per char,
 
2848
                                        so the length has to be even. */
 
2849
                                        ut_a(!(len & 1));
 
2850
                                        /* Pad with 0x0020. */
 
2851
                                        while (len) {
 
2852
                                                *d++ = 0x00;
 
2853
                                                *d++ = 0x20;
 
2854
                                                len -= 2;
 
2855
                                        }
 
2856
                                        continue;
 
2857
                                }
 
2858
                                pad_char = 0x20;
 
2859
                                break;
 
2860
                        default:
 
2861
                                pad_char = 0x00;
 
2862
                                break;
 
2863
                        }
 
2864
 
 
2865
                        ut_ad(!pad_char || templ->mbminlen == 1);
 
2866
                        memset(mysql_rec + templ->mysql_col_offset,
 
2867
                               pad_char, templ->mysql_col_len);
2840
2868
                }
2841
2869
        }
2842
2870
 
2843
2871
        return(TRUE);
2844
2872
}
2845
2873
 
2846
 
/*********************************************************************//**
2847
 
Builds a previous version of a clustered index record for a consistent read
2848
 
@return DB_SUCCESS or error code */
 
2874
/*************************************************************************
 
2875
Builds a previous version of a clustered index record for a consistent read */
2849
2876
static
2850
2877
ulint
2851
2878
row_sel_build_prev_vers_for_mysql(
2852
2879
/*==============================*/
2853
 
        read_view_t*    read_view,      /*!< in: read view */
2854
 
        dict_index_t*   clust_index,    /*!< in: clustered index */
2855
 
        row_prebuilt_t* prebuilt,       /*!< in: prebuilt struct */
2856
 
        const rec_t*    rec,            /*!< in: record in a clustered index */
2857
 
        ulint**         offsets,        /*!< in/out: offsets returned by
 
2880
                                        /* out: DB_SUCCESS or error code */
 
2881
        read_view_t*    read_view,      /* in: read view */
 
2882
        dict_index_t*   clust_index,    /* in: clustered index */
 
2883
        row_prebuilt_t* prebuilt,       /* in: prebuilt struct */
 
2884
        const rec_t*    rec,            /* in: record in a clustered index */
 
2885
        ulint**         offsets,        /* in/out: offsets returned by
2858
2886
                                        rec_get_offsets(rec, clust_index) */
2859
 
        mem_heap_t**    offset_heap,    /*!< in/out: memory heap from which
 
2887
        mem_heap_t**    offset_heap,    /* in/out: memory heap from which
2860
2888
                                        the offsets are allocated */
2861
 
        rec_t**         old_vers,       /*!< out: old version, or NULL if the
 
2889
        rec_t**         old_vers,       /* out: old version, or NULL if the
2862
2890
                                        record does not exist in the view:
2863
2891
                                        i.e., it was freshly inserted
2864
2892
                                        afterwards */
2865
 
        mtr_t*          mtr)            /*!< in: mtr */
 
2893
        mtr_t*          mtr)            /* in: mtr */
2866
2894
{
2867
2895
        ulint   err;
2868
2896
 
2878
2906
        return(err);
2879
2907
}
2880
2908
 
2881
 
/*********************************************************************//**
 
2909
/*************************************************************************
2882
2910
Retrieves the clustered index record corresponding to a record in a
2883
2911
non-clustered index. Does the necessary locking. Used in the MySQL
2884
 
interface.
2885
 
@return DB_SUCCESS, DB_SUCCESS_LOCKED_REC, or error code */
 
2912
interface. */
2886
2913
static
2887
 
enum db_err
 
2914
ulint
2888
2915
row_sel_get_clust_rec_for_mysql(
2889
2916
/*============================*/
2890
 
        row_prebuilt_t* prebuilt,/*!< in: prebuilt struct in the handle */
2891
 
        dict_index_t*   sec_index,/*!< in: secondary index where rec resides */
2892
 
        const rec_t*    rec,    /*!< in: record in a non-clustered index; if
 
2917
                                /* out: DB_SUCCESS or error code */
 
2918
        row_prebuilt_t* prebuilt,/* in: prebuilt struct in the handle */
 
2919
        dict_index_t*   sec_index,/* in: secondary index where rec resides */
 
2920
        const rec_t*    rec,    /* in: record in a non-clustered index; if
2893
2921
                                this is a locking read, then rec is not
2894
2922
                                allowed to be delete-marked, and that would
2895
2923
                                not make sense either */
2896
 
        que_thr_t*      thr,    /*!< in: query thread */
2897
 
        const rec_t**   out_rec,/*!< out: clustered record or an old version of
 
2924
        que_thr_t*      thr,    /* in: query thread */
 
2925
        const rec_t**   out_rec,/* out: clustered record or an old version of
2898
2926
                                it, NULL if the old version did not exist
2899
2927
                                in the read view, i.e., it was a fresh
2900
2928
                                inserted version */
2901
 
        ulint**         offsets,/*!< in: offsets returned by
 
2929
        ulint**         offsets,/* in: offsets returned by
2902
2930
                                rec_get_offsets(rec, sec_index);
2903
2931
                                out: offsets returned by
2904
2932
                                rec_get_offsets(out_rec, clust_index) */
2905
 
        mem_heap_t**    offset_heap,/*!< in/out: memory heap from which
 
2933
        mem_heap_t**    offset_heap,/* in/out: memory heap from which
2906
2934
                                the offsets are allocated */
2907
 
        mtr_t*          mtr)    /*!< in: mtr used to get access to the
 
2935
        mtr_t*          mtr)    /* in: mtr used to get access to the
2908
2936
                                non-clustered record; the same mtr is used to
2909
2937
                                access the clustered index */
2910
2938
{
2911
2939
        dict_index_t*   clust_index;
2912
2940
        const rec_t*    clust_rec;
2913
2941
        rec_t*          old_vers;
2914
 
        enum db_err     err;
 
2942
        ulint           err;
2915
2943
        trx_t*          trx;
2916
2944
 
2917
2945
        *out_rec = NULL;
2970
2998
 
2971
2999
                clust_rec = NULL;
2972
3000
 
2973
 
                err = DB_SUCCESS;
2974
3001
                goto func_exit;
2975
3002
        }
2976
3003
 
2985
3012
                err = lock_clust_rec_read_check_and_lock(
2986
3013
                        0, btr_pcur_get_block(prebuilt->clust_pcur),
2987
3014
                        clust_rec, clust_index, *offsets,
2988
 
                        static_cast<lock_mode>(prebuilt->select_lock_type),
2989
 
                        LOCK_REC_NOT_GAP, thr);
2990
 
                switch (err) {
2991
 
                case DB_SUCCESS:
2992
 
                case DB_SUCCESS_LOCKED_REC:
2993
 
                        break;
2994
 
                default:
 
3015
                        prebuilt->select_lock_type, LOCK_REC_NOT_GAP, thr);
 
3016
                if (err != DB_SUCCESS) {
 
3017
 
2995
3018
                        goto err_exit;
2996
3019
                }
2997
3020
        } else {
3010
3033
 
3011
3034
                        /* The following call returns 'offsets' associated with
3012
3035
                        'old_vers' */
3013
 
                  err = static_cast<db_err>(row_sel_build_prev_vers_for_mysql(
 
3036
                        err = row_sel_build_prev_vers_for_mysql(
3014
3037
                                trx->read_view, clust_index, prebuilt,
3015
3038
                                clust_rec, offsets, offset_heap, &old_vers,
3016
 
                                mtr));
 
3039
                                mtr);
3017
3040
 
3018
3041
                        if (err != DB_SUCCESS || old_vers == NULL) {
3019
3042
 
3038
3061
 
3039
3062
                if (clust_rec
3040
3063
                    && (old_vers
3041
 
                        || trx->isolation_level <= TRX_ISO_READ_UNCOMMITTED
3042
3064
                        || rec_get_deleted_flag(rec, dict_table_is_comp(
3043
3065
                                                        sec_index->table)))
3044
3066
                    && !row_sel_sec_rec_is_for_clust_rec(
3051
3073
                                     rec, sec_index, clust_rec, clust_index));
3052
3074
#endif
3053
3075
                }
3054
 
 
3055
 
                err = DB_SUCCESS;
3056
3076
        }
3057
3077
 
3058
3078
func_exit:
3059
3079
        *out_rec = clust_rec;
3060
3080
 
3061
 
        if (prebuilt->select_lock_type != LOCK_NONE) {
3062
 
                /* We may use the cursor in update or in unlock_row():
3063
 
                store its position */
 
3081
        if (prebuilt->select_lock_type == LOCK_X) {
 
3082
                /* We may use the cursor in update: store its position */
3064
3083
 
3065
3084
                btr_pcur_store_position(prebuilt->clust_pcur, mtr);
3066
3085
        }
3067
3086
 
 
3087
        err = DB_SUCCESS;
3068
3088
err_exit:
3069
3089
        return(err);
3070
3090
}
3071
3091
 
3072
 
/********************************************************************//**
 
3092
/************************************************************************
3073
3093
Restores cursor position after it has been stored. We have to take into
3074
3094
account that the record cursor was positioned on may have been deleted.
3075
 
Then we may have to move the cursor one step up or down.
3076
 
@return TRUE if we may need to process the record the cursor is now
3077
 
positioned on (i.e. we should not go to the next record yet) */
 
3095
Then we may have to move the cursor one step up or down. */
3078
3096
static
3079
3097
ibool
3080
3098
sel_restore_position_for_mysql(
3081
3099
/*===========================*/
3082
 
        ibool*          same_user_rec,  /*!< out: TRUE if we were able to restore
 
3100
                                        /* out: TRUE if we may need to
 
3101
                                        process the record the cursor is
 
3102
                                        now positioned on (i.e. we should
 
3103
                                        not go to the next record yet) */
 
3104
        ibool*          same_user_rec,  /* out: TRUE if we were able to restore
3083
3105
                                        the cursor on a user record with the
3084
3106
                                        same ordering prefix in in the
3085
3107
                                        B-tree index */
3086
 
        ulint           latch_mode,     /*!< in: latch mode wished in
 
3108
        ulint           latch_mode,     /* in: latch mode wished in
3087
3109
                                        restoration */
3088
 
        btr_pcur_t*     pcur,           /*!< in: cursor whose position
 
3110
        btr_pcur_t*     pcur,           /* in: cursor whose position
3089
3111
                                        has been stored */
3090
 
        ibool           moves_up,       /*!< in: TRUE if the cursor moves up
 
3112
        ibool           moves_up,       /* in: TRUE if the cursor moves up
3091
3113
                                        in the index */
3092
 
        mtr_t*          mtr)            /*!< in: mtr; CAUTION: may commit
 
3114
        mtr_t*          mtr)            /* in: mtr; CAUTION: may commit
3093
3115
                                        mtr temporarily! */
3094
3116
{
3095
3117
        ibool   success;
3137
3159
        return(TRUE);
3138
3160
}
3139
3161
 
3140
 
/********************************************************************//**
 
3162
/************************************************************************
3141
3163
Pops a cached row for MySQL from the fetch cache. */
3142
3164
UNIV_INLINE
3143
3165
void
3144
3166
row_sel_pop_cached_row_for_mysql(
3145
3167
/*=============================*/
3146
 
        byte*           buf,            /*!< in/out: buffer where to copy the
 
3168
        byte*           buf,            /* in/out: buffer where to copy the
3147
3169
                                        row */
3148
 
        row_prebuilt_t* prebuilt)       /*!< in: prebuilt struct */
 
3170
        row_prebuilt_t* prebuilt)       /* in: prebuilt struct */
3149
3171
{
3150
3172
        ulint                   i;
3151
 
        const mysql_row_templ_t*templ;
 
3173
        mysql_row_templ_t*      templ;
3152
3174
        byte*                   cached_rec;
3153
3175
        ut_ad(prebuilt->n_fetch_cached > 0);
3154
3176
        ut_ad(prebuilt->mysql_prefix_len <= prebuilt->mysql_row_len);
3161
3183
 
3162
3184
                for (i = 0; i < prebuilt->n_template; i++) {
3163
3185
                        templ = prebuilt->mysql_template + i;
3164
 
#if 0 /* Some of the cached_rec may legitimately be uninitialized. */
3165
 
                        UNIV_MEM_ASSERT_RW(cached_rec
3166
 
                                           + templ->mysql_col_offset,
3167
 
                                           templ->mysql_col_len);
3168
 
#endif
3169
3186
                        ut_memcpy(buf + templ->mysql_col_offset,
3170
3187
                                  cached_rec + templ->mysql_col_offset,
3171
3188
                                  templ->mysql_col_len);
3180
3197
                }
3181
3198
        }
3182
3199
        else {
3183
 
#if 0 /* Some of the cached_rec may legitimately be uninitialized. */
3184
 
                UNIV_MEM_ASSERT_RW(prebuilt->fetch_cache
3185
 
                                   [prebuilt->fetch_cache_first],
3186
 
                                   prebuilt->mysql_prefix_len);
3187
 
#endif
3188
3200
                ut_memcpy(buf,
3189
3201
                          prebuilt->fetch_cache[prebuilt->fetch_cache_first],
3190
3202
                          prebuilt->mysql_prefix_len);
3197
3209
        }
3198
3210
}
3199
3211
 
3200
 
/********************************************************************//**
3201
 
Pushes a row for MySQL to the fetch cache.
3202
 
@return TRUE on success, FALSE if the record contains incomplete BLOBs */
 
3212
/************************************************************************
 
3213
Pushes a row for MySQL to the fetch cache. */
3203
3214
UNIV_INLINE
3204
 
#ifdef __GNUC__
3205
 
__attribute__((warn_unused_result))
3206
 
#endif
3207
 
ibool
 
3215
void
3208
3216
row_sel_push_cache_row_for_mysql(
3209
3217
/*=============================*/
3210
 
        row_prebuilt_t* prebuilt,       /*!< in: prebuilt struct */
3211
 
        const rec_t*    rec,            /*!< in: record to push, in the index
3212
 
                                        which was described in prebuilt's
3213
 
                                        template, or in the clustered index;
3214
 
                                        must be protected by a page latch */
3215
 
        ibool           rec_clust,      /*!< in: TRUE if rec is in the
3216
 
                                        clustered index instead of
3217
 
                                        prebuilt->index */
3218
 
        const ulint*    offsets)        /*!< in: rec_get_offsets(rec) */
 
3218
        row_prebuilt_t* prebuilt,       /* in: prebuilt struct */
 
3219
        const rec_t*    rec,            /* in: record to push; must
 
3220
                                        be protected by a page latch */
 
3221
        const ulint*    offsets,        /* in: rec_get_offsets() */
 
3222
        ulint           start_field_no, /* psergy: start from this field */
 
3223
        byte*           remainder_buf)  /* if above !=0 -> where to take
 
3224
                                           prev fields */
3219
3225
{
3220
3226
        byte*   buf;
3221
3227
        ulint   i;
3222
3228
 
3223
3229
        ut_ad(prebuilt->n_fetch_cached < MYSQL_FETCH_CACHE_SIZE);
3224
3230
        ut_ad(rec_offs_validate(rec, NULL, offsets));
3225
 
        ut_ad(!rec_get_deleted_flag(rec, rec_offs_comp(offsets)));
3226
3231
        ut_a(!prebuilt->templ_contains_blob);
3227
3232
 
3228
3233
        if (prebuilt->fetch_cache[0] == NULL) {
3234
3239
                        buffers in Linux. Put magic numbers there to help
3235
3240
                        to track a possible bug. */
3236
3241
 
3237
 
                        buf = static_cast<byte *>(mem_alloc(prebuilt->mysql_row_len + 8));
 
3242
                        buf = mem_alloc(prebuilt->mysql_row_len + 8);
3238
3243
 
3239
3244
                        prebuilt->fetch_cache[i] = buf + 4;
3240
3245
 
3245
3250
        }
3246
3251
 
3247
3252
        ut_ad(prebuilt->fetch_cache_first == 0);
3248
 
        UNIV_MEM_INVALID(prebuilt->fetch_cache[prebuilt->n_fetch_cached],
3249
 
                         prebuilt->mysql_row_len);
3250
3253
 
3251
3254
        if (UNIV_UNLIKELY(!row_sel_store_mysql_rec(
3252
3255
                                  prebuilt->fetch_cache[
3253
3256
                                          prebuilt->n_fetch_cached],
3254
 
                                  prebuilt, rec, rec_clust, offsets))) {
3255
 
                return(FALSE);
 
3257
                                  prebuilt, rec, offsets, start_field_no,
 
3258
                                  prebuilt->n_template))) {
 
3259
                ut_error;
3256
3260
        }
3257
3261
 
 
3262
        if (start_field_no) {
 
3263
          for (i=0; i < start_field_no; i++) {
 
3264
            register ulint offs;
 
3265
            mysql_row_templ_t* templ;
 
3266
            templ = prebuilt->mysql_template + i;
 
3267
 
 
3268
            if (templ->mysql_null_bit_mask) {
 
3269
              offs= templ->mysql_null_byte_offset;
 
3270
              if (*(remainder_buf + offs) & templ->mysql_null_bit_mask)
 
3271
                 *(prebuilt->fetch_cache[prebuilt->n_fetch_cached] + offs) |= 
 
3272
                /*  (*(remainder_buf + offs) &*/( templ->mysql_null_bit_mask);
 
3273
              else
 
3274
                *(prebuilt->fetch_cache[prebuilt->n_fetch_cached] + offs) &= 
 
3275
                  ~templ->mysql_null_bit_mask;
 
3276
 
 
3277
            }
 
3278
            offs= templ->mysql_col_offset;
 
3279
            memcpy(prebuilt->fetch_cache[prebuilt->n_fetch_cached] + offs,
 
3280
                   remainder_buf + offs,
 
3281
                   templ->mysql_col_len);
 
3282
          }
 
3283
        }
 
3284
 
 
3285
 
3258
3286
        prebuilt->n_fetch_cached++;
3259
 
        return(TRUE);
3260
3287
}
3261
3288
 
3262
 
/*********************************************************************//**
 
3289
/*************************************************************************
3263
3290
Tries to do a shortcut to fetch a clustered index record with a unique key,
3264
3291
using the hash index if possible (not always). We assume that the search
3265
3292
mode is PAGE_CUR_GE, it is a consistent read, there is a read view in trx,
3266
 
btr search latch has been locked in S-mode.
3267
 
@return SEL_FOUND, SEL_EXHAUSTED, SEL_RETRY */
 
3293
btr search latch has been locked in S-mode. */
3268
3294
static
3269
3295
ulint
3270
3296
row_sel_try_search_shortcut_for_mysql(
3271
3297
/*==================================*/
3272
 
        const rec_t**   out_rec,/*!< out: record if found */
3273
 
        row_prebuilt_t* prebuilt,/*!< in: prebuilt struct */
3274
 
        ulint**         offsets,/*!< in/out: for rec_get_offsets(*out_rec) */
3275
 
        mem_heap_t**    heap,   /*!< in/out: heap for rec_get_offsets() */
3276
 
        mtr_t*          mtr)    /*!< in: started mtr */
 
3298
                                /* out: SEL_FOUND, SEL_EXHAUSTED, SEL_RETRY */
 
3299
        const rec_t**   out_rec,/* out: record if found */
 
3300
        row_prebuilt_t* prebuilt,/* in: prebuilt struct */
 
3301
        ulint**         offsets,/* in/out: for rec_get_offsets(*out_rec) */
 
3302
        mem_heap_t**    heap,   /* in/out: heap for rec_get_offsets() */
 
3303
        mtr_t*          mtr)    /* in: started mtr */
3277
3304
{
3278
3305
        dict_index_t*   index           = prebuilt->index;
3279
3306
        const dtuple_t* search_tuple    = prebuilt->search_tuple;
3284
3311
        ut_ad(dict_index_is_clust(index));
3285
3312
        ut_ad(!prebuilt->templ_contains_blob);
3286
3313
 
3287
 
#ifndef UNIV_SEARCH_DEBUG
3288
3314
        btr_pcur_open_with_no_init(index, search_tuple, PAGE_CUR_GE,
3289
3315
                                   BTR_SEARCH_LEAF, pcur,
 
3316
#ifndef UNIV_SEARCH_DEBUG
3290
3317
                                   RW_S_LATCH,
3291
 
                                   mtr);
3292
 
#else /* UNIV_SEARCH_DEBUG */
3293
 
        btr_pcur_open_with_no_init(index, search_tuple, PAGE_CUR_GE,
3294
 
                                   BTR_SEARCH_LEAF, pcur,
 
3318
#else
3295
3319
                                   0,
 
3320
#endif
3296
3321
                                   mtr);
3297
 
#endif /* UNIV_SEARCH_DEBUG */
3298
3322
        rec = btr_pcur_get_rec(pcur);
3299
3323
 
3300
3324
        if (!page_rec_is_user_rec(rec)) {
3333
3357
        return(SEL_FOUND);
3334
3358
}
3335
3359
 
3336
 
/********************************************************************//**
 
3360
/************************************************************************
3337
3361
Searches for rows in the database. This is used in the interface to
3338
3362
MySQL. This function opens a cursor, and also implements fetch next
3339
3363
and fetch prev. NOTE that if we do a search with a full key value
3340
3364
from a unique index (ROW_SEL_EXACT), then we will not store the cursor
3341
 
position and fetch next or fetch prev must not be tried to the cursor!
3342
 
@return DB_SUCCESS, DB_RECORD_NOT_FOUND, DB_END_OF_INDEX, DB_DEADLOCK,
3343
 
DB_LOCK_TABLE_FULL, DB_CORRUPTION, or DB_TOO_BIG_RECORD */
 
3365
position and fetch next or fetch prev must not be tried to the cursor! */
3344
3366
UNIV_INTERN
3345
3367
ulint
3346
3368
row_search_for_mysql(
3347
3369
/*=================*/
3348
 
        byte*           buf,            /*!< in/out: buffer for the fetched
 
3370
                                        /* out: DB_SUCCESS,
 
3371
                                        DB_RECORD_NOT_FOUND,
 
3372
                                        DB_END_OF_INDEX, DB_DEADLOCK,
 
3373
                                        DB_LOCK_TABLE_FULL, DB_CORRUPTION,
 
3374
                                        or DB_TOO_BIG_RECORD */
 
3375
        byte*           buf,            /* in/out: buffer for the fetched
3349
3376
                                        row in the MySQL format */
3350
 
        ulint           mode,           /*!< in: search mode PAGE_CUR_L, ... */
3351
 
        row_prebuilt_t* prebuilt,       /*!< in: prebuilt struct for the
 
3377
        ulint           mode,           /* in: search mode PAGE_CUR_L, ... */
 
3378
        row_prebuilt_t* prebuilt,       /* in: prebuilt struct for the
3352
3379
                                        table handle; this contains the info
3353
3380
                                        of search_tuple, index; if search
3354
3381
                                        tuple contains 0 fields then we
3355
3382
                                        position the cursor at the start or
3356
3383
                                        the end of the index, depending on
3357
3384
                                        'mode' */
3358
 
        ulint           match_mode,     /*!< in: 0 or ROW_SEL_EXACT or
 
3385
        ulint           match_mode,     /* in: 0 or ROW_SEL_EXACT or
3359
3386
                                        ROW_SEL_EXACT_PREFIX */
3360
 
        ulint           direction)      /*!< in: 0 or ROW_SEL_NEXT or
 
3387
        ulint           direction)      /* in: 0 or ROW_SEL_NEXT or
3361
3388
                                        ROW_SEL_PREV; NOTE: if this is != 0,
3362
3389
                                        then prebuilt must have a pcur
3363
3390
                                        with stored position! In opening of a
3394
3421
        mem_heap_t*     heap                            = NULL;
3395
3422
        ulint           offsets_[REC_OFFS_NORMAL_SIZE];
3396
3423
        ulint*          offsets                         = offsets_;
3397
 
        ibool           table_lock_waited               = FALSE;
 
3424
        ibool           some_fields_in_buffer;
 
3425
        ibool           get_clust_rec= 0;
3398
3426
 
3399
3427
        rec_offs_init(offsets_);
3400
3428
 
3412
3440
                        "InnoDB: the MySQL datadir, or have you used"
3413
3441
                        " DISCARD TABLESPACE?\n"
3414
3442
                        "InnoDB: Look from\n"
3415
 
                        "InnoDB: " REFMAN "innodb-troubleshooting.html\n"
 
3443
                        "InnoDB: http://dev.mysql.com/doc/refman/5.1/en/"
 
3444
                        "innodb-troubleshooting.html\n"
3416
3445
                        "InnoDB: how you can resolve the problem.\n",
3417
3446
                        prebuilt->table->name);
3418
3447
 
3419
3448
                return(DB_ERROR);
3420
3449
        }
3421
3450
 
3422
 
        if (UNIV_UNLIKELY(!prebuilt->index_usable)) {
3423
 
 
3424
 
                return(DB_MISSING_HISTORY);
3425
 
        }
3426
 
 
3427
3451
        if (UNIV_UNLIKELY(prebuilt->magic_n != ROW_PREBUILT_ALLOCATED)) {
3428
3452
                fprintf(stderr,
3429
3453
                        "InnoDB: Error: trying to free a corrupt\n"
3438
3462
        }
3439
3463
 
3440
3464
#if 0
 
3465
        /* August 19, 2005 by Heikki: temporarily disable this error
 
3466
        print until the cursor lock count is done correctly.
 
3467
        See bugs #12263 and #12456!*/
 
3468
 
 
3469
        if (trx->n_mysql_tables_in_use == 0
 
3470
            && UNIV_UNLIKELY(prebuilt->select_lock_type == LOCK_NONE)) {
 
3471
                /* Note that if MySQL uses an InnoDB temp table that it
 
3472
                created inside LOCK TABLES, then n_mysql_tables_in_use can
 
3473
                be zero; in that case select_lock_type is set to LOCK_X in
 
3474
                ::start_stmt. */
 
3475
 
 
3476
                fputs("InnoDB: Error: MySQL is trying to perform a SELECT\n"
 
3477
                      "InnoDB: but it has not locked"
 
3478
                      " any tables in ::external_lock()!\n",
 
3479
                      stderr);
 
3480
                trx_print(stderr, trx, 600);
 
3481
                fputc('\n', stderr);
 
3482
        }
 
3483
#endif
 
3484
 
 
3485
#if 0
3441
3486
        fprintf(stderr, "Match mode %lu\n search tuple ",
3442
3487
                (ulong) match_mode);
3443
3488
        dtuple_print(search_tuple);
3448
3493
        /* PHASE 0: Release a possible s-latch we are holding on the
3449
3494
        adaptive hash index latch if there is someone waiting behind */
3450
3495
 
3451
 
        if (UNIV_UNLIKELY(rw_lock_get_writer(&btr_search_latch) != RW_LOCK_NOT_LOCKED)
 
3496
        if (UNIV_UNLIKELY(btr_search_latch.writer != RW_LOCK_NOT_LOCKED)
3452
3497
            && trx->has_search_latch) {
3453
3498
 
3454
3499
                /* There is an x-latch request on the adaptive hash index:
3466
3511
        is set or session is using a READ COMMITED isolation level. Then
3467
3512
        we are able to remove the record locks set here on an individual
3468
3513
        row. */
3469
 
        prebuilt->new_rec_locks = 0;
 
3514
 
 
3515
        if ((srv_locks_unsafe_for_binlog
 
3516
             || trx->isolation_level == TRX_ISO_READ_COMMITTED)
 
3517
            && prebuilt->select_lock_type != LOCK_NONE) {
 
3518
 
 
3519
                trx_reset_new_rec_lock_info(trx);
 
3520
        }
3470
3521
 
3471
3522
        /*-------------------------------------------------------------*/
3472
3523
        /* PHASE 1: Try to pop the row from the prefetch cache */
3559
3610
 
3560
3611
                /* Even if the condition is unique, MySQL seems to try to
3561
3612
                retrieve also a second row if a primary key contains more than
3562
 
                1 column.*/
 
3613
                1 column. Return immediately if this is not a HANDLER
 
3614
                command. */
3563
3615
 
3564
 
                if (UNIV_UNLIKELY(direction != 0)) {
 
3616
                if (UNIV_UNLIKELY(direction != 0
 
3617
                                  && !prebuilt->used_in_HANDLER)) {
3565
3618
 
3566
3619
                        err = DB_RECORD_NOT_FOUND;
3567
3620
                        goto func_exit;
3583
3636
            && unique_search
3584
3637
            && dict_index_is_clust(index)
3585
3638
            && !prebuilt->templ_contains_blob
 
3639
            && !prebuilt->used_in_HANDLER
3586
3640
            && (prebuilt->mysql_row_len < UNIV_PAGE_SIZE / 8)) {
3587
3641
 
3588
3642
                mode = PAGE_CUR_GE;
3625
3679
                                row_sel_try_search_shortcut_for_mysql().
3626
3680
                                The latch will not be released until
3627
3681
                                mtr_commit(&mtr). */
3628
 
                                ut_ad(!rec_get_deleted_flag(rec, comp));
3629
3682
 
3630
3683
                                if (!row_sel_store_mysql_rec(buf, prebuilt,
3631
 
                                                             rec, FALSE,
3632
 
                                                             offsets)) {
3633
 
                                        /* Only fresh inserts may contain
3634
 
                                        incomplete externally stored
3635
 
                                        columns. Pretend that such
3636
 
                                        records do not exist. Such
3637
 
                                        records may only be accessed
3638
 
                                        at the READ UNCOMMITTED
3639
 
                                        isolation level or when
3640
 
                                        rolling back a recovered
3641
 
                                        transaction. Rollback happens
3642
 
                                        at a lower level, not here. */
3643
 
                                        ut_a(trx->isolation_level
3644
 
                                             == TRX_ISO_READ_UNCOMMITTED);
 
3684
                                                             rec, offsets, 0,
 
3685
                                                             prebuilt->n_template)) {
 
3686
                                        err = DB_TOO_BIG_RECORD;
3645
3687
 
3646
 
                                        /* Proceed as in case SEL_RETRY. */
3647
 
                                        break;
 
3688
                                        /* We let the main loop to do the
 
3689
                                        error handling */
 
3690
                                        goto shortcut_fails_too_big_rec;
3648
3691
                                }
3649
3692
 
3650
3693
                                mtr_commit(&mtr);
3684
3727
                        default:
3685
3728
                                ut_ad(0);
3686
3729
                        }
3687
 
 
 
3730
shortcut_fails_too_big_rec:
3688
3731
                        mtr_commit(&mtr);
3689
3732
                        mtr_start(&mtr);
3690
3733
                }
3698
3741
                trx->has_search_latch = FALSE;
3699
3742
        }
3700
3743
 
3701
 
        ut_ad(prebuilt->sql_stat_start || trx->conc_state == TRX_ACTIVE);
3702
 
        ut_ad(trx->conc_state == TRX_NOT_STARTED
3703
 
              || trx->conc_state == TRX_ACTIVE);
3704
 
        ut_ad(prebuilt->sql_stat_start
3705
 
              || prebuilt->select_lock_type != LOCK_NONE
3706
 
              || trx->read_view);
3707
 
 
3708
 
        ut_ad(prebuilt->sql_stat_start || trx->conc_state == TRX_ACTIVE);
3709
 
        ut_ad(trx->conc_state == TRX_NOT_STARTED
3710
 
              || trx->conc_state == TRX_ACTIVE);
3711
 
        ut_ad(prebuilt->sql_stat_start
3712
 
              || prebuilt->select_lock_type != LOCK_NONE
3713
 
              || trx->read_view);
3714
 
 
3715
3744
        trx_start_if_not_started(trx);
3716
3745
 
3717
3746
        if (trx->isolation_level <= TRX_ISO_READ_COMMITTED
3742
3771
 
3743
3772
        clust_index = dict_table_get_first_index(index->table);
3744
3773
 
3745
 
        /* Do some start-of-statement preparations */
3746
 
 
3747
 
        if (!prebuilt->sql_stat_start) {
3748
 
                /* No need to set an intention lock or assign a read view */
3749
 
 
3750
 
                if (trx->read_view == NULL
3751
 
                    && prebuilt->select_lock_type == LOCK_NONE) {
3752
 
 
3753
 
                        fputs("InnoDB: Error: MySQL is trying to"
3754
 
                              " perform a consistent read\n"
3755
 
                              "InnoDB: but the read view is not assigned!\n",
3756
 
                              stderr);
3757
 
                        trx_print(stderr, trx, 600);
3758
 
                        fputc('\n', stderr);
3759
 
                        ut_error;
3760
 
                }
3761
 
        } else if (prebuilt->select_lock_type == LOCK_NONE) {
3762
 
                /* This is a consistent read */
3763
 
                /* Assign a read view for the query */
3764
 
 
3765
 
                trx_assign_read_view(trx);
3766
 
                prebuilt->sql_stat_start = FALSE;
3767
 
        } else {
3768
 
wait_table_again:
3769
 
                err = lock_table(0, index->table,
3770
 
                                 prebuilt->select_lock_type == LOCK_S
3771
 
                                 ? LOCK_IS : LOCK_IX, thr);
3772
 
 
3773
 
                if (err != DB_SUCCESS) {
3774
 
 
3775
 
                        table_lock_waited = TRUE;
3776
 
                        goto lock_table_wait;
3777
 
                }
3778
 
                prebuilt->sql_stat_start = FALSE;
3779
 
        }
3780
 
 
3781
 
        /* Open or restore index cursor position */
3782
 
 
3783
3774
        if (UNIV_LIKELY(direction != 0)) {
3784
3775
                ibool   need_to_process = sel_restore_position_for_mysql(
3785
3776
                        &same_user_rec, BTR_SEARCH_LEAF,
3820
3811
                    && !page_rec_is_supremum(rec)
3821
3812
                    && set_also_gap_locks
3822
3813
                    && !(srv_locks_unsafe_for_binlog
3823
 
                         || trx->isolation_level <= TRX_ISO_READ_COMMITTED)
 
3814
                         || trx->isolation_level == TRX_ISO_READ_COMMITTED)
3824
3815
                    && prebuilt->select_lock_type != LOCK_NONE) {
3825
3816
 
3826
3817
                        /* Try to place a gap lock on the next index record
3834
3825
                                               prebuilt->select_lock_type,
3835
3826
                                               LOCK_GAP, thr);
3836
3827
 
3837
 
                        switch (err) {
3838
 
                        case DB_SUCCESS_LOCKED_REC:
3839
 
                                err = DB_SUCCESS;
3840
 
                        case DB_SUCCESS:
3841
 
                                break;
3842
 
                        default:
 
3828
                        if (err != DB_SUCCESS) {
 
3829
 
3843
3830
                                goto lock_wait_or_error;
3844
3831
                        }
3845
3832
                }
3855
3842
                }
3856
3843
        }
3857
3844
 
 
3845
        if (!prebuilt->sql_stat_start) {
 
3846
                /* No need to set an intention lock or assign a read view */
 
3847
 
 
3848
                if (trx->read_view == NULL
 
3849
                    && prebuilt->select_lock_type == LOCK_NONE) {
 
3850
 
 
3851
                        fputs("InnoDB: Error: MySQL is trying to"
 
3852
                              " perform a consistent read\n"
 
3853
                              "InnoDB: but the read view is not assigned!\n",
 
3854
                              stderr);
 
3855
                        trx_print(stderr, trx, 600);
 
3856
                        fputc('\n', stderr);
 
3857
                        ut_a(0);
 
3858
                }
 
3859
        } else if (prebuilt->select_lock_type == LOCK_NONE) {
 
3860
                /* This is a consistent read */
 
3861
                /* Assign a read view for the query */
 
3862
 
 
3863
                trx_assign_read_view(trx);
 
3864
                prebuilt->sql_stat_start = FALSE;
 
3865
        } else {
 
3866
                ulint   lock_mode;
 
3867
                if (prebuilt->select_lock_type == LOCK_S) {
 
3868
                        lock_mode = LOCK_IS;
 
3869
                } else {
 
3870
                        lock_mode = LOCK_IX;
 
3871
                }
 
3872
                err = lock_table(0, index->table, lock_mode, thr);
 
3873
 
 
3874
                if (err != DB_SUCCESS) {
 
3875
 
 
3876
                        goto lock_wait_or_error;
 
3877
                }
 
3878
                prebuilt->sql_stat_start = FALSE;
 
3879
        }
 
3880
 
3858
3881
rec_loop:
3859
3882
        /*-------------------------------------------------------------*/
3860
3883
        /* PHASE 4: Look for matching records in a loop */
3884
3907
 
3885
3908
                if (set_also_gap_locks
3886
3909
                    && !(srv_locks_unsafe_for_binlog
3887
 
                         || trx->isolation_level <= TRX_ISO_READ_COMMITTED)
 
3910
                         || trx->isolation_level == TRX_ISO_READ_COMMITTED)
3888
3911
                    && prebuilt->select_lock_type != LOCK_NONE) {
3889
3912
 
3890
3913
                        /* Try to place a lock on the index record */
3901
3924
                                               prebuilt->select_lock_type,
3902
3925
                                               LOCK_ORDINARY, thr);
3903
3926
 
3904
 
                        switch (err) {
3905
 
                        case DB_SUCCESS_LOCKED_REC:
3906
 
                                err = DB_SUCCESS;
3907
 
                        case DB_SUCCESS:
3908
 
                                break;
3909
 
                        default:
 
3927
                        if (err != DB_SUCCESS) {
 
3928
 
3910
3929
                                goto lock_wait_or_error;
3911
3930
                        }
3912
3931
                }
4022
4041
                        if (set_also_gap_locks
4023
4042
                            && !(srv_locks_unsafe_for_binlog
4024
4043
                                 || trx->isolation_level
4025
 
                                 <= TRX_ISO_READ_COMMITTED)
 
4044
                                 == TRX_ISO_READ_COMMITTED)
4026
4045
                            && prebuilt->select_lock_type != LOCK_NONE) {
4027
4046
 
4028
4047
                                /* Try to place a gap lock on the index
4036
4055
                                        prebuilt->select_lock_type, LOCK_GAP,
4037
4056
                                        thr);
4038
4057
 
4039
 
                                switch (err) {
4040
 
                                case DB_SUCCESS_LOCKED_REC:
4041
 
                                case DB_SUCCESS:
4042
 
                                        break;
4043
 
                                default:
 
4058
                                if (err != DB_SUCCESS) {
 
4059
 
4044
4060
                                        goto lock_wait_or_error;
4045
4061
                                }
4046
4062
                        }
4061
4077
                        if (set_also_gap_locks
4062
4078
                            && !(srv_locks_unsafe_for_binlog
4063
4079
                                 || trx->isolation_level
4064
 
                                 <= TRX_ISO_READ_COMMITTED)
 
4080
                                 == TRX_ISO_READ_COMMITTED)
4065
4081
                            && prebuilt->select_lock_type != LOCK_NONE) {
4066
4082
 
4067
4083
                                /* Try to place a gap lock on the index
4075
4091
                                        prebuilt->select_lock_type, LOCK_GAP,
4076
4092
                                        thr);
4077
4093
 
4078
 
                                switch (err) {
4079
 
                                case DB_SUCCESS_LOCKED_REC:
4080
 
                                case DB_SUCCESS:
4081
 
                                        break;
4082
 
                                default:
 
4094
                                if (err != DB_SUCCESS) {
 
4095
 
4083
4096
                                        goto lock_wait_or_error;
4084
4097
                                }
4085
4098
                        }
4112
4125
 
4113
4126
                if (!set_also_gap_locks
4114
4127
                    || srv_locks_unsafe_for_binlog
4115
 
                    || trx->isolation_level <= TRX_ISO_READ_COMMITTED
 
4128
                    || trx->isolation_level == TRX_ISO_READ_COMMITTED
4116
4129
                    || (unique_search
4117
4130
                        && !UNIV_UNLIKELY(rec_get_deleted_flag(rec, comp)))) {
4118
4131
 
4149
4162
 
4150
4163
                switch (err) {
4151
4164
                        const rec_t*    old_vers;
4152
 
                case DB_SUCCESS_LOCKED_REC:
4153
 
                        if (srv_locks_unsafe_for_binlog
4154
 
                            || trx->isolation_level
4155
 
                            <= TRX_ISO_READ_COMMITTED) {
4156
 
                                /* Note that a record of
4157
 
                                prebuilt->index was locked. */
4158
 
                                prebuilt->new_rec_locks = 1;
4159
 
                        }
4160
 
                        err = DB_SUCCESS;
4161
4165
                case DB_SUCCESS:
4162
4166
                        break;
4163
4167
                case DB_LOCK_WAIT:
4164
 
                        /* Never unlock rows that were part of a conflict. */
4165
 
                        prebuilt->new_rec_locks = 0;
4166
 
 
4167
4168
                        if (UNIV_LIKELY(prebuilt->row_read_type
4168
4169
                                        != ROW_READ_TRY_SEMI_CONSISTENT)
4169
 
                            || unique_search
4170
4170
                            || index != clust_index) {
4171
4171
 
4172
4172
                                goto lock_wait_or_error;
4178
4178
                                clust_index, prebuilt, rec,
4179
4179
                                &offsets, &heap, &old_vers, &mtr);
4180
4180
 
4181
 
                        switch (err) {
4182
 
                        case DB_SUCCESS_LOCKED_REC:
4183
 
                                err = DB_SUCCESS;
4184
 
                        case DB_SUCCESS:
4185
 
                                break;
4186
 
                        default:
 
4181
                        if (err != DB_SUCCESS) {
 
4182
 
4187
4183
                                goto lock_wait_or_error;
4188
4184
                        }
4189
4185
 
4197
4193
                        if (UNIV_LIKELY(trx->wait_lock != NULL)) {
4198
4194
                                lock_cancel_waiting_and_release(
4199
4195
                                        trx->wait_lock);
 
4196
                                trx_reset_new_rec_lock_info(trx);
4200
4197
                        } else {
4201
4198
                                mutex_exit(&kernel_mutex);
4202
4199
 
4253
4250
                                        prebuilt, rec, &offsets, &heap,
4254
4251
                                        &old_vers, &mtr);
4255
4252
 
4256
 
                                switch (err) {
4257
 
                                case DB_SUCCESS_LOCKED_REC:
4258
 
                                case DB_SUCCESS:
4259
 
                                        break;
4260
 
                                default:
 
4253
                                if (err != DB_SUCCESS) {
 
4254
 
4261
4255
                                        goto lock_wait_or_error;
4262
4256
                                }
4263
4257
 
4270
4264
 
4271
4265
                                rec = old_vers;
4272
4266
                        }
4273
 
                } else {
 
4267
                } else if (!lock_sec_rec_cons_read_sees(rec, trx->read_view)) {
4274
4268
                        /* We are looking into a non-clustered index,
4275
4269
                        and to get the right version of the record we
4276
4270
                        have to look also into the clustered index: this
4277
4271
                        is necessary, because we can only get the undo
4278
4272
                        information via the clustered index record. */
4279
4273
 
4280
 
                        ut_ad(!dict_index_is_clust(index));
4281
 
                        if (!lock_sec_rec_cons_read_sees(
4282
 
                                    rec, trx->read_view)) {
4283
 
                                goto requires_clust_rec;
4284
 
                        }
 
4274
                        ut_ad(index != clust_index);
 
4275
                        get_clust_rec= TRUE;
 
4276
                        goto idx_cond_check;
4285
4277
                }
4286
4278
        }
4287
4279
 
4295
4287
                /* The record is delete-marked: we can skip it */
4296
4288
 
4297
4289
                if ((srv_locks_unsafe_for_binlog
4298
 
                     || trx->isolation_level <= TRX_ISO_READ_COMMITTED)
 
4290
                     || trx->isolation_level == TRX_ISO_READ_COMMITTED)
4299
4291
                    && prebuilt->select_lock_type != LOCK_NONE
4300
4292
                    && !did_semi_consistent_read) {
4301
4293
 
4325
4317
                goto next_rec;
4326
4318
        }
4327
4319
 
 
4320
idx_cond_check:
 
4321
        if (prebuilt->idx_cond_func)
 
4322
        {
 
4323
          int res;
 
4324
          ut_ad(prebuilt->template_type != ROW_DRIZZLE_DUMMY_TEMPLATE);
 
4325
          offsets = rec_get_offsets(rec, index, offsets, ULINT_UNDEFINED, &heap);
 
4326
          row_sel_store_mysql_rec(buf, prebuilt, rec,
 
4327
                                  offsets, 0, prebuilt->n_index_fields);
 
4328
          res= prebuilt->idx_cond_func(prebuilt->idx_cond_func_arg);
 
4329
          if (res == 0)
 
4330
            goto next_rec;
 
4331
          if (res == 2)
 
4332
          {
 
4333
            err = DB_RECORD_NOT_FOUND;
 
4334
            goto idx_cond_failed;
 
4335
          }
 
4336
        }
 
4337
 
4328
4338
        /* Get the clustered index record if needed, if we did not do the
4329
4339
        search using the clustered index. */
4330
4340
 
4331
 
        if (index != clust_index && prebuilt->need_to_access_clustered) {
 
4341
        if (get_clust_rec || (index != clust_index &&
 
4342
            prebuilt->need_to_access_clustered)) {
4332
4343
 
4333
 
requires_clust_rec:
4334
4344
                /* We use a 'goto' to the preceding label if a consistent
4335
4345
                read of a secondary index record requires us to look up old
4336
4346
                versions of the associated clustered index record. */
4349
4359
                err = row_sel_get_clust_rec_for_mysql(prebuilt, index, rec,
4350
4360
                                                      thr, &clust_rec,
4351
4361
                                                      &offsets, &heap, &mtr);
4352
 
                switch (err) {
4353
 
                case DB_SUCCESS:
4354
 
                        if (clust_rec == NULL) {
4355
 
                                /* The record did not exist in the read view */
4356
 
                                ut_ad(prebuilt->select_lock_type == LOCK_NONE);
 
4362
                if (err != DB_SUCCESS) {
4357
4363
 
4358
 
                                goto next_rec;
4359
 
                        }
4360
 
                        break;
4361
 
                case DB_SUCCESS_LOCKED_REC:
4362
 
                        ut_a(clust_rec != NULL);
4363
 
                        if (srv_locks_unsafe_for_binlog
4364
 
                             || trx->isolation_level
4365
 
                            <= TRX_ISO_READ_COMMITTED) {
4366
 
                                /* Note that the clustered index record
4367
 
                                was locked. */
4368
 
                                prebuilt->new_rec_locks = 2;
4369
 
                        }
4370
 
                        err = DB_SUCCESS;
4371
 
                        break;
4372
 
                default:
4373
4364
                        goto lock_wait_or_error;
4374
4365
                }
4375
4366
 
 
4367
                if (clust_rec == NULL) {
 
4368
                        /* The record did not exist in the read view */
 
4369
                        ut_ad(prebuilt->select_lock_type == LOCK_NONE);
 
4370
 
 
4371
                        goto next_rec;
 
4372
                }
 
4373
 
4376
4374
                if (UNIV_UNLIKELY(rec_get_deleted_flag(clust_rec, comp))) {
4377
4375
 
4378
4376
                        /* The record is delete marked: we can skip it */
4379
4377
 
4380
4378
                        if ((srv_locks_unsafe_for_binlog
4381
 
                             || trx->isolation_level <= TRX_ISO_READ_COMMITTED)
 
4379
                             || trx->isolation_level == TRX_ISO_READ_COMMITTED)
4382
4380
                            && prebuilt->select_lock_type != LOCK_NONE) {
4383
4381
 
4384
4382
                                /* No need to keep a lock on a delete-marked
4391
4389
                        goto next_rec;
4392
4390
                }
4393
4391
 
4394
 
                result_rec = clust_rec;
4395
 
                ut_ad(rec_offs_validate(result_rec, clust_index, offsets));
 
4392
                if (prebuilt->need_to_access_clustered) {
 
4393
 
 
4394
                        result_rec = clust_rec;
 
4395
 
 
4396
                        ut_ad(rec_offs_validate(result_rec, clust_index,
 
4397
                                                offsets));
 
4398
                } else {
 
4399
                        /* We used 'offsets' for the clust rec, recalculate
 
4400
                        them for 'rec' */
 
4401
                        offsets = rec_get_offsets(rec, index, offsets,
 
4402
                                                  ULINT_UNDEFINED, &heap);
 
4403
                        result_rec = rec;
 
4404
                }
4396
4405
        } else {
4397
4406
                result_rec = rec;
4398
4407
        }
4403
4412
        ut_ad(rec_offs_validate(result_rec,
4404
4413
                                result_rec != rec ? clust_index : index,
4405
4414
                                offsets));
4406
 
        ut_ad(!rec_get_deleted_flag(result_rec, comp));
4407
4415
 
4408
4416
        /* At this point, the clustered index record is protected
4409
4417
        by a page latch that was acquired when pcur was positioned.
4414
4422
            && prebuilt->select_lock_type == LOCK_NONE
4415
4423
            && !prebuilt->templ_contains_blob
4416
4424
            && !prebuilt->clust_index_was_generated
 
4425
            && !prebuilt->used_in_HANDLER
4417
4426
            && prebuilt->template_type
4418
4427
            != ROW_MYSQL_DUMMY_TEMPLATE) {
4419
4428
 
4425
4434
                are BLOBs in the fields to be fetched. In HANDLER we do
4426
4435
                not cache rows because there the cursor is a scrollable
4427
4436
                cursor. */
 
4437
                some_fields_in_buffer= (index != clust_index &&
 
4438
                                        prebuilt->idx_cond_func);
4428
4439
 
4429
 
                if (!row_sel_push_cache_row_for_mysql(prebuilt, result_rec,
4430
 
                                                      result_rec != rec,
4431
 
                                                      offsets)) {
4432
 
                        /* Only fresh inserts may contain incomplete
4433
 
                        externally stored columns. Pretend that such
4434
 
                        records do not exist. Such records may only be
4435
 
                        accessed at the READ UNCOMMITTED isolation
4436
 
                        level or when rolling back a recovered
4437
 
                        transaction. Rollback happens at a lower
4438
 
                        level, not here. */
4439
 
                        ut_a(trx->isolation_level == TRX_ISO_READ_UNCOMMITTED);
4440
 
                } else if (prebuilt->n_fetch_cached
4441
 
                           == MYSQL_FETCH_CACHE_SIZE) {
 
4440
                row_sel_push_cache_row_for_mysql(prebuilt, result_rec,
 
4441
                                                 offsets,
 
4442
                                                 some_fields_in_buffer?
 
4443
                                                 prebuilt->n_index_fields: 0,
 
4444
                                                 buf);
 
4445
                if (prebuilt->n_fetch_cached == MYSQL_FETCH_CACHE_SIZE) {
4442
4446
 
4443
4447
                        goto got_row;
4444
4448
                }
4445
4449
 
4446
4450
                goto next_rec;
4447
4451
        } else {
4448
 
                if (UNIV_UNLIKELY
4449
 
                    (prebuilt->template_type == ROW_MYSQL_DUMMY_TEMPLATE)) {
4450
 
                        /* CHECK TABLE: fetch the row */
4451
 
 
4452
 
                        if (result_rec != rec
4453
 
                            && !prebuilt->need_to_access_clustered) {
4454
 
                                /* We used 'offsets' for the clust
4455
 
                                rec, recalculate them for 'rec' */
4456
 
                                offsets = rec_get_offsets(rec, index, offsets,
4457
 
                                                          ULINT_UNDEFINED,
4458
 
                                                          &heap);
4459
 
                                result_rec = rec;
4460
 
                        }
4461
 
 
 
4452
                if (prebuilt->template_type == ROW_MYSQL_DUMMY_TEMPLATE) {
4462
4453
                        memcpy(buf + 4, result_rec
4463
4454
                               - rec_offs_extra_size(offsets),
4464
4455
                               rec_offs_size(offsets));
4465
4456
                        mach_write_to_4(buf,
4466
4457
                                        rec_offs_extra_size(offsets) + 4);
4467
4458
                } else {
4468
 
                        /* Returning a row to MySQL */
 
4459
                        if (!row_sel_store_mysql_rec(buf, prebuilt,
 
4460
                                                     result_rec, offsets,
 
4461
                                                     prebuilt->idx_cond_func?
 
4462
                                                     prebuilt->n_index_fields: 0,
 
4463
                                                     prebuilt->n_template)) {
 
4464
                                err = DB_TOO_BIG_RECORD;
4469
4465
 
4470
 
                        if (!row_sel_store_mysql_rec(buf, prebuilt, result_rec,
4471
 
                                                     result_rec != rec,
4472
 
                                                     offsets)) {
4473
 
                                /* Only fresh inserts may contain
4474
 
                                incomplete externally stored
4475
 
                                columns. Pretend that such records do
4476
 
                                not exist. Such records may only be
4477
 
                                accessed at the READ UNCOMMITTED
4478
 
                                isolation level or when rolling back a
4479
 
                                recovered transaction. Rollback
4480
 
                                happens at a lower level, not here. */
4481
 
                                ut_a(trx->isolation_level
4482
 
                                     == TRX_ISO_READ_UNCOMMITTED);
4483
 
                                goto next_rec;
 
4466
                                goto lock_wait_or_error;
4484
4467
                        }
4485
4468
                }
4486
4469
 
4505
4488
        HANDLER command where the user can move the cursor with PREV or NEXT
4506
4489
        even after a unique search. */
4507
4490
 
 
4491
idx_cond_failed:
4508
4492
        if (!unique_search_from_clust_index
4509
 
            || prebuilt->select_lock_type != LOCK_NONE) {
 
4493
            || prebuilt->select_lock_type != LOCK_NONE
 
4494
            || prebuilt->used_in_HANDLER) {
4510
4495
 
4511
4496
                /* Inside an update always store the cursor position */
4512
4497
 
4524
4509
                prebuilt->row_read_type = ROW_READ_TRY_SEMI_CONSISTENT;
4525
4510
        }
4526
4511
        did_semi_consistent_read = FALSE;
4527
 
        prebuilt->new_rec_locks = 0;
 
4512
 
 
4513
        if (UNIV_UNLIKELY(srv_locks_unsafe_for_binlog
 
4514
                          || trx->isolation_level == TRX_ISO_READ_COMMITTED)
 
4515
            && prebuilt->select_lock_type != LOCK_NONE) {
 
4516
 
 
4517
                trx_reset_new_rec_lock_info(trx);
 
4518
        }
4528
4519
 
4529
4520
        /*-------------------------------------------------------------*/
4530
4521
        /* PHASE 5: Move the cursor to the next index record */
4589
4580
 
4590
4581
        btr_pcur_store_position(pcur, &mtr);
4591
4582
 
4592
 
lock_table_wait:
4593
4583
        mtr_commit(&mtr);
4594
4584
        mtr_has_extra_clust_latch = FALSE;
4595
4585
 
4607
4597
                thr->lock_state = QUE_THR_LOCK_NOLOCK;
4608
4598
                mtr_start(&mtr);
4609
4599
 
4610
 
                /* Table lock waited, go try to obtain table lock
4611
 
                again */
4612
 
                if (table_lock_waited) {
4613
 
                        table_lock_waited = FALSE;
4614
 
 
4615
 
                        goto wait_table_again;
4616
 
                }
4617
 
 
4618
4600
                sel_restore_position_for_mysql(&same_user_rec,
4619
4601
                                               BTR_SEARCH_LEAF, pcur,
4620
4602
                                               moves_up, &mtr);
4621
4603
 
4622
4604
                if ((srv_locks_unsafe_for_binlog
4623
 
                     || trx->isolation_level <= TRX_ISO_READ_COMMITTED)
 
4605
                     || trx->isolation_level == TRX_ISO_READ_COMMITTED)
4624
4606
                    && !same_user_rec) {
4625
4607
 
4626
4608
                        /* Since we were not able to restore the cursor
4639
4621
                        rec_loop we will again try to set a lock, and
4640
4622
                        new_rec_lock_info in trx will be right at the end. */
4641
4623
 
4642
 
                        prebuilt->new_rec_locks = 0;
 
4624
                        trx_reset_new_rec_lock_info(trx);
4643
4625
                }
4644
4626
 
4645
4627
                mode = pcur->search_mode;
4699
4681
        return(err);
4700
4682
}
4701
4683
 
4702
 
/*******************************************************************//**
 
4684
/***********************************************************************
4703
4685
Checks if MySQL at the moment is allowed for this table to retrieve a
4704
 
consistent read result, or store it to the query cache.
4705
 
@return TRUE if storing or retrieving from the query cache is permitted */
 
4686
consistent read result, or store it to the query cache. */
4706
4687
UNIV_INTERN
4707
4688
ibool
4708
4689
row_search_check_if_query_cache_permitted(
4709
4690
/*======================================*/
4710
 
        trx_t*          trx,            /*!< in: transaction object */
4711
 
        const char*     norm_name)      /*!< in: concatenation of database name,
 
4691
                                        /* out: TRUE if storing or retrieving
 
4692
                                        from the query cache is permitted */
 
4693
        trx_t*          trx,            /* in: transaction object */
 
4694
        const char*     norm_name)      /* in: concatenation of database name,
4712
4695
                                        '/' char, table name */
4713
4696
{
4714
4697
        dict_table_t*   table;
4733
4716
        IX type locks actually would require ret = FALSE. */
4734
4717
 
4735
4718
        if (UT_LIST_GET_LEN(table->locks) == 0
4736
 
            && trx->id >= table->query_cache_inv_trx_id) {
 
4719
            && ut_dulint_cmp(trx->id,
 
4720
                             table->query_cache_inv_trx_id) >= 0) {
4737
4721
 
4738
4722
                ret = TRUE;
4739
4723
 
4754
4738
        return(ret);
4755
4739
}
4756
4740
 
4757
 
/*******************************************************************//**
 
4741
/***********************************************************************
4758
4742
Read the AUTOINC column from the current row. If the value is less than
4759
 
0 and the type is not unsigned then we reset the value to 0.
4760
 
@return value read from the column */
 
4743
0 and the type is not unsigned then we reset the value to 0. */
4761
4744
static
4762
4745
ib_uint64_t
4763
4746
row_search_autoinc_read_column(
4764
4747
/*===========================*/
4765
 
        dict_index_t*   index,          /*!< in: index to read from */
4766
 
        const rec_t*    rec,            /*!< in: current rec */
4767
 
        ulint           col_no,         /*!< in: column number */
4768
 
        ulint           mtype,          /*!< in: column main type */
4769
 
        ibool           unsigned_type)  /*!< in: signed or unsigned flag */
 
4748
                                        /* out: value read from the column */
 
4749
        dict_index_t*   index,          /* in: index to read from */
 
4750
        const rec_t*    rec,            /* in: current rec */
 
4751
        ulint           col_no,         /* in: column number */
 
4752
        ibool           unsigned_type)  /* in: signed or unsigned flag */
4770
4753
{
4771
4754
        ulint           len;
4772
4755
        const byte*     data;
4782
4765
        data = rec_get_nth_field(rec, offsets, col_no, &len);
4783
4766
 
4784
4767
        ut_a(len != UNIV_SQL_NULL);
4785
 
 
4786
 
        switch (mtype) {
4787
 
        case DATA_INT:
4788
 
                ut_a(len <= sizeof value);
4789
 
                value = mach_read_int_type(data, len, unsigned_type);
4790
 
                break;
4791
 
 
4792
 
        case DATA_FLOAT:
4793
 
                ut_a(len == sizeof(float));
4794
 
                value = (ib_uint64_t) mach_float_read(data);
4795
 
                break;
4796
 
 
4797
 
        case DATA_DOUBLE:
4798
 
                ut_a(len == sizeof(double));
4799
 
                value = (ib_uint64_t) mach_double_read(data);
4800
 
                break;
4801
 
 
4802
 
        default:
4803
 
                ut_error;
4804
 
        }
 
4768
        ut_a(len <= sizeof value);
 
4769
 
 
4770
        /* we assume AUTOINC value cannot be negative */
 
4771
        value = mach_read_int_type(data, len, unsigned_type);
4805
4772
 
4806
4773
        if (UNIV_LIKELY_NULL(heap)) {
4807
4774
                mem_heap_free(heap);
4814
4781
        return(value);
4815
4782
}
4816
4783
 
4817
 
/*******************************************************************//**
4818
 
Get the last row.
4819
 
@return current rec or NULL */
 
4784
/***********************************************************************
 
4785
Get the last row. */
4820
4786
static
4821
4787
const rec_t*
4822
4788
row_search_autoinc_get_rec(
4823
4789
/*=======================*/
4824
 
        btr_pcur_t*     pcur,           /*!< in: the current cursor */
4825
 
        mtr_t*          mtr)            /*!< in: mini transaction */
 
4790
                                        /* out: current rec or NULL */
 
4791
        btr_pcur_t*     pcur,           /* in: the current cursor */
 
4792
        mtr_t*          mtr)            /* in: mini transaction */
4826
4793
{
4827
4794
        do {
4828
4795
                const rec_t* rec = btr_pcur_get_rec(pcur);
4835
4802
        return(NULL);
4836
4803
}
4837
4804
 
4838
 
/*******************************************************************//**
4839
 
Read the max AUTOINC value from an index.
4840
 
@return DB_SUCCESS if all OK else error code, DB_RECORD_NOT_FOUND if
4841
 
column name can't be found in index */
 
4805
/***********************************************************************
 
4806
Read the max AUTOINC value from an index. */
4842
4807
UNIV_INTERN
4843
4808
ulint
4844
4809
row_search_max_autoinc(
4845
4810
/*===================*/
4846
 
        dict_index_t*   index,          /*!< in: index to search */
4847
 
        const char*     col_name,       /*!< in: name of autoinc column */
4848
 
        ib_uint64_t*    value)          /*!< out: AUTOINC value read */
 
4811
                                        /* out: DB_SUCCESS if all OK else
 
4812
                                        error code, DB_RECORD_NOT_FOUND if
 
4813
                                        column name can't be found in index */
 
4814
        dict_index_t*   index,          /* in: index to search */
 
4815
        const char*     col_name,       /* in: name of autoinc column */
 
4816
        ib_uint64_t*    value)          /* out: AUTOINC value read */
4849
4817
{
4850
4818
        ulint           i;
4851
4819
        ulint           n_cols;
4887
4855
                                        dfield->col->prtype & DATA_UNSIGNED);
4888
4856
 
4889
4857
                                *value = row_search_autoinc_read_column(
4890
 
                                        index, rec, i,
4891
 
                                        dfield->col->mtype, unsigned_type);
 
4858
                                        index, rec, i, unsigned_type);
4892
4859
                        }
4893
4860
                }
4894
4861