29 #include "pars0opt.ic"
38 #include "pars0grm.hh"
43 #define OPT_COMPARISON 2
45 #define OPT_NOT_COND 1
46 #define OPT_END_COND 2
47 #define OPT_TEST_COND 3
48 #define OPT_SCROLL_COND 4
62 }
else if (op ==
'>') {
64 }
else if (op ==
'=') {
66 }
else if (op == PARS_LE_TOKEN) {
67 return(PARS_GE_TOKEN);
68 }
else if (op == PARS_GE_TOKEN) {
69 return(PARS_LE_TOKEN);
84 opt_check_exp_determined_before(
96 ut_ad(exp && sel_node);
101 arg = func_node->
args;
104 if (!opt_check_exp_determined_before(arg, sel_node,
124 for (i = 0; i < nth_table; i++) {
128 if (sym_node->
table == table) {
143 opt_look_for_col_in_comparison_before(
165 || (search_cond->
func ==
'>')
166 || (search_cond->
func ==
'=')
167 || (search_cond->
func == PARS_GE_TOKEN)
168 || (search_cond->
func == PARS_LE_TOKEN));
172 if ((cmp_type == OPT_EQUAL) && (search_cond->
func !=
'=')) {
176 }
else if ((cmp_type == OPT_COMPARISON)
177 && (search_cond->
func !=
'<')
178 && (search_cond->
func !=
'>')
179 && (search_cond->
func != PARS_GE_TOKEN)
180 && (search_cond->
func != PARS_LE_TOKEN)) {
185 arg = search_cond->
args;
191 && (sym_node->
table == table)
192 && (sym_node->
col_no == col_no)) {
201 if (opt_check_exp_determined_before(exp, sel_node,
203 *op = search_cond->
func;
210 exp = search_cond->
args;
217 && (sym_node->
table == table)
218 && (sym_node->
col_no == col_no)) {
220 if (opt_check_exp_determined_before(exp, sel_node,
222 *op = opt_invert_cmp_op(search_cond->
func);
240 opt_look_for_col_in_cond_before(
255 if (search_cond == NULL) {
261 ut_a(search_cond->
func != PARS_OR_TOKEN);
262 ut_a(search_cond->
func != PARS_NOT_TOKEN);
264 if (search_cond->
func == PARS_AND_TOKEN) {
267 exp = opt_look_for_col_in_cond_before(cmp_type, col_no,
277 exp = opt_look_for_col_in_cond_before(cmp_type, col_no,
283 exp = opt_look_for_col_in_comparison_before(cmp_type, col_no,
284 search_cond, sel_node,
295 if (sel_node->
asc && ((*op ==
'<') || (*op == PARS_LE_TOKEN))) {
299 }
else if (!sel_node->
asc
300 && ((*op ==
'>') || (*op == PARS_GE_TOKEN))) {
318 opt_calc_index_goodness(
323 que_node_t** index_plan,
344 for (j = 0; j < n_fields; j++) {
348 exp = opt_look_for_col_in_cond_before(
351 sel_node, nth_table, &op);
362 exp = opt_look_for_col_in_cond_before(
363 OPT_COMPARISON, col_no, static_cast<func_node_t *>(sel_node->
search_cond),
364 sel_node, nth_table, &op);
398 opt_calc_n_fields_from_goodness(
402 return(((goodness % 1024) + 2) / 4);
411 opt_op_to_search_mode(
423 }
else if (op ==
'<') {
426 }
else if (op ==
'>') {
429 }
else if (op == PARS_GE_TOKEN) {
432 }
else if (op == PARS_LE_TOKEN) {
449 que_node_t* arg_node,
454 arg = func_node->
args;
457 if (arg == arg_node) {
501 for (i = 0; i < sel_node->
n_tables; i++) {
505 if (i < sel_node->n_tables - 1) {
526 opt_search_plan_for_table(
537 ulint last_op = 75946965;
540 ulint best_last_op = 0;
541 que_node_t* index_plan[256];
542 que_node_t* best_index_plan[256];
547 plan->
asc = sel_node->
asc;
553 index = dict_table_get_first_index(table);
559 goodness = opt_calc_index_goodness(index, sel_node, i,
560 index_plan, &last_op);
561 if (goodness > best_goodness) {
564 best_goodness = goodness;
565 n_fields = opt_calc_n_fields_from_goodness(goodness);
568 n_fields *
sizeof(
void*));
569 best_last_op = last_op;
572 index = dict_table_get_next_index(index);
575 plan->
index = best_index;
577 n_fields = opt_calc_n_fields_from_goodness(best_goodness);
585 dict_index_copy_types(plan->
tuple, plan->
index, n_fields);
588 n_fields *
sizeof(
void*)));
591 n_fields *
sizeof(
void*));
592 if (best_last_op ==
'=') {
598 plan->
mode = opt_op_to_search_mode(sel_node->
asc,
624 opt_classify_comparison(
635 ut_ad(cond && sel_node);
642 if (!opt_check_exp_determined_before(cond, sel_node, i + 1)) {
644 return(OPT_NOT_COND);
647 if ((i > 0) && opt_check_exp_determined_before(cond, sel_node, i)) {
649 return(OPT_NOT_COND);
665 return(OPT_END_COND);
676 && opt_is_arg(plan->
tuple_exps[n_fields - 1], cond)) {
678 return(OPT_SCROLL_COND);
687 && opt_look_for_col_in_comparison_before(
691 cond, sel_node, i, &op)) {
693 if (sel_node->
asc && ((op ==
'<') || (op == PARS_LE_TOKEN))) {
695 return(OPT_END_COND);
698 if (!sel_node->
asc && ((op ==
'>') || (op == PARS_GE_TOKEN))) {
700 return(OPT_END_COND);
706 return(OPT_TEST_COND);
729 if (cond->
func == PARS_AND_TOKEN) {
732 opt_find_test_conds(sel_node, i, new_cond);
736 opt_find_test_conds(sel_node, i, new_cond);
743 func_class = opt_classify_comparison(sel_node, i, cond);
745 if (func_class == OPT_END_COND) {
748 }
else if (func_class == OPT_TEST_COND) {
760 opt_normalize_cmp_conds(
779 && (sym_node->
table == table)) {
788 cond->
func = opt_invert_cmp_op(cond->
func);
802 opt_determine_and_normalize_test_conds(
816 opt_find_test_conds(sel_node, i, static_cast<func_node_t *>(sel_node->
search_cond));
838 sym_node_list_t* col_list,
858 arg = func_node->
args;
891 if (col_node == sym_node) {
900 sym_node->
alias = col_node;
917 dict_table_get_first_index(index->
table), sym_node->
col_no);
922 col_pos = dict_index_get_nth_col_pos(index, sym_node->
col_no);
924 if (col_pos == ULINT_UNDEFINED) {
949 if (search_cond == NULL) {
956 if (search_cond->
func == PARS_AND_TOKEN) {
959 opt_find_copy_cols(sel_node, i, new_cond);
963 opt_find_copy_cols(sel_node, i, new_cond);
968 if (!opt_check_exp_determined_before(search_cond, sel_node, i + 1)) {
1016 opt_find_copy_cols(sel_node, i, static_cast<func_node_t *>(sel_node->
search_cond));
1046 index = plan->
index;
1060 table = index->
table;
1062 clust_index = dict_table_get_first_index(table);
1066 heap = pars_sym_tab_global->
heap;
1070 dict_index_copy_types(plan->
clust_ref, clust_index, n_fields);
1074 for (i = 0; i < n_fields; i++) {
1075 pos = dict_index_get_nth_field_pos(index, clust_index, i);
1077 ut_a(pos != ULINT_UNDEFINED);
1082 if (dict_index_get_nth_field(index, pos)->prefix_len != 0
1083 || dict_index_get_nth_field(clust_index, i)
1084 ->prefix_len != 0) {
1086 "InnoDB: Error in pars0opt.c:"
1087 " table %s has prefix_len != 0\n",
1093 ut_ad(pos != ULINT_UNDEFINED);
1122 sel_node->
asc = TRUE;
1126 sel_node->
asc = order_by->
asc;
1129 for (i = 0; i < sel_node->
n_tables; i++) {
1131 table = table_node->
table;
1135 opt_search_plan_for_table(sel_node, i, table);
1140 opt_determine_and_normalize_test_conds(sel_node, i);
1147 for (i = 0; i < sel_node->
n_tables; i++) {
1152 opt_classify_cols(sel_node, i);
1157 opt_clust_access(sel_node, i);
1165 opt_check_order_by(sel_node);
1167 #ifdef UNIV_SQL_DEBUG
1184 fputs(
"QUERY PLAN FOR A SELECT NODE\n", stderr);
1186 fputs(sel_node->
asc ?
"Asc. search; " :
"Desc. search; ", stderr);
1189 fputs(
"sets row x-locks; ", stderr);
1193 fputs(
"consistent read; ", stderr);
1196 fputs(
"sets row s-locks; ", stderr);
1201 for (i = 0; i < sel_node->
n_tables; i++) {
1210 fputs(
"Table ", stderr);
1211 dict_index_name_print(stderr, NULL, plan->
index);
1212 fprintf(stderr,
"; exact m. %lu, match %lu, end conds %lu\n",
1214 (
unsigned long) n_fields,