26 #include "ha_ndbcluster_glue.h"
28 #ifdef WITH_NDBCLUSTER_STORAGE_ENGINE
30 #include "ha_ndbcluster.h"
31 #include "ha_ndbcluster_push.h"
32 #include "ha_ndbcluster_binlog.h"
33 #include "ha_ndbcluster_cond.h"
34 #include "abstract_query_plan.h"
36 #include <ndbapi/NdbApi.hpp>
37 #include <ndbapi/NdbInterpretedCode.hpp>
38 #include "../storage/ndb/src/ndbapi/NdbQueryBuilder.hpp"
39 #include "../storage/ndb/src/ndbapi/NdbQueryOperation.hpp"
41 #include <ndb_version.h>
43 #define EXPLAIN_NO_PUSH(msgfmt, ...) \
46 if (unlikely(current_thd->lex->describe & DESCRIBE_EXTENDED)) \
48 ndbcluster_explain_no_push ((msgfmt), __VA_ARGS__); \
54 static inline const char* get_referred_field_name(
const Item_field* field_item)
56 DBUG_ASSERT(field_item->type() == Item::FIELD_ITEM);
57 return field_item->field->field_name;
60 static const char* get_referred_table_access_name(
const Item_field* field_item)
62 DBUG_ASSERT(field_item->type() == Item::FIELD_ITEM);
63 return field_item->field->table->alias;
77 static void ndbcluster_explain_no_push(
const char* msgfmt, ...)
81 va_start(args,msgfmt);
82 (void) my_vsnprintf (wbuff,
sizeof(wbuff), msgfmt, args);
91 push_warning(current_thd, Sql_condition::WARN_LEVEL_NOTE, warn_code,
97 ndb_table_access_map::first_table(uint start)
const
99 for (uint table_no= start; table_no<length(); table_no++)
101 if (contain(table_no))
108 ndb_table_access_map::last_table(uint start)
const
110 uint table_no= start;
113 if (contain(table_no))
115 else if (table_no == 0)
121 ndb_pushed_join::ndb_pushed_join(
125 m_query_def(query_def),
126 m_operation_count(0),
127 m_field_count(builder.m_fld_refs)
129 DBUG_ASSERT(query_def != NULL);
130 DBUG_ASSERT(builder.m_fld_refs <= MAX_REFERRED_FIELDS);
132 for (uint tab_no= 0; !(searched==builder.m_join_scope); tab_no++)
135 if (builder.m_join_scope.contain(tab_no))
137 DBUG_ASSERT(m_operation_count < MAX_PUSHED_OPERATIONS);
138 m_tables[m_operation_count++] = join_tab->
get_table();
139 searched.add(tab_no);
142 for (uint
i= 0;
i < builder.m_fld_refs;
i++)
144 m_referred_fields[
i] = builder.m_referred_fields[
i];
148 ndb_pushed_join::~ndb_pushed_join()
151 m_query_def->destroy();
157 bool needSorted)
const
160 m_query_def->getQueryOperation((uint)0);
162 root_operation->getType();
164 if (def_type != type)
167 (
"Cannot execute push join. Root operation prepared as %s "
168 "not executable as %s",
169 NdbQueryOperationDef::getTypeName(def_type),
179 DBUG_ASSERT(idx!=NULL);
180 DBUG_ASSERT(idx->unique_index == expected_index);
184 DBUG_ASSERT(idx!=NULL);
186 if (idx->unique_index != expected_index)
188 DBUG_PRINT(
"info", (
"Actual index %s differs from expected index %s."
189 "Therefore, join cannot be pushed.",
197 DBUG_ASSERT (idx==NULL && expected_index==NULL);
201 (
"TableScan access can not be provied as sorted result. "
202 "Therefore, join cannot be pushed."));
208 DBUG_ASSERT(idx!=NULL);
210 if (idx->index != expected_index)
212 DBUG_PRINT(
"info", (
"Actual index %s differs from expected index %s. "
213 "Therefore, join cannot be pushed.",
221 (
"OrderedIndexScan with scan siblings "
222 "can not execute as pushed join."));
239 Field* field= m_referred_fields[
i];
240 if (field->is_real_null())
243 (
"paramValue is NULL, can not execute as pushed join"));
256 DBUG_ENTER(
"make_query_instance");
258 (
"executing chain of %d pushed joins."
259 " First table is %s, accessed as %s.",
262 NdbQueryOperationDef::getTypeName(
263 m_query_def->getQueryOperation((uint)0)->getType())
275 if (unlikely(outer_fields > 0))
280 for (uint
i= 0;
i < paramCnt;
i++)
287 for (uint
i= 0;
i < outer_fields;
i++)
289 Field* field= m_referred_fields[
i];
290 DBUG_ASSERT(!field->is_real_null());
293 paramValues= extendedParams;
297 if (unlikely(extendedParams != NULL))
299 for (uint
i = 0;
i < paramCnt + outer_fields;
i++)
301 extendedParams[
i].~NdbQueryParamValue();
303 my_afree(extendedParams);
319 const uint count= m_plan.get_access_count();
325 for (uint
i= 0;
i < count;
i++)
327 m_tables[
i].m_maybe_pushable= 0;
330 if (table->
get_table()->file->ht != ndbcluster_hton)
332 EXPLAIN_NO_PUSH(
"Table '%s' not in ndb engine, not pushable",
344 EXPLAIN_NO_PUSH(
"Table '%s' was optimized away, or const'ified by optimizer",
349 EXPLAIN_NO_PUSH(
"Table '%s' is not pushable: %s",
355 EXPLAIN_NO_PUSH(
"Table '%s' is not pushable: "
356 "Access type was not chosen at 'prepare' time",
361 const char* reason= NULL;
365 if (handler->maybe_pushable_join(reason))
367 m_tables[
i].m_maybe_pushable= PUSHABLE_AS_CHILD | PUSHABLE_AS_PARENT;
371 EXPLAIN_NO_PUSH(
"Table '%s' is not pushable: %s",
378 m_tables[0].m_maybe_pushable &= ~PUSHABLE_AS_CHILD;
379 m_tables[count-1].m_maybe_pushable &= ~PUSHABLE_AS_PARENT;
382 for (uint
i= 0;
i < count;
i++)
385 uint external= table->
get_table()->tablenr;
388 m_remap[
i].to_external= external;
389 m_remap[external].to_internal=
i;
394 ndb_pushed_builder_ctx::~ndb_pushed_builder_ctx()
402 const NdbError& ndb_pushed_builder_ctx::getNdbError()
const
404 DBUG_ASSERT(m_builder);
412 ndb_pushed_builder_ctx::get_table_no(
const Item* key_item)
const
414 DBUG_ASSERT(key_item->type() == Item::FIELD_ITEM);
415 table_map bitmap= key_item->used_tables();
417 for (uint
i= 0; i<MAX_TABLES && bitmap!=0; i++, bitmap>>=1)
421 DBUG_ASSERT(bitmap == 0x01);
422 return m_remap[
i].to_internal;
455 DBUG_ENTER(
"make_pushed_join");
458 if (is_pushable_with_root(join_root))
461 error= optimize_query_plan();
465 error= build_query();
469 const NdbQueryDef*
const query_def= m_builder->prepare();
470 if (unlikely(query_def == NULL))
474 if (unlikely (pushed_join == NULL))
475 DBUG_RETURN(HA_ERR_OUT_OF_MEM);
477 DBUG_PRINT(
"info", (
"Created pushed join with %d child operations",
492 DBUG_ENTER(
"is_pushable_with_root");
495 if ((m_tables[root_no].m_maybe_pushable & PUSHABLE_AS_PARENT) != PUSHABLE_AS_PARENT)
497 DBUG_PRINT(
"info", (
"Table %d already reported 'not pushable_as_parent'", root_no));
506 EXPLAIN_NO_PUSH(
"Table '%s' is not pushable, "
507 "access type 'MULTI_UNIQUE_KEY' not implemented",
509 m_tables[root_no].m_maybe_pushable &= ~PUSHABLE_AS_PARENT;
517 DBUG_PRINT(
"info", (
"Table %d is pushable as root", root->
get_access_no()));
521 m_const_scope.set_prefix(root_no);
528 if (is_pushable_as_child(table))
533 DBUG_RETURN(push_cnt>0);
557 ndb_pushed_builder_ctx::is_pushable_as_child(
560 DBUG_ENTER(
"is_pushable_as_child");
564 DBUG_ASSERT(tab_no > root_no);
566 if ((m_tables[tab_no].m_maybe_pushable & PUSHABLE_AS_CHILD) != PUSHABLE_AS_CHILD)
568 DBUG_PRINT(
"info", (
"Table %s already known 'not is_pushable_as_child'", table->
get_table()->alias));
575 if (!(ndbcluster_is_lookup_operation(access_type) ||
578 EXPLAIN_NO_PUSH(
"Can't push table '%s' as child, 'type' must be a 'ref' access",
580 m_tables[tab_no].m_maybe_pushable &= ~PUSHABLE_AS_CHILD;
586 ndbcluster_is_lookup_operation(root_type))
588 EXPLAIN_NO_PUSH(
"Push of table '%s' as scan-child "
589 "with lookup-root '%s' not implemented",
599 EXPLAIN_NO_PUSH(
"Push of table '%s' as scan-child "
600 "with ordered indexscan-root '%s' not implemented",
608 EXPLAIN_NO_PUSH(
"Can't push table '%s' as child, "
609 "to many ref'ed parent fields",
611 m_tables[tab_no].m_maybe_pushable &= ~PUSHABLE_AS_CHILD;
615 for (uint
i = tab_no - 1;
i >= root_no &&
i < ~uint(0);
620 EXPLAIN_NO_PUSH(
"Cannot push table '%s' as child of table '%s'. Doing so "
621 "would prevent using join buffer for table '%s'.",
629 DBUG_PRINT(
"info", (
"Table:%d, Checking %d REF keys", tab_no,
655 for (uint key_part_no= 0;
662 if (key_item->const_item())
664 DBUG_PRINT(
"info", (
" Item type:%d is 'const_item'", key_item->type()));
665 if (!is_const_item_pushable(key_item, key_part))
670 else if (key_item->type() == Item::FIELD_ITEM)
677 if (!is_field_item_pushable(table, key_item, key_part, field_parents))
682 if (key_item->type() == Item::FIELD_ITEM)
684 uint referred_table_no= get_table_no(key_item);
685 current_parents.add(referred_table_no);
692 common_parents.intersect(field_parents);
702 extend_parents.add(field_parents);
704 const uint first= field_parents.first_table(root_no);
705 depend_parents.add(first);
709 EXPLAIN_NO_PUSH(
"Can't push table '%s' as child, "
710 "column '%s' does neither 'ref' a column nor a constant",
712 key_part->field->field_name);
713 m_tables[tab_no].m_maybe_pushable &= ~PUSHABLE_AS_CHILD;
718 if (m_const_scope.contain(current_parents))
723 EXPLAIN_NO_PUSH(
"Can't push table '%s' as child of '%s', "
724 "their dependency is 'const'",
729 else if (extend_parents.is_clear_all())
731 EXPLAIN_NO_PUSH(
"Can't push table '%s' as child of '%s', "
732 "no parents found within scope",
769 EXPLAIN_NO_PUSH(
"Can't push table '%s' as child of '%s', "
770 "outer join of scan-child not implemented",
782 grandparents.clear_bit(root_no);
783 uint ancestor_no= root_no+1;
784 while (!grandparents.is_clear_all())
786 if (grandparents.contain(ancestor_no))
788 grandparents.clear_bit(ancestor_no);
789 if (grandparents.is_clear_all())
795 if (ancestor->
get_join_type(m_join_root) == AQP::JT_OUTER_JOIN)
797 EXPLAIN_NO_PUSH(
"Can't push table '%s' as child of '%s', "
798 "dependencies on outer joined grandparents not implemented",
807 DBUG_ASSERT(m_join_scope.contain(common_parents));
808 DBUG_ASSERT(m_join_scope.contain(extend_parents));
809 DBUG_ASSERT(extend_parents.is_clear_all() ||
810 extend_parents.contain(common_parents));
814 m_tables[tab_no].m_common_parents= common_parents;
815 m_tables[tab_no].m_extend_parents= extend_parents;
816 m_tables[tab_no].m_depend_parents= depend_parents;
819 m_tables[tab_no].m_maybe_pushable= 0;
820 m_join_scope.add(tab_no);
840 bool ndb_pushed_builder_ctx::is_field_item_pushable(
842 const Item* key_item,
846 DBUG_ENTER(
"is_field_item_pushable()");
848 DBUG_ASSERT(key_item->type() == Item::FIELD_ITEM);
853 DBUG_PRINT(
"info", (
"keyPart:%d, field:%s.%s",
855 key_item_field->field->table->alias,
856 key_item_field->field->field_name));
858 if (!key_item_field->field->eq_def(key_part->field))
860 EXPLAIN_NO_PUSH(
"Can't push table '%s' as child, "
861 "column '%s' does not have same datatype as ref'ed "
864 key_part->field->field_name,
865 key_item_field->field->table->alias,
866 key_item_field->field->field_name);
867 m_tables[tab_no].m_maybe_pushable &= ~PUSHABLE_AS_CHILD;
886 field_parents.clear_all();
891 uint referred_table_no= get_table_no(key_item_field);
892 if (m_join_scope.contain(referred_table_no))
894 field_parents.add(referred_table_no);
906 while ((substitute_field= equal_iter.
next()) != NULL)
908 if (substitute_field != key_item_field)
910 const uint substitute_table_no= get_table_no(substitute_field);
911 if (m_join_scope.contain(substitute_table_no))
914 (
" join_items[%d] %s.%s can be replaced with %s.%s",
916 get_referred_table_access_name(key_item_field),
917 get_referred_field_name(key_item_field),
918 get_referred_table_access_name(substitute_field),
919 get_referred_field_name(substitute_field)));
921 field_parents.add(substitute_table_no);
926 if (!field_parents.is_clear_all())
931 if (m_const_scope.contain(referred_table_no))
935 DBUG_ASSERT(field_parents.is_clear_all());
942 const TABLE*
const referred_tab = key_item_field->field->table;
943 uint access_no = tab_no;
946 DBUG_ASSERT(access_no > 0);
950 EXPLAIN_NO_PUSH(
"Cannot push table '%s' as child of '%s', since "
951 "it referes to column '%s.%s' which will be stored "
955 get_referred_table_access_name(key_item_field),
956 get_referred_field_name(key_item_field));
968 EXPLAIN_NO_PUSH(
"Can't push table '%s' as child of '%s', "
969 "column '%s.%s' is outside scope of pushable join",
971 get_referred_table_access_name(key_item_field),
972 get_referred_field_name(key_item_field));
978 bool ndb_pushed_builder_ctx::is_const_item_pushable(
979 const Item* key_item,
982 DBUG_ENTER(
"is_const_item_pushable()");
983 DBUG_ASSERT(key_item->const_item());
989 Field*
const field= key_part->field;
991 const_cast<Item*
>(key_item)->save_in_field_no_warnings(field,
true);
994 DBUG_PRINT(
"info", (
"Failed to store constant Item into Field -> not"
998 if (field->is_real_null())
1000 DBUG_PRINT(
"info", (
"NULL constValues in key -> not pushable"));
1008 ndb_pushed_builder_ctx::optimize_query_plan()
1010 DBUG_ENTER(
"optimize_query_plan");
1018 struct pushed_tables &table= m_tables[tab_no];
1019 if (!m_join_scope.contain(tab_no))
1028 if (!table.m_depend_parents.is_clear_all())
1031 DBUG_ASSERT(!dependency.contain(tab_no));
1033 uint depends_on_parent= dependency.last_table(tab_no-1);
1035 dependency_mask.set_prefix(depends_on_parent);
1037 if (table.m_extend_parents.is_overlapping(dependency_mask))
1039 table.m_extend_parents.subtract(dependency_mask);
1040 DBUG_ASSERT(table.m_extend_parents.contain(depends_on_parent) ||
1042 table.m_extend_parents.add(depends_on_parent);
1044 if (table.m_common_parents.is_overlapping(dependency_mask))
1046 table.m_common_parents.clear_all();
1056 table.m_common_parents.is_clear_all()
1057 ? table.m_extend_parents
1058 : table.m_common_parents;
1060 DBUG_ASSERT(!parents.is_clear_all());
1061 DBUG_ASSERT(!parents.contain(tab_no));
1068 parent_no= parents.first_table(root_no);
1069 DBUG_ASSERT(parent_no < tab_no);
1070 table.m_parent= parent_no;
1073 dependency.clear_bit(parent_no);
1074 m_tables[parent_no].m_depend_parents.add(dependency);
1078 for (uint tab_no= root_no+1;
1082 if (m_join_scope.contain(tab_no))
1084 struct pushed_tables &table= m_tables[tab_no];
1085 const uint parent_no= table.m_parent;
1086 table.m_ancestors= m_tables[parent_no].m_ancestors;
1087 table.m_ancestors.add(parent_no);
1088 DBUG_ASSERT(table.m_ancestors.contain(table.m_depend_parents));
1096 ndb_pushed_builder_ctx::collect_key_refs(
1098 const Item* key_refs[])
const
1100 DBUG_ENTER(
"collect_key_refs");
1103 const uint parent_no= m_tables[tab_no].m_parent;
1106 DBUG_ASSERT(m_join_scope.contain(ancestors));
1107 DBUG_ASSERT(ancestors.contain(parent_no));
1114 for (uint key_part_no= 0;
1119 key_refs[key_part_no]= key_item;
1121 DBUG_ASSERT(key_item->const_item() || key_item->type()==Item::FIELD_ITEM);
1123 if (key_item->type() == Item::FIELD_ITEM)
1126 uint referred_table_no= get_table_no(join_item);
1129 if (referred_table_no != parent_no &&
1134 while ((substitute_field= iter.
next()) != NULL)
1139 const uint substitute_table_no= get_table_no(substitute_field);
1140 if (substitute_table_no == parent_no)
1143 (
" Replacing key_refs[%d] %s.%s with %s.%s (parent)",
1145 get_referred_table_access_name(join_item),
1146 get_referred_field_name(join_item),
1147 get_referred_table_access_name(substitute_field),
1148 get_referred_field_name(substitute_field)));
1150 referred_table_no= substitute_table_no;
1151 key_refs[key_part_no]= join_item= substitute_field;
1154 else if (ancestors.contain(substitute_table_no))
1156 DBUG_ASSERT(substitute_table_no <= parent_no);
1165 if (!ancestors.contain(referred_table_no) ||
1166 referred_table_no < substitute_table_no)
1169 (
" Replacing key_refs[%d] %s.%s with %s.%s (grandparent)",
1171 get_referred_table_access_name(join_item),
1172 get_referred_field_name(join_item),
1173 get_referred_table_access_name(substitute_field),
1174 get_referred_field_name(substitute_field)));
1176 referred_table_no= substitute_table_no;
1177 key_refs[key_part_no]= join_item= substitute_field;
1182 DBUG_ASSERT (referred_table_no == parent_no ||
1183 !m_join_scope.contain(referred_table_no) ||
1184 !m_tables[tab_no].m_common_parents.contain(parent_no));
1198 DBUG_ENTER(
"build_key");
1204 if (table == m_join_root)
1210 op_key[
i]= m_builder->paramValue();
1211 if (unlikely(op_key[
i] == NULL))
1222 DBUG_ASSERT(key_fields > 0 && key_fields <= key->user_defined_key_parts);
1229 ndbcluster_build_key_map(handler->m_table,
1235 for (uint ix = 0; ix < key_fields; ix++)
1242 collect_key_refs(table,join_items);
1245 for (uint
i= 0;
i < key_fields;
i++, key_part++)
1247 const Item*
const item= join_items[
i];
1248 op_key[map[
i]]= NULL;
1250 DBUG_ASSERT(item->const_item() == item->const_during_execution());
1251 if (item->const_item())
1257 Field*
const field= key_part->field;
1258 DBUG_ASSERT(!field->is_real_null());
1259 const uchar*
const ptr= (field->real_type() == MYSQL_TYPE_VARCHAR)
1263 op_key[map[
i]]= m_builder->constValue(ptr, field->data_length());
1267 DBUG_ASSERT(item->type() == Item::FIELD_ITEM);
1269 const uint referred_table_no= get_table_no(field_item);
1271 if (m_join_scope.contain(referred_table_no))
1276 DBUG_ASSERT(parent_op != NULL);
1279 op_key[map[
i]]= m_builder->linkedValue(parent_op,
1280 field_item->field_name);
1284 DBUG_ASSERT(m_const_scope.contain(referred_table_no));
1289 DBUG_PRINT(
"info", (
"Too many Field refs ( >= MAX_REFERRED_FIELDS) "
1293 m_referred_fields[m_fld_refs++]= field_item->field;
1294 op_key[map[
i]]= m_builder->paramValue();
1298 if (unlikely(op_key[map[
i]] == NULL))
1303 op_key[key_fields]= NULL;
1310 ndb_pushed_builder_ctx::build_query()
1312 DBUG_ENTER(
"build_query");
1314 DBUG_PRINT(
"enter", (
"Table %d as root is pushable", m_join_root->
get_access_no()));
1315 DBUG_EXECUTE(
"info", m_join_root->
dbug_print(););
1318 DBUG_ASSERT(m_join_scope.contain(root_no));
1320 if (m_builder == NULL)
1323 if (unlikely (m_builder==NULL))
1325 DBUG_RETURN(HA_ERR_OUT_OF_MEM);
1331 if (!m_join_scope.contain(tab_no))
1342 const int error= build_key(table, op_key);
1343 if (unlikely(error))
1348 if (handler->m_cond)
1351 if (handler->m_cond->generate_scan_filter(&
code, NULL) != 0)
1357 if (table != m_join_root)
1359 DBUG_ASSERT(m_tables[tab_no].m_parent!=
MAX_TABLES);
1360 const uint parent_no= m_tables[tab_no].m_parent;
1363 if (!m_tables[tab_no].m_common_parents.contain(parent_no))
1365 DBUG_ASSERT(m_tables[parent_no].m_op != NULL);
1366 options.
setParent(m_tables[parent_no].m_op);
1375 if (ndbcluster_is_lookup_operation(access_type))
1381 DBUG_PRINT(
"info", (
"Operation is 'primary-key-lookup'"));
1382 query_op= m_builder->readTuple(handler->m_table, op_key, &options);
1387 DBUG_PRINT(
"info", (
"Operation is 'unique-index-lookup'"));
1389 = handler->m_index[table->
get_index_no()].unique_index;
1391 query_op= m_builder->readTuple(index, handler->m_table, op_key, &options);
1405 DBUG_ASSERT(handler->m_index[table->
get_index_no()].index != NULL);
1407 DBUG_PRINT(
"info", (
"Operation is 'equal-range-lookup'"));
1408 DBUG_PRINT(
"info", (
"Creating scanIndex on index id:%d, name:%s",
1414 query_op= m_builder->scanIndex(handler->m_index[table->
get_index_no()].index,
1415 handler->m_table, &bounds, &options);
1419 DBUG_PRINT(
"info", (
"Operation is 'table scan'"));
1420 query_op= m_builder->scanTable(handler->m_table, &options);
1427 if (unlikely(!query_op))
1430 m_tables[tab_no].m_op= query_op;
1448 if (index.unique_index_attrid_map)
1452 ix_map[ix]= index.unique_index_attrid_map[ix];
1460 assert (index.type == PRIMARY_KEY_ORDERED_INDEX || index.type == PRIMARY_KEY_INDEX);
1462 for (ix = 0, key_part= key_def->key_part; ix < key_def->user_defined_key_parts; ix++, key_part++)
1468 if (key_part->fieldnr < columnnr)
1476 while (columnnr < key_part->fieldnr-1)
1483 ix_map[ix]= key_pos;
1491 #endif // WITH_NDBCLUSTER_STORAGE_ENGINE