63 #include "my_compare.h"
66 #define SEL_MAX_N_PREFETCH 16
70 #define SEL_PREFETCH_LIMIT 1
75 #define SEL_COST_LIMIT 100
79 #define SEL_EXHAUSTED 1
91 row_sel_sec_rec_is_for_blob(
97 const byte* clust_field,
104 const byte* sec_field,
119 ut_ad(prefix_len >= sec_len);
120 ut_ad(prefix_len > 0);
121 ut_a(prefix_len <=
sizeof buf);
135 clust_field, clust_len);
137 if (UNIV_UNLIKELY(len == 0)) {
147 prefix_len, len, (
const char*) buf);
149 return(!
cmp_data_data(mtype, prtype, buf, len, sec_field, sec_len));
163 row_sel_sec_rec_is_for_clust_rec(
165 const rec_t* sec_rec,
167 const rec_t* clust_rec,
173 const byte* sec_field;
175 const byte* clust_field;
179 ulint clust_offsets_[REC_OFFS_NORMAL_SIZE];
180 ulint sec_offsets_[REC_OFFS_SMALL_SIZE];
181 ulint* clust_offs = clust_offsets_;
182 ulint* sec_offs = sec_offsets_;
183 ibool is_equal = TRUE;
185 rec_offs_init(clust_offsets_);
186 rec_offs_init(sec_offsets_);
198 clust_offs = rec_get_offsets(clust_rec, clust_index, clust_offs,
199 ULINT_UNDEFINED, &heap);
200 sec_offs = rec_get_offsets(sec_rec, sec_index, sec_offs,
201 ULINT_UNDEFINED, &heap);
205 for (i = 0; i <
n; i++) {
212 ifield = dict_index_get_nth_field(sec_index, i);
216 clust_field = rec_get_nth_field(
217 clust_rec, clust_offs, clust_pos, &clust_len);
218 sec_field = rec_get_nth_field(sec_rec, sec_offs, i, &sec_len);
222 if (ifield->
prefix_len > 0 && len != UNIV_SQL_NULL
223 && sec_len != UNIV_SQL_NULL) {
231 ifield->
prefix_len, len, (
char*) clust_field);
235 if (!row_sel_sec_rec_is_for_blob(
238 clust_field, clust_len,
241 clust_index->
table)) {
251 sec_field, sec_len)) {
259 if (UNIV_LIKELY_NULL(heap)) {
299 if (node->
plans != NULL) {
300 for (i = 0; i < node->
n_tables; i++) {
376 for (func_node = static_cast<func_node_t*>(node->
select_list);
378 func_node = static_cast<func_node_t*>(
412 row_sel_fetch_columns(
427 ut_ad(rec_offs_validate(rec, index, offsets));
439 field_no = column->
field_nos[index_type];
441 if (field_no != ULINT_UNDEFINED) {
454 field_no, &len, heap);
467 ut_a(len != UNIV_SQL_NULL);
471 data = rec_get_nth_field(rec, offsets,
485 if (UNIV_LIKELY_NULL(heap)) {
498 sel_col_prefetch_buf_alloc(
508 mem_alloc(SEL_MAX_N_PREFETCH *
sizeof(
sel_buf_t)));
510 for (i = 0; i < SEL_MAX_N_PREFETCH; i++) {
513 sel_buf->
data = NULL;
531 for (i = 0; i < SEL_MAX_N_PREFETCH; i++) {
532 sel_buf = prefetch_buf +
i;
548 sel_dequeue_prefetched_row(
582 data = sel_buf->
data;
590 sel_buf->
data =
static_cast<byte*
>(dfield_get_data(val));
636 ut_ad(pos < SEL_MAX_N_PREFETCH);
651 sel_col_prefetch_buf_alloc(column);
658 data =
static_cast<byte*
>(dfield_get_data(val));
669 sel_buf->
data = data;
678 static __attribute__((nonnull, warn_unused_result))
680 row_sel_build_prev_vers(
698 if (*old_vers_heap) {
705 rec, mtr, index, offsets, read_view, offset_heap,
706 *old_vers_heap, old_vers);
713 static __attribute__((nonnull))
715 row_sel_build_committed_vers_for_mysql(
730 if (prebuilt->old_vers_heap) {
738 rec, mtr, clust_index, offsets, offset_heap,
739 prebuilt->old_vers_heap, old_vers);
748 row_sel_test_end_conds(
784 row_sel_test_other_conds(
811 static __attribute__((nonnull, warn_unused_result))
813 row_sel_get_clust_rec(
832 ulint offsets_[REC_OFFS_NORMAL_SIZE];
833 ulint* offsets = offsets_;
834 rec_offs_init(offsets_);
838 offsets = rec_get_offsets(rec,
839 btr_pcur_get_btr_cur(&plan->pcur)->index,
840 offsets, ULINT_UNDEFINED, &heap);
844 index = dict_table_get_first_index(plan->table);
846 btr_pcur_open_with_no_init(index, plan->clust_ref, PAGE_CUR_LE,
850 clust_rec = btr_pcur_get_rec(&(plan->clust_pcur));
861 ut_a(node->read_view);
875 offsets = rec_get_offsets(clust_rec, index, offsets,
876 ULINT_UNDEFINED, &heap);
878 if (!node->read_view) {
898 0, btr_pcur_get_block(&plan->clust_pcur),
899 clust_rec, index, offsets,
900 static_cast<enum lock_mode>(node->row_lock_mode),
909 UNIV_MEM_INVALID(&err,
sizeof err);
923 err = row_sel_build_prev_vers(
924 node->read_view, index, clust_rec,
925 &offsets, &heap, &plan->old_vers_heap,
928 if (err != DB_SUCCESS) {
935 if (clust_rec == NULL) {
956 && !row_sel_sec_rec_is_for_clust_rec(rec, plan->index,
968 row_sel_fetch_columns(index, clust_rec, offsets,
970 *out_rec = clust_rec;
974 if (UNIV_LIKELY_NULL(heap)) {
990 const ulint* offsets,
1010 0, block, rec, index, offsets,
1011 static_cast<enum lock_mode>(mode), type, thr);
1014 0, block, rec, index, offsets,
1015 static_cast<enum lock_mode>(mode), type, thr);
1028 ibool search_latch_locked,
1038 ulint has_search_latch = 0;
1041 if (search_latch_locked) {
1042 has_search_latch = RW_S_LATCH;
1045 index = plan->
index;
1069 for (i = 0; i < n_fields; i++) {
1078 btr_pcur_open_with_no_init(index, plan->
tuple, plan->
mode,
1080 has_search_latch, mtr);
1086 &(plan->
pcur),
false, 0, mtr);
1104 row_sel_restore_pcur_pos(
1109 ibool equal_position;
1110 ulint relative_position;
1117 &(plan->
pcur), mtr);
1136 if (relative_position == BTR_PCUR_ON) {
1138 if (equal_position) {
1146 ut_ad(relative_position == BTR_PCUR_AFTER
1147 || relative_position == BTR_PCUR_AFTER_LAST_IN_TREE);
1169 if (relative_position == BTR_PCUR_BEFORE
1170 || relative_position == BTR_PCUR_BEFORE_FIRST_IN_TREE) {
1175 if (relative_position == BTR_PCUR_ON) {
1177 if (equal_position) {
1185 ut_ad(relative_position == BTR_PCUR_AFTER
1186 || relative_position == BTR_PCUR_AFTER_LAST_IN_TREE);
1211 row_sel_try_search_shortcut(
1216 ibool search_latch_locked,
1224 ulint offsets_[REC_OFFS_NORMAL_SIZE];
1225 ulint* offsets = offsets_;
1227 rec_offs_init(offsets_);
1229 index = plan->
index;
1234 #ifdef UNIV_SYNC_DEBUG
1235 if (search_latch_locked) {
1240 row_sel_open_pcur(plan, search_latch_locked, mtr);
1242 rec = btr_pcur_get_rec(&(plan->
pcur));
1257 return(SEL_EXHAUSTED);
1263 offsets = rec_get_offsets(rec, index, offsets, ULINT_UNDEFINED, &heap);
1281 ret = SEL_EXHAUSTED;
1290 row_sel_fetch_columns(index, rec, offsets,
1295 if (!row_sel_test_other_conds(plan)) {
1297 ret = SEL_EXHAUSTED;
1306 if (UNIV_LIKELY_NULL(heap)) {
1315 static __attribute__((nonnull, warn_unused_result))
1329 ibool search_latch_locked;
1330 ibool consistent_read;
1337 ibool cons_read_requires_clust_rec = FALSE;
1338 ulint cost_counter = 0;
1339 ibool cursor_just_opened;
1340 ibool must_go_to_next;
1341 ibool mtr_has_extra_clust_latch = FALSE;
1351 ulint offsets_[REC_OFFS_NORMAL_SIZE];
1352 ulint* offsets = offsets_;
1353 rec_offs_init(offsets_);
1355 ut_ad(thr->run_node == node);
1357 search_latch_locked = FALSE;
1359 if (node->read_view) {
1367 consistent_read = TRUE;
1369 consistent_read = FALSE;
1379 ut_ad(mtr_has_extra_clust_latch == FALSE);
1382 index = plan->
index;
1385 sel_dequeue_prefetched_row(plan);
1387 goto next_table_no_mtr;
1397 goto table_exhausted_no_mtr;
1407 if (!search_latch_locked) {
1410 search_latch_locked = TRUE;
1424 found_flag = row_sel_try_search_shortcut(node, plan,
1425 search_latch_locked,
1428 if (found_flag == SEL_FOUND) {
1432 }
else if (found_flag == SEL_EXHAUSTED) {
1434 goto table_exhausted;
1437 ut_ad(found_flag == SEL_RETRY);
1439 plan_reset_cursor(plan);
1445 if (search_latch_locked) {
1448 search_latch_locked = FALSE;
1455 row_sel_open_pcur(plan, search_latch_locked, &mtr);
1457 cursor_just_opened = TRUE;
1464 must_go_to_next = row_sel_restore_pcur_pos(plan, &mtr);
1466 cursor_just_opened = FALSE;
1468 if (must_go_to_next) {
1489 ut_ad(mtr_has_extra_clust_latch == FALSE);
1491 rec = btr_pcur_get_rec(&(plan->
pcur));
1495 if (!node->asc && cursor_just_opened
1504 if (!consistent_read) {
1517 offsets = rec_get_offsets(next_rec, index, offsets,
1518 ULINT_UNDEFINED, &heap);
1522 <= TRX_ISO_READ_COMMITTED) {
1534 err = sel_set_rec_lock(btr_pcur_get_block(&plan->
pcur),
1535 next_rec, index, offsets,
1536 node->row_lock_mode,
1548 goto lock_wait_or_error;
1566 if (!consistent_read) {
1577 offsets = rec_get_offsets(rec, index, offsets,
1578 ULINT_UNDEFINED, &heap);
1595 err = sel_set_rec_lock(btr_pcur_get_block(&plan->
pcur),
1596 rec, index, offsets,
1597 node->row_lock_mode, lock_type, thr);
1605 goto lock_wait_or_error;
1619 if (cost_counter > SEL_COST_LIMIT) {
1628 goto stop_for_a_while;
1644 goto table_exhausted;
1656 cons_read_requires_clust_rec = FALSE;
1657 offsets = rec_get_offsets(rec, index, offsets, ULINT_UNDEFINED, &heap);
1659 if (consistent_read) {
1668 err = row_sel_build_prev_vers(
1669 node->read_view, index, rec,
1673 if (err != DB_SUCCESS) {
1675 goto lock_wait_or_error;
1678 if (old_vers == NULL) {
1686 offsets = rec_get_offsets(
1687 rec, index, offsets,
1688 ULINT_UNDEFINED, &heap);
1699 row_sel_fetch_columns(
1700 index, rec, offsets,
1704 if (!row_sel_test_end_conds(plan)) {
1706 goto table_exhausted;
1716 cons_read_requires_clust_rec = TRUE;
1727 row_sel_fetch_columns(index, rec, offsets,
1738 }
else if (!row_sel_test_end_conds(plan)) {
1740 goto table_exhausted;
1744 && !cons_read_requires_clust_rec) {
1752 goto table_exhausted;
1766 err = row_sel_get_clust_rec(node, plan, rec, thr, &clust_rec,
1768 mtr_has_extra_clust_latch = TRUE;
1770 if (err != DB_SUCCESS) {
1772 goto lock_wait_or_error;
1780 if (clust_rec == NULL) {
1782 ut_ad(consistent_read);
1795 if (node->can_get_updated) {
1803 if (!row_sel_test_other_conds(plan)) {
1807 goto table_exhausted;
1835 sel_dequeue_prefetched_row(plan);
1841 ut_ad(!search_latch_locked);
1843 if (mtr_has_extra_clust_latch) {
1850 goto commit_mtr_for_a_while;
1861 goto table_exhausted;
1864 cursor_just_opened = FALSE;
1880 ut_ad(!search_latch_locked);
1889 mtr_has_extra_clust_latch = FALSE;
1895 if (node->fetch_table + 1 == node->n_tables) {
1899 if (node->is_aggregate) {
1912 node->fetch_table++;
1929 mtr_has_extra_clust_latch = FALSE;
1934 sel_dequeue_prefetched_row(plan);
1936 goto next_table_no_mtr;
1939 table_exhausted_no_mtr:
1940 if (node->fetch_table == 0) {
1943 if (node->is_aggregate && !node->aggregate_already_fetched) {
1945 node->aggregate_already_fetched = TRUE;
1959 node->fetch_table--;
1972 ut_ad(!search_latch_locked);
1979 #ifdef UNIV_SYNC_DEBUG
1980 ut_ad(sync_thread_levels_empty_except_dict());
1985 commit_mtr_for_a_while:
1992 ut_ad(!search_latch_locked);
1997 mtr_has_extra_clust_latch = FALSE;
1999 #ifdef UNIV_SYNC_DEBUG
2000 ut_ad(sync_thread_levels_empty_except_dict());
2009 ut_ad(!search_latch_locked);
2016 #ifdef UNIV_SYNC_DEBUG
2017 ut_ad(sync_thread_levels_empty_except_dict());
2021 if (search_latch_locked) {
2024 if (UNIV_LIKELY_NULL(heap)) {
2072 enum lock_mode i_lock_mode;
2075 i_lock_mode = LOCK_IX;
2077 i_lock_mode = LOCK_IS;
2082 table_node = static_cast<sym_node_t*>(
2086 0, table_node->
table, i_lock_mode,
2089 if (err != DB_SUCCESS) {
2120 dberr_t err = row_sel(node, thr);
2128 if (err != DB_SUCCESS) {
2188 "InnoDB: Error: fetch called on a closed cursor\n");
2216 fprintf(stderr,
"row_fetch_print: row %p\n", row);
2223 const dtype_t* type = dfield_get_type(dfield);
2225 fprintf(stderr,
" column %lu:\n", (ulong) i);
2235 fputs(
" <NULL>;\n", stderr);
2291 fputs(
" ::: ", stderr);
2329 const byte* key_ptr,
2333 byte* original_buf =
buf;
2334 const byte* original_key_ptr = key_ptr;
2339 ulint data_field_len;
2341 const byte* key_end;
2347 key_end = key_ptr + key_len;
2353 dfield = dtuple_get_nth_field(tuple, 0);
2354 field = dict_index_get_nth_field(index, 0);
2356 if (UNIV_UNLIKELY(dfield_get_type(dfield)->mtype == DATA_SYS)) {
2363 ut_a(key_len == DATA_ROW_ID_LEN);
2372 while (key_ptr < key_end) {
2374 ulint type = dfield_get_type(dfield)->mtype;
2380 if (!(dfield_get_type(dfield)->prtype & DATA_NOT_NULL)) {
2386 if (*key_ptr != 0) {
2395 if (type == DATA_BLOB) {
2410 data_len = key_ptr[data_offset]
2411 + 256 * key_ptr[data_offset + 1];
2412 data_field_len = data_offset + 2 + field->
prefix_len;
2432 data_field_len = data_offset + data_len;
2434 data_len = dfield_get_type(dfield)->len;
2435 data_field_len = data_offset + data_len;
2440 == DATA_MYSQL_TRUE_VARCHAR)
2441 && UNIV_LIKELY(type != DATA_INT)) {
2452 data_field_len += 2;
2457 if (UNIV_LIKELY(!is_null)) {
2458 ut_a(buf + data_len <= original_buf + buf_len);
2462 key_ptr + data_offset, data_len,
2467 key_ptr += data_field_len;
2469 if (UNIV_UNLIKELY(key_ptr > key_end)) {
2481 fputs(
" InnoDB: Warning: using a partial-field"
2482 " key prefix in search.\n"
2483 "InnoDB: ", stderr);
2485 fprintf(stderr,
". Last data field length %lu bytes,\n"
2486 "InnoDB: key ptr now exceeds"
2487 " key end by %lu bytes.\n"
2488 "InnoDB: Key value in the MySQL format:\n",
2489 (ulong) data_field_len,
2490 (ulong) (key_ptr - key_end));
2498 - (ulint) (key_ptr - key_end));
2508 DBUG_EXECUTE_IF(
"innodb_srch_key_buffer_full",
2509 ut_a(buf == (original_buf + buf_len)););
2511 ut_a(buf <= original_buf + buf_len);
2523 row_sel_store_row_id_to_prebuilt(
2526 const rec_t* index_rec,
2528 const ulint* offsets)
2534 ut_ad(rec_offs_validate(index_rec, index, offsets));
2536 data = rec_get_nth_field(
2540 if (UNIV_UNLIKELY(len != DATA_ROW_ID_LEN)) {
2542 "InnoDB: Error: Row id field is"
2543 " wrong length %lu in ", (ulong) len);
2545 fprintf(stderr,
"\n"
2546 "InnoDB: Field number %lu, record:\n",
2559 # define row_sel_field_store_in_mysql_format(dest,templ,idx,field,src,len) \
2560 row_sel_field_store_in_mysql_format_func(dest,templ,idx,field,src,len)
2563 # define row_sel_field_store_in_mysql_format(dest,templ,idx,field,src,len) \
2564 row_sel_field_store_in_mysql_format_func(dest,templ,src,len)
2570 static __attribute__((nonnull))
2572 row_sel_field_store_in_mysql_format_func(
2599 = dict_index_get_nth_field(index, field_no);
2602 ut_ad(len != UNIV_SQL_NULL);
2603 UNIV_MEM_ASSERT_RW(data, len);
2604 UNIV_MEM_ASSERT_W(dest, templ->mysql_col_len);
2605 UNIV_MEM_INVALID(dest, templ->mysql_col_len);
2607 switch (templ->type) {
2608 const byte* field_end;
2625 if (!templ->is_unsigned) {
2626 dest[len - 1] = (byte) (dest[len - 1] ^ 128);
2629 ut_ad(templ->mysql_col_len == len);
2635 field_end = dest + templ->mysql_col_len;
2637 if (templ->mysql_type == DATA_MYSQL_TRUE_VARCHAR) {
2643 dest, len, templ->mysql_length_bytes);
2646 memcpy(dest, data, len);
2657 ut_ad(templ->mbminlen <= templ->mbmaxlen);
2660 switch (templ->mbminlen) {
2670 if (UNIV_UNLIKELY(len & 1)) {
2674 if (pad < field_end) {
2692 memcpy(dest, data, len);
2694 ut_ad(templ->mysql_col_len >= len);
2695 ut_ad(templ->mbmaxlen >= templ->mbminlen);
2704 ut_ad(templ->mbmaxlen > templ->mbminlen
2705 || templ->mysql_col_len == len
2706 || (field_no == templ->icp_rec_field_no
2711 ut_ad(!templ->mbmaxlen
2712 || !(templ->mysql_col_len % templ->mbmaxlen));
2713 ut_ad(len * templ->mbmaxlen >= templ->mysql_col_len
2714 || (field_no == templ->icp_rec_field_no
2718 if (templ->mbminlen == 1 && templ->mbmaxlen != 1) {
2723 memset(dest + len, 0x20, templ->mysql_col_len - len);
2729 case DATA_SYS_CHILD:
2735 case DATA_FIXBINARY:
2743 : templ->mysql_col_len == len);
2744 memcpy(dest, data, len);
2750 # define row_sel_store_mysql_field(m,p,r,i,o,f,t) \
2751 row_sel_store_mysql_field_func(m,p,r,i,o,f,t)
2754 # define row_sel_store_mysql_field(m,p,r,i,o,f,t) \
2755 row_sel_store_mysql_field_func(m,p,r,o,f,t)
2759 static __attribute__((warn_unused_result))
2761 row_sel_store_mysql_field_func(
2782 ut_ad(prebuilt->default_rec);
2784 ut_ad(templ >= prebuilt->mysql_template);
2785 ut_ad(templ < &prebuilt->mysql_template[prebuilt->n_template]);
2786 ut_ad(field_no == templ->clust_rec_field_no
2787 || field_no == templ->rec_field_no
2788 || field_no == templ->icp_rec_field_no);
2789 ut_ad(rec_offs_validate(rec, index, offsets));
2796 ut_a(!prebuilt->trx->has_search_latch);
2797 ut_ad(field_no == templ->clust_rec_field_no);
2799 if (UNIV_UNLIKELY(templ->type == DATA_BLOB)) {
2800 if (prebuilt->blob_heap == NULL) {
2805 heap = prebuilt->blob_heap;
2817 field_no, &len, heap);
2819 if (UNIV_UNLIKELY(!data)) {
2825 if (heap != prebuilt->blob_heap) {
2829 ut_a(prebuilt->trx->isolation_level
2830 == TRX_ISO_READ_UNCOMMITTED);
2834 ut_a(len != UNIV_SQL_NULL);
2836 row_sel_field_store_in_mysql_format(
2837 mysql_rec + templ->mysql_col_offset,
2838 templ, index, field_no, data, len);
2840 if (heap != prebuilt->blob_heap) {
2846 data = rec_get_nth_field(rec, offsets, field_no, &len);
2848 if (len == UNIV_SQL_NULL) {
2851 ut_ad(templ->mysql_null_bit_mask);
2853 UNIV_MEM_ASSERT_RW(prebuilt->default_rec
2854 + templ->mysql_col_offset,
2855 templ->mysql_col_len);
2856 mysql_rec[templ->mysql_null_byte_offset]
2857 |= (byte) templ->mysql_null_bit_mask;
2858 memcpy(mysql_rec + templ->mysql_col_offset,
2859 (
const byte*) prebuilt->default_rec
2860 + templ->mysql_col_offset,
2861 templ->mysql_col_len);
2865 if (UNIV_UNLIKELY(templ->type == DATA_BLOB)) {
2877 if (prebuilt->blob_heap == NULL) {
2882 data =
static_cast<byte*
>(
2886 row_sel_field_store_in_mysql_format(
2887 mysql_rec + templ->mysql_col_offset,
2888 templ, index, field_no, data, len);
2891 ut_ad(len != UNIV_SQL_NULL);
2893 if (templ->mysql_null_bit_mask) {
2896 mysql_rec[templ->mysql_null_byte_offset]
2897 &= ~(byte) templ->mysql_null_bit_mask;
2909 static __attribute__((warn_unused_result))
2911 row_sel_store_mysql_rec(
2923 const ulint* offsets)
2928 ut_ad(rec_clust || index == prebuilt->index);
2931 if (UNIV_LIKELY_NULL(prebuilt->blob_heap)) {
2933 prebuilt->blob_heap = NULL;
2936 for (i = 0; i < prebuilt->n_template; i++) {
2938 const ulint field_no
2944 ut_ad(dict_index_get_nth_field(index, field_no)->prefix_len
2947 if (!row_sel_store_mysql_field(mysql_rec, prebuilt,
2948 rec, index, offsets,
2962 prebuilt->table, rec, NULL);
2971 static __attribute__((nonnull, warn_unused_result))
2973 row_sel_build_prev_vers_for_mysql(
2991 if (prebuilt->old_vers_heap) {
2998 rec, mtr, clust_index, offsets, read_view, offset_heap,
2999 prebuilt->old_vers_heap, old_vers);
3008 static __attribute__((nonnull, warn_unused_result))
3010 row_sel_get_clust_rec_for_mysql(
3019 const rec_t** out_rec,
3034 const rec_t* clust_rec;
3043 sec_index, *offsets, trx);
3045 clust_index = dict_table_get_first_index(sec_index->table);
3047 btr_pcur_open_with_no_init(clust_index, prebuilt->clust_ref,
3049 &prebuilt->clust_pcur, 0, mtr);
3051 clust_rec = btr_pcur_get_rec(&prebuilt->clust_pcur);
3053 prebuilt->clust_pcur.trx_if_known =
trx;
3073 || prebuilt->select_lock_type != LOCK_NONE) {
3075 fputs(
" InnoDB: error clustered record"
3076 " for sec rec not found\n"
3077 "InnoDB: ", stderr);
3080 "InnoDB: sec index record ", stderr);
3083 "InnoDB: clust index record ", stderr);
3084 rec_print(stderr, clust_rec, clust_index);
3088 "InnoDB: Submit a detailed bug report"
3089 " to http://bugs.mysql.com\n", stderr);
3099 *offsets = rec_get_offsets(clust_rec, clust_index, *offsets,
3100 ULINT_UNDEFINED, offset_heap);
3102 if (prebuilt->select_lock_type != LOCK_NONE) {
3108 0, btr_pcur_get_block(&prebuilt->clust_pcur),
3109 clust_rec, clust_index, *offsets,
3110 static_cast<enum lock_mode>(prebuilt->select_lock_type),
3132 clust_rec, clust_index, *offsets,
3137 err = row_sel_build_prev_vers_for_mysql(
3139 clust_rec, offsets, offset_heap, &old_vers,
3142 if (err != DB_SUCCESS || old_vers == NULL) {
3168 && !row_sel_sec_rec_is_for_clust_rec(
3169 rec, sec_index, clust_rec, clust_index)) {
3171 #ifdef UNIV_SEARCH_DEBUG
3173 ut_a(clust_rec == NULL
3174 || row_sel_sec_rec_is_for_clust_rec(
3175 rec, sec_index, clust_rec, clust_index));
3183 *out_rec = clust_rec;
3187 if (prebuilt->select_lock_type != LOCK_NONE
3188 || prebuilt->innodb_api) {
3207 sel_restore_position_for_mysql(
3209 ibool* same_user_rec,
3223 ulint relative_position;
3225 relative_position = pcur->
rel_pos;
3227 success = btr_pcur_restore_position(latch_mode, pcur, mtr);
3229 *same_user_rec = success;
3231 if (relative_position == BTR_PCUR_ON) {
3243 if (relative_position == BTR_PCUR_AFTER
3244 || relative_position == BTR_PCUR_AFTER_LAST_IN_TREE) {
3257 ut_ad(relative_position == BTR_PCUR_BEFORE
3258 || relative_position == BTR_PCUR_BEFORE_FIRST_IN_TREE);
3271 row_sel_copy_cached_field_for_mysql(
3284 if (templ->
mysql_type == DATA_MYSQL_TRUE_VARCHAR
3285 && templ->
type != DATA_INT) {
3304 row_sel_dequeue_cached_row_for_mysql(
3312 const byte* cached_rec;
3326 row_sel_copy_cached_field_for_mysql(
3327 buf, cached_rec, templ);
3348 row_sel_copy_cached_field_for_mysql(
3367 row_sel_prefetch_cache_init(
3377 ptr =
static_cast<byte*
>(mem_alloc(sz));
3379 for (i = 0; i < UT_ARR_SIZE(prebuilt->
fetch_cache); i++) {
3401 row_sel_fetch_last_buf(
3412 row_sel_prefetch_cache_init(prebuilt);
3426 row_sel_enqueue_cache_row_for_mysql(
3435 byte* dest = row_sel_fetch_last_buf(prebuilt);
3451 row_sel_try_search_shortcut_for_mysql(
3453 const rec_t** out_rec,
3468 #ifndef UNIV_SEARCH_DEBUG
3469 btr_pcur_open_with_no_init(index, search_tuple, PAGE_CUR_GE,
3476 btr_pcur_open_with_no_init(index, search_tuple, PAGE_CUR_GE,
3481 rec = btr_pcur_get_rec(pcur);
3494 return(SEL_EXHAUSTED);
3500 *offsets = rec_get_offsets(rec, index, *offsets,
3501 ULINT_UNDEFINED, heap);
3511 return(SEL_EXHAUSTED);
3524 row_search_idx_cond_check(
3533 const ulint* offsets)
3535 enum icp_result result;
3538 ut_ad(rec_offs_validate(rec, prebuilt->
index, offsets));
3549 if (UNIV_LIKELY_NULL(prebuilt->
blob_heap)) {
3556 if (!row_sel_store_mysql_field(mysql_rec, prebuilt,
3557 rec, prebuilt->
index, offsets,
3560 return(ICP_NO_MATCH);
3578 if (!row_sel_store_mysql_rec(
3579 mysql_rec, prebuilt, rec, FALSE,
3580 prebuilt->
index, offsets)) {
3582 return(ICP_NO_MATCH);
3590 case ICP_OUT_OF_RANGE:
3637 const rec_t* result_rec = NULL;
3638 const rec_t* clust_rec;
3640 ibool unique_search = FALSE;
3641 ibool mtr_has_extra_clust_latch = FALSE;
3642 ibool moves_up = FALSE;
3643 ibool set_also_gap_locks = TRUE;
3646 ibool did_semi_consistent_read = FALSE;
3650 #ifdef UNIV_SEARCH_DEBUG
3654 ibool same_user_rec;
3657 ulint offsets_[REC_OFFS_NORMAL_SIZE];
3658 ulint* offsets = offsets_;
3659 ibool table_lock_waited = FALSE;
3662 rec_offs_init(offsets_);
3664 ut_ad(index && pcur && search_tuple);
3670 if (index->
type & DICT_FTS) {
3671 return(DB_END_OF_INDEX);
3674 #ifdef UNIV_SYNC_DEBUG
3684 return(DB_TABLESPACE_NOT_FOUND);
3694 }
else if (prebuilt->
magic_n != ROW_PREBUILT_ALLOCATED) {
3696 "InnoDB: Error: trying to free a corrupt\n"
3697 "InnoDB: table handle. Magic n %lu, table name ",
3719 fputs(
"InnoDB: Error: MySQL is trying to perform a SELECT\n"
3720 "InnoDB: but it has not locked"
3721 " any tables in ::external_lock()!\n",
3724 fputc(
'\n', stderr);
3729 fprintf(stderr,
"Match mode %lu\n search tuple ",
3730 (ulong) match_mode);
3732 fprintf(stderr,
"N tables locked %lu\n",
3762 if (UNIV_UNLIKELY(direction == 0)) {
3763 trx->
op_info =
"starting index read";
3774 trx->
op_info =
"fetching rows";
3794 row_sel_dequeue_cached_row_for_mysql(buf, prebuilt);
3809 err = DB_RECORD_NOT_FOUND;
3845 unique_search = TRUE;
3852 if (UNIV_UNLIKELY(direction != 0
3855 err = DB_RECORD_NOT_FOUND;
3871 if (UNIV_UNLIKELY(direction == 0)
3898 #ifndef UNIV_SEARCH_DEBUG
3904 switch (row_sel_try_search_shortcut_for_mysql(
3905 &rec, prebuilt, &offsets, &heap,
3908 #ifdef UNIV_SEARCH_DEBUG
3920 switch (row_search_idx_cond_check(
3924 case ICP_OUT_OF_RANGE:
3925 goto shortcut_mismatch;
3927 goto shortcut_match;
3931 if (!row_sel_store_mysql_rec(
3933 rec, FALSE, index, offsets)) {
3956 goto release_search_latch_if_needed;
3965 err = DB_RECORD_NOT_FOUND;
3966 release_search_latch_if_needed:
4007 || trx->
state == TRX_STATE_ACTIVE);
4013 trx_start_if_not_started(trx);
4022 set_also_gap_locks = FALSE;
4029 if (UNIV_UNLIKELY(direction == 0)) {
4030 if (mode == PAGE_CUR_GE || mode == PAGE_CUR_G) {
4041 clust_index = dict_table_get_first_index(index->
table);
4052 fputs(
"InnoDB: Error: MySQL is trying to"
4053 " perform a consistent read\n"
4054 "InnoDB: but the read view is not assigned!\n",
4057 fputc(
'\n', stderr);
4070 ? LOCK_IS : LOCK_IX, thr);
4072 if (err != DB_SUCCESS) {
4074 table_lock_waited = TRUE;
4075 goto lock_table_wait;
4082 if (UNIV_LIKELY(direction != 0)) {
4083 ibool need_to_process = sel_restore_position_for_mysql(
4085 pcur, moves_up, &mtr);
4087 if (UNIV_UNLIKELY(need_to_process)) {
4089 == ROW_READ_DID_SEMI_CONSISTENT)) {
4094 = ROW_READ_TRY_SEMI_CONSISTENT;
4097 != ROW_READ_DID_SEMI_CONSISTENT)) {
4110 btr_pcur_open_with_no_init(index, search_tuple, mode,
4116 rec = btr_pcur_get_rec(pcur);
4120 && set_also_gap_locks
4129 offsets = rec_get_offsets(next_rec, index, offsets,
4130 ULINT_UNDEFINED, &heap);
4131 err = sel_set_rec_lock(btr_pcur_get_block(pcur),
4132 next_rec, index, offsets,
4142 goto lock_wait_or_error;
4145 }
else if (mode == PAGE_CUR_G || mode == PAGE_CUR_L) {
4148 pcur,
false, 0, &mtr);
4152 DEBUG_SYNC_C(
"row_search_rec_loop");
4155 err = DB_INTERRUPTED;
4162 rec = btr_pcur_get_rec(pcur);
4164 #ifdef UNIV_SEARCH_DEBUG
4187 if (set_also_gap_locks
4199 offsets = rec_get_offsets(rec, index, offsets,
4200 ULINT_UNDEFINED, &heap);
4201 err = sel_set_rec_lock(btr_pcur_get_block(pcur),
4202 rec, index, offsets,
4212 goto lock_wait_or_error;
4227 if (UNIV_UNLIKELY(next_offs < PAGE_NEW_SUPREMUM)) {
4233 if (UNIV_UNLIKELY(next_offs < PAGE_OLD_SUPREMUM)) {
4239 if (UNIV_UNLIKELY(next_offs >= UNIV_PAGE_SIZE - PAGE_DIR)) {
4247 "\nInnoDB: rec address %p,"
4248 " buf block fix count %lu\n",
4249 (
void*) rec, (ulong)
4250 btr_cur_get_block(btr_pcur_get_btr_cur(pcur))
4251 ->
page.buf_fix_count);
4253 "InnoDB: Index corruption: rec offs %lu"
4254 " next offs %lu, page no %lu,\n"
4260 fputs(
". Run CHECK TABLE. You may need to\n"
4261 "InnoDB: restore from a backup, or"
4262 " dump + drop + reimport the table.\n",
4267 goto lock_wait_or_error;
4273 "InnoDB: Index corruption: rec offs %lu"
4274 " next offs %lu, page no %lu,\n"
4280 fputs(
". We try to skip the rest of the page.\n",
4295 offsets = rec_get_offsets(rec, index, offsets, ULINT_UNDEFINED, &heap);
4301 "InnoDB: Index corruption: rec offs %lu"
4302 " next offs %lu, page no %lu,\n"
4308 fputs(
". We try to skip the record.\n",
4328 if (set_also_gap_locks
4331 <= TRX_ISO_READ_COMMITTED)
4339 err = sel_set_rec_lock(
4340 btr_pcur_get_block(pcur),
4341 rec, index, offsets,
4350 goto lock_wait_or_error;
4356 err = DB_RECORD_NOT_FOUND;
4359 fputs(
" record not found 3\n", stderr);
4369 if (set_also_gap_locks
4372 <= TRX_ISO_READ_COMMITTED)
4380 err = sel_set_rec_lock(
4381 btr_pcur_get_block(pcur),
4382 rec, index, offsets,
4391 goto lock_wait_or_error;
4397 err = DB_RECORD_NOT_FOUND;
4400 fputs(
" record not found 4\n", stderr);
4423 if (!set_also_gap_locks
4444 if (index == clust_index
4445 && mode == PAGE_CUR_GE
4454 err = sel_set_rec_lock(btr_pcur_get_block(pcur),
4455 rec, index, offsets,
4464 <= TRX_ISO_READ_COMMITTED) {
4477 != ROW_READ_TRY_SEMI_CONSISTENT)
4479 || index != clust_index) {
4481 goto lock_wait_or_error;
4486 row_sel_build_committed_vers_for_mysql(
4487 clust_index, prebuilt, rec,
4488 &offsets, &heap, &old_vers, &mtr);
4502 offsets = rec_get_offsets(
4503 rec, index, offsets, ULINT_UNDEFINED,
4507 goto lock_wait_or_error;
4515 if (old_vers == NULL) {
4521 did_semi_consistent_read = TRUE;
4526 goto lock_wait_or_error;
4537 }
else if (index == clust_index) {
4551 err = row_sel_build_prev_vers_for_mysql(
4553 prebuilt, rec, &offsets, &heap,
4556 if (err != DB_SUCCESS) {
4558 goto lock_wait_or_error;
4561 if (old_vers == NULL) {
4586 switch (row_search_idx_cond_check(
4587 buf, prebuilt, rec, offsets)) {
4590 case ICP_OUT_OF_RANGE:
4591 err = DB_RECORD_NOT_FOUND;
4592 goto idx_cond_failed;
4594 goto requires_clust_rec;
4615 && !did_semi_consistent_read) {
4636 if (index == clust_index && unique_search
4639 err = DB_RECORD_NOT_FOUND;
4648 switch (row_search_idx_cond_check(buf, prebuilt, rec, offsets)) {
4650 if (did_semi_consistent_read) {
4654 case ICP_OUT_OF_RANGE:
4655 err = DB_RECORD_NOT_FOUND;
4656 goto idx_cond_failed;
4667 ut_ad(index != clust_index);
4672 ut_ad(rec_offs_validate(rec, index, offsets));
4677 mtr_has_extra_clust_latch = TRUE;
4683 err = row_sel_get_clust_rec_for_mysql(prebuilt, index, rec,
4685 &offsets, &heap, &mtr);
4688 if (clust_rec == NULL) {
4696 ut_a(clust_rec != NULL);
4699 <= TRX_ISO_READ_COMMITTED) {
4707 goto lock_wait_or_error;
4728 result_rec = clust_rec;
4729 ut_ad(rec_offs_validate(result_rec, clust_index, offsets));
4744 if (!row_sel_store_mysql_rec(
4745 buf, prebuilt, result_rec,
4746 TRUE, clust_index, offsets)) {
4757 ut_ad(rec_offs_validate(result_rec,
4758 result_rec != rec ? clust_index : index,
4774 != ROW_MYSQL_DUMMY_TEMPLATE
4808 ? row_sel_fetch_last_buf(prebuilt) : buf;
4810 if (!row_sel_store_mysql_rec(
4811 next_buf, prebuilt, result_rec,
4813 result_rec != rec ? clust_index : index,
4816 if (next_buf == buf) {
4831 if (next_buf != buf) {
4832 row_sel_enqueue_cache_row_for_mysql(
4833 next_buf, prebuilt);
4836 row_sel_enqueue_cache_row_for_mysql(buf, prebuilt);
4848 if (result_rec != rec
4852 offsets = rec_get_offsets(rec, index, offsets,
4858 memcpy(buf + 4, result_rec
4865 if (!row_sel_store_mysql_rec(
4866 buf, prebuilt, result_rec,
4868 result_rec != rec ? clust_index : index,
4883 row_sel_store_row_id_to_prebuilt(
4884 prebuilt, result_rec,
4885 result_rec == rec ? index : clust_index,
4923 == ROW_READ_DID_SEMI_CONSISTENT)) {
4926 did_semi_consistent_read = FALSE;
4944 if (UNIV_UNLIKELY(mtr_has_extra_clust_latch)) {
4953 mtr_has_extra_clust_latch = FALSE;
4956 if (sel_restore_position_for_mysql(&same_user_rec,
4958 pcur, moves_up, &mtr)) {
4959 #ifdef UNIV_SEARCH_DEBUG
4972 if (match_mode != 0) {
4973 err = DB_RECORD_NOT_FOUND;
4975 err = DB_END_OF_INDEX;
4986 #ifdef UNIV_SEARCH_DEBUG
4995 == ROW_READ_DID_SEMI_CONSISTENT)) {
4998 did_semi_consistent_read = FALSE;
5006 mtr_has_extra_clust_latch = FALSE;
5024 if (table_lock_waited) {
5025 table_lock_waited = FALSE;
5027 goto wait_table_again;
5030 sel_restore_position_for_mysql(&same_user_rec,
5036 && !same_user_rec) {
5064 #ifdef UNIV_SEARCH_DEBUG
5085 row_sel_dequeue_cached_row_for_mysql(buf, prebuilt);
5089 }
else if (next_buf != 0) {
5098 #ifdef UNIV_SEARCH_DEBUG
5106 if (UNIV_LIKELY_NULL(heap)) {
5114 || !did_semi_consistent_read);
5116 if (UNIV_UNLIKELY(prebuilt->
row_read_type != ROW_READ_WITH_LOCKS)) {
5117 if (UNIV_UNLIKELY(did_semi_consistent_read)) {
5124 #ifdef UNIV_SYNC_DEBUG
5128 DEBUG_SYNC_C(
"innodb_row_search_for_mysql_exit");
5142 const char* norm_name)
5165 if (table == NULL) {
5172 trx_start_if_not_started(trx);
5208 row_search_autoinc_read_column(
5214 ibool unsigned_type)
5220 ulint offsets_[REC_OFFS_NORMAL_SIZE];
5221 ulint* offsets = offsets_;
5223 rec_offs_init(offsets_);
5225 offsets = rec_get_offsets(rec, index, offsets, col_no + 1, &heap);
5233 data = rec_get_nth_field(rec, offsets, col_no, &len);
5237 ut_a(len <=
sizeof value);
5242 ut_a(len ==
sizeof(
float));
5247 ut_a(len ==
sizeof(
double));
5255 if (!unsigned_type && (ib_int64_t) value < 0) {
5260 if (UNIV_LIKELY_NULL(heap)) {
5272 row_search_autoinc_get_rec(
5278 const rec_t* rec = btr_pcur_get_rec(pcur);
5297 const char* col_name,
5308 for (i = 0; i < n_cols; ++
i) {
5309 dfield = dict_index_get_nth_field(index, i);
5311 if (strcmp(col_name, dfield->
name) == 0) {
5319 if (i < n_cols && dfield) {
5332 rec = row_search_autoinc_get_rec(&pcur, &mtr);
5335 ibool unsigned_type = (
5338 *value = row_search_autoinc_read_column(
5340 dfield->
col->
mtype, unsigned_type);
5348 error = DB_RECORD_NOT_FOUND;