~drizzle-trunk/drizzle/development

« back to all changes in this revision

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

  • Committer: Lee Bieber
  • Date: 2010-10-27 18:28:56 UTC
  • mfrom: (1883.1.3 build)
  • Revision ID: kalebral@gmail.com-20101027182856-q3wqtbv1t4egkjsk
Merge Andrew - fix bug 667360: --defaults-file not processed before paths read           
Merge Andrew - fix bug 656577: Importing SQL script results in silent failure    
Merge Andrew - fix bug 667053: drizzledump minor output cleanup needed

Show diffs side-by-side

added added

removed removed

Lines of Context:
1
1
/*****************************************************************************
2
2
 
3
 
Copyright (C) 1997, 2010, Innobase Oy. All Rights Reserved.
4
 
Copyright (C) 2008, Google Inc.
 
3
Copyright (c) 1997, 2009, Innobase Oy. All Rights Reserved.
 
4
Copyright (c) 2008, Google Inc.
5
5
 
6
6
Portions of this file contain modifications contributed and copyrighted by
7
7
Google, Inc. Those modifications are gratefully acknowledged and are described
88
88
/*========================*/
89
89
        ulint           mtype,          /*!< in: main type */
90
90
        ulint           prtype,         /*!< in: precise type */
91
 
        ulint           mbminmaxlen,    /*!< in: minimum and maximum length of
92
 
                                        a multi-byte character */
 
91
        ulint           mbminlen,       /*!< in: minimum length of a
 
92
                                        multi-byte character */
 
93
        ulint           mbmaxlen,       /*!< in: maximum length of a
 
94
                                        multi-byte character */
93
95
        const byte*     clust_field,    /*!< in: the locally stored part of
94
96
                                        the clustered index column, including
95
97
                                        the BLOB pointer; the clustered
104
106
        ulint   len;
105
107
        byte    buf[DICT_MAX_INDEX_COL_LEN];
106
108
 
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
109
        len = btr_copy_externally_stored_field_prefix(buf, sizeof buf,
120
110
                                                      zip_size,
121
111
                                                      clust_field, clust_len);
129
119
                return(FALSE);
130
120
        }
131
121
 
132
 
        len = dtype_get_at_most_n_mbchars(prtype, mbminmaxlen,
 
122
        len = dtype_get_at_most_n_mbchars(prtype, mbminlen, mbmaxlen,
133
123
                                          sec_len, len, (const char*) buf);
134
124
 
135
125
        return(!cmp_data_data(mtype, prtype, buf, len, sec_field, sec_len));
142
132
NOTE: the comparison is NOT done as a binary comparison, but character
143
133
fields are compared with collation!
144
134
@return TRUE if the secondary record is equal to the corresponding
145
 
fields in the clustered record, when compared with collation;
146
 
FALSE if not equal or if the clustered record has been marked for deletion */
 
135
fields in the clustered record, when compared with collation */
147
136
static
148
137
ibool
149
138
row_sel_sec_rec_is_for_clust_rec(
212
201
                        }
213
202
 
214
203
                        len = dtype_get_at_most_n_mbchars(
215
 
                                col->prtype, col->mbminmaxlen,
 
204
                                col->prtype, col->mbminlen, col->mbmaxlen,
216
205
                                ifield->prefix_len, len, (char*) clust_field);
217
206
 
218
207
                        if (rec_offs_nth_extern(clust_offs, clust_pos)
219
208
                            && len < sec_len) {
220
209
                                if (!row_sel_sec_rec_is_for_blob(
221
210
                                            col->mtype, col->prtype,
222
 
                                            col->mbminmaxlen,
 
211
                                            col->mbminlen, col->mbmaxlen,
223
212
                                            clust_field, clust_len,
224
213
                                            sec_field, sec_len,
225
214
                                            dict_table_zip_size(
258
247
{
259
248
        sel_node_t*     node;
260
249
 
261
 
        node = static_cast<sel_node_t *>(mem_heap_alloc(heap, sizeof(sel_node_t)));
 
250
        node = mem_heap_alloc(heap, sizeof(sel_node_t));
262
251
        node->common.type = QUE_NODE_SELECT;
263
252
        node->state = SEL_NODE_OPEN;
264
253
 
338
327
                eval_node_copy_val(var->alias, exp);
339
328
 
340
329
                exp = que_node_get_next(exp);
341
 
                var = static_cast<sym_node_t *>(que_node_get_next(var));
 
330
                var = que_node_get_next(var);
342
331
        }
343
332
}
344
333
 
355
344
 
356
345
        ut_ad(node->is_aggregate);
357
346
 
358
 
        func_node = static_cast<func_node_t *>(node->select_list);
 
347
        func_node = node->select_list;
359
348
 
360
349
        while (func_node) {
361
350
                eval_node_set_int_val(func_node, 0);
362
351
 
363
 
                func_node = static_cast<func_node_t *>(que_node_get_next(func_node));
 
352
                func_node = que_node_get_next(func_node);
364
353
        }
365
354
 
366
355
        node->aggregate_already_fetched = FALSE;
426
415
                                                              field_no))) {
427
416
 
428
417
                                /* Copy an externally stored field to the
429
 
                                temporary heap, if possible. */
 
418
                                temporary heap */
430
419
 
431
420
                                heap = mem_heap_create(1);
432
421
 
435
424
                                        dict_table_zip_size(index->table),
436
425
                                        field_no, &len, heap);
437
426
 
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
427
                                ut_a(len != UNIV_SQL_NULL);
450
428
 
451
429
                                needs_copy = TRUE;
453
431
                                data = rec_get_nth_field(rec, offsets,
454
432
                                                         field_no, &len);
455
433
 
 
434
                                if (len == UNIV_SQL_NULL) {
 
435
                                        len = UNIV_SQL_NULL;
 
436
                                }
 
437
 
456
438
                                needs_copy = column->copy_val;
457
439
                        }
458
440
 
486
468
 
487
469
        ut_ad(que_node_get_type(column) == QUE_NODE_SYMBOL);
488
470
 
489
 
        column->prefetch_buf = static_cast<sel_buf_t *>(mem_alloc(SEL_MAX_N_PREFETCH
490
 
                                                                  * sizeof(sel_buf_t)));
 
471
        column->prefetch_buf = mem_alloc(SEL_MAX_N_PREFETCH
 
472
                                         * sizeof(sel_buf_t));
491
473
        for (i = 0; i < SEL_MAX_N_PREFETCH; i++) {
492
474
                sel_buf = column->prefetch_buf + i;
493
475
 
566
548
                column values to be able to free it later: therefore
567
549
                we swap the values for sel_buf and val */
568
550
 
569
 
                sel_buf->data = static_cast<byte *>(dfield_get_data(val));
 
551
                sel_buf->data = dfield_get_data(val);
570
552
                sel_buf->len = dfield_get_len(val);
571
553
                sel_buf->val_buf_size = que_node_get_val_buf_size(column);
572
554
 
634
616
 
635
617
                val = que_node_get_val(column);
636
618
 
637
 
                data = static_cast<byte *>(dfield_get_data(val));
 
619
                data = dfield_get_data(val);
638
620
                len = dfield_get_len(val);
639
621
                val_buf_size = que_node_get_val_buf_size(column);
640
622
 
746
728
                /* Evaluate the left side of the comparison, i.e., get the
747
729
                column value if there is an indirection */
748
730
 
749
 
          eval_sym(static_cast<sym_node_t *>(cond->args));
 
731
                eval_sym(cond->args);
750
732
 
751
733
                /* Do the comparison */
752
734
 
873
855
                trx = thr_get_trx(thr);
874
856
 
875
857
                if (srv_locks_unsafe_for_binlog
876
 
                    || trx->isolation_level <= TRX_ISO_READ_COMMITTED) {
 
858
                    || trx->isolation_level == TRX_ISO_READ_COMMITTED) {
877
859
                        lock_type = LOCK_REC_NOT_GAP;
878
860
                } else {
879
861
                        lock_type = LOCK_ORDINARY;
882
864
                err = lock_clust_rec_read_check_and_lock(
883
865
                        0, btr_pcur_get_block(&plan->clust_pcur),
884
866
                        clust_rec, index, offsets,
885
 
                        static_cast<lock_mode>(node->row_lock_mode), lock_type, thr);
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:
 
867
                        node->row_lock_mode, lock_type, thr);
 
868
 
 
869
                if (err != DB_SUCCESS) {
 
870
 
895
871
                        goto err_exit;
896
872
                }
897
873
        } else {
947
923
        when plan->clust_pcur was positioned.  The latch will not be
948
924
        released until mtr_commit(mtr). */
949
925
 
950
 
        ut_ad(!rec_get_deleted_flag(clust_rec, rec_offs_comp(offsets)));
951
926
        row_sel_fetch_columns(index, clust_rec, offsets,
952
927
                              UT_LIST_GET_FIRST(plan->columns));
953
928
        *out_rec = clust_rec;
962
937
 
963
938
/*********************************************************************//**
964
939
Sets a lock on a record.
965
 
@return DB_SUCCESS, DB_SUCCESS_LOCKED_REC, or error code */
 
940
@return DB_SUCCESS or error code */
966
941
UNIV_INLINE
967
 
enum db_err
 
942
ulint
968
943
sel_set_rec_lock(
969
944
/*=============*/
970
945
        const buf_block_t*      block,  /*!< in: buffer block of rec */
976
951
                                        LOC_REC_NOT_GAP */
977
952
        que_thr_t*              thr)    /*!< in: query thread */
978
953
{
979
 
        trx_t*          trx;
980
 
        enum db_err     err;
 
954
        trx_t*  trx;
 
955
        ulint   err;
981
956
 
982
957
        trx = thr_get_trx(thr);
983
958
 
989
964
        }
990
965
 
991
966
        if (dict_index_is_clust(index)) {
992
 
                err = lock_clust_rec_read_check_and_lock(0, block, rec, index,
993
 
                                                         offsets, static_cast<lock_mode>(mode), type, thr);
 
967
                err = lock_clust_rec_read_check_and_lock(
 
968
                        0, block, rec, index, offsets, mode, type, thr);
994
969
        } else {
995
 
                err = lock_sec_rec_read_check_and_lock(0, block, rec, index,
996
 
                                                       offsets, static_cast<lock_mode>(mode), type, thr);
 
970
                err = lock_sec_rec_read_check_and_lock(
 
971
                        0, block, rec, index, offsets, mode, type, thr);
997
972
        }
998
973
 
999
974
        return(err);
1493
1468
 
1494
1469
                        if (srv_locks_unsafe_for_binlog
1495
1470
                            || trx->isolation_level
1496
 
                            <= TRX_ISO_READ_COMMITTED) {
 
1471
                            == TRX_ISO_READ_COMMITTED) {
1497
1472
 
1498
1473
                                if (page_rec_is_supremum(next_rec)) {
1499
1474
 
1510
1485
                                               node->row_lock_mode,
1511
1486
                                               lock_type, thr);
1512
1487
 
1513
 
                        switch (err) {
1514
 
                        case DB_SUCCESS_LOCKED_REC:
1515
 
                                err = DB_SUCCESS;
1516
 
                        case DB_SUCCESS:
1517
 
                                break;
1518
 
                        default:
 
1488
                        if (err != DB_SUCCESS) {
1519
1489
                                /* Note that in this case we will store in pcur
1520
1490
                                the PREDECESSOR of the record we are waiting
1521
1491
                                the lock for */
 
1492
 
1522
1493
                                goto lock_wait_or_error;
1523
1494
                        }
1524
1495
                }
1554
1525
                trx = thr_get_trx(thr);
1555
1526
 
1556
1527
                if (srv_locks_unsafe_for_binlog
1557
 
                    || trx->isolation_level <= TRX_ISO_READ_COMMITTED) {
 
1528
                    || trx->isolation_level == TRX_ISO_READ_COMMITTED) {
1558
1529
 
1559
1530
                        if (page_rec_is_supremum(rec)) {
1560
1531
 
1570
1541
                                       rec, index, offsets,
1571
1542
                                       node->row_lock_mode, lock_type, thr);
1572
1543
 
1573
 
                switch (err) {
1574
 
                case DB_SUCCESS_LOCKED_REC:
1575
 
                        err = DB_SUCCESS;
1576
 
                case DB_SUCCESS:
1577
 
                        break;
1578
 
                default:
 
1544
                if (err != DB_SUCCESS) {
 
1545
 
1579
1546
                        goto lock_wait_or_error;
1580
1547
                }
1581
1548
        }
1650
1617
                                }
1651
1618
 
1652
1619
                                if (old_vers == NULL) {
1653
 
                                        /* The record does not exist
1654
 
                                        in our read view. Skip it, but
1655
 
                                        first attempt to determine
1656
 
                                        whether the index segment we
1657
 
                                        are searching through has been
1658
 
                                        exhausted. */
1659
 
 
1660
1620
                                        offsets = rec_get_offsets(
1661
1621
                                                rec, index, offsets,
1662
1622
                                                ULINT_UNDEFINED, &heap);
1741
1701
                                            &mtr);
1742
1702
                mtr_has_extra_clust_latch = TRUE;
1743
1703
 
1744
 
                switch (err) {
1745
 
                case DB_SUCCESS_LOCKED_REC:
1746
 
                        err = DB_SUCCESS;
1747
 
                case DB_SUCCESS:
1748
 
                        break;
1749
 
                default:
 
1704
                if (err != DB_SUCCESS) {
 
1705
 
1750
1706
                        goto lock_wait_or_error;
1751
1707
                }
1752
1708
 
1931
1887
                        thr->run_node = que_node_get_parent(node);
1932
1888
                }
1933
1889
 
1934
 
                err = DB_SUCCESS;
1935
1890
                goto func_exit;
1936
1891
        }
1937
1892
 
2023
1978
 
2024
1979
        ut_ad(thr);
2025
1980
 
2026
 
        node = static_cast<sel_node_t *>(thr->run_node);
 
1981
        node = thr->run_node;
2027
1982
 
2028
1983
        ut_ad(que_node_get_type(node) == QUE_NODE_SELECT);
2029
1984
 
2060
2015
 
2061
2016
                        while (table_node) {
2062
2017
                                err = lock_table(0, table_node->table,
2063
 
                                                 static_cast<lock_mode>(i_lock_mode), thr);
 
2018
                                                 i_lock_mode, thr);
2064
2019
                                if (err != DB_SUCCESS) {
2065
2020
                                        thr_get_trx(thr)->error_state = err;
2066
2021
 
2067
2022
                                        return(NULL);
2068
2023
                                }
2069
2024
 
2070
 
                                table_node = static_cast<sym_node_t *>(que_node_get_next(table_node));
 
2025
                                table_node = que_node_get_next(table_node);
2071
2026
                        }
2072
2027
                }
2073
2028
 
2089
2044
                        /* Reset the aggregate total values */
2090
2045
                        sel_reset_aggregate_vals(node);
2091
2046
                }
2092
 
 
2093
 
                err = DB_SUCCESS;
2094
2047
        }
2095
2048
 
2096
2049
        err = row_sel(node, thr);
2124
2077
 
2125
2078
        ut_ad(thr);
2126
2079
 
2127
 
        node = static_cast<fetch_node_t *>(thr->run_node);
 
2080
        node = thr->run_node;
2128
2081
        sel_node = node->cursor_def;
2129
2082
 
2130
2083
        ut_ad(que_node_get_type(node) == QUE_NODE_FETCH);
2183
2136
        void*   row,            /*!< in:  sel_node_t* */
2184
2137
        void*   user_arg)       /*!< in:  not used */
2185
2138
{
2186
 
        sel_node_t *node = static_cast<sel_node_t *>(row);
 
2139
        sel_node_t*     node = row;
2187
2140
        que_node_t*     exp;
2188
2141
        ulint           i = 0;
2189
2142
 
2217
2170
        return((void*)42);
2218
2171
}
2219
2172
 
 
2173
/****************************************************************//**
 
2174
Callback function for fetch that stores an unsigned 4 byte integer to the
 
2175
location pointed. The column's type must be DATA_INT, DATA_UNSIGNED, length
 
2176
= 4.
 
2177
@return always returns NULL */
 
2178
UNIV_INTERN
 
2179
void*
 
2180
row_fetch_store_uint4(
 
2181
/*==================*/
 
2182
        void*   row,            /*!< in:  sel_node_t* */
 
2183
        void*   user_arg)       /*!< in:  data pointer */
 
2184
{
 
2185
        sel_node_t*     node = row;
 
2186
        ib_uint32_t*    val = user_arg;
 
2187
        ulint           tmp;
 
2188
 
 
2189
        dfield_t*       dfield = que_node_get_val(node->select_list);
 
2190
        const dtype_t*  type = dfield_get_type(dfield);
 
2191
        ulint           len = dfield_get_len(dfield);
 
2192
 
 
2193
        ut_a(dtype_get_mtype(type) == DATA_INT);
 
2194
        ut_a(dtype_get_prtype(type) & DATA_UNSIGNED);
 
2195
        ut_a(len == 4);
 
2196
 
 
2197
        tmp = mach_read_from_4(dfield_get_data(dfield));
 
2198
        *val = (ib_uint32_t) tmp;
 
2199
 
 
2200
        return(NULL);
 
2201
}
 
2202
 
2220
2203
/***********************************************************//**
2221
2204
Prints a row in a select result.
2222
2205
@return query thread to run next or NULL */
2232
2215
 
2233
2216
        ut_ad(thr);
2234
2217
 
2235
 
        node = static_cast<row_printf_node_t *>(thr->run_node);
 
2218
        node = thr->run_node;
2236
2219
 
2237
2220
        sel_node = node->sel_node;
2238
2221
 
2544
2527
        ulint           len)    /*!< in: length of the data */
2545
2528
{
2546
2529
        byte*   ptr;
 
2530
        byte*   field_end;
 
2531
        byte*   pad_ptr;
2547
2532
 
2548
2533
        ut_ad(len != UNIV_SQL_NULL);
2549
 
        UNIV_MEM_ASSERT_RW(data, len);
2550
2534
 
2551
2535
        switch (templ->type) {
2552
 
                const byte*     field_end;
2553
 
                byte*           pad;
2554
2536
        case DATA_INT:
2555
2537
                /* Convert integer data from Innobase to a little-endian
2556
2538
                format, sign bit restored to normal */
2594
2576
                unused end of a >= 5.0.3 true VARCHAR column, just in case
2595
2577
                MySQL expects its contents to be deterministic. */
2596
2578
 
2597
 
                pad = dest + len;
 
2579
                pad_ptr = dest + len;
2598
2580
 
2599
2581
                ut_ad(templ->mbminlen <= templ->mbmaxlen);
2600
2582
 
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 */
 
2583
                /* We handle UCS2 charset strings differently. */
 
2584
                if (templ->mbminlen == 2) {
 
2585
                        /* A space char is two bytes, 0x0020 in UCS2 */
2611
2586
 
2612
 
                        if (UNIV_UNLIKELY(len & 1)) {
 
2587
                        if (len & 1) {
2613
2588
                                /* A 0x20 has been stripped from the column.
2614
2589
                                Pad it back. */
2615
2590
 
2616
 
                                if (pad < field_end) {
2617
 
                                        *pad++ = 0x20;
 
2591
                                if (pad_ptr < field_end) {
 
2592
                                        *pad_ptr = 0x20;
 
2593
                                        pad_ptr++;
2618
2594
                                }
2619
2595
                        }
 
2596
 
 
2597
                        /* Pad the rest of the string with 0x0020 */
 
2598
 
 
2599
                        while (pad_ptr < field_end) {
 
2600
                                *pad_ptr = 0x00;
 
2601
                                pad_ptr++;
 
2602
                                *pad_ptr = 0x20;
 
2603
                                pad_ptr++;
 
2604
                        }
 
2605
                } else {
 
2606
                        ut_ad(templ->mbminlen == 1);
 
2607
                        /* space=0x20 */
 
2608
 
 
2609
                        memset(pad_ptr, 0x20, field_end - pad_ptr);
2620
2610
                }
2621
 
 
2622
 
                row_mysql_pad_col(templ->mbminlen, pad, field_end - pad);
2623
2611
                break;
2624
2612
 
2625
2613
        case DATA_BLOB:
2644
2632
                      || !(templ->mysql_col_len % templ->mbmaxlen));
2645
2633
                ut_ad(len * templ->mbmaxlen >= templ->mysql_col_len);
2646
2634
 
2647
 
                if (templ->mbminlen == 1 && templ->mbmaxlen != 1) {
 
2635
                if (templ->mbminlen != templ->mbmaxlen) {
2648
2636
                        /* Pad with spaces. This undoes the stripping
2649
 
                        done in row0mysql.c, function
 
2637
                        done in row0mysql.ic, function
2650
2638
                        row_mysql_store_col_in_innobase_format(). */
2651
2639
 
2652
2640
                        memset(dest + len, 0x20, templ->mysql_col_len - len);
2677
2665
Note that the template in prebuilt may advise us to copy only a few
2678
2666
columns to mysql_rec, other columns are left blank. All columns may not
2679
2667
be needed in the query.
2680
 
@return TRUE on success, FALSE if not all columns could be retrieved */
 
2668
@return TRUE if success, FALSE if could not allocate memory for a BLOB
 
2669
(though we may also assert in that case) */
2681
2670
static
2682
 
#ifdef __GNUC__
2683
 
 __attribute__((warn_unused_result))
2684
 
#endif
2685
2671
ibool
2686
2672
row_sel_store_mysql_rec(
2687
2673
/*====================*/
2689
2675
        row_prebuilt_t* prebuilt,       /*!< in: prebuilt struct */
2690
2676
        const rec_t*    rec,            /*!< in: Innobase record in the index
2691
2677
                                        which was described in prebuilt's
2692
 
                                        template, or in the clustered index;
2693
 
                                        must be protected by a page latch */
2694
 
        ibool           rec_clust,      /*!< in: TRUE if rec is in the
2695
 
                                        clustered index instead of
2696
 
                                        prebuilt->index */
 
2678
                                        template; must be protected by
 
2679
                                        a page latch */
2697
2680
        const ulint*    offsets)        /*!< in: array returned by
2698
 
                                        rec_get_offsets(rec) */
 
2681
                                        rec_get_offsets() */
2699
2682
{
2700
 
        mem_heap_t*     extern_field_heap       = NULL;
2701
 
        mem_heap_t*     heap;
2702
 
        ulint           i;
 
2683
        mysql_row_templ_t*      templ;
 
2684
        mem_heap_t*             extern_field_heap       = NULL;
 
2685
        mem_heap_t*             heap;
 
2686
        const byte*             data;
 
2687
        ulint                   len;
 
2688
        ulint                   i;
2703
2689
 
2704
2690
        ut_ad(prebuilt->mysql_template);
2705
2691
        ut_ad(prebuilt->default_rec);
2706
2692
        ut_ad(rec_offs_validate(rec, NULL, offsets));
2707
 
        ut_ad(!rec_get_deleted_flag(rec, rec_offs_comp(offsets)));
2708
2693
 
2709
2694
        if (UNIV_LIKELY_NULL(prebuilt->blob_heap)) {
2710
2695
                mem_heap_free(prebuilt->blob_heap);
2713
2698
 
2714
2699
        for (i = 0; i < prebuilt->n_template ; i++) {
2715
2700
 
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))) {
 
2701
                templ = prebuilt->mysql_template + i;
 
2702
 
 
2703
                if (UNIV_UNLIKELY(rec_offs_nth_extern(offsets,
 
2704
                                                      templ->rec_field_no))) {
2725
2705
 
2726
2706
                        /* Copy an externally stored field to the temporary
2727
2707
                        heap */
2749
2729
                        data = btr_rec_copy_externally_stored_field(
2750
2730
                                rec, offsets,
2751
2731
                                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
 
                        }
 
2732
                                templ->rec_field_no, &len, heap);
2783
2733
 
2784
2734
                        ut_a(len != UNIV_SQL_NULL);
2785
2735
                } else {
2786
2736
                        /* Field is stored in the row. */
2787
2737
 
2788
 
                        data = rec_get_nth_field(rec, offsets, field_no, &len);
 
2738
                        data = rec_get_nth_field(rec, offsets,
 
2739
                                                 templ->rec_field_no, &len);
2789
2740
 
2790
2741
                        if (UNIV_UNLIKELY(templ->type == DATA_BLOB)
2791
2742
                            && len != UNIV_SQL_NULL) {
2801
2752
                                                UNIV_PAGE_SIZE);
2802
2753
                                }
2803
2754
 
2804
 
                                data = static_cast<byte *>(memcpy(mem_heap_alloc(
 
2755
                                data = memcpy(mem_heap_alloc(
2805
2756
                                                prebuilt->blob_heap, len),
2806
 
                                                                  data, len));
 
2757
                                                data, len);
2807
2758
                        }
2808
2759
                }
2809
2760
 
2828
2779
                        /* MySQL assumes that the field for an SQL
2829
2780
                        NULL value is set to the default value. */
2830
2781
 
2831
 
                        UNIV_MEM_ASSERT_RW(prebuilt->default_rec
2832
 
                                           + templ->mysql_col_offset,
2833
 
                                           templ->mysql_col_len);
2834
2782
                        mysql_rec[templ->mysql_null_byte_offset]
2835
2783
                                |= (byte) templ->mysql_null_bit_mask;
2836
2784
                        memcpy(mysql_rec + templ->mysql_col_offset,
2882
2830
Retrieves the clustered index record corresponding to a record in a
2883
2831
non-clustered index. Does the necessary locking. Used in the MySQL
2884
2832
interface.
2885
 
@return DB_SUCCESS, DB_SUCCESS_LOCKED_REC, or error code */
 
2833
@return DB_SUCCESS or error code */
2886
2834
static
2887
 
enum db_err
 
2835
ulint
2888
2836
row_sel_get_clust_rec_for_mysql(
2889
2837
/*============================*/
2890
2838
        row_prebuilt_t* prebuilt,/*!< in: prebuilt struct in the handle */
2911
2859
        dict_index_t*   clust_index;
2912
2860
        const rec_t*    clust_rec;
2913
2861
        rec_t*          old_vers;
2914
 
        enum db_err     err;
 
2862
        ulint           err;
2915
2863
        trx_t*          trx;
2916
2864
 
2917
2865
        *out_rec = NULL;
2970
2918
 
2971
2919
                clust_rec = NULL;
2972
2920
 
2973
 
                err = DB_SUCCESS;
2974
2921
                goto func_exit;
2975
2922
        }
2976
2923
 
2985
2932
                err = lock_clust_rec_read_check_and_lock(
2986
2933
                        0, btr_pcur_get_block(prebuilt->clust_pcur),
2987
2934
                        clust_rec, clust_index, *offsets,
2988
 
                        static_cast<lock_mode>(prebuilt->select_lock_type),
2989
 
                        LOCK_REC_NOT_GAP, thr);
2990
 
                switch (err) {
2991
 
                case DB_SUCCESS:
2992
 
                case DB_SUCCESS_LOCKED_REC:
2993
 
                        break;
2994
 
                default:
 
2935
                        prebuilt->select_lock_type, LOCK_REC_NOT_GAP, thr);
 
2936
                if (err != DB_SUCCESS) {
 
2937
 
2995
2938
                        goto err_exit;
2996
2939
                }
2997
2940
        } else {
3010
2953
 
3011
2954
                        /* The following call returns 'offsets' associated with
3012
2955
                        'old_vers' */
3013
 
                  err = static_cast<db_err>(row_sel_build_prev_vers_for_mysql(
 
2956
                        err = row_sel_build_prev_vers_for_mysql(
3014
2957
                                trx->read_view, clust_index, prebuilt,
3015
2958
                                clust_rec, offsets, offset_heap, &old_vers,
3016
 
                                mtr));
 
2959
                                mtr);
3017
2960
 
3018
2961
                        if (err != DB_SUCCESS || old_vers == NULL) {
3019
2962
 
3038
2981
 
3039
2982
                if (clust_rec
3040
2983
                    && (old_vers
3041
 
                        || trx->isolation_level <= TRX_ISO_READ_UNCOMMITTED
3042
2984
                        || rec_get_deleted_flag(rec, dict_table_is_comp(
3043
2985
                                                        sec_index->table)))
3044
2986
                    && !row_sel_sec_rec_is_for_clust_rec(
3051
2993
                                     rec, sec_index, clust_rec, clust_index));
3052
2994
#endif
3053
2995
                }
3054
 
 
3055
 
                err = DB_SUCCESS;
3056
2996
        }
3057
2997
 
3058
2998
func_exit:
3065
3005
                btr_pcur_store_position(prebuilt->clust_pcur, mtr);
3066
3006
        }
3067
3007
 
 
3008
        err = DB_SUCCESS;
3068
3009
err_exit:
3069
3010
        return(err);
3070
3011
}
3148
3089
        row_prebuilt_t* prebuilt)       /*!< in: prebuilt struct */
3149
3090
{
3150
3091
        ulint                   i;
3151
 
        const mysql_row_templ_t*templ;
 
3092
        mysql_row_templ_t*      templ;
3152
3093
        byte*                   cached_rec;
3153
3094
        ut_ad(prebuilt->n_fetch_cached > 0);
3154
3095
        ut_ad(prebuilt->mysql_prefix_len <= prebuilt->mysql_row_len);
3161
3102
 
3162
3103
                for (i = 0; i < prebuilt->n_template; i++) {
3163
3104
                        templ = prebuilt->mysql_template + i;
3164
 
#if 0 /* Some of the cached_rec may legitimately be uninitialized. */
3165
 
                        UNIV_MEM_ASSERT_RW(cached_rec
3166
 
                                           + templ->mysql_col_offset,
3167
 
                                           templ->mysql_col_len);
3168
 
#endif
3169
3105
                        ut_memcpy(buf + templ->mysql_col_offset,
3170
3106
                                  cached_rec + templ->mysql_col_offset,
3171
3107
                                  templ->mysql_col_len);
3180
3116
                }
3181
3117
        }
3182
3118
        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
3119
                ut_memcpy(buf,
3189
3120
                          prebuilt->fetch_cache[prebuilt->fetch_cache_first],
3190
3121
                          prebuilt->mysql_prefix_len);
3198
3129
}
3199
3130
 
3200
3131
/********************************************************************//**
3201
 
Pushes a row for MySQL to the fetch cache.
3202
 
@return TRUE on success, FALSE if the record contains incomplete BLOBs */
 
3132
Pushes a row for MySQL to the fetch cache. */
3203
3133
UNIV_INLINE
3204
 
#ifdef __GNUC__
3205
 
__attribute__((warn_unused_result))
3206
 
#endif
3207
 
ibool
 
3134
void
3208
3135
row_sel_push_cache_row_for_mysql(
3209
3136
/*=============================*/
3210
3137
        row_prebuilt_t* prebuilt,       /*!< in: prebuilt struct */
3211
 
        const rec_t*    rec,            /*!< in: record to push, in the index
3212
 
                                        which was described in prebuilt's
3213
 
                                        template, or in the clustered index;
3214
 
                                        must be protected by a page latch */
3215
 
        ibool           rec_clust,      /*!< in: TRUE if rec is in the
3216
 
                                        clustered index instead of
3217
 
                                        prebuilt->index */
3218
 
        const ulint*    offsets)        /*!< in: rec_get_offsets(rec) */
 
3138
        const rec_t*    rec,            /*!< in: record to push; must
 
3139
                                        be protected by a page latch */
 
3140
        const ulint*    offsets)        /*!<in: rec_get_offsets() */
3219
3141
{
3220
3142
        byte*   buf;
3221
3143
        ulint   i;
3222
3144
 
3223
3145
        ut_ad(prebuilt->n_fetch_cached < MYSQL_FETCH_CACHE_SIZE);
3224
3146
        ut_ad(rec_offs_validate(rec, NULL, offsets));
3225
 
        ut_ad(!rec_get_deleted_flag(rec, rec_offs_comp(offsets)));
3226
3147
        ut_a(!prebuilt->templ_contains_blob);
3227
3148
 
3228
3149
        if (prebuilt->fetch_cache[0] == NULL) {
3234
3155
                        buffers in Linux. Put magic numbers there to help
3235
3156
                        to track a possible bug. */
3236
3157
 
3237
 
                        buf = static_cast<byte *>(mem_alloc(prebuilt->mysql_row_len + 8));
 
3158
                        buf = mem_alloc(prebuilt->mysql_row_len + 8);
3238
3159
 
3239
3160
                        prebuilt->fetch_cache[i] = buf + 4;
3240
3161
 
3245
3166
        }
3246
3167
 
3247
3168
        ut_ad(prebuilt->fetch_cache_first == 0);
3248
 
        UNIV_MEM_INVALID(prebuilt->fetch_cache[prebuilt->n_fetch_cached],
3249
 
                         prebuilt->mysql_row_len);
3250
3169
 
3251
3170
        if (UNIV_UNLIKELY(!row_sel_store_mysql_rec(
3252
3171
                                  prebuilt->fetch_cache[
3253
3172
                                          prebuilt->n_fetch_cached],
3254
 
                                  prebuilt, rec, rec_clust, offsets))) {
3255
 
                return(FALSE);
 
3173
                                  prebuilt, rec, offsets))) {
 
3174
                ut_error;
3256
3175
        }
3257
3176
 
3258
3177
        prebuilt->n_fetch_cached++;
3259
 
        return(TRUE);
3260
3178
}
3261
3179
 
3262
3180
/*********************************************************************//**
3284
3202
        ut_ad(dict_index_is_clust(index));
3285
3203
        ut_ad(!prebuilt->templ_contains_blob);
3286
3204
 
3287
 
#ifndef UNIV_SEARCH_DEBUG
3288
3205
        btr_pcur_open_with_no_init(index, search_tuple, PAGE_CUR_GE,
3289
3206
                                   BTR_SEARCH_LEAF, pcur,
 
3207
#ifndef UNIV_SEARCH_DEBUG
3290
3208
                                   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,
 
3209
#else
3295
3210
                                   0,
 
3211
#endif
3296
3212
                                   mtr);
3297
 
#endif /* UNIV_SEARCH_DEBUG */
3298
3213
        rec = btr_pcur_get_rec(pcur);
3299
3214
 
3300
3215
        if (!page_rec_is_user_rec(rec)) {
3394
3309
        mem_heap_t*     heap                            = NULL;
3395
3310
        ulint           offsets_[REC_OFFS_NORMAL_SIZE];
3396
3311
        ulint*          offsets                         = offsets_;
3397
 
        ibool           table_lock_waited               = FALSE;
3398
3312
 
3399
3313
        rec_offs_init(offsets_);
3400
3314
 
3625
3539
                                row_sel_try_search_shortcut_for_mysql().
3626
3540
                                The latch will not be released until
3627
3541
                                mtr_commit(&mtr). */
3628
 
                                ut_ad(!rec_get_deleted_flag(rec, comp));
3629
3542
 
3630
3543
                                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);
 
3544
                                                             rec, offsets)) {
 
3545
                                        err = DB_TOO_BIG_RECORD;
3645
3546
 
3646
 
                                        /* Proceed as in case SEL_RETRY. */
3647
 
                                        break;
 
3547
                                        /* We let the main loop to do the
 
3548
                                        error handling */
 
3549
                                        goto shortcut_fails_too_big_rec;
3648
3550
                                }
3649
3551
 
3650
3552
                                mtr_commit(&mtr);
3684
3586
                        default:
3685
3587
                                ut_ad(0);
3686
3588
                        }
3687
 
 
 
3589
shortcut_fails_too_big_rec:
3688
3590
                        mtr_commit(&mtr);
3689
3591
                        mtr_start(&mtr);
3690
3592
                }
3698
3600
                trx->has_search_latch = FALSE;
3699
3601
        }
3700
3602
 
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
3603
        trx_start_if_not_started(trx);
3716
3604
 
3717
3605
        if (trx->isolation_level <= TRX_ISO_READ_COMMITTED
3742
3630
 
3743
3631
        clust_index = dict_table_get_first_index(index->table);
3744
3632
 
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
3633
        if (UNIV_LIKELY(direction != 0)) {
3784
3634
                ibool   need_to_process = sel_restore_position_for_mysql(
3785
3635
                        &same_user_rec, BTR_SEARCH_LEAF,
3820
3670
                    && !page_rec_is_supremum(rec)
3821
3671
                    && set_also_gap_locks
3822
3672
                    && !(srv_locks_unsafe_for_binlog
3823
 
                         || trx->isolation_level <= TRX_ISO_READ_COMMITTED)
 
3673
                         || trx->isolation_level == TRX_ISO_READ_COMMITTED)
3824
3674
                    && prebuilt->select_lock_type != LOCK_NONE) {
3825
3675
 
3826
3676
                        /* Try to place a gap lock on the next index record
3834
3684
                                               prebuilt->select_lock_type,
3835
3685
                                               LOCK_GAP, thr);
3836
3686
 
3837
 
                        switch (err) {
3838
 
                        case DB_SUCCESS_LOCKED_REC:
3839
 
                                err = DB_SUCCESS;
3840
 
                        case DB_SUCCESS:
3841
 
                                break;
3842
 
                        default:
 
3687
                        if (err != DB_SUCCESS) {
 
3688
 
3843
3689
                                goto lock_wait_or_error;
3844
3690
                        }
3845
3691
                }
3855
3701
                }
3856
3702
        }
3857
3703
 
 
3704
        if (!prebuilt->sql_stat_start) {
 
3705
                /* No need to set an intention lock or assign a read view */
 
3706
 
 
3707
                if (trx->read_view == NULL
 
3708
                    && prebuilt->select_lock_type == LOCK_NONE) {
 
3709
 
 
3710
                        fputs("InnoDB: Error: MySQL is trying to"
 
3711
                              " perform a consistent read\n"
 
3712
                              "InnoDB: but the read view is not assigned!\n",
 
3713
                              stderr);
 
3714
                        trx_print(stderr, trx, 600);
 
3715
                        fputc('\n', stderr);
 
3716
                        ut_a(0);
 
3717
                }
 
3718
        } else if (prebuilt->select_lock_type == LOCK_NONE) {
 
3719
                /* This is a consistent read */
 
3720
                /* Assign a read view for the query */
 
3721
 
 
3722
                trx_assign_read_view(trx);
 
3723
                prebuilt->sql_stat_start = FALSE;
 
3724
        } else {
 
3725
                ulint   lock_mode;
 
3726
                if (prebuilt->select_lock_type == LOCK_S) {
 
3727
                        lock_mode = LOCK_IS;
 
3728
                } else {
 
3729
                        lock_mode = LOCK_IX;
 
3730
                }
 
3731
                err = lock_table(0, index->table, lock_mode, thr);
 
3732
 
 
3733
                if (err != DB_SUCCESS) {
 
3734
 
 
3735
                        goto lock_wait_or_error;
 
3736
                }
 
3737
                prebuilt->sql_stat_start = FALSE;
 
3738
        }
 
3739
 
3858
3740
rec_loop:
3859
3741
        /*-------------------------------------------------------------*/
3860
3742
        /* PHASE 4: Look for matching records in a loop */
3884
3766
 
3885
3767
                if (set_also_gap_locks
3886
3768
                    && !(srv_locks_unsafe_for_binlog
3887
 
                         || trx->isolation_level <= TRX_ISO_READ_COMMITTED)
 
3769
                         || trx->isolation_level == TRX_ISO_READ_COMMITTED)
3888
3770
                    && prebuilt->select_lock_type != LOCK_NONE) {
3889
3771
 
3890
3772
                        /* Try to place a lock on the index record */
3901
3783
                                               prebuilt->select_lock_type,
3902
3784
                                               LOCK_ORDINARY, thr);
3903
3785
 
3904
 
                        switch (err) {
3905
 
                        case DB_SUCCESS_LOCKED_REC:
3906
 
                                err = DB_SUCCESS;
3907
 
                        case DB_SUCCESS:
3908
 
                                break;
3909
 
                        default:
 
3786
                        if (err != DB_SUCCESS) {
 
3787
 
3910
3788
                                goto lock_wait_or_error;
3911
3789
                        }
3912
3790
                }
4022
3900
                        if (set_also_gap_locks
4023
3901
                            && !(srv_locks_unsafe_for_binlog
4024
3902
                                 || trx->isolation_level
4025
 
                                 <= TRX_ISO_READ_COMMITTED)
 
3903
                                 == TRX_ISO_READ_COMMITTED)
4026
3904
                            && prebuilt->select_lock_type != LOCK_NONE) {
4027
3905
 
4028
3906
                                /* Try to place a gap lock on the index
4036
3914
                                        prebuilt->select_lock_type, LOCK_GAP,
4037
3915
                                        thr);
4038
3916
 
4039
 
                                switch (err) {
4040
 
                                case DB_SUCCESS_LOCKED_REC:
4041
 
                                case DB_SUCCESS:
4042
 
                                        break;
4043
 
                                default:
 
3917
                                if (err != DB_SUCCESS) {
 
3918
 
4044
3919
                                        goto lock_wait_or_error;
4045
3920
                                }
4046
3921
                        }
4061
3936
                        if (set_also_gap_locks
4062
3937
                            && !(srv_locks_unsafe_for_binlog
4063
3938
                                 || trx->isolation_level
4064
 
                                 <= TRX_ISO_READ_COMMITTED)
 
3939
                                 == TRX_ISO_READ_COMMITTED)
4065
3940
                            && prebuilt->select_lock_type != LOCK_NONE) {
4066
3941
 
4067
3942
                                /* Try to place a gap lock on the index
4075
3950
                                        prebuilt->select_lock_type, LOCK_GAP,
4076
3951
                                        thr);
4077
3952
 
4078
 
                                switch (err) {
4079
 
                                case DB_SUCCESS_LOCKED_REC:
4080
 
                                case DB_SUCCESS:
4081
 
                                        break;
4082
 
                                default:
 
3953
                                if (err != DB_SUCCESS) {
 
3954
 
4083
3955
                                        goto lock_wait_or_error;
4084
3956
                                }
4085
3957
                        }
4112
3984
 
4113
3985
                if (!set_also_gap_locks
4114
3986
                    || srv_locks_unsafe_for_binlog
4115
 
                    || trx->isolation_level <= TRX_ISO_READ_COMMITTED
 
3987
                    || trx->isolation_level == TRX_ISO_READ_COMMITTED
4116
3988
                    || (unique_search
4117
3989
                        && !UNIV_UNLIKELY(rec_get_deleted_flag(rec, comp)))) {
4118
3990
 
4149
4021
 
4150
4022
                switch (err) {
4151
4023
                        const rec_t*    old_vers;
4152
 
                case DB_SUCCESS_LOCKED_REC:
 
4024
                case DB_SUCCESS:
4153
4025
                        if (srv_locks_unsafe_for_binlog
4154
 
                            || trx->isolation_level
4155
 
                            <= TRX_ISO_READ_COMMITTED) {
 
4026
                            || trx->isolation_level == TRX_ISO_READ_COMMITTED) {
4156
4027
                                /* Note that a record of
4157
4028
                                prebuilt->index was locked. */
4158
4029
                                prebuilt->new_rec_locks = 1;
4159
4030
                        }
4160
 
                        err = DB_SUCCESS;
4161
 
                case DB_SUCCESS:
4162
4031
                        break;
4163
4032
                case DB_LOCK_WAIT:
4164
 
                        /* Never unlock rows that were part of a conflict. */
4165
 
                        prebuilt->new_rec_locks = 0;
4166
 
 
4167
4033
                        if (UNIV_LIKELY(prebuilt->row_read_type
4168
4034
                                        != ROW_READ_TRY_SEMI_CONSISTENT)
4169
 
                            || unique_search
4170
4035
                            || index != clust_index) {
4171
4036
 
4172
4037
                                goto lock_wait_or_error;
4178
4043
                                clust_index, prebuilt, rec,
4179
4044
                                &offsets, &heap, &old_vers, &mtr);
4180
4045
 
4181
 
                        switch (err) {
4182
 
                        case DB_SUCCESS_LOCKED_REC:
4183
 
                                err = DB_SUCCESS;
4184
 
                        case DB_SUCCESS:
4185
 
                                break;
4186
 
                        default:
 
4046
                        if (err != DB_SUCCESS) {
 
4047
 
4187
4048
                                goto lock_wait_or_error;
4188
4049
                        }
4189
4050
 
4197
4058
                        if (UNIV_LIKELY(trx->wait_lock != NULL)) {
4198
4059
                                lock_cancel_waiting_and_release(
4199
4060
                                        trx->wait_lock);
 
4061
                                prebuilt->new_rec_locks = 0;
4200
4062
                        } else {
4201
4063
                                mutex_exit(&kernel_mutex);
4202
4064
 
4208
4070
                                                          ULINT_UNDEFINED,
4209
4071
                                                          &heap);
4210
4072
                                err = DB_SUCCESS;
 
4073
                                /* Note that a record of
 
4074
                                prebuilt->index was locked. */
 
4075
                                prebuilt->new_rec_locks = 1;
4211
4076
                                break;
4212
4077
                        }
4213
4078
                        mutex_exit(&kernel_mutex);
4253
4118
                                        prebuilt, rec, &offsets, &heap,
4254
4119
                                        &old_vers, &mtr);
4255
4120
 
4256
 
                                switch (err) {
4257
 
                                case DB_SUCCESS_LOCKED_REC:
4258
 
                                case DB_SUCCESS:
4259
 
                                        break;
4260
 
                                default:
 
4121
                                if (err != DB_SUCCESS) {
 
4122
 
4261
4123
                                        goto lock_wait_or_error;
4262
4124
                                }
4263
4125
 
4270
4132
 
4271
4133
                                rec = old_vers;
4272
4134
                        }
4273
 
                } else {
 
4135
                } else if (!lock_sec_rec_cons_read_sees(rec, trx->read_view)) {
4274
4136
                        /* We are looking into a non-clustered index,
4275
4137
                        and to get the right version of the record we
4276
4138
                        have to look also into the clustered index: this
4277
4139
                        is necessary, because we can only get the undo
4278
4140
                        information via the clustered index record. */
4279
4141
 
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
 
                        }
 
4142
                        ut_ad(index != clust_index);
 
4143
                        goto requires_clust_rec;
4285
4144
                }
4286
4145
        }
4287
4146
 
4295
4154
                /* The record is delete-marked: we can skip it */
4296
4155
 
4297
4156
                if ((srv_locks_unsafe_for_binlog
4298
 
                     || trx->isolation_level <= TRX_ISO_READ_COMMITTED)
 
4157
                     || trx->isolation_level == TRX_ISO_READ_COMMITTED)
4299
4158
                    && prebuilt->select_lock_type != LOCK_NONE
4300
4159
                    && !did_semi_consistent_read) {
4301
4160
 
4349
4208
                err = row_sel_get_clust_rec_for_mysql(prebuilt, index, rec,
4350
4209
                                                      thr, &clust_rec,
4351
4210
                                                      &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);
 
4211
                if (err != DB_SUCCESS) {
4357
4212
 
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
4213
                        goto lock_wait_or_error;
4374
4214
                }
4375
4215
 
 
4216
                if (clust_rec == NULL) {
 
4217
                        /* The record did not exist in the read view */
 
4218
                        ut_ad(prebuilt->select_lock_type == LOCK_NONE);
 
4219
 
 
4220
                        goto next_rec;
 
4221
                }
 
4222
 
 
4223
                if ((srv_locks_unsafe_for_binlog
 
4224
                     || trx->isolation_level == TRX_ISO_READ_COMMITTED)
 
4225
                    && prebuilt->select_lock_type != LOCK_NONE) {
 
4226
                        /* Note that both the secondary index record
 
4227
                        and the clustered index record were locked. */
 
4228
                        ut_ad(prebuilt->new_rec_locks == 1);
 
4229
                        prebuilt->new_rec_locks = 2;
 
4230
                }
 
4231
 
4376
4232
                if (UNIV_UNLIKELY(rec_get_deleted_flag(clust_rec, comp))) {
4377
4233
 
4378
4234
                        /* The record is delete marked: we can skip it */
4379
4235
 
4380
4236
                        if ((srv_locks_unsafe_for_binlog
4381
 
                             || trx->isolation_level <= TRX_ISO_READ_COMMITTED)
 
4237
                             || trx->isolation_level == TRX_ISO_READ_COMMITTED)
4382
4238
                            && prebuilt->select_lock_type != LOCK_NONE) {
4383
4239
 
4384
4240
                                /* No need to keep a lock on a delete-marked
4391
4247
                        goto next_rec;
4392
4248
                }
4393
4249
 
4394
 
                result_rec = clust_rec;
4395
 
                ut_ad(rec_offs_validate(result_rec, clust_index, offsets));
 
4250
                if (prebuilt->need_to_access_clustered) {
 
4251
 
 
4252
                        result_rec = clust_rec;
 
4253
 
 
4254
                        ut_ad(rec_offs_validate(result_rec, clust_index,
 
4255
                                                offsets));
 
4256
                } else {
 
4257
                        /* We used 'offsets' for the clust rec, recalculate
 
4258
                        them for 'rec' */
 
4259
                        offsets = rec_get_offsets(rec, index, offsets,
 
4260
                                                  ULINT_UNDEFINED, &heap);
 
4261
                        result_rec = rec;
 
4262
                }
4396
4263
        } else {
4397
4264
                result_rec = rec;
4398
4265
        }
4403
4270
        ut_ad(rec_offs_validate(result_rec,
4404
4271
                                result_rec != rec ? clust_index : index,
4405
4272
                                offsets));
4406
 
        ut_ad(!rec_get_deleted_flag(result_rec, comp));
4407
4273
 
4408
4274
        /* At this point, the clustered index record is protected
4409
4275
        by a page latch that was acquired when pcur was positioned.
4426
4292
                not cache rows because there the cursor is a scrollable
4427
4293
                cursor. */
4428
4294
 
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) {
 
4295
                row_sel_push_cache_row_for_mysql(prebuilt, result_rec,
 
4296
                                                 offsets);
 
4297
                if (prebuilt->n_fetch_cached == MYSQL_FETCH_CACHE_SIZE) {
4442
4298
 
4443
4299
                        goto got_row;
4444
4300
                }
4445
4301
 
4446
4302
                goto next_rec;
4447
4303
        } 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
 
 
 
4304
                if (prebuilt->template_type == ROW_MYSQL_DUMMY_TEMPLATE) {
4462
4305
                        memcpy(buf + 4, result_rec
4463
4306
                               - rec_offs_extra_size(offsets),
4464
4307
                               rec_offs_size(offsets));
4465
4308
                        mach_write_to_4(buf,
4466
4309
                                        rec_offs_extra_size(offsets) + 4);
4467
4310
                } else {
4468
 
                        /* Returning a row to MySQL */
 
4311
                        if (!row_sel_store_mysql_rec(buf, prebuilt,
 
4312
                                                     result_rec, offsets)) {
 
4313
                                err = DB_TOO_BIG_RECORD;
4469
4314
 
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;
 
4315
                                goto lock_wait_or_error;
4484
4316
                        }
4485
4317
                }
4486
4318
 
4589
4421
 
4590
4422
        btr_pcur_store_position(pcur, &mtr);
4591
4423
 
4592
 
lock_table_wait:
4593
4424
        mtr_commit(&mtr);
4594
4425
        mtr_has_extra_clust_latch = FALSE;
4595
4426
 
4607
4438
                thr->lock_state = QUE_THR_LOCK_NOLOCK;
4608
4439
                mtr_start(&mtr);
4609
4440
 
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
4441
                sel_restore_position_for_mysql(&same_user_rec,
4619
4442
                                               BTR_SEARCH_LEAF, pcur,
4620
4443
                                               moves_up, &mtr);
4621
4444
 
4622
4445
                if ((srv_locks_unsafe_for_binlog
4623
 
                     || trx->isolation_level <= TRX_ISO_READ_COMMITTED)
 
4446
                     || trx->isolation_level == TRX_ISO_READ_COMMITTED)
4624
4447
                    && !same_user_rec) {
4625
4448
 
4626
4449
                        /* Since we were not able to restore the cursor
4733
4556
        IX type locks actually would require ret = FALSE. */
4734
4557
 
4735
4558
        if (UT_LIST_GET_LEN(table->locks) == 0
4736
 
            && trx->id >= table->query_cache_inv_trx_id) {
 
4559
            && ut_dulint_cmp(trx->id,
 
4560
                             table->query_cache_inv_trx_id) >= 0) {
4737
4561
 
4738
4562
                ret = TRUE;
4739
4563
 
4765
4589
        dict_index_t*   index,          /*!< in: index to read from */
4766
4590
        const rec_t*    rec,            /*!< in: current rec */
4767
4591
        ulint           col_no,         /*!< in: column number */
4768
 
        ulint           mtype,          /*!< in: column main type */
4769
4592
        ibool           unsigned_type)  /*!< in: signed or unsigned flag */
4770
4593
{
4771
4594
        ulint           len;
4782
4605
        data = rec_get_nth_field(rec, offsets, col_no, &len);
4783
4606
 
4784
4607
        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
 
        }
 
4608
        ut_a(len <= sizeof value);
 
4609
 
 
4610
        /* we assume AUTOINC value cannot be negative */
 
4611
        value = mach_read_int_type(data, len, unsigned_type);
4805
4612
 
4806
4613
        if (UNIV_LIKELY_NULL(heap)) {
4807
4614
                mem_heap_free(heap);
4887
4694
                                        dfield->col->prtype & DATA_UNSIGNED);
4888
4695
 
4889
4696
                                *value = row_search_autoinc_read_column(
4890
 
                                        index, rec, i,
4891
 
                                        dfield->col->mtype, unsigned_type);
 
4697
                                        index, rec, i, unsigned_type);
4892
4698
                        }
4893
4699
                }
4894
4700