~drizzle-trunk/drizzle/development

« back to all changes in this revision

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

  • Committer: Brian Aker
  • Date: 2008-10-28 08:36:02 UTC
  • mfrom: (520.4.13 merge-innodb-plugin)
  • Revision ID: brian@tangent.org-20081028083602-0p3zzlhlxr5q2sqo
Merging Monty's work

Show diffs side-by-side

added added

removed removed

Lines of Context:
51
51
#define SEL_RETRY       2
52
52
 
53
53
/************************************************************************
 
54
Returns TRUE if the user-defined column in a secondary index record
 
55
is alphabetically the same as the corresponding BLOB column in the clustered
 
56
index record.
 
57
NOTE: the comparison is NOT done as a binary comparison, but character
 
58
fields are compared with collation! */
 
59
static
 
60
ibool
 
61
row_sel_sec_rec_is_for_blob(
 
62
/*========================*/
 
63
                                        /* out: TRUE if the columns
 
64
                                        are equal */
 
65
        ulint           mtype,          /* in: main type */
 
66
        ulint           prtype,         /* in: precise type */
 
67
        ulint           mbminlen,       /* in: minimum length of a
 
68
                                        multi-byte character */
 
69
        ulint           mbmaxlen,       /* in: maximum length of a
 
70
                                        multi-byte character */
 
71
        const byte*     clust_field,    /* in: the locally stored part of
 
72
                                        the clustered index column, including
 
73
                                        the BLOB pointer; the clustered
 
74
                                        index record must be covered by
 
75
                                        a lock or a page latch to protect it
 
76
                                        against deletion (rollback or purge) */
 
77
        ulint           clust_len,      /* in: length of clust_field */
 
78
        const byte*     sec_field,      /* in: column in secondary index */
 
79
        ulint           sec_len,        /* in: length of sec_field */
 
80
        ulint           zip_size)       /* in: compressed page size, or 0 */
 
81
{
 
82
        ulint   len;
 
83
        byte    buf[DICT_MAX_INDEX_COL_LEN];
 
84
 
 
85
        len = btr_copy_externally_stored_field_prefix(buf, sizeof buf,
 
86
                                                      zip_size,
 
87
                                                      clust_field, clust_len);
 
88
        len = dtype_get_at_most_n_mbchars(prtype, mbminlen, mbmaxlen,
 
89
                                          sec_len, len, (const char*) buf);
 
90
 
 
91
        return(!cmp_data_data(mtype, prtype, buf, len, sec_field, sec_len));
 
92
}
 
93
 
 
94
/************************************************************************
54
95
Returns TRUE if the user-defined column values in a secondary index record
55
96
are alphabetically the same as the corresponding columns in the clustered
56
97
index record.
64
105
                                        record is equal to the corresponding
65
106
                                        fields in the clustered record,
66
107
                                        when compared with collation */
67
 
        rec_t*          sec_rec,        /* in: secondary index record */
 
108
        const rec_t*    sec_rec,        /* in: secondary index record */
68
109
        dict_index_t*   sec_index,      /* in: secondary index */
69
 
        rec_t*          clust_rec,      /* in: clustered index record */
 
110
        const rec_t*    clust_rec,      /* in: clustered index record;
 
111
                                        must be protected by a lock or
 
112
                                        a page latch against deletion
 
113
                                        in rollback or purge */
70
114
        dict_index_t*   clust_index)    /* in: clustered index */
71
115
{
72
 
        byte*           sec_field;
 
116
        const byte*     sec_field;
73
117
        ulint           sec_len;
74
 
        byte*           clust_field;
75
 
        ulint           clust_len;
 
118
        const byte*     clust_field;
76
119
        ulint           n;
77
120
        ulint           i;
78
121
        mem_heap_t*     heap            = NULL;
82
125
        ulint*          sec_offs        = sec_offsets_;
83
126
        ibool           is_equal        = TRUE;
84
127
 
85
 
        *clust_offsets_ = (sizeof clust_offsets_) / sizeof *clust_offsets_;
86
 
        *sec_offsets_ = (sizeof sec_offsets_) / sizeof *sec_offsets_;
 
128
        rec_offs_init(clust_offsets_);
 
129
        rec_offs_init(sec_offsets_);
 
130
 
 
131
        if (rec_get_deleted_flag(clust_rec,
 
132
                                 dict_table_is_comp(clust_index->table))) {
 
133
 
 
134
                /* The clustered index record is delete-marked;
 
135
                it is not visible in the read view.  Besides,
 
136
                if there are any externally stored columns,
 
137
                some of them may have already been purged. */
 
138
                return(FALSE);
 
139
        }
87
140
 
88
141
        clust_offs = rec_get_offsets(clust_rec, clust_index, clust_offs,
89
142
                                     ULINT_UNDEFINED, &heap);
95
148
        for (i = 0; i < n; i++) {
96
149
                const dict_field_t*     ifield;
97
150
                const dict_col_t*       col;
 
151
                ulint                   clust_pos;
 
152
                ulint                   clust_len;
 
153
                ulint                   len;
98
154
 
99
155
                ifield = dict_index_get_nth_field(sec_index, i);
100
156
                col = dict_field_get_col(ifield);
 
157
                clust_pos = dict_col_get_clust_pos(col, clust_index);
101
158
 
102
159
                clust_field = rec_get_nth_field(
103
 
                        clust_rec, clust_offs,
104
 
                        dict_col_get_clust_pos(col, clust_index), &clust_len);
 
160
                        clust_rec, clust_offs, clust_pos, &clust_len);
105
161
                sec_field = rec_get_nth_field(sec_rec, sec_offs, i, &sec_len);
106
162
 
107
 
                if (ifield->prefix_len > 0 && clust_len != UNIV_SQL_NULL) {
108
 
 
109
 
                        clust_len = dtype_get_at_most_n_mbchars(
 
163
                len = clust_len;
 
164
 
 
165
                if (ifield->prefix_len > 0 && len != UNIV_SQL_NULL) {
 
166
 
 
167
                        if (rec_offs_nth_extern(clust_offs, clust_pos)) {
 
168
                                len -= BTR_EXTERN_FIELD_REF_SIZE;
 
169
                        }
 
170
 
 
171
                        len = dtype_get_at_most_n_mbchars(
110
172
                                col->prtype, col->mbminlen, col->mbmaxlen,
111
 
                                ifield->prefix_len,
112
 
                                clust_len, (char*) clust_field);
 
173
                                ifield->prefix_len, len, (char*) clust_field);
 
174
 
 
175
                        if (rec_offs_nth_extern(clust_offs, clust_pos)
 
176
                            && len < sec_len) {
 
177
                                if (!row_sel_sec_rec_is_for_blob(
 
178
                                            col->mtype, col->prtype,
 
179
                                            col->mbminlen, col->mbmaxlen,
 
180
                                            clust_field, clust_len,
 
181
                                            sec_field, sec_len,
 
182
                                            dict_table_zip_size(
 
183
                                                    clust_index->table))) {
 
184
                                        goto inequal;
 
185
                                }
 
186
 
 
187
                                continue;
 
188
                        }
113
189
                }
114
190
 
115
191
                if (0 != cmp_data_data(col->mtype, col->prtype,
116
 
                                       clust_field, clust_len,
 
192
                                       clust_field, len,
117
193
                                       sec_field, sec_len)) {
 
194
inequal:
118
195
                        is_equal = FALSE;
119
196
                        goto func_exit;
120
197
                }
129
206
 
130
207
/*************************************************************************
131
208
Creates a select node struct. */
132
 
 
 
209
UNIV_INTERN
133
210
sel_node_t*
134
211
sel_node_create(
135
212
/*============*/
153
230
/*************************************************************************
154
231
Frees the memory private to a select node when a query graph is freed,
155
232
does not free the heap where the node was originally created. */
156
 
 
 
233
UNIV_INTERN
157
234
void
158
235
sel_node_free_private(
159
236
/*==================*/
277
354
row_sel_fetch_columns(
278
355
/*==================*/
279
356
        dict_index_t*   index,  /* in: record index */
280
 
        rec_t*          rec,    /* in: record in a clustered or non-clustered
281
 
                                index */
 
357
        const rec_t*    rec,    /* in: record in a clustered or non-clustered
 
358
                                index; must be protected by a page latch */
282
359
        const ulint*    offsets,/* in: rec_get_offsets(rec, index) */
283
360
        sym_node_t*     column) /* in: first column in a column list, or
284
361
                                NULL */
286
363
        dfield_t*       val;
287
364
        ulint           index_type;
288
365
        ulint           field_no;
289
 
        byte*           data;
 
366
        const byte*     data;
290
367
        ulint           len;
291
368
 
292
369
        ut_ad(rec_offs_validate(rec, index, offsets));
293
370
 
294
 
        if (index->type & DICT_CLUSTERED) {
 
371
        if (dict_index_is_clust(index)) {
295
372
                index_type = SYM_CLUST_FIELD_NO;
296
373
        } else {
297
374
                index_type = SYM_SEC_FIELD_NO;
314
391
                                heap = mem_heap_create(1);
315
392
 
316
393
                                data = btr_rec_copy_externally_stored_field(
317
 
                                        rec, offsets, field_no, &len, heap);
 
394
                                        rec, offsets,
 
395
                                        dict_table_zip_size(index->table),
 
396
                                        field_no, &len, heap);
318
397
 
319
398
                                ut_a(len != UNIV_SQL_NULL);
320
399
 
323
402
                                data = rec_get_nth_field(rec, offsets,
324
403
                                                         field_no, &len);
325
404
 
 
405
                                if (len == UNIV_SQL_NULL) {
 
406
                                        len = UNIV_SQL_NULL;
 
407
                                }
 
408
 
326
409
                                needs_copy = column->copy_val;
327
410
                        }
328
411
 
370
453
/*************************************************************************
371
454
Frees a prefetch buffer for a column, including the dynamically allocated
372
455
memory for data stored there. */
373
 
 
 
456
UNIV_INTERN
374
457
void
375
458
sel_col_prefetch_buf_free(
376
459
/*======================*/
418
501
 
419
502
                        ut_ad(!column->prefetch_buf);
420
503
                        ut_ad(que_node_get_val_buf_size(column) == 0);
421
 
#ifdef UNIV_DEBUG
422
 
                        dfield_set_data(val, NULL, 0);
423
 
#endif
 
504
                        ut_d(dfield_set_null(val));
 
505
 
424
506
                        goto next_col;
425
507
                }
426
508
 
427
509
                ut_ad(column->prefetch_buf);
 
510
                ut_ad(!dfield_is_ext(val));
428
511
 
429
512
                sel_buf = column->prefetch_buf + plan->first_prefetched;
430
513
 
568
651
                                        /* out: DB_SUCCESS or error code */
569
652
        dict_index_t*   clust_index,    /* in: clustered index */
570
653
        row_prebuilt_t* prebuilt,       /* in: prebuilt struct */
571
 
        rec_t*          rec,            /* in: record in a clustered index */
 
654
        const rec_t*    rec,            /* in: record in a clustered index */
572
655
        ulint**         offsets,        /* in/out: offsets returned by
573
656
                                        rec_get_offsets(rec, clust_index) */
574
657
        mem_heap_t**    offset_heap,    /* in/out: memory heap from which
575
658
                                        the offsets are allocated */
576
 
        rec_t**         old_vers,       /* out: old version, or NULL if the
 
659
        const rec_t**   old_vers,       /* out: old version, or NULL if the
577
660
                                        record does not exist in the view:
578
661
                                        i.e., it was freshly inserted
579
662
                                        afterwards */
686
769
        mem_heap_t*     heap            = NULL;
687
770
        ulint           offsets_[REC_OFFS_NORMAL_SIZE];
688
771
        ulint*          offsets         = offsets_;
689
 
        *offsets_ = (sizeof offsets_) / sizeof *offsets_;
 
772
        rec_offs_init(offsets_);
690
773
 
691
774
        *out_rec = NULL;
692
775
 
750
833
                }
751
834
 
752
835
                err = lock_clust_rec_read_check_and_lock(
753
 
                        0, clust_rec, index, offsets,
 
836
                        0, btr_pcur_get_block(&plan->clust_pcur),
 
837
                        clust_rec, index, offsets,
754
838
                        node->row_lock_mode, lock_type, thr);
755
839
 
756
840
                if (err != DB_SUCCESS) {
805
889
                }
806
890
        }
807
891
 
808
 
        /* Fetch the columns needed in test conditions */
 
892
        /* Fetch the columns needed in test conditions.  The clustered
 
893
        index record is protected by a page latch that was acquired
 
894
        when plan->clust_pcur was positioned.  The latch will not be
 
895
        released until mtr_commit(mtr). */
809
896
 
810
897
        row_sel_fetch_columns(index, clust_rec, offsets,
811
898
                              UT_LIST_GET_FIRST(plan->columns));
825
912
ulint
826
913
sel_set_rec_lock(
827
914
/*=============*/
828
 
                                /* out: DB_SUCCESS or error code */
829
 
        rec_t*          rec,    /* in: record */
830
 
        dict_index_t*   index,  /* in: index */
831
 
        const ulint*    offsets,/* in: rec_get_offsets(rec, index) */
832
 
        ulint           mode,   /* in: lock mode */
833
 
        ulint           type,   /* in: LOCK_ORDINARY, LOCK_GAP, or
834
 
                                LOC_REC_NOT_GAP */
835
 
        que_thr_t*      thr)    /* in: query thread */
 
915
                                        /* out: DB_SUCCESS or error code */
 
916
        const buf_block_t*      block,  /* in: buffer block of rec */
 
917
        const rec_t*            rec,    /* in: record */
 
918
        dict_index_t*           index,  /* in: index */
 
919
        const ulint*            offsets,/* in: rec_get_offsets(rec, index) */
 
920
        ulint                   mode,   /* in: lock mode */
 
921
        ulint                   type,   /* in: LOCK_ORDINARY, LOCK_GAP, or
 
922
                                        LOC_REC_NOT_GAP */
 
923
        que_thr_t*              thr)    /* in: query thread */
836
924
{
837
925
        trx_t*  trx;
838
926
        ulint   err;
846
934
                }
847
935
        }
848
936
 
849
 
        if (index->type & DICT_CLUSTERED) {
 
937
        if (dict_index_is_clust(index)) {
850
938
                err = lock_clust_rec_read_check_and_lock(
851
 
                        0, rec, index, offsets, mode, type, thr);
 
939
                        0, block, rec, index, offsets, mode, type, thr);
852
940
        } else {
853
941
                err = lock_sec_rec_read_check_and_lock(
854
 
                        0, rec, index, offsets, mode, type, thr);
 
942
                        0, block, rec, index, offsets, mode, type, thr);
855
943
        }
856
944
 
857
945
        return(err);
1063
1151
        ulint           offsets_[REC_OFFS_NORMAL_SIZE];
1064
1152
        ulint*          offsets         = offsets_;
1065
1153
        ulint           ret;
1066
 
        *offsets_ = (sizeof offsets_) / sizeof *offsets_;
 
1154
        rec_offs_init(offsets_);
1067
1155
 
1068
1156
        index = plan->index;
1069
1157
 
1099
1187
 
1100
1188
        offsets = rec_get_offsets(rec, index, offsets, ULINT_UNDEFINED, &heap);
1101
1189
 
1102
 
        if (index->type & DICT_CLUSTERED) {
 
1190
        if (dict_index_is_clust(index)) {
1103
1191
                if (!lock_clust_rec_cons_read_sees(rec, index, offsets,
1104
1192
                                                   node->read_view)) {
1105
1193
                        ret = SEL_RETRY;
1106
1194
                        goto func_exit;
1107
1195
                }
1108
 
        } else if (!lock_sec_rec_cons_read_sees(rec, index, node->read_view)) {
 
1196
        } else if (!lock_sec_rec_cons_read_sees(rec, node->read_view)) {
1109
1197
 
1110
1198
                ret = SEL_RETRY;
1111
1199
                goto func_exit;
1112
1200
        }
1113
1201
 
1114
 
        /* Test deleted flag. Fetch the columns needed in test conditions. */
1115
 
 
1116
 
        row_sel_fetch_columns(index, rec, offsets,
1117
 
                              UT_LIST_GET_FIRST(plan->columns));
 
1202
        /* Test the deleted flag. */
1118
1203
 
1119
1204
        if (rec_get_deleted_flag(rec, dict_table_is_comp(plan->table))) {
1120
1205
 
1122
1207
                goto func_exit;
1123
1208
        }
1124
1209
 
 
1210
        /* Fetch the columns needed in test conditions.  The index
 
1211
        record is protected by a page latch that was acquired when
 
1212
        plan->pcur was positioned.  The latch will not be released
 
1213
        until mtr_commit(mtr). */
 
1214
 
 
1215
        row_sel_fetch_columns(index, rec, offsets,
 
1216
                              UT_LIST_GET_FIRST(plan->columns));
 
1217
 
1125
1218
        /* Test the rest of search conditions */
1126
1219
 
1127
1220
        if (!row_sel_test_other_conds(plan)) {
1189
1282
        mem_heap_t*     heap                            = NULL;
1190
1283
        ulint           offsets_[REC_OFFS_NORMAL_SIZE];
1191
1284
        ulint*          offsets                         = offsets_;
1192
 
        *offsets_ = (sizeof offsets_) / sizeof *offsets_;
 
1285
        rec_offs_init(offsets_);
1193
1286
 
1194
1287
        ut_ad(thr->run_node == node);
1195
1288
 
1369
1462
                                lock_type = LOCK_ORDINARY;
1370
1463
                        }
1371
1464
 
1372
 
                        err = sel_set_rec_lock(next_rec, index, offsets,
 
1465
                        err = sel_set_rec_lock(btr_pcur_get_block(&plan->pcur),
 
1466
                                               next_rec, index, offsets,
1373
1467
                                               node->row_lock_mode,
1374
1468
                                               lock_type, thr);
1375
1469
 
1425
1519
                        lock_type = LOCK_ORDINARY;
1426
1520
                }
1427
1521
 
1428
 
                err = sel_set_rec_lock(rec, index, offsets,
 
1522
                err = sel_set_rec_lock(btr_pcur_get_block(&plan->pcur),
 
1523
                                       rec, index, offsets,
1429
1524
                                       node->row_lock_mode, lock_type, thr);
1430
1525
 
1431
1526
                if (err != DB_SUCCESS) {
1488
1583
                /* This is a non-locking consistent read: if necessary, fetch
1489
1584
                a previous version of the record */
1490
1585
 
1491
 
                if (index->type & DICT_CLUSTERED) {
 
1586
                if (dict_index_is_clust(index)) {
1492
1587
 
1493
1588
                        if (!lock_clust_rec_cons_read_sees(rec, index, offsets,
1494
1589
                                                           node->read_view)) {
1507
1602
                                        offsets = rec_get_offsets(
1508
1603
                                                rec, index, offsets,
1509
1604
                                                ULINT_UNDEFINED, &heap);
 
1605
 
 
1606
                                        /* Fetch the columns needed in
 
1607
                                        test conditions. The clustered
 
1608
                                        index record is protected by a
 
1609
                                        page latch that was acquired
 
1610
                                        by row_sel_open_pcur() or
 
1611
                                        row_sel_restore_pcur_pos().
 
1612
                                        The latch will not be released
 
1613
                                        until mtr_commit(mtr). */
 
1614
 
1510
1615
                                        row_sel_fetch_columns(
1511
1616
                                                index, rec, offsets,
1512
1617
                                                UT_LIST_GET_FIRST(
1522
1627
 
1523
1628
                                rec = old_vers;
1524
1629
                        }
1525
 
                } else if (!lock_sec_rec_cons_read_sees(rec, index,
 
1630
                } else if (!lock_sec_rec_cons_read_sees(rec,
1526
1631
                                                        node->read_view)) {
1527
1632
                        cons_read_requires_clust_rec = TRUE;
1528
1633
                }
1530
1635
 
1531
1636
        /* PHASE 4: Test search end conditions and deleted flag */
1532
1637
 
1533
 
        /* Fetch the columns needed in test conditions */
 
1638
        /* Fetch the columns needed in test conditions.  The record is
 
1639
        protected by a page latch that was acquired by
 
1640
        row_sel_open_pcur() or row_sel_restore_pcur_pos().  The latch
 
1641
        will not be released until mtr_commit(mtr). */
1534
1642
 
1535
1643
        row_sel_fetch_columns(index, rec, offsets,
1536
1644
                              UT_LIST_GET_FIRST(plan->columns));
1563
1671
                goto next_rec;
1564
1672
        }
1565
1673
 
 
1674
 
1566
1675
        /* PHASE 5: Get the clustered index record, if needed and if we did
1567
1676
        not do the search using the clustered index */
1568
1677
 
1681
1790
        }
1682
1791
 
1683
1792
        if (leaf_contains_updates
1684
 
            && btr_pcur_is_after_last_on_page(&(plan->pcur), &mtr)) {
 
1793
            && btr_pcur_is_after_last_on_page(&plan->pcur)) {
1685
1794
 
1686
1795
                /* We must commit &mtr if we are moving to a different page,
1687
1796
                because we have done updates to the x-latched leaf page, and
1714
1823
        /* We found a record which satisfies the conditions: we can move to
1715
1824
        the next table or return a row in the result set */
1716
1825
 
1717
 
        ut_ad(btr_pcur_is_on_user_rec(&(plan->pcur), &mtr));
 
1826
        ut_ad(btr_pcur_is_on_user_rec(&plan->pcur));
1718
1827
 
1719
1828
        if (plan->unique_search && !node->can_get_updated) {
1720
1829
 
1749
1858
 
1750
1859
                thr->run_node = que_node_get_parent(node);
1751
1860
 
1752
 
                if (search_latch_locked) {
1753
 
                        rw_lock_s_unlock(&btr_search_latch);
1754
 
                }
1755
 
 
1756
1861
                err = DB_SUCCESS;
1757
1862
                goto func_exit;
1758
1863
        }
1796
1901
                        sel_assign_into_var_values(node->into_list, node);
1797
1902
 
1798
1903
                        thr->run_node = que_node_get_parent(node);
1799
 
 
1800
 
                        if (search_latch_locked) {
1801
 
                                rw_lock_s_unlock(&btr_search_latch);
1802
 
                        }
1803
 
 
1804
 
                        goto func_exit;
1805
 
                }
1806
 
 
1807
 
                node->state = SEL_NODE_NO_MORE_ROWS;
1808
 
 
1809
 
                thr->run_node = que_node_get_parent(node);
1810
 
 
1811
 
                if (search_latch_locked) {
1812
 
                        rw_lock_s_unlock(&btr_search_latch);
 
1904
                } else {
 
1905
                        node->state = SEL_NODE_NO_MORE_ROWS;
 
1906
 
 
1907
                        thr->run_node = que_node_get_parent(node);
1813
1908
                }
1814
1909
 
1815
1910
                goto func_exit;
1865
1960
lock_wait_or_error:
1866
1961
        /* See the note at stop_for_a_while: the same holds for this case */
1867
1962
 
1868
 
        ut_ad(!btr_pcur_is_before_first_on_page(&(plan->pcur), &mtr)
1869
 
              || !node->asc);
 
1963
        ut_ad(!btr_pcur_is_before_first_on_page(&plan->pcur) || !node->asc);
1870
1964
        ut_ad(!search_latch_locked);
1871
1965
 
1872
1966
        plan->stored_cursor_rec_processed = FALSE;
1879
1973
#endif /* UNIV_SYNC_DEBUG */
1880
1974
 
1881
1975
func_exit:
 
1976
        if (search_latch_locked) {
 
1977
                rw_lock_s_unlock(&btr_search_latch);
 
1978
        }
1882
1979
        if (UNIV_LIKELY_NULL(heap)) {
1883
1980
                mem_heap_free(heap);
1884
1981
        }
1888
1985
/**************************************************************************
1889
1986
Performs a select step. This is a high-level function used in SQL execution
1890
1987
graphs. */
1891
 
 
 
1988
UNIV_INTERN
1892
1989
que_thr_t*
1893
1990
row_sel_step(
1894
1991
/*=========*/
1989
2086
 
1990
2087
/**************************************************************************
1991
2088
Performs a fetch for a cursor. */
1992
 
 
 
2089
UNIV_INTERN
1993
2090
que_thr_t*
1994
2091
fetch_step(
1995
2092
/*=======*/
2052
2149
 
2053
2150
/********************************************************************
2054
2151
Sample callback function for fetch that prints each row.*/
2055
 
 
 
2152
UNIV_INTERN
2056
2153
void*
2057
2154
row_fetch_print(
2058
2155
/*============*/
2072
2169
 
2073
2170
        while (exp) {
2074
2171
                dfield_t*       dfield = que_node_get_val(exp);
2075
 
                dtype_t*        type = dfield_get_type(dfield);
 
2172
                const dtype_t*  type = dfield_get_type(dfield);
2076
2173
 
2077
2174
                fprintf(stderr, " column %lu:\n", (ulong)i);
2078
2175
 
2099
2196
Callback function for fetch that stores an unsigned 4 byte integer to the
2100
2197
location pointed. The column's type must be DATA_INT, DATA_UNSIGNED, length
2101
2198
= 4. */
2102
 
 
 
2199
UNIV_INTERN
2103
2200
void*
2104
2201
row_fetch_store_uint4(
2105
2202
/*==================*/
2112
2209
        ulint           tmp;
2113
2210
 
2114
2211
        dfield_t*       dfield = que_node_get_val(node->select_list);
2115
 
        dtype_t*        type = dfield_get_type(dfield);
 
2212
        const dtype_t*  type = dfield_get_type(dfield);
2116
2213
        ulint           len = dfield_get_len(dfield);
2117
2214
 
2118
2215
        ut_a(dtype_get_mtype(type) == DATA_INT);
2127
2224
 
2128
2225
/***************************************************************
2129
2226
Prints a row in a select result. */
2130
 
 
 
2227
UNIV_INTERN
2131
2228
que_thr_t*
2132
2229
row_printf_step(
2133
2230
/*============*/
2195
2292
last field is only a prefix of the full key field len and print a warning if
2196
2293
such appears. A counterpart of this function is
2197
2294
ha_innobase::store_key_val_for_row() in ha_innodb.cc. */
2198
 
 
 
2295
UNIV_INTERN
2199
2296
void
2200
2297
row_sel_convert_mysql_key_to_innobase(
2201
2298
/*==================================*/
2202
 
        dtuple_t*       tuple,          /* in: tuple where to build;
 
2299
        dtuple_t*       tuple,          /* in/out: tuple where to build;
2203
2300
                                        NOTE: we assume that the type info
2204
2301
                                        in the tuple is already according
2205
2302
                                        to index! */
2207
2304
                                        conversions */
2208
2305
        ulint           buf_len,        /* in: buffer length */
2209
2306
        dict_index_t*   index,          /* in: index of the key value */
2210
 
        byte*           key_ptr,        /* in: MySQL key value */
 
2307
        const byte*     key_ptr,        /* in: MySQL key value */
2211
2308
        ulint           key_len,        /* in: MySQL key value length */
2212
2309
        trx_t*          trx)            /* in: transaction */
2213
2310
{
2214
2311
        byte*           original_buf    = buf;
2215
 
        byte*           original_key_ptr = key_ptr;
 
2312
        const byte*     original_key_ptr = key_ptr;
2216
2313
        dict_field_t*   field;
2217
2314
        dfield_t*       dfield;
2218
2315
        ulint           data_offset;
2219
2316
        ulint           data_len;
2220
2317
        ulint           data_field_len;
2221
2318
        ibool           is_null;
2222
 
        byte*           key_end;
 
2319
        const byte*     key_end;
2223
2320
        ulint           n_fields = 0;
2224
 
        ulint           type;
2225
2321
 
2226
2322
        /* For documentation of the key value storage format in MySQL, see
2227
2323
        ha_innobase::store_key_val_for_row() in ha_innodb.cc. */
2235
2331
        dfield = dtuple_get_nth_field(tuple, 0);
2236
2332
        field = dict_index_get_nth_field(index, 0);
2237
2333
 
2238
 
        if (dfield_get_type(dfield)->mtype == DATA_SYS) {
 
2334
        if (UNIV_UNLIKELY(dfield_get_type(dfield)->mtype == DATA_SYS)) {
2239
2335
                /* A special case: we are looking for a position in the
2240
2336
                generated clustered index which InnoDB automatically added
2241
2337
                to a table with no primary key: the first and the only
2253
2349
 
2254
2350
        while (key_ptr < key_end) {
2255
2351
 
2256
 
                ut_a(field->col->mtype == dfield_get_type(dfield)->mtype);
 
2352
                ulint   type = dfield_get_type(dfield)->mtype;
 
2353
                ut_a(field->col->mtype == type);
2257
2354
 
2258
2355
                data_offset = 0;
2259
2356
                is_null = FALSE;
2265
2362
                        data_offset = 1;
2266
2363
 
2267
2364
                        if (*key_ptr != 0) {
2268
 
                                dfield_set_data(dfield, NULL, UNIV_SQL_NULL);
 
2365
                                dfield_set_null(dfield);
2269
2366
 
2270
2367
                                is_null = TRUE;
2271
2368
                        }
2272
2369
                }
2273
2370
 
2274
 
                type = dfield_get_type(dfield)->mtype;
2275
 
 
2276
2371
                /* Calculate data length and data field total length */
2277
2372
 
2278
2373
                if (type == DATA_BLOB) {
2318
2413
                        data_field_len = data_offset + data_len;
2319
2414
                }
2320
2415
 
2321
 
                if (dtype_get_mysql_type(dfield_get_type(dfield))
2322
 
                    == DATA_DRIZZLE_TRUE_VARCHAR
2323
 
                    && dfield_get_type(dfield)->mtype != DATA_INT) {
 
2416
                if (UNIV_UNLIKELY
 
2417
                    (dtype_get_mysql_type(dfield_get_type(dfield))
 
2418
                     == DATA_MYSQL_TRUE_VARCHAR)
 
2419
                    && UNIV_LIKELY(type != DATA_INT)) {
2324
2420
                        /* In a MySQL key value format, a true VARCHAR is
2325
2421
                        always preceded by 2 bytes of a length field.
2326
2422
                        dfield_get_type(dfield)->len returns the maximum
2336
2432
 
2337
2433
                /* Storing may use at most data_len bytes of buf */
2338
2434
 
2339
 
                if (!is_null) {
 
2435
                if (UNIV_LIKELY(!is_null)) {
2340
2436
                        row_mysql_store_col_in_innobase_format(
2341
2437
                                dfield, buf,
2342
2438
                                FALSE, /* MySQL key value format col */
2347
2443
 
2348
2444
                key_ptr += data_field_len;
2349
2445
 
2350
 
                if (key_ptr > key_end) {
 
2446
                if (UNIV_UNLIKELY(key_ptr > key_end)) {
2351
2447
                        /* The last field in key was not a complete key field
2352
2448
                        but a prefix of it.
2353
2449
 
2374
2470
                        fprintf(stderr, "\n");
2375
2471
 
2376
2472
                        if (!is_null) {
2377
 
                                dfield->len -= (ulint)(key_ptr - key_end);
 
2473
                                ulint   len = dfield_get_len(dfield);
 
2474
                                dfield_set_len(dfield, len
 
2475
                                               - (ulint) (key_ptr - key_end));
2378
2476
                        }
2379
2477
                }
2380
2478
 
2397
2495
void
2398
2496
row_sel_store_row_id_to_prebuilt(
2399
2497
/*=============================*/
2400
 
        row_prebuilt_t* prebuilt,       /* in: prebuilt */
2401
 
        rec_t*          index_rec,      /* in: record */
2402
 
        dict_index_t*   index,          /* in: index of the record */
2403
 
        const ulint*    offsets)        /* in: rec_get_offsets
2404
 
                                        (index_rec, index) */
 
2498
        row_prebuilt_t*         prebuilt,       /* in/out: prebuilt */
 
2499
        const rec_t*            index_rec,      /* in: record */
 
2500
        const dict_index_t*     index,          /* in: index of the record */
 
2501
        const ulint*            offsets)        /* in: rec_get_offsets
 
2502
                                                (index_rec, index) */
2405
2503
{
2406
 
        byte*   data;
2407
 
        ulint   len;
 
2504
        const byte*     data;
 
2505
        ulint           len;
2408
2506
 
2409
2507
        ut_ad(rec_offs_validate(index_rec, index, offsets));
2410
2508
 
2412
2510
                index_rec, offsets,
2413
2511
                dict_index_get_sys_col_pos(index, DATA_ROW_ID), &len);
2414
2512
 
2415
 
        if (len != DATA_ROW_ID_LEN) {
 
2513
        if (UNIV_UNLIKELY(len != DATA_ROW_ID_LEN)) {
2416
2514
                fprintf(stderr,
2417
2515
                        "InnoDB: Error: Row id field is"
2418
2516
                        " wrong length %lu in ", (ulong) len);
2436
2534
void
2437
2535
row_sel_field_store_in_mysql_format(
2438
2536
/*================================*/
2439
 
        byte*   dest,   /* in/out: buffer where to store; NOTE that BLOBs
2440
 
                        are not in themselves stored here: the caller must
2441
 
                        allocate and copy the BLOB into buffer before, and pass
2442
 
                        the pointer to the BLOB in 'data' */
2443
 
        const mysql_row_templ_t* templ, /* in: MySQL column template.
2444
 
                        Its following fields are referenced:
2445
 
                        type, is_unsigned, mysql_col_len, mbminlen, mbmaxlen */
2446
 
        byte*   data,   /* in: data to store */
2447
 
        ulint   len)    /* in: length of the data */
 
2537
        byte*           dest,   /* in/out: buffer where to store; NOTE
 
2538
                                that BLOBs are not in themselves
 
2539
                                stored here: the caller must allocate
 
2540
                                and copy the BLOB into buffer before,
 
2541
                                and pass the pointer to the BLOB in
 
2542
                                'data' */
 
2543
        const mysql_row_templ_t* templ,
 
2544
                                /* in: MySQL column template.
 
2545
                                Its following fields are referenced:
 
2546
                                type, is_unsigned, mysql_col_len,
 
2547
                                mbminlen, mbmaxlen */
 
2548
        const byte*     data,   /* in: data to store */
 
2549
        ulint           len)    /* in: length of the data */
2448
2550
{
2449
2551
        byte*   ptr;
2450
2552
        byte*   field_end;
2452
2554
 
2453
2555
        ut_ad(len != UNIV_SQL_NULL);
2454
2556
 
2455
 
        if (templ->type == DATA_INT) {
 
2557
        switch (templ->type) {
 
2558
        case DATA_INT:
2456
2559
                /* Convert integer data from Innobase to a little-endian
2457
2560
                format, sign bit restored to normal */
2458
2561
 
2472
2575
                }
2473
2576
 
2474
2577
                ut_ad(templ->mysql_col_len == len);
2475
 
        } else if (templ->type == DATA_VARCHAR
2476
 
                   || templ->type == DATA_VARMYSQL
2477
 
                   || templ->type == DATA_BINARY) {
 
2578
                break;
2478
2579
 
 
2580
        case DATA_VARCHAR:
 
2581
        case DATA_VARMYSQL:
 
2582
        case DATA_BINARY:
2479
2583
                field_end = dest + templ->mysql_col_len;
2480
2584
 
2481
 
                if (templ->mysql_type == DATA_DRIZZLE_TRUE_VARCHAR) {
 
2585
                if (templ->mysql_type == DATA_MYSQL_TRUE_VARCHAR) {
2482
2586
                        /* This is a >= 5.0.3 type true VARCHAR. Store the
2483
2587
                        length of the data to the first byte or the first
2484
2588
                        two bytes of dest. */
2526
2630
 
2527
2631
                        memset(pad_ptr, 0x20, field_end - pad_ptr);
2528
2632
                }
2529
 
        } else if (templ->type == DATA_BLOB) {
 
2633
                break;
 
2634
 
 
2635
        case DATA_BLOB:
2530
2636
                /* Store a pointer to the BLOB buffer to dest: the BLOB was
2531
2637
                already copied to the buffer in row_sel_store_mysql_rec */
2532
2638
 
2533
2639
                row_mysql_store_blob_ref(dest, templ->mysql_col_len, data,
2534
2640
                                         len);
2535
 
        } else if (templ->type == DATA_MYSQL) {
 
2641
                break;
 
2642
 
 
2643
        case DATA_MYSQL:
2536
2644
                memcpy(dest, data, len);
2537
2645
 
2538
2646
                ut_ad(templ->mysql_col_len >= len);
2553
2661
 
2554
2662
                        memset(dest + len, 0x20, templ->mysql_col_len - len);
2555
2663
                }
2556
 
        } else {
2557
 
                ut_ad(templ->type == DATA_CHAR
2558
 
                      || templ->type == DATA_FIXBINARY
2559
 
                      /*|| templ->type == DATA_SYS_CHILD
2560
 
                      || templ->type == DATA_SYS*/
2561
 
                      || templ->type == DATA_FLOAT
2562
 
                      || templ->type == DATA_DOUBLE
2563
 
                      || templ->type == DATA_DECIMAL);
 
2664
                break;
 
2665
 
 
2666
        default:
 
2667
#ifdef UNIV_DEBUG
 
2668
        case DATA_SYS_CHILD:
 
2669
        case DATA_SYS:
 
2670
                /* These column types should never be shipped to MySQL. */
 
2671
                ut_ad(0);
 
2672
 
 
2673
        case DATA_CHAR:
 
2674
        case DATA_FIXBINARY:
 
2675
        case DATA_FLOAT:
 
2676
        case DATA_DOUBLE:
 
2677
        case DATA_DECIMAL:
 
2678
                /* Above are the valid column types for MySQL data. */
 
2679
#endif /* UNIV_DEBUG */
2564
2680
                ut_ad(templ->mysql_col_len == len);
2565
 
 
2566
2681
                memcpy(dest, data, len);
2567
2682
        }
2568
2683
}
2582
2697
                                        case) */
2583
2698
        byte*           mysql_rec,      /* out: row in the MySQL format */
2584
2699
        row_prebuilt_t* prebuilt,       /* in: prebuilt struct */
2585
 
        rec_t*          rec,            /* in: Innobase record in the index
 
2700
        const rec_t*    rec,            /* in: Innobase record in the index
2586
2701
                                        which was described in prebuilt's
2587
 
                                        template */
2588
 
        const ulint*    offsets,        /* in: array returned by
 
2702
                                        template; must be protected by
 
2703
                                        a page latch */
 
2704
        const ulint*    offsets,        /* in: array returned by
2589
2705
                                        rec_get_offsets() */
2590
 
        ulint start_field_no,
2591
 
        ulint end_field_no)
 
2706
        ulint start_field_no,
 
2707
        ulint end_field_no)
2592
2708
{
2593
2709
        mysql_row_templ_t*      templ;
2594
2710
        mem_heap_t*             extern_field_heap       = NULL;
2595
2711
        mem_heap_t*             heap;
2596
 
        byte*                   data;
 
2712
        const byte*             data;
2597
2713
        ulint                   len;
2598
2714
        ulint                   i;
2599
2715
 
2605
2721
                prebuilt->blob_heap = NULL;
2606
2722
        }
2607
2723
 
2608
 
        for (i = start_field_no; i < end_field_no /* prebuilt->n_template */ ; i++) {
 
2724
        for (i = start_field_no; i < end_field_no /* prebuilt->n_template */; i++) {
2609
2725
 
2610
2726
                templ = prebuilt->mysql_template + i;
2611
2727
 
2636
2752
                        causes an assert */
2637
2753
 
2638
2754
                        data = btr_rec_copy_externally_stored_field(
2639
 
                                rec, offsets, templ->rec_field_no,
2640
 
                                &len, heap);
 
2755
                                rec, offsets,
 
2756
                                dict_table_zip_size(prebuilt->table),
 
2757
                                templ->rec_field_no, &len, heap);
2641
2758
 
2642
2759
                        ut_a(len != UNIV_SQL_NULL);
2643
2760
                } else {
2698
2815
                        case DATA_BINARY:
2699
2816
                        case DATA_VARMYSQL:
2700
2817
                                if (templ->mysql_type
2701
 
                                    == DATA_DRIZZLE_TRUE_VARCHAR) {
 
2818
                                    == DATA_MYSQL_TRUE_VARCHAR) {
2702
2819
                                        /* This is a >= 5.0.3 type
2703
2820
                                        true VARCHAR.  Zero the field. */
2704
2821
                                        pad_char = 0x00;
2712
2829
                                BLOB, TEXT and true VARCHAR) with space. */
2713
2830
                                if (UNIV_UNLIKELY(templ->mbminlen == 2)) {
2714
2831
                                        /* Treat UCS2 as a special case. */
2715
 
                                        data = mysql_rec
 
2832
                                        byte* d = mysql_rec
2716
2833
                                                + templ->mysql_col_offset;
2717
2834
                                        len = templ->mysql_col_len;
2718
2835
                                        /* There are two UCS2 bytes per char,
2720
2837
                                        ut_a(!(len & 1));
2721
2838
                                        /* Pad with 0x0020. */
2722
2839
                                        while (len) {
2723
 
                                                *data++ = 0x00;
2724
 
                                                *data++ = 0x20;
 
2840
                                                *d++ = 0x00;
 
2841
                                                *d++ = 0x20;
2725
2842
                                                len -= 2;
2726
2843
                                        }
2727
2844
                                        continue;
2752
2869
        read_view_t*    read_view,      /* in: read view */
2753
2870
        dict_index_t*   clust_index,    /* in: clustered index */
2754
2871
        row_prebuilt_t* prebuilt,       /* in: prebuilt struct */
2755
 
        rec_t*          rec,            /* in: record in a clustered index */
 
2872
        const rec_t*    rec,            /* in: record in a clustered index */
2756
2873
        ulint**         offsets,        /* in/out: offsets returned by
2757
2874
                                        rec_get_offsets(rec, clust_index) */
2758
2875
        mem_heap_t**    offset_heap,    /* in/out: memory heap from which
2788
2905
                                /* out: DB_SUCCESS or error code */
2789
2906
        row_prebuilt_t* prebuilt,/* in: prebuilt struct in the handle */
2790
2907
        dict_index_t*   sec_index,/* in: secondary index where rec resides */
2791
 
        rec_t*          rec,    /* in: record in a non-clustered index; if
 
2908
        const rec_t*    rec,    /* in: record in a non-clustered index; if
2792
2909
                                this is a locking read, then rec is not
2793
2910
                                allowed to be delete-marked, and that would
2794
2911
                                not make sense either */
2795
2912
        que_thr_t*      thr,    /* in: query thread */
2796
 
        rec_t**         out_rec,/* out: clustered record or an old version of
 
2913
        const rec_t**   out_rec,/* out: clustered record or an old version of
2797
2914
                                it, NULL if the old version did not exist
2798
2915
                                in the read view, i.e., it was a fresh
2799
2916
                                inserted version */
2800
 
        ulint**         offsets,/* out: offsets returned by
 
2917
        ulint**         offsets,/* in: offsets returned by
 
2918
                                rec_get_offsets(rec, sec_index);
 
2919
                                out: offsets returned by
2801
2920
                                rec_get_offsets(out_rec, clust_index) */
2802
2921
        mem_heap_t**    offset_heap,/* in/out: memory heap from which
2803
2922
                                the offsets are allocated */
2806
2925
                                access the clustered index */
2807
2926
{
2808
2927
        dict_index_t*   clust_index;
2809
 
        rec_t*          clust_rec;
 
2928
        const rec_t*    clust_rec;
2810
2929
        rec_t*          old_vers;
2811
2930
        ulint           err;
2812
2931
        trx_t*          trx;
2814
2933
        *out_rec = NULL;
2815
2934
        trx = thr_get_trx(thr);
2816
2935
 
2817
 
        row_build_row_ref_in_tuple(prebuilt->clust_ref, sec_index, rec, trx);
 
2936
        row_build_row_ref_in_tuple(prebuilt->clust_ref, rec,
 
2937
                                   sec_index, *offsets, trx);
2818
2938
 
2819
2939
        clust_index = dict_table_get_first_index(sec_index->table);
2820
2940
 
2878
2998
                we set a LOCK_REC_NOT_GAP type lock */
2879
2999
 
2880
3000
                err = lock_clust_rec_read_check_and_lock(
2881
 
                        0, clust_rec, clust_index, *offsets,
 
3001
                        0, btr_pcur_get_block(prebuilt->clust_pcur),
 
3002
                        clust_rec, clust_index, *offsets,
2882
3003
                        prebuilt->select_lock_type, LOCK_REC_NOT_GAP, thr);
2883
3004
                if (err != DB_SUCCESS) {
2884
3005
 
2905
3026
                                clust_rec, offsets, offset_heap, &old_vers,
2906
3027
                                mtr);
2907
3028
 
2908
 
                        if (err != DB_SUCCESS) {
 
3029
                        if (err != DB_SUCCESS || old_vers == NULL) {
2909
3030
 
2910
3031
                                goto err_exit;
2911
3032
                        }
2926
3047
                visit through secondary index records that would not really
2927
3048
                exist in our snapshot. */
2928
3049
 
2929
 
                if (clust_rec && (old_vers || rec_get_deleted_flag(
2930
 
                                          rec,
2931
 
                                          dict_table_is_comp(
2932
 
                                                  sec_index->table)))
 
3050
                if (clust_rec
 
3051
                    && (old_vers
 
3052
                        || rec_get_deleted_flag(rec, dict_table_is_comp(
 
3053
                                                        sec_index->table)))
2933
3054
                    && !row_sel_sec_rec_is_for_clust_rec(
2934
3055
                            rec, sec_index, clust_rec, clust_index)) {
2935
3056
                        clust_rec = NULL;
 
3057
#ifdef UNIV_SEARCH_DEBUG
2936
3058
                } else {
2937
 
#ifdef UNIV_SEARCH_DEBUG
2938
3059
                        ut_a(clust_rec == NULL
2939
3060
                             || row_sel_sec_rec_is_for_clust_rec(
2940
3061
                                     rec, sec_index, clust_rec, clust_index));
3009
3130
                        return(TRUE);
3010
3131
                }
3011
3132
 
3012
 
                if (btr_pcur_is_on_user_rec(pcur, mtr)) {
 
3133
                if (btr_pcur_is_on_user_rec(pcur)) {
3013
3134
                        btr_pcur_move_to_prev(pcur, mtr);
3014
3135
                }
3015
3136
 
3019
3140
        ut_ad(relative_position == BTR_PCUR_BEFORE
3020
3141
              || relative_position == BTR_PCUR_BEFORE_FIRST_IN_TREE);
3021
3142
 
3022
 
        if (moves_up && btr_pcur_is_on_user_rec(pcur, mtr)) {
 
3143
        if (moves_up && btr_pcur_is_on_user_rec(pcur)) {
3023
3144
                btr_pcur_move_to_next(pcur, mtr);
3024
3145
        }
3025
3146
 
3083
3204
row_sel_push_cache_row_for_mysql(
3084
3205
/*=============================*/
3085
3206
        row_prebuilt_t* prebuilt,       /* in: prebuilt struct */
3086
 
        rec_t*          rec,            /* in: record to push */
 
3207
        const rec_t*    rec,            /* in: record to push; must
 
3208
                                        be protected by a page latch */
3087
3209
        const ulint*    offsets,        /* in: rec_get_offsets() */
3088
 
        ulint           start_field_no, /* psergey: start from this field */
3089
 
        byte*           remainder_buf)  /* if above !=0 -> where to take prev fields */
 
3210
        ulint           start_field_no, /* psergy: start from this field */
 
3211
        byte*           remainder_buf)  /* if above !=0 -> where to take
 
3212
                                           prev fields */
3090
3213
{
3091
3214
        byte*   buf;
3092
3215
        ulint   i;
3093
3216
 
3094
 
        ut_ad(prebuilt->n_fetch_cached < DRIZZLE_FETCH_CACHE_SIZE);
 
3217
        ut_ad(prebuilt->n_fetch_cached < MYSQL_FETCH_CACHE_SIZE);
3095
3218
        ut_ad(rec_offs_validate(rec, NULL, offsets));
3096
3219
        ut_a(!prebuilt->templ_contains_blob);
3097
3220
 
3098
3221
        if (prebuilt->fetch_cache[0] == NULL) {
3099
3222
                /* Allocate memory for the fetch cache */
3100
3223
 
3101
 
                for (i = 0; i < DRIZZLE_FETCH_CACHE_SIZE; i++) {
 
3224
                for (i = 0; i < MYSQL_FETCH_CACHE_SIZE; i++) {
3102
3225
 
3103
3226
                        /* A user has reported memory corruption in these
3104
3227
                        buffers in Linux. Put magic numbers there to help
3120
3243
                                  prebuilt->fetch_cache[
3121
3244
                                          prebuilt->n_fetch_cached],
3122
3245
                                  prebuilt, rec, offsets, start_field_no,
3123
 
                                  prebuilt->n_template))) {
 
3246
                                  prebuilt->n_template))) {
3124
3247
                ut_error;
3125
3248
        }
 
3249
 
3126
3250
        if (start_field_no) {
3127
3251
          for (i=0; i < start_field_no; i++) {
3128
3252
            register ulint offs;
3129
 
            mysql_row_templ_t* templ;
 
3253
            mysql_row_templ_t* templ;
3130
3254
            templ = prebuilt->mysql_template + i;
3131
3255
 
3132
3256
            if (templ->mysql_null_bit_mask) {
3133
3257
              offs= templ->mysql_null_byte_offset;
3134
 
              *(prebuilt->fetch_cache[prebuilt->n_fetch_cached] + offs) ^= 
3135
 
                (*(remainder_buf + offs) & templ->mysql_null_bit_mask);
 
3258
              if (*(remainder_buf + offs) & templ->mysql_null_bit_mask)
 
3259
                 *(prebuilt->fetch_cache[prebuilt->n_fetch_cached] + offs) |= 
 
3260
                /*  (*(remainder_buf + offs) &*/( templ->mysql_null_bit_mask);
 
3261
              else
 
3262
                *(prebuilt->fetch_cache[prebuilt->n_fetch_cached] + offs) &= 
 
3263
                  ~templ->mysql_null_bit_mask;
 
3264
 
3136
3265
            }
3137
3266
            offs= templ->mysql_col_offset;
3138
3267
            memcpy(prebuilt->fetch_cache[prebuilt->n_fetch_cached] + offs,
3141
3270
          }
3142
3271
        }
3143
3272
 
 
3273
 
3144
3274
        prebuilt->n_fetch_cached++;
3145
3275
}
3146
3276
 
3154
3284
row_sel_try_search_shortcut_for_mysql(
3155
3285
/*==================================*/
3156
3286
                                /* out: SEL_FOUND, SEL_EXHAUSTED, SEL_RETRY */
3157
 
        rec_t**         out_rec,/* out: record if found */
 
3287
        const rec_t**   out_rec,/* out: record if found */
3158
3288
        row_prebuilt_t* prebuilt,/* in: prebuilt struct */
3159
3289
        ulint**         offsets,/* in/out: for rec_get_offsets(*out_rec) */
3160
3290
        mem_heap_t**    heap,   /* in/out: heap for rec_get_offsets() */
3161
3291
        mtr_t*          mtr)    /* in: started mtr */
3162
3292
{
3163
3293
        dict_index_t*   index           = prebuilt->index;
3164
 
        dtuple_t*       search_tuple    = prebuilt->search_tuple;
 
3294
        const dtuple_t* search_tuple    = prebuilt->search_tuple;
3165
3295
        btr_pcur_t*     pcur            = prebuilt->pcur;
3166
3296
        trx_t*          trx             = prebuilt->trx;
3167
 
        rec_t*          rec;
 
3297
        const rec_t*    rec;
3168
3298
 
3169
 
        ut_ad(index->type & DICT_CLUSTERED);
 
3299
        ut_ad(dict_index_is_clust(index));
3170
3300
        ut_ad(!prebuilt->templ_contains_blob);
3171
3301
 
3172
3302
        btr_pcur_open_with_no_init(index, search_tuple, PAGE_CUR_GE,
3221
3351
and fetch prev. NOTE that if we do a search with a full key value
3222
3352
from a unique index (ROW_SEL_EXACT), then we will not store the cursor
3223
3353
position and fetch next or fetch prev must not be tried to the cursor! */
3224
 
 
 
3354
UNIV_INTERN
3225
3355
ulint
3226
3356
row_search_for_mysql(
3227
3357
/*=================*/
3250
3380
{
3251
3381
        dict_index_t*   index           = prebuilt->index;
3252
3382
        ibool           comp            = dict_table_is_comp(index->table);
3253
 
        dtuple_t*       search_tuple    = prebuilt->search_tuple;
 
3383
        const dtuple_t* search_tuple    = prebuilt->search_tuple;
3254
3384
        btr_pcur_t*     pcur            = prebuilt->pcur;
3255
3385
        trx_t*          trx             = prebuilt->trx;
3256
3386
        dict_index_t*   clust_index;
3257
3387
        que_thr_t*      thr;
3258
 
        rec_t*          rec;
3259
 
        rec_t*          result_rec;
3260
 
        rec_t*          clust_rec;
 
3388
        const rec_t*    rec;
 
3389
        const rec_t*    result_rec;
 
3390
        const rec_t*    clust_rec;
3261
3391
        ulint           err                             = DB_SUCCESS;
3262
3392
        ibool           unique_search                   = FALSE;
3263
3393
        ibool           unique_search_from_clust_index  = FALSE;
3279
3409
        mem_heap_t*     heap                            = NULL;
3280
3410
        ulint           offsets_[REC_OFFS_NORMAL_SIZE];
3281
3411
        ulint*          offsets                         = offsets_;
3282
 
        ibool           some_fields_in_buffer;
3283
 
        ibool           get_clust_rec= 0;
 
3412
        ibool           some_fields_in_buffer;
 
3413
        ibool           get_clust_rec= 0;
3284
3414
 
3285
 
        *offsets_ = (sizeof offsets_) / sizeof *offsets_;
 
3415
        rec_offs_init(offsets_);
3286
3416
 
3287
3417
        ut_ad(index && pcur && search_tuple);
3288
3418
        ut_ad(trx->mysql_thread_id == os_thread_get_curr_id());
3422
3552
                }
3423
3553
 
3424
3554
                if (prebuilt->fetch_cache_first > 0
3425
 
                    && prebuilt->fetch_cache_first < DRIZZLE_FETCH_CACHE_SIZE) {
 
3555
                    && prebuilt->fetch_cache_first < MYSQL_FETCH_CACHE_SIZE) {
3426
3556
 
3427
3557
                        /* The previous returned row was popped from the fetch
3428
3558
                        cache, but the cache was not full at the time of the
3452
3582
        locks when locking delete-marked records. */
3453
3583
 
3454
3584
        if (match_mode == ROW_SEL_EXACT
3455
 
            && index->type & DICT_UNIQUE
 
3585
            && dict_index_is_unique(index)
3456
3586
            && dtuple_get_n_fields(search_tuple)
3457
3587
            == dict_index_get_n_unique(index)
3458
 
            && (index->type & DICT_CLUSTERED
 
3588
            && (dict_index_is_clust(index)
3459
3589
                || !dtuple_contains_null(search_tuple))) {
3460
3590
 
3461
3591
                /* Note above that a UNIQUE secondary index can contain many
3492
3622
 
3493
3623
        if (UNIV_UNLIKELY(direction == 0)
3494
3624
            && unique_search
3495
 
            && index->type & DICT_CLUSTERED
 
3625
            && dict_index_is_clust(index)
3496
3626
            && !prebuilt->templ_contains_blob
3497
3627
            && !prebuilt->used_in_HANDLER
3498
3628
            && (prebuilt->mysql_row_len < UNIV_PAGE_SIZE / 8)) {
3532
3662
                                ut_a(0 == cmp_dtuple_rec(search_tuple,
3533
3663
                                                         rec, offsets));
3534
3664
#endif
 
3665
                                /* At this point, rec is protected by
 
3666
                                a page latch that was acquired by
 
3667
                                row_sel_try_search_shortcut_for_mysql().
 
3668
                                The latch will not be released until
 
3669
                                mtr_commit(&mtr). */
 
3670
 
3535
3671
                                if (!row_sel_store_mysql_rec(buf, prebuilt,
3536
 
                                                             rec, offsets, 0, 
3537
 
                                                             prebuilt->n_template)) {
 
3672
                                                             rec, offsets, 0,
 
3673
                                                             prebuilt->n_template)) {
3538
3674
                                        err = DB_TOO_BIG_RECORD;
3539
3675
 
3540
3676
                                        /* We let the main loop to do the
3549
3685
 
3550
3686
                                srv_n_rows_read++;
3551
3687
 
3552
 
                                if (trx->search_latch_timeout > 0
3553
 
                                    && trx->has_search_latch) {
3554
 
 
3555
 
                                        trx->search_latch_timeout--;
3556
 
 
3557
 
                                        rw_lock_s_unlock(&btr_search_latch);
3558
 
                                        trx->has_search_latch = FALSE;
3559
 
                                }
3560
 
 
3561
 
                                /* NOTE that we do NOT store the cursor
3562
 
                                position */
3563
3688
                                err = DB_SUCCESS;
3564
 
                                goto func_exit;
 
3689
                                goto release_search_latch_if_needed;
3565
3690
 
3566
3691
                        case SEL_EXHAUSTED:
3567
3692
                                mtr_commit(&mtr);
3569
3694
                                /* ut_print_name(stderr, index->name);
3570
3695
                                fputs(" record not found 2\n", stderr); */
3571
3696
 
 
3697
                                err = DB_RECORD_NOT_FOUND;
 
3698
release_search_latch_if_needed:
3572
3699
                                if (trx->search_latch_timeout > 0
3573
3700
                                    && trx->has_search_latch) {
3574
3701
 
3580
3707
 
3581
3708
                                /* NOTE that we do NOT store the cursor
3582
3709
                                position */
3583
 
 
3584
 
                                err = DB_RECORD_NOT_FOUND;
3585
3710
                                goto func_exit;
 
3711
 
 
3712
                        case SEL_RETRY:
 
3713
                                break;
 
3714
 
 
3715
                        default:
 
3716
                                ut_ad(0);
3586
3717
                        }
3587
3718
shortcut_fails_too_big_rec:
3588
3719
                        mtr_commit(&mtr);
3602
3733
 
3603
3734
        if (trx->isolation_level <= TRX_ISO_READ_COMMITTED
3604
3735
            && prebuilt->select_lock_type != LOCK_NONE
 
3736
#ifdef BUILD_DRIZZLE
 
3737
            && trx->mysql_session != NULL
 
3738
#else
 
3739
            && trx->mysql_thd != NULL
 
3740
#endif
3605
3741
            && trx->mysql_query_str != NULL
3606
 
            && *trx->mysql_query_str != NULL
3607
 
            && trx->mysql_session != NULL) {
 
3742
            && *trx->mysql_query_str != NULL) {
3608
3743
 
3609
3744
                /* Scan the MySQL query string; check if SELECT is the first
3610
3745
                word there */
3681
3816
 
3682
3817
                        /* Try to place a gap lock on the next index record
3683
3818
                        to prevent phantoms in ORDER BY ... DESC queries */
 
3819
                        const rec_t*    next = page_rec_get_next_const(rec);
3684
3820
 
3685
 
                        offsets = rec_get_offsets(page_rec_get_next(rec),
3686
 
                                                  index, offsets,
 
3821
                        offsets = rec_get_offsets(next, index, offsets,
3687
3822
                                                  ULINT_UNDEFINED, &heap);
3688
 
                        err = sel_set_rec_lock(page_rec_get_next(rec),
3689
 
                                               index, offsets,
 
3823
                        err = sel_set_rec_lock(btr_pcur_get_block(pcur),
 
3824
                                               next, index, offsets,
3690
3825
                                               prebuilt->select_lock_type,
3691
3826
                                               LOCK_GAP, thr);
3692
3827
 
3754
3889
        fputs("Using ", stderr);
3755
3890
        dict_index_name_print(stderr, index);
3756
3891
        fprintf(stderr, " cnt %lu ; Page no %lu\n", cnt,
3757
 
        buf_frame_get_page_no(buf_frame_align(rec)));
 
3892
        page_get_page_no(page_align(rec)));
3758
3893
        rec_print(rec);
3759
3894
        */
3760
3895
#endif /* UNIV_SEARCH_DEBUG */
3784
3919
 
3785
3920
                        offsets = rec_get_offsets(rec, index, offsets,
3786
3921
                                                  ULINT_UNDEFINED, &heap);
3787
 
                        err = sel_set_rec_lock(rec, index, offsets,
 
3922
                        err = sel_set_rec_lock(btr_pcur_get_block(pcur),
 
3923
                                               rec, index, offsets,
3788
3924
                                               prebuilt->select_lock_type,
3789
3925
                                               LOCK_ORDINARY, thr);
3790
3926
 
3822
3958
wrong_offs:
3823
3959
                if (srv_force_recovery == 0 || moves_up == FALSE) {
3824
3960
                        ut_print_timestamp(stderr);
3825
 
                        buf_page_print(buf_frame_align(rec));
 
3961
                        buf_page_print(page_align(rec), 0);
3826
3962
                        fprintf(stderr,
3827
 
                                "\nInnoDB: rec address %p, first"
3828
 
                                " buffer frame %p\n"
3829
 
                                "InnoDB: buffer pool high end %p,"
 
3963
                                "\nInnoDB: rec address %p,"
3830
3964
                                " buf block fix count %lu\n",
3831
 
                                (void*) rec, (void*) buf_pool->frame_zero,
3832
 
                                (void*) buf_pool->high_end,
3833
 
                                (ulong)buf_block_align(rec)->buf_fix_count);
 
3965
                                (void*) rec, (ulong)
 
3966
                                btr_cur_get_block(btr_pcur_get_btr_cur(pcur))
 
3967
                                ->page.buf_fix_count);
3834
3968
                        fprintf(stderr,
3835
3969
                                "InnoDB: Index corruption: rec offs %lu"
3836
3970
                                " next offs %lu, page no %lu,\n"
3837
3971
                                "InnoDB: ",
3838
3972
                                (ulong) page_offset(rec),
3839
3973
                                (ulong) next_offs,
3840
 
                                (ulong) buf_frame_get_page_no(rec));
 
3974
                                (ulong) page_get_page_no(page_align(rec)));
3841
3975
                        dict_index_name_print(stderr, trx, index);
3842
3976
                        fputs(". Run CHECK TABLE. You may need to\n"
3843
3977
                              "InnoDB: restore from a backup, or"
3857
3991
                                "InnoDB: ",
3858
3992
                                (ulong) page_offset(rec),
3859
3993
                                (ulong) next_offs,
3860
 
                                (ulong) buf_frame_get_page_no(rec));
 
3994
                                (ulong) page_get_page_no(page_align(rec)));
3861
3995
                        dict_index_name_print(stderr, trx, index);
3862
3996
                        fputs(". We try to skip the rest of the page.\n",
3863
3997
                              stderr);
3882
4016
                                "InnoDB: ",
3883
4017
                                (ulong) page_offset(rec),
3884
4018
                                (ulong) next_offs,
3885
 
                                (ulong) buf_frame_get_page_no(rec));
 
4019
                                (ulong) page_get_page_no(page_align(rec)));
3886
4020
                        dict_index_name_print(stderr, trx, index);
3887
4021
                        fputs(". We try to skip the record.\n",
3888
4022
                              stderr);
3916
4050
                                using a READ COMMITTED isolation level. */
3917
4051
 
3918
4052
                                err = sel_set_rec_lock(
 
4053
                                        btr_pcur_get_block(pcur),
3919
4054
                                        rec, index, offsets,
3920
4055
                                        prebuilt->select_lock_type, LOCK_GAP,
3921
4056
                                        thr);
3951
4086
                                using a READ COMMITTED isolation level. */
3952
4087
 
3953
4088
                                err = sel_set_rec_lock(
 
4089
                                        btr_pcur_get_block(pcur),
3954
4090
                                        rec, index, offsets,
3955
4091
                                        prebuilt->select_lock_type, LOCK_GAP,
3956
4092
                                        thr);
4019
4155
                        lock_type = LOCK_REC_NOT_GAP;
4020
4156
                }
4021
4157
 
4022
 
                err = sel_set_rec_lock(rec, index, offsets,
 
4158
                err = sel_set_rec_lock(btr_pcur_get_block(pcur),
 
4159
                                       rec, index, offsets,
4023
4160
                                       prebuilt->select_lock_type,
4024
4161
                                       lock_type, thr);
4025
4162
 
4026
4163
                switch (err) {
4027
 
                        rec_t*  old_vers;
 
4164
                        const rec_t*    old_vers;
4028
4165
                case DB_SUCCESS:
4029
4166
                        break;
4030
4167
                case DB_LOCK_WAIT:
4127
4264
 
4128
4265
                                rec = old_vers;
4129
4266
                        }
4130
 
                } else if (!lock_sec_rec_cons_read_sees(rec, index,
4131
 
                                                        trx->read_view)) {
 
4267
                } else if (!lock_sec_rec_cons_read_sees(rec, trx->read_view)) {
4132
4268
                        /* We are looking into a non-clustered index,
4133
4269
                        and to get the right version of the record we
4134
4270
                        have to look also into the clustered index: this
4136
4272
                        information via the clustered index record. */
4137
4273
 
4138
4274
                        ut_ad(index != clust_index);
4139
 
                        get_clust_rec= TRUE;
 
4275
                        get_clust_rec= TRUE;
4140
4276
                        goto idx_cond_check;
4141
4277
                }
4142
4278
        }
4181
4317
                goto next_rec;
4182
4318
        }
4183
4319
 
4184
 
 
4185
4320
idx_cond_check:
4186
4321
        if (prebuilt->idx_cond_func)
4187
4322
        {
4202
4337
 
4203
4338
        /* Get the clustered index record if needed, if we did not do the
4204
4339
        search using the clustered index. */
 
4340
 
4205
4341
        if (get_clust_rec || (index != clust_index &&
4206
 
            prebuilt->need_to_access_clustered)) {
 
4342
            prebuilt->need_to_access_clustered)) {
4207
4343
 
4208
4344
                /* We use a 'goto' to the preceding label if a consistent
4209
4345
                read of a secondary index record requires us to look up old
4210
4346
                versions of the associated clustered index record. */
4211
4347
 
4212
4348
                ut_ad(rec_offs_validate(rec, index, offsets));
4213
 
                
 
4349
 
4214
4350
                /* It was a non-clustered index and we must fetch also the
4215
4351
                clustered index record */
4216
4352
 
4277
4413
                                result_rec != rec ? clust_index : index,
4278
4414
                                offsets));
4279
4415
 
 
4416
        /* At this point, the clustered index record is protected
 
4417
        by a page latch that was acquired when pcur was positioned.
 
4418
        The latch will not be released until mtr_commit(&mtr). */
 
4419
 
4280
4420
        if ((match_mode == ROW_SEL_EXACT
4281
 
             || prebuilt->n_rows_fetched >= DRIZZLE_FETCH_CACHE_THRESHOLD)
 
4421
             || prebuilt->n_rows_fetched >= MYSQL_FETCH_CACHE_THRESHOLD)
4282
4422
            && prebuilt->select_lock_type == LOCK_NONE
4283
4423
            && !prebuilt->templ_contains_blob
4284
4424
            && !prebuilt->clust_index_was_generated
4285
4425
            && !prebuilt->used_in_HANDLER
4286
4426
            && prebuilt->template_type
4287
 
            != ROW_DRIZZLE_DUMMY_TEMPLATE) {
 
4427
            != ROW_MYSQL_DUMMY_TEMPLATE) {
4288
4428
 
4289
4429
                /* Inside an update, for example, we do not cache rows,
4290
4430
                since we may use the cursor position to do the actual
4294
4434
                are BLOBs in the fields to be fetched. In HANDLER we do
4295
4435
                not cache rows because there the cursor is a scrollable
4296
4436
                cursor. */
4297
 
                some_fields_in_buffer= (index != clust_index &&
 
4437
                some_fields_in_buffer= (index != clust_index &&
4298
4438
                                        prebuilt->idx_cond_func);
4299
4439
 
4300
4440
                row_sel_push_cache_row_for_mysql(prebuilt, result_rec,
4301
 
                                                 offsets, 
4302
 
                                                 some_fields_in_buffer? 
4303
 
                                                 prebuilt->n_index_fields: 0,
4304
 
                                                 buf);
4305
 
                if (prebuilt->n_fetch_cached == DRIZZLE_FETCH_CACHE_SIZE) {
 
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) {
4306
4446
 
4307
4447
                        goto got_row;
4308
4448
                }
4309
4449
 
4310
4450
                goto next_rec;
4311
4451
        } else {
4312
 
                if (prebuilt->template_type == ROW_DRIZZLE_DUMMY_TEMPLATE) {
 
4452
                if (prebuilt->template_type == ROW_MYSQL_DUMMY_TEMPLATE) {
4313
4453
                        memcpy(buf + 4, result_rec
4314
4454
                               - rec_offs_extra_size(offsets),
4315
4455
                               rec_offs_size(offsets));
4318
4458
                } else {
4319
4459
                        if (!row_sel_store_mysql_rec(buf, prebuilt,
4320
4460
                                                     result_rec, offsets,
4321
 
                                                     prebuilt->idx_cond_func? 
 
4461
                                                     prebuilt->idx_cond_func?
4322
4462
                                                     prebuilt->n_index_fields: 0,
4323
4463
                                                     prebuilt->n_template)) {
4324
4464
                                err = DB_TOO_BIG_RECORD;
4348
4488
        HANDLER command where the user can move the cursor with PREV or NEXT
4349
4489
        even after a unique search. */
4350
4490
 
4351
 
        err = DB_SUCCESS;
4352
 
 
4353
4491
idx_cond_failed:
4354
4492
        if (!unique_search_from_clust_index
4355
4493
            || prebuilt->select_lock_type != LOCK_NONE
4360
4498
                btr_pcur_store_position(pcur, &mtr);
4361
4499
        }
4362
4500
 
 
4501
        err = DB_SUCCESS;
 
4502
 
4363
4503
        goto normal_return;
4364
4504
 
4365
4505
next_rec:
4366
4506
        /* Reset the old and new "did semi-consistent read" flags. */
4367
 
        get_clust_rec= FALSE;
4368
4507
        if (UNIV_UNLIKELY(prebuilt->row_read_type
4369
4508
                          == ROW_READ_DID_SEMI_CONSISTENT)) {
4370
4509
                prebuilt->row_read_type = ROW_READ_TRY_SEMI_CONSISTENT;
4545
4684
/***********************************************************************
4546
4685
Checks if MySQL at the moment is allowed for this table to retrieve a
4547
4686
consistent read result, or store it to the query cache. */
4548
 
 
 
4687
UNIV_INTERN
4549
4688
ibool
4550
4689
row_search_check_if_query_cache_permitted(
4551
4690
/*======================================*/
4603
4742
Read the AUTOINC column from the current row. If the value is less than
4604
4743
0 and the type is not unsigned then we reset the value to 0. */
4605
4744
static
4606
 
ib_longlong
 
4745
ib_uint64_t
4607
4746
row_search_autoinc_read_column(
4608
4747
/*===========================*/
4609
4748
                                        /* out: value read from the column */
4610
4749
        dict_index_t*   index,          /* in: index to read from */
4611
 
        rec_t*  rec,            /* in: current rec */
 
4750
        const rec_t*    rec,            /* in: current rec */
4612
4751
        ulint           col_no,         /* in: column number */
4613
4752
        ibool           unsigned_type)  /* in: signed or unsigned flag */
4614
4753
{
4615
4754
        ulint           len;
4616
4755
        const byte*     data;
4617
 
        ib_longlong     value;
 
4756
        ib_uint64_t     value;
4618
4757
        mem_heap_t*     heap = NULL;
4619
 
        /* Our requirement is that dest should be word aligned. */
4620
 
        byte            dest[sizeof(value)];
4621
4758
        ulint           offsets_[REC_OFFS_NORMAL_SIZE];
4622
4759
        ulint*          offsets = offsets_;
4623
4760
 
4624
 
        *offsets_ = sizeof offsets_ / sizeof *offsets_;
 
4761
        rec_offs_init(offsets_);
4625
4762
 
4626
4763
        offsets = rec_get_offsets(rec, index, offsets, ULINT_UNDEFINED, &heap);
4627
4764
 
4630
4767
        ut_a(len != UNIV_SQL_NULL);
4631
4768
        ut_a(len <= sizeof value);
4632
4769
 
4633
 
        mach_read_int_type(dest, data, len, unsigned_type);
4634
 
 
4635
 
        /* The assumption here is that the AUTOINC value can't be negative
4636
 
        and that dest is word aligned. */
4637
 
        switch (len) {
4638
 
        case 8:
4639
 
                value = *(ib_longlong*) dest;
4640
 
                break;
4641
 
 
4642
 
        case 4:
4643
 
                value = *(ib_uint32_t*) dest;
4644
 
                break;
4645
 
 
4646
 
        case 3:
4647
 
                value = *(ib_uint32_t*) dest;
4648
 
                value &= 0xFFFFFF;
4649
 
                break;
4650
 
 
4651
 
        case 2:
4652
 
                value = *(uint16_t *) dest;
4653
 
                break;
4654
 
 
4655
 
        case 1:
4656
 
                value = *dest;
4657
 
                break;
4658
 
 
4659
 
        default:
4660
 
                ut_error;
4661
 
        }
 
4770
        /* we assume AUTOINC value cannot be negative */
 
4771
        value = mach_read_int_type(data, len, unsigned_type);
4662
4772
 
4663
4773
        if (UNIV_LIKELY_NULL(heap)) {
4664
4774
                mem_heap_free(heap);
4665
4775
        }
4666
4776
 
4667
 
        if (!unsigned_type && value < 0) {
 
4777
        if (!unsigned_type && (ib_int64_t) value < 0) {
4668
4778
                value = 0;
4669
4779
        }
4670
4780
 
4674
4784
/***********************************************************************
4675
4785
Get the last row. */
4676
4786
static
4677
 
rec_t*
 
4787
const rec_t*
4678
4788
row_search_autoinc_get_rec(
4679
4789
/*=======================*/
4680
4790
                                        /* out: current rec or NULL */
4682
4792
        mtr_t*          mtr)            /* in: mini transaction */
4683
4793
{
4684
4794
        do {
4685
 
                rec_t* rec = btr_pcur_get_rec(pcur);
 
4795
                const rec_t* rec = btr_pcur_get_rec(pcur);
4686
4796
 
4687
4797
                if (page_rec_is_user_rec(rec)) {
4688
4798
                        return(rec);
4694
4804
 
4695
4805
/***********************************************************************
4696
4806
Read the max AUTOINC value from an index. */
4697
 
 
 
4807
UNIV_INTERN
4698
4808
ulint
4699
4809
row_search_max_autoinc(
4700
4810
/*===================*/
4703
4813
                                        column name can't be found in index */
4704
4814
        dict_index_t*   index,          /* in: index to search */
4705
4815
        const char*     col_name,       /* in: name of autoinc column */
4706
 
        ib_longlong*    value)          /* out: AUTOINC value read */
 
4816
        ib_uint64_t*    value)          /* out: AUTOINC value read */
4707
4817
{
4708
4818
        ulint           i;
4709
4819
        ulint           n_cols;
4736
4846
                        FALSE, index, BTR_SEARCH_LEAF, &pcur, TRUE, &mtr);
4737
4847
 
4738
4848
                if (page_get_n_recs(btr_pcur_get_page(&pcur)) > 0) {
4739
 
                        rec_t*  rec;
 
4849
                        const rec_t*    rec;
4740
4850
 
4741
4851
                        rec = row_search_autoinc_get_rec(&pcur, &mtr);
4742
4852