51
51
#define SEL_RETRY 2
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
57
NOTE: the comparison is NOT done as a binary comparison, but character
58
fields are compared with collation! */
61
row_sel_sec_rec_is_for_blob(
62
/*========================*/
63
/* out: TRUE if the columns
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 */
83
byte buf[DICT_MAX_INDEX_COL_LEN];
85
len = btr_copy_externally_stored_field_prefix(buf, sizeof buf,
87
clust_field, clust_len);
88
len = dtype_get_at_most_n_mbchars(prtype, mbminlen, mbmaxlen,
89
sec_len, len, (const char*) buf);
91
return(!cmp_data_data(mtype, prtype, buf, len, sec_field, sec_len));
94
/************************************************************************
95
54
Returns TRUE if the user-defined column values in a secondary index record
96
55
are alphabetically the same as the corresponding columns in the clustered
105
64
record is equal to the corresponding
106
65
fields in the clustered record,
107
66
when compared with collation */
108
const rec_t* sec_rec, /* in: secondary index record */
67
rec_t* sec_rec, /* in: secondary index record */
109
68
dict_index_t* sec_index, /* in: secondary index */
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 */
69
rec_t* clust_rec, /* in: clustered index record */
114
70
dict_index_t* clust_index) /* in: clustered index */
116
const byte* sec_field;
118
const byte* clust_field;
121
78
mem_heap_t* heap = NULL;
125
82
ulint* sec_offs = sec_offsets_;
126
83
ibool is_equal = TRUE;
128
rec_offs_init(clust_offsets_);
129
rec_offs_init(sec_offsets_);
131
if (rec_get_deleted_flag(clust_rec,
132
dict_table_is_comp(clust_index->table))) {
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. */
85
*clust_offsets_ = (sizeof clust_offsets_) / sizeof *clust_offsets_;
86
*sec_offsets_ = (sizeof sec_offsets_) / sizeof *sec_offsets_;
141
88
clust_offs = rec_get_offsets(clust_rec, clust_index, clust_offs,
142
89
ULINT_UNDEFINED, &heap);
148
95
for (i = 0; i < n; i++) {
149
96
const dict_field_t* ifield;
150
97
const dict_col_t* col;
155
99
ifield = dict_index_get_nth_field(sec_index, i);
156
100
col = dict_field_get_col(ifield);
157
clust_pos = dict_col_get_clust_pos(col, clust_index);
159
102
clust_field = rec_get_nth_field(
160
clust_rec, clust_offs, clust_pos, &clust_len);
103
clust_rec, clust_offs,
104
dict_col_get_clust_pos(col, clust_index), &clust_len);
161
105
sec_field = rec_get_nth_field(sec_rec, sec_offs, i, &sec_len);
165
if (ifield->prefix_len > 0 && len != UNIV_SQL_NULL) {
167
if (rec_offs_nth_extern(clust_offs, clust_pos)) {
168
len -= BTR_EXTERN_FIELD_REF_SIZE;
171
len = dtype_get_at_most_n_mbchars(
107
if (ifield->prefix_len > 0 && clust_len != UNIV_SQL_NULL) {
109
clust_len = dtype_get_at_most_n_mbchars(
172
110
col->prtype, col->mbminlen, col->mbmaxlen,
173
ifield->prefix_len, len, (char*) clust_field);
175
if (rec_offs_nth_extern(clust_offs, clust_pos)
177
if (!row_sel_sec_rec_is_for_blob(
178
col->mtype, col->prtype,
179
col->mbminlen, col->mbmaxlen,
180
clust_field, clust_len,
183
clust_index->table))) {
112
clust_len, (char*) clust_field);
191
115
if (0 != cmp_data_data(col->mtype, col->prtype,
116
clust_field, clust_len,
193
117
sec_field, sec_len)) {
195
118
is_equal = FALSE;
354
277
row_sel_fetch_columns(
355
278
/*==================*/
356
279
dict_index_t* index, /* in: record index */
357
const rec_t* rec, /* in: record in a clustered or non-clustered
358
index; must be protected by a page latch */
280
rec_t* rec, /* in: record in a clustered or non-clustered
359
282
const ulint* offsets,/* in: rec_get_offsets(rec, index) */
360
283
sym_node_t* column) /* in: first column in a column list, or
364
287
ulint index_type;
369
292
ut_ad(rec_offs_validate(rec, index, offsets));
371
if (dict_index_is_clust(index)) {
294
if (index->type & DICT_CLUSTERED) {
372
295
index_type = SYM_CLUST_FIELD_NO;
374
297
index_type = SYM_SEC_FIELD_NO;
391
314
heap = mem_heap_create(1);
393
316
data = btr_rec_copy_externally_stored_field(
395
dict_table_zip_size(index->table),
396
field_no, &len, heap);
317
rec, offsets, field_no, &len, heap);
398
319
ut_a(len != UNIV_SQL_NULL);
453
370
/*************************************************************************
454
371
Frees a prefetch buffer for a column, including the dynamically allocated
455
372
memory for data stored there. */
458
375
sel_col_prefetch_buf_free(
459
376
/*======================*/
502
419
ut_ad(!column->prefetch_buf);
503
420
ut_ad(que_node_get_val_buf_size(column) == 0);
504
ut_d(dfield_set_null(val));
422
dfield_set_data(val, NULL, 0);
509
427
ut_ad(column->prefetch_buf);
510
ut_ad(!dfield_is_ext(val));
512
429
sel_buf = column->prefetch_buf + plan->first_prefetched;
651
568
/* out: DB_SUCCESS or error code */
652
569
dict_index_t* clust_index, /* in: clustered index */
653
570
row_prebuilt_t* prebuilt, /* in: prebuilt struct */
654
const rec_t* rec, /* in: record in a clustered index */
571
rec_t* rec, /* in: record in a clustered index */
655
572
ulint** offsets, /* in/out: offsets returned by
656
573
rec_get_offsets(rec, clust_index) */
657
574
mem_heap_t** offset_heap, /* in/out: memory heap from which
658
575
the offsets are allocated */
659
const rec_t** old_vers, /* out: old version, or NULL if the
576
rec_t** old_vers, /* out: old version, or NULL if the
660
577
record does not exist in the view:
661
578
i.e., it was freshly inserted
835
752
err = lock_clust_rec_read_check_and_lock(
836
0, btr_pcur_get_block(&plan->clust_pcur),
837
clust_rec, index, offsets,
753
0, clust_rec, index, offsets,
838
754
node->row_lock_mode, lock_type, thr);
840
756
if (err != DB_SUCCESS) {
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). */
808
/* Fetch the columns needed in test conditions */
897
810
row_sel_fetch_columns(index, clust_rec, offsets,
898
811
UT_LIST_GET_FIRST(plan->columns));
913
826
sel_set_rec_lock(
914
827
/*=============*/
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
923
que_thr_t* thr) /* in: query thread */
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
835
que_thr_t* thr) /* in: query thread */
937
if (dict_index_is_clust(index)) {
849
if (index->type & DICT_CLUSTERED) {
938
850
err = lock_clust_rec_read_check_and_lock(
939
0, block, rec, index, offsets, mode, type, thr);
851
0, rec, index, offsets, mode, type, thr);
941
853
err = lock_sec_rec_read_check_and_lock(
942
0, block, rec, index, offsets, mode, type, thr);
854
0, rec, index, offsets, mode, type, thr);
1188
1100
offsets = rec_get_offsets(rec, index, offsets, ULINT_UNDEFINED, &heap);
1190
if (dict_index_is_clust(index)) {
1102
if (index->type & DICT_CLUSTERED) {
1191
1103
if (!lock_clust_rec_cons_read_sees(rec, index, offsets,
1192
1104
node->read_view)) {
1193
1105
ret = SEL_RETRY;
1194
1106
goto func_exit;
1196
} else if (!lock_sec_rec_cons_read_sees(rec, node->read_view)) {
1108
} else if (!lock_sec_rec_cons_read_sees(rec, index, node->read_view)) {
1198
1110
ret = SEL_RETRY;
1199
1111
goto func_exit;
1202
/* Test the deleted flag. */
1114
/* Test deleted flag. Fetch the columns needed in test conditions. */
1116
row_sel_fetch_columns(index, rec, offsets,
1117
UT_LIST_GET_FIRST(plan->columns));
1204
1119
if (rec_get_deleted_flag(rec, dict_table_is_comp(plan->table))) {
1207
1122
goto func_exit;
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). */
1215
row_sel_fetch_columns(index, rec, offsets,
1216
UT_LIST_GET_FIRST(plan->columns));
1218
1125
/* Test the rest of search conditions */
1220
1127
if (!row_sel_test_other_conds(plan)) {
1462
1369
lock_type = LOCK_ORDINARY;
1465
err = sel_set_rec_lock(btr_pcur_get_block(&plan->pcur),
1466
next_rec, index, offsets,
1372
err = sel_set_rec_lock(next_rec, index, offsets,
1467
1373
node->row_lock_mode,
1468
1374
lock_type, thr);
1519
1425
lock_type = LOCK_ORDINARY;
1522
err = sel_set_rec_lock(btr_pcur_get_block(&plan->pcur),
1523
rec, index, offsets,
1428
err = sel_set_rec_lock(rec, index, offsets,
1524
1429
node->row_lock_mode, lock_type, thr);
1526
1431
if (err != DB_SUCCESS) {
1583
1488
/* This is a non-locking consistent read: if necessary, fetch
1584
1489
a previous version of the record */
1586
if (dict_index_is_clust(index)) {
1491
if (index->type & DICT_CLUSTERED) {
1588
1493
if (!lock_clust_rec_cons_read_sees(rec, index, offsets,
1589
1494
node->read_view)) {
1602
1507
offsets = rec_get_offsets(
1603
1508
rec, index, offsets,
1604
1509
ULINT_UNDEFINED, &heap);
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). */
1615
1510
row_sel_fetch_columns(
1616
1511
index, rec, offsets,
1617
1512
UT_LIST_GET_FIRST(
1636
1531
/* PHASE 4: Test search end conditions and deleted flag */
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). */
1533
/* Fetch the columns needed in test conditions */
1643
1535
row_sel_fetch_columns(index, rec, offsets,
1644
1536
UT_LIST_GET_FIRST(plan->columns));
1792
1683
if (leaf_contains_updates
1793
&& btr_pcur_is_after_last_on_page(&plan->pcur)) {
1684
&& btr_pcur_is_after_last_on_page(&(plan->pcur), &mtr)) {
1795
1686
/* We must commit &mtr if we are moving to a different page,
1796
1687
because we have done updates to the x-latched leaf page, and
1823
1714
/* We found a record which satisfies the conditions: we can move to
1824
1715
the next table or return a row in the result set */
1826
ut_ad(btr_pcur_is_on_user_rec(&plan->pcur));
1717
ut_ad(btr_pcur_is_on_user_rec(&(plan->pcur), &mtr));
1828
1719
if (plan->unique_search && !node->can_get_updated) {
1901
1796
sel_assign_into_var_values(node->into_list, node);
1903
1798
thr->run_node = que_node_get_parent(node);
1905
node->state = SEL_NODE_NO_MORE_ROWS;
1907
thr->run_node = que_node_get_parent(node);
1800
if (search_latch_locked) {
1801
rw_lock_s_unlock(&btr_search_latch);
1807
node->state = SEL_NODE_NO_MORE_ROWS;
1809
thr->run_node = que_node_get_parent(node);
1811
if (search_latch_locked) {
1812
rw_lock_s_unlock(&btr_search_latch);
1910
1815
goto func_exit;
1960
1865
lock_wait_or_error:
1961
1866
/* See the note at stop_for_a_while: the same holds for this case */
1963
ut_ad(!btr_pcur_is_before_first_on_page(&plan->pcur) || !node->asc);
1868
ut_ad(!btr_pcur_is_before_first_on_page(&(plan->pcur), &mtr)
1964
1870
ut_ad(!search_latch_locked);
1966
1872
plan->stored_cursor_rec_processed = FALSE;
2171
2074
dfield_t* dfield = que_node_get_val(exp);
2172
const dtype_t* type = dfield_get_type(dfield);
2075
dtype_t* type = dfield_get_type(dfield);
2174
2077
fprintf(stderr, " column %lu:\n", (ulong)i);
2211
2114
dfield_t* dfield = que_node_get_val(node->select_list);
2212
const dtype_t* type = dfield_get_type(dfield);
2115
dtype_t* type = dfield_get_type(dfield);
2213
2116
ulint len = dfield_get_len(dfield);
2215
2118
ut_a(dtype_get_mtype(type) == DATA_INT);
2292
2195
last field is only a prefix of the full key field len and print a warning if
2293
2196
such appears. A counterpart of this function is
2294
2197
ha_innobase::store_key_val_for_row() in ha_innodb.cc. */
2297
2200
row_sel_convert_mysql_key_to_innobase(
2298
2201
/*==================================*/
2299
dtuple_t* tuple, /* in/out: tuple where to build;
2202
dtuple_t* tuple, /* in: tuple where to build;
2300
2203
NOTE: we assume that the type info
2301
2204
in the tuple is already according
2305
2208
ulint buf_len, /* in: buffer length */
2306
2209
dict_index_t* index, /* in: index of the key value */
2307
const byte* key_ptr, /* in: MySQL key value */
2210
byte* key_ptr, /* in: MySQL key value */
2308
2211
ulint key_len, /* in: MySQL key value length */
2309
2212
trx_t* trx) /* in: transaction */
2311
2214
byte* original_buf = buf;
2312
const byte* original_key_ptr = key_ptr;
2215
byte* original_key_ptr = key_ptr;
2313
2216
dict_field_t* field;
2314
2217
dfield_t* dfield;
2315
2218
ulint data_offset;
2316
2219
ulint data_len;
2317
2220
ulint data_field_len;
2319
const byte* key_end;
2320
2223
ulint n_fields = 0;
2322
2226
/* For documentation of the key value storage format in MySQL, see
2323
2227
ha_innobase::store_key_val_for_row() in ha_innodb.cc. */
2331
2235
dfield = dtuple_get_nth_field(tuple, 0);
2332
2236
field = dict_index_get_nth_field(index, 0);
2334
if (UNIV_UNLIKELY(dfield_get_type(dfield)->mtype == DATA_SYS)) {
2238
if (dfield_get_type(dfield)->mtype == DATA_SYS) {
2335
2239
/* A special case: we are looking for a position in the
2336
2240
generated clustered index which InnoDB automatically added
2337
2241
to a table with no primary key: the first and the only
2413
2318
data_field_len = data_offset + data_len;
2417
(dtype_get_mysql_type(dfield_get_type(dfield))
2418
== DATA_MYSQL_TRUE_VARCHAR)
2419
&& UNIV_LIKELY(type != DATA_INT)) {
2321
if (dtype_get_mysql_type(dfield_get_type(dfield))
2322
== DATA_DRIZZLE_TRUE_VARCHAR
2323
&& dfield_get_type(dfield)->mtype != DATA_INT) {
2420
2324
/* In a MySQL key value format, a true VARCHAR is
2421
2325
always preceded by 2 bytes of a length field.
2422
2326
dfield_get_type(dfield)->len returns the maximum
2496
2398
row_sel_store_row_id_to_prebuilt(
2497
2399
/*=============================*/
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) */
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) */
2507
2409
ut_ad(rec_offs_validate(index_rec, index, offsets));
2510
2412
index_rec, offsets,
2511
2413
dict_index_get_sys_col_pos(index, DATA_ROW_ID), &len);
2513
if (UNIV_UNLIKELY(len != DATA_ROW_ID_LEN)) {
2415
if (len != DATA_ROW_ID_LEN) {
2514
2416
fprintf(stderr,
2515
2417
"InnoDB: Error: Row id field is"
2516
2418
" wrong length %lu in ", (ulong) len);
2535
2437
row_sel_field_store_in_mysql_format(
2536
2438
/*================================*/
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
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 */
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 */
2552
2450
byte* field_end;
2577
2474
ut_ad(templ->mysql_col_len == len);
2475
} else if (templ->type == DATA_VARCHAR
2476
|| templ->type == DATA_VARMYSQL
2477
|| templ->type == DATA_BINARY) {
2583
2479
field_end = dest + templ->mysql_col_len;
2585
if (templ->mysql_type == DATA_MYSQL_TRUE_VARCHAR) {
2481
if (templ->mysql_type == DATA_DRIZZLE_TRUE_VARCHAR) {
2586
2482
/* This is a >= 5.0.3 type true VARCHAR. Store the
2587
2483
length of the data to the first byte or the first
2588
2484
two bytes of dest. */
2631
2527
memset(pad_ptr, 0x20, field_end - pad_ptr);
2529
} else if (templ->type == DATA_BLOB) {
2636
2530
/* Store a pointer to the BLOB buffer to dest: the BLOB was
2637
2531
already copied to the buffer in row_sel_store_mysql_rec */
2639
2533
row_mysql_store_blob_ref(dest, templ->mysql_col_len, data,
2535
} else if (templ->type == DATA_MYSQL) {
2644
2536
memcpy(dest, data, len);
2646
2538
ut_ad(templ->mysql_col_len >= len);
2662
2554
memset(dest + len, 0x20, templ->mysql_col_len - len);
2668
case DATA_SYS_CHILD:
2670
/* These column types should never be shipped to MySQL. */
2674
case DATA_FIXBINARY:
2678
/* Above are the valid column types for MySQL data. */
2679
#endif /* UNIV_DEBUG */
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);
2680
2564
ut_ad(templ->mysql_col_len == len);
2681
2566
memcpy(dest, data, len);
2698
2583
byte* mysql_rec, /* out: row in the MySQL format */
2699
2584
row_prebuilt_t* prebuilt, /* in: prebuilt struct */
2700
const rec_t* rec, /* in: Innobase record in the index
2585
rec_t* rec, /* in: Innobase record in the index
2701
2586
which was described in prebuilt's
2702
template; must be protected by
2704
const ulint* offsets, /* in: array returned by
2588
const ulint* offsets, /* in: array returned by
2705
2589
rec_get_offsets() */
2706
ulint start_field_no,
2590
ulint start_field_no,
2709
2593
mysql_row_templ_t* templ;
2710
2594
mem_heap_t* extern_field_heap = NULL;
2711
2595
mem_heap_t* heap;
2752
2636
causes an assert */
2754
2638
data = btr_rec_copy_externally_stored_field(
2756
dict_table_zip_size(prebuilt->table),
2757
templ->rec_field_no, &len, heap);
2639
rec, offsets, templ->rec_field_no,
2759
2642
ut_a(len != UNIV_SQL_NULL);
2829
2712
BLOB, TEXT and true VARCHAR) with space. */
2830
2713
if (UNIV_UNLIKELY(templ->mbminlen == 2)) {
2831
2714
/* Treat UCS2 as a special case. */
2833
2716
+ templ->mysql_col_offset;
2834
2717
len = templ->mysql_col_len;
2835
2718
/* There are two UCS2 bytes per char,
2869
2752
read_view_t* read_view, /* in: read view */
2870
2753
dict_index_t* clust_index, /* in: clustered index */
2871
2754
row_prebuilt_t* prebuilt, /* in: prebuilt struct */
2872
const rec_t* rec, /* in: record in a clustered index */
2755
rec_t* rec, /* in: record in a clustered index */
2873
2756
ulint** offsets, /* in/out: offsets returned by
2874
2757
rec_get_offsets(rec, clust_index) */
2875
2758
mem_heap_t** offset_heap, /* in/out: memory heap from which
2905
2788
/* out: DB_SUCCESS or error code */
2906
2789
row_prebuilt_t* prebuilt,/* in: prebuilt struct in the handle */
2907
2790
dict_index_t* sec_index,/* in: secondary index where rec resides */
2908
const rec_t* rec, /* in: record in a non-clustered index; if
2791
rec_t* rec, /* in: record in a non-clustered index; if
2909
2792
this is a locking read, then rec is not
2910
2793
allowed to be delete-marked, and that would
2911
2794
not make sense either */
2912
2795
que_thr_t* thr, /* in: query thread */
2913
const rec_t** out_rec,/* out: clustered record or an old version of
2796
rec_t** out_rec,/* out: clustered record or an old version of
2914
2797
it, NULL if the old version did not exist
2915
2798
in the read view, i.e., it was a fresh
2916
2799
inserted version */
2917
ulint** offsets,/* in: offsets returned by
2918
rec_get_offsets(rec, sec_index);
2919
out: offsets returned by
2800
ulint** offsets,/* out: offsets returned by
2920
2801
rec_get_offsets(out_rec, clust_index) */
2921
2802
mem_heap_t** offset_heap,/* in/out: memory heap from which
2922
2803
the offsets are allocated */
2933
2814
*out_rec = NULL;
2934
2815
trx = thr_get_trx(thr);
2936
row_build_row_ref_in_tuple(prebuilt->clust_ref, rec,
2937
sec_index, *offsets, trx);
2817
row_build_row_ref_in_tuple(prebuilt->clust_ref, sec_index, rec, trx);
2939
2819
clust_index = dict_table_get_first_index(sec_index->table);
2998
2878
we set a LOCK_REC_NOT_GAP type lock */
3000
2880
err = lock_clust_rec_read_check_and_lock(
3001
0, btr_pcur_get_block(prebuilt->clust_pcur),
3002
clust_rec, clust_index, *offsets,
2881
0, clust_rec, clust_index, *offsets,
3003
2882
prebuilt->select_lock_type, LOCK_REC_NOT_GAP, thr);
3004
2883
if (err != DB_SUCCESS) {
3047
2926
visit through secondary index records that would not really
3048
2927
exist in our snapshot. */
3052
|| rec_get_deleted_flag(rec, dict_table_is_comp(
2929
if (clust_rec && (old_vers || rec_get_deleted_flag(
3054
2933
&& !row_sel_sec_rec_is_for_clust_rec(
3055
2934
rec, sec_index, clust_rec, clust_index)) {
3056
2935
clust_rec = NULL;
3057
2937
#ifdef UNIV_SEARCH_DEBUG
3059
2938
ut_a(clust_rec == NULL
3060
2939
|| row_sel_sec_rec_is_for_clust_rec(
3061
2940
rec, sec_index, clust_rec, clust_index));
3140
3019
ut_ad(relative_position == BTR_PCUR_BEFORE
3141
3020
|| relative_position == BTR_PCUR_BEFORE_FIRST_IN_TREE);
3143
if (moves_up && btr_pcur_is_on_user_rec(pcur)) {
3022
if (moves_up && btr_pcur_is_on_user_rec(pcur, mtr)) {
3144
3023
btr_pcur_move_to_next(pcur, mtr);
3204
3083
row_sel_push_cache_row_for_mysql(
3205
3084
/*=============================*/
3206
3085
row_prebuilt_t* prebuilt, /* in: prebuilt struct */
3207
const rec_t* rec, /* in: record to push; must
3208
be protected by a page latch */
3086
rec_t* rec, /* in: record to push */
3209
3087
const ulint* offsets, /* in: rec_get_offsets() */
3210
ulint start_field_no, /* psergy: start from this field */
3211
byte* remainder_buf) /* if above !=0 -> where to take
3088
ulint start_field_no, /* psergey: start from this field */
3089
byte* remainder_buf) /* if above !=0 -> where to take prev fields */
3217
ut_ad(prebuilt->n_fetch_cached < MYSQL_FETCH_CACHE_SIZE);
3094
ut_ad(prebuilt->n_fetch_cached < DRIZZLE_FETCH_CACHE_SIZE);
3218
3095
ut_ad(rec_offs_validate(rec, NULL, offsets));
3219
3096
ut_a(!prebuilt->templ_contains_blob);
3221
3098
if (prebuilt->fetch_cache[0] == NULL) {
3222
3099
/* Allocate memory for the fetch cache */
3224
for (i = 0; i < MYSQL_FETCH_CACHE_SIZE; i++) {
3101
for (i = 0; i < DRIZZLE_FETCH_CACHE_SIZE; i++) {
3226
3103
/* A user has reported memory corruption in these
3227
3104
buffers in Linux. Put magic numbers there to help
3243
3120
prebuilt->fetch_cache[
3244
3121
prebuilt->n_fetch_cached],
3245
3122
prebuilt, rec, offsets, start_field_no,
3246
prebuilt->n_template))) {
3123
prebuilt->n_template))) {
3250
3126
if (start_field_no) {
3251
3127
for (i=0; i < start_field_no; i++) {
3252
3128
register ulint offs;
3253
mysql_row_templ_t* templ;
3129
mysql_row_templ_t* templ;
3254
3130
templ = prebuilt->mysql_template + i;
3256
3132
if (templ->mysql_null_bit_mask) {
3257
3133
offs= templ->mysql_null_byte_offset;
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);
3262
*(prebuilt->fetch_cache[prebuilt->n_fetch_cached] + offs) &=
3263
~templ->mysql_null_bit_mask;
3134
*(prebuilt->fetch_cache[prebuilt->n_fetch_cached] + offs) ^=
3135
(*(remainder_buf + offs) & templ->mysql_null_bit_mask);
3266
3137
offs= templ->mysql_col_offset;
3267
3138
memcpy(prebuilt->fetch_cache[prebuilt->n_fetch_cached] + offs,
3284
3154
row_sel_try_search_shortcut_for_mysql(
3285
3155
/*==================================*/
3286
3156
/* out: SEL_FOUND, SEL_EXHAUSTED, SEL_RETRY */
3287
const rec_t** out_rec,/* out: record if found */
3157
rec_t** out_rec,/* out: record if found */
3288
3158
row_prebuilt_t* prebuilt,/* in: prebuilt struct */
3289
3159
ulint** offsets,/* in/out: for rec_get_offsets(*out_rec) */
3290
3160
mem_heap_t** heap, /* in/out: heap for rec_get_offsets() */
3291
3161
mtr_t* mtr) /* in: started mtr */
3293
3163
dict_index_t* index = prebuilt->index;
3294
const dtuple_t* search_tuple = prebuilt->search_tuple;
3164
dtuple_t* search_tuple = prebuilt->search_tuple;
3295
3165
btr_pcur_t* pcur = prebuilt->pcur;
3296
3166
trx_t* trx = prebuilt->trx;
3299
ut_ad(dict_index_is_clust(index));
3169
ut_ad(index->type & DICT_CLUSTERED);
3300
3170
ut_ad(!prebuilt->templ_contains_blob);
3302
3172
btr_pcur_open_with_no_init(index, search_tuple, PAGE_CUR_GE,
3381
3251
dict_index_t* index = prebuilt->index;
3382
3252
ibool comp = dict_table_is_comp(index->table);
3383
const dtuple_t* search_tuple = prebuilt->search_tuple;
3253
dtuple_t* search_tuple = prebuilt->search_tuple;
3384
3254
btr_pcur_t* pcur = prebuilt->pcur;
3385
3255
trx_t* trx = prebuilt->trx;
3386
3256
dict_index_t* clust_index;
3387
3257
que_thr_t* thr;
3389
const rec_t* result_rec;
3390
const rec_t* clust_rec;
3391
3261
ulint err = DB_SUCCESS;
3392
3262
ibool unique_search = FALSE;
3393
3263
ibool unique_search_from_clust_index = FALSE;
3409
3279
mem_heap_t* heap = NULL;
3410
3280
ulint offsets_[REC_OFFS_NORMAL_SIZE];
3411
3281
ulint* offsets = offsets_;
3412
ibool some_fields_in_buffer;
3413
ibool get_clust_rec= 0;
3282
ibool some_fields_in_buffer;
3283
ibool get_clust_rec= 0;
3415
rec_offs_init(offsets_);
3285
*offsets_ = (sizeof offsets_) / sizeof *offsets_;
3417
3287
ut_ad(index && pcur && search_tuple);
3418
3288
ut_ad(trx->mysql_thread_id == os_thread_get_curr_id());
3554
3424
if (prebuilt->fetch_cache_first > 0
3555
&& prebuilt->fetch_cache_first < MYSQL_FETCH_CACHE_SIZE) {
3425
&& prebuilt->fetch_cache_first < DRIZZLE_FETCH_CACHE_SIZE) {
3557
3427
/* The previous returned row was popped from the fetch
3558
3428
cache, but the cache was not full at the time of the
3582
3452
locks when locking delete-marked records. */
3584
3454
if (match_mode == ROW_SEL_EXACT
3585
&& dict_index_is_unique(index)
3455
&& index->type & DICT_UNIQUE
3586
3456
&& dtuple_get_n_fields(search_tuple)
3587
3457
== dict_index_get_n_unique(index)
3588
&& (dict_index_is_clust(index)
3458
&& (index->type & DICT_CLUSTERED
3589
3459
|| !dtuple_contains_null(search_tuple))) {
3591
3461
/* Note above that a UNIQUE secondary index can contain many
3623
3493
if (UNIV_UNLIKELY(direction == 0)
3624
3494
&& unique_search
3625
&& dict_index_is_clust(index)
3495
&& index->type & DICT_CLUSTERED
3626
3496
&& !prebuilt->templ_contains_blob
3627
3497
&& !prebuilt->used_in_HANDLER
3628
3498
&& (prebuilt->mysql_row_len < UNIV_PAGE_SIZE / 8)) {
3662
3532
ut_a(0 == cmp_dtuple_rec(search_tuple,
3663
3533
rec, offsets));
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). */
3671
3535
if (!row_sel_store_mysql_rec(buf, prebuilt,
3673
prebuilt->n_template)) {
3537
prebuilt->n_template)) {
3674
3538
err = DB_TOO_BIG_RECORD;
3676
3540
/* We let the main loop to do the
3686
3550
srv_n_rows_read++;
3552
if (trx->search_latch_timeout > 0
3553
&& trx->has_search_latch) {
3555
trx->search_latch_timeout--;
3557
rw_lock_s_unlock(&btr_search_latch);
3558
trx->has_search_latch = FALSE;
3561
/* NOTE that we do NOT store the cursor
3688
3563
err = DB_SUCCESS;
3689
goto release_search_latch_if_needed;
3691
3566
case SEL_EXHAUSTED:
3692
3567
mtr_commit(&mtr);
3694
3569
/* ut_print_name(stderr, index->name);
3695
3570
fputs(" record not found 2\n", stderr); */
3697
err = DB_RECORD_NOT_FOUND;
3698
release_search_latch_if_needed:
3699
3572
if (trx->search_latch_timeout > 0
3700
3573
&& trx->has_search_latch) {
3734
3603
if (trx->isolation_level <= TRX_ISO_READ_COMMITTED
3735
3604
&& prebuilt->select_lock_type != LOCK_NONE
3736
&& trx->mysql_thd != NULL
3737
3605
&& trx->mysql_query_str != NULL
3738
&& *trx->mysql_query_str != NULL) {
3606
&& *trx->mysql_query_str != NULL
3607
&& trx->mysql_thd != NULL) {
3740
3609
/* Scan the MySQL query string; check if SELECT is the first
3813
3682
/* Try to place a gap lock on the next index record
3814
3683
to prevent phantoms in ORDER BY ... DESC queries */
3815
const rec_t* next = page_rec_get_next_const(rec);
3817
offsets = rec_get_offsets(next, index, offsets,
3685
offsets = rec_get_offsets(page_rec_get_next(rec),
3818
3687
ULINT_UNDEFINED, &heap);
3819
err = sel_set_rec_lock(btr_pcur_get_block(pcur),
3820
next, index, offsets,
3688
err = sel_set_rec_lock(page_rec_get_next(rec),
3821
3690
prebuilt->select_lock_type,
3822
3691
LOCK_GAP, thr);
3885
3754
fputs("Using ", stderr);
3886
3755
dict_index_name_print(stderr, index);
3887
3756
fprintf(stderr, " cnt %lu ; Page no %lu\n", cnt,
3888
page_get_page_no(page_align(rec)));
3757
buf_frame_get_page_no(buf_frame_align(rec)));
3889
3758
rec_print(rec);
3891
3760
#endif /* UNIV_SEARCH_DEBUG */
3916
3785
offsets = rec_get_offsets(rec, index, offsets,
3917
3786
ULINT_UNDEFINED, &heap);
3918
err = sel_set_rec_lock(btr_pcur_get_block(pcur),
3919
rec, index, offsets,
3787
err = sel_set_rec_lock(rec, index, offsets,
3920
3788
prebuilt->select_lock_type,
3921
3789
LOCK_ORDINARY, thr);
3955
3823
if (srv_force_recovery == 0 || moves_up == FALSE) {
3956
3824
ut_print_timestamp(stderr);
3957
buf_page_print(page_align(rec), 0);
3825
buf_page_print(buf_frame_align(rec));
3958
3826
fprintf(stderr,
3959
"\nInnoDB: rec address %p,"
3827
"\nInnoDB: rec address %p, first"
3828
" buffer frame %p\n"
3829
"InnoDB: buffer pool high end %p,"
3960
3830
" buf block fix count %lu\n",
3961
(void*) rec, (ulong)
3962
btr_cur_get_block(btr_pcur_get_btr_cur(pcur))
3963
->page.buf_fix_count);
3831
(void*) rec, (void*) buf_pool->frame_zero,
3832
(void*) buf_pool->high_end,
3833
(ulong)buf_block_align(rec)->buf_fix_count);
3964
3834
fprintf(stderr,
3965
3835
"InnoDB: Index corruption: rec offs %lu"
3966
3836
" next offs %lu, page no %lu,\n"
3968
3838
(ulong) page_offset(rec),
3969
3839
(ulong) next_offs,
3970
(ulong) page_get_page_no(page_align(rec)));
3840
(ulong) buf_frame_get_page_no(rec));
3971
3841
dict_index_name_print(stderr, trx, index);
3972
3842
fputs(". Run CHECK TABLE. You may need to\n"
3973
3843
"InnoDB: restore from a backup, or"
3988
3858
(ulong) page_offset(rec),
3989
3859
(ulong) next_offs,
3990
(ulong) page_get_page_no(page_align(rec)));
3860
(ulong) buf_frame_get_page_no(rec));
3991
3861
dict_index_name_print(stderr, trx, index);
3992
3862
fputs(". We try to skip the rest of the page.\n",
4013
3883
(ulong) page_offset(rec),
4014
3884
(ulong) next_offs,
4015
(ulong) page_get_page_no(page_align(rec)));
3885
(ulong) buf_frame_get_page_no(rec));
4016
3886
dict_index_name_print(stderr, trx, index);
4017
3887
fputs(". We try to skip the record.\n",
4151
4019
lock_type = LOCK_REC_NOT_GAP;
4154
err = sel_set_rec_lock(btr_pcur_get_block(pcur),
4155
rec, index, offsets,
4022
err = sel_set_rec_lock(rec, index, offsets,
4156
4023
prebuilt->select_lock_type,
4157
4024
lock_type, thr);
4160
const rec_t* old_vers;
4161
4028
case DB_SUCCESS:
4163
4030
case DB_LOCK_WAIT:
4261
4128
rec = old_vers;
4263
} else if (!lock_sec_rec_cons_read_sees(rec, trx->read_view)) {
4130
} else if (!lock_sec_rec_cons_read_sees(rec, index,
4264
4132
/* We are looking into a non-clustered index,
4265
4133
and to get the right version of the record we
4266
4134
have to look also into the clustered index: this
4334
4203
/* Get the clustered index record if needed, if we did not do the
4335
4204
search using the clustered index. */
4337
4205
if (get_clust_rec || (index != clust_index &&
4338
prebuilt->need_to_access_clustered)) {
4206
prebuilt->need_to_access_clustered)) {
4340
4208
/* We use a 'goto' to the preceding label if a consistent
4341
4209
read of a secondary index record requires us to look up old
4342
4210
versions of the associated clustered index record. */
4344
4212
ut_ad(rec_offs_validate(rec, index, offsets));
4346
4214
/* It was a non-clustered index and we must fetch also the
4347
4215
clustered index record */
4409
4277
result_rec != rec ? clust_index : index,
4412
/* At this point, the clustered index record is protected
4413
by a page latch that was acquired when pcur was positioned.
4414
The latch will not be released until mtr_commit(&mtr). */
4416
4280
if ((match_mode == ROW_SEL_EXACT
4417
|| prebuilt->n_rows_fetched >= MYSQL_FETCH_CACHE_THRESHOLD)
4281
|| prebuilt->n_rows_fetched >= DRIZZLE_FETCH_CACHE_THRESHOLD)
4418
4282
&& prebuilt->select_lock_type == LOCK_NONE
4419
4283
&& !prebuilt->templ_contains_blob
4420
4284
&& !prebuilt->clust_index_was_generated
4421
4285
&& !prebuilt->used_in_HANDLER
4422
4286
&& prebuilt->template_type
4423
!= ROW_MYSQL_DUMMY_TEMPLATE) {
4287
!= ROW_DRIZZLE_DUMMY_TEMPLATE) {
4425
4289
/* Inside an update, for example, we do not cache rows,
4426
4290
since we may use the cursor position to do the actual
4430
4294
are BLOBs in the fields to be fetched. In HANDLER we do
4431
4295
not cache rows because there the cursor is a scrollable
4433
some_fields_in_buffer= (index != clust_index &&
4297
some_fields_in_buffer= (index != clust_index &&
4434
4298
prebuilt->idx_cond_func);
4436
4300
row_sel_push_cache_row_for_mysql(prebuilt, result_rec,
4438
some_fields_in_buffer?
4439
prebuilt->n_index_fields: 0,
4441
if (prebuilt->n_fetch_cached == MYSQL_FETCH_CACHE_SIZE) {
4302
some_fields_in_buffer?
4303
prebuilt->n_index_fields: 0,
4305
if (prebuilt->n_fetch_cached == DRIZZLE_FETCH_CACHE_SIZE) {
4448
if (prebuilt->template_type == ROW_MYSQL_DUMMY_TEMPLATE) {
4312
if (prebuilt->template_type == ROW_DRIZZLE_DUMMY_TEMPLATE) {
4449
4313
memcpy(buf + 4, result_rec
4450
4314
- rec_offs_extra_size(offsets),
4451
4315
rec_offs_size(offsets));
4494
4360
btr_pcur_store_position(pcur, &mtr);
4499
4363
goto normal_return;
4502
4366
/* Reset the old and new "did semi-consistent read" flags. */
4367
get_clust_rec= FALSE;
4503
4368
if (UNIV_UNLIKELY(prebuilt->row_read_type
4504
4369
== ROW_READ_DID_SEMI_CONSISTENT)) {
4505
4370
prebuilt->row_read_type = ROW_READ_TRY_SEMI_CONSISTENT;
4680
4545
/***********************************************************************
4681
4546
Checks if MySQL at the moment is allowed for this table to retrieve a
4682
4547
consistent read result, or store it to the query cache. */
4685
4550
row_search_check_if_query_cache_permitted(
4686
4551
/*======================================*/
4738
4603
Read the AUTOINC column from the current row. If the value is less than
4739
4604
0 and the type is not unsigned then we reset the value to 0. */
4742
4607
row_search_autoinc_read_column(
4743
4608
/*===========================*/
4744
4609
/* out: value read from the column */
4745
4610
dict_index_t* index, /* in: index to read from */
4746
const rec_t* rec, /* in: current rec */
4611
rec_t* rec, /* in: current rec */
4747
4612
ulint col_no, /* in: column number */
4748
4613
ibool unsigned_type) /* in: signed or unsigned flag */
4751
4616
const byte* data;
4753
4618
mem_heap_t* heap = NULL;
4619
/* Our requirement is that dest should be word aligned. */
4620
byte dest[sizeof(value)];
4754
4621
ulint offsets_[REC_OFFS_NORMAL_SIZE];
4755
4622
ulint* offsets = offsets_;
4757
rec_offs_init(offsets_);
4624
*offsets_ = sizeof offsets_ / sizeof *offsets_;
4759
4626
offsets = rec_get_offsets(rec, index, offsets, ULINT_UNDEFINED, &heap);
4763
4630
ut_a(len != UNIV_SQL_NULL);
4764
4631
ut_a(len <= sizeof value);
4766
/* we assume AUTOINC value cannot be negative */
4767
value = mach_read_int_type(data, len, unsigned_type);
4633
mach_read_int_type(dest, data, len, unsigned_type);
4635
/* The assumption here is that the AUTOINC value can't be negative
4636
and that dest is word aligned. */
4639
value = *(ib_longlong*) dest;
4643
value = *(ib_uint32_t*) dest;
4647
value = *(ib_uint32_t*) dest;
4652
value = *(uint16_t *) dest;
4769
4663
if (UNIV_LIKELY_NULL(heap)) {
4770
4664
mem_heap_free(heap);
4773
if (!unsigned_type && (ib_int64_t) value < 0) {
4667
if (!unsigned_type && value < 0) {
4809
4703
column name can't be found in index */
4810
4704
dict_index_t* index, /* in: index to search */
4811
4705
const char* col_name, /* in: name of autoinc column */
4812
ib_uint64_t* value) /* out: AUTOINC value read */
4706
ib_longlong* value) /* out: AUTOINC value read */
4842
4736
FALSE, index, BTR_SEARCH_LEAF, &pcur, TRUE, &mtr);
4844
4738
if (page_get_n_recs(btr_pcur_get_page(&pcur)) > 0) {
4847
4741
rec = row_search_autoinc_get_rec(&pcur, &mtr);