diff options
author | Evgeny Potemkin <epotemkin@mysql.com> | 2010-08-14 13:11:33 +0400 |
---|---|---|
committer | Evgeny Potemkin <epotemkin@mysql.com> | 2010-08-14 13:11:33 +0400 |
commit | 827a89996a06255b471ae9f24d3f3d3cbf9f99fd (patch) | |
tree | e62f523aa32ed6704ce025ceef21724a2e6c29a3 | |
parent | 0058f16d933d6de41e670348080ce625d8109b47 (diff) | |
download | mariadb-git-827a89996a06255b471ae9f24d3f3d3cbf9f99fd.tar.gz |
Bug#49746: Const expression caching led to NDB not using engine condition
pushdown.
NDB supports only a limited set of item nodes for use in engine condition
pushdown. Because of this adding cache for const expression effectively
disabled this optimization.
The ndb_serialize_cond function is extended to support Item_cache and treat
it as a constant values.
A helper function called ndb_serialize_const is added. It is used to create
Ndb_cond value node from given const item.
mysql-test/suite/ndb/t/disabled.def:
Bug#49746: Const expression caching led to NDB not using engine condition
pushdown.
Enabled ndb_condition_pushdown test after fixing appropriate bug.
sql/ha_ndbcluster_cond.cc:
Bug#49746: Const expression caching led to NDB not using engine condition
pushdown.
The ndb_serialize_cond function is extended to support Item_cache and treat
it as a constant values.
A helper function called ndb_serialize_const is added. It is used to create
Ndb_cond value node from given const item.
sql/item.cc:
Bug#49746: Const expression caching led to NDB not using engine condition
pushdown.
The Item::cache_const_expr_analyzer function is adjusted to not create
cache for Item_int_with_ref objects.
sql/item.h:
Bug#49746: Const expression caching led to NDB not using engine condition
pushdown.
The result_type() method is added to Item_cache class.
The Item_cache_str now initializes its collation.
-rw-r--r-- | mysql-test/suite/ndb/t/disabled.def | 1 | ||||
-rw-r--r-- | sql/ha_ndbcluster_cond.cc | 227 | ||||
-rw-r--r-- | sql/item.cc | 3 | ||||
-rw-r--r-- | sql/item.h | 10 |
4 files changed, 135 insertions, 106 deletions
diff --git a/mysql-test/suite/ndb/t/disabled.def b/mysql-test/suite/ndb/t/disabled.def index d38f60d6a54..c3c046e7ece 100644 --- a/mysql-test/suite/ndb/t/disabled.def +++ b/mysql-test/suite/ndb/t/disabled.def @@ -11,7 +11,6 @@ ############################################################################## ndb_binlog_discover : Bug#54851 2010-07-02 alik ndb.ndb_binlog_discover crashes the server -ndb_condition_pushdown : Bug#49746 2010-02-08 alik ndb_condition_pushdown fails in mysql-next-mr ndb_partition_error2 : Bug#40989 ndb_partition_error2 needs maintenance diff --git a/sql/ha_ndbcluster_cond.cc b/sql/ha_ndbcluster_cond.cc index 6df1f4881c3..8a96ae41453 100644 --- a/sql/ha_ndbcluster_cond.cc +++ b/sql/ha_ndbcluster_cond.cc @@ -35,6 +35,110 @@ typedef NdbDictionary::Column NDBCOL; typedef NdbDictionary::Table NDBTAB; + +/** + Serialize a constant item into a Ndb_cond node. + + @param const_type item's result type + @param item item to be serialized + @param curr_cond Ndb_cond node the item to be serialized into + @param context Traverse context +*/ + +static void ndb_serialize_const(Item_result const_type, const Item *item, + Ndb_cond *curr_cond, + Ndb_cond_traverse_context *context) +{ + DBUG_ASSERT(item->const_item()); + switch (const_type) { + case STRING_RESULT: + { + NDB_ITEM_QUALIFICATION q; + q.value_type= Item::STRING_ITEM; + curr_cond->ndb_item= new Ndb_item(NDB_VALUE, q, item); + if (! context->expecting_no_field_result()) + { + // We have not seen the field argument yet + context->expect_only(Item::FIELD_ITEM); + context->expect_only_field_result(STRING_RESULT); + context->expect_collation(item->collation.collation); + } + else + { + // Expect another logical expression + context->expect_only(Item::FUNC_ITEM); + context->expect(Item::COND_ITEM); + // Check that string result have correct collation + if (!context->expecting_collation(item->collation.collation)) + { + DBUG_PRINT("info", ("Found non-matching collation %s", + item->collation.collation->name)); + context->supported= FALSE; + } + } + break; + } + case REAL_RESULT: + { + NDB_ITEM_QUALIFICATION q; + q.value_type= Item::REAL_ITEM; + curr_cond->ndb_item= new Ndb_item(NDB_VALUE, q, item); + if (! context->expecting_no_field_result()) + { + // We have not seen the field argument yet + context->expect_only(Item::FIELD_ITEM); + context->expect_only_field_result(REAL_RESULT); + } + else + { + // Expect another logical expression + context->expect_only(Item::FUNC_ITEM); + context->expect(Item::COND_ITEM); + } + break; + } + case INT_RESULT: + { + NDB_ITEM_QUALIFICATION q; + q.value_type= Item::INT_ITEM; + curr_cond->ndb_item= new Ndb_item(NDB_VALUE, q, item); + if (! context->expecting_no_field_result()) + { + // We have not seen the field argument yet + context->expect_only(Item::FIELD_ITEM); + context->expect_only_field_result(INT_RESULT); + } + else + { + // Expect another logical expression + context->expect_only(Item::FUNC_ITEM); + context->expect(Item::COND_ITEM); + } + break; + } + case DECIMAL_RESULT: + { + NDB_ITEM_QUALIFICATION q; + q.value_type= Item::DECIMAL_ITEM; + curr_cond->ndb_item= new Ndb_item(NDB_VALUE, q, item); + if (! context->expecting_no_field_result()) + { + // We have not seen the field argument yet + context->expect_only(Item::FIELD_ITEM); + context->expect_only_field_result(DECIMAL_RESULT); + } + else + { + // Expect another logical expression + context->expect_only(Item::FUNC_ITEM); + context->expect(Item::COND_ITEM); + } + break; + } + default: + break; + } +} /* Serialize the item tree into a linked list represented by Ndb_cond for fast generation of NbdScanFilter. Adds information such as @@ -113,7 +217,7 @@ void ndb_serialize_cond(const Item *item, void *arg) to ndb_serialize_cond and end of rewrite statement is wrapped in end of ndb_serialize_cond */ - if (context->expecting(item->type())) + if (context->expecting(item->type()) || item->const_item()) { // This is the <field>|<const> item, save it in the rewrite context rewrite_context2->left_hand_item= item; @@ -597,108 +701,12 @@ void ndb_serialize_cond(const Item *item, void *arg) DBUG_PRINT("info", ("result type %d", func_item->result_type())); if (func_item->const_item()) { - switch (func_item->result_type()) { - case STRING_RESULT: - { - NDB_ITEM_QUALIFICATION q; - q.value_type= Item::STRING_ITEM; - curr_cond->ndb_item= new Ndb_item(NDB_VALUE, q, item); - if (! context->expecting_no_field_result()) - { - // We have not seen the field argument yet - context->expect_only(Item::FIELD_ITEM); - context->expect_only_field_result(STRING_RESULT); - context->expect_collation(func_item->collation.collation); - } - else - { - // Expect another logical expression - context->expect_only(Item::FUNC_ITEM); - context->expect(Item::COND_ITEM); - // Check that string result have correct collation - if (!context->expecting_collation(item->collation.collation)) - { - DBUG_PRINT("info", ("Found non-matching collation %s", - item->collation.collation->name)); - context->supported= FALSE; - } - } - // Skip any arguments since we will evaluate function instead - DBUG_PRINT("info", ("Skip until end of arguments marker")); - context->skip= func_item->argument_count(); - break; - } - case REAL_RESULT: - { - NDB_ITEM_QUALIFICATION q; - q.value_type= Item::REAL_ITEM; - curr_cond->ndb_item= new Ndb_item(NDB_VALUE, q, item); - if (! context->expecting_no_field_result()) - { - // We have not seen the field argument yet - context->expect_only(Item::FIELD_ITEM); - context->expect_only_field_result(REAL_RESULT); - } - else - { - // Expect another logical expression - context->expect_only(Item::FUNC_ITEM); - context->expect(Item::COND_ITEM); - } - - // Skip any arguments since we will evaluate function instead - DBUG_PRINT("info", ("Skip until end of arguments marker")); - context->skip= func_item->argument_count(); - break; - } - case INT_RESULT: - { - NDB_ITEM_QUALIFICATION q; - q.value_type= Item::INT_ITEM; - curr_cond->ndb_item= new Ndb_item(NDB_VALUE, q, item); - if (! context->expecting_no_field_result()) - { - // We have not seen the field argument yet - context->expect_only(Item::FIELD_ITEM); - context->expect_only_field_result(INT_RESULT); - } - else - { - // Expect another logical expression - context->expect_only(Item::FUNC_ITEM); - context->expect(Item::COND_ITEM); - } - - // Skip any arguments since we will evaluate function instead - DBUG_PRINT("info", ("Skip until end of arguments marker")); - context->skip= func_item->argument_count(); - break; - } - case DECIMAL_RESULT: - { - NDB_ITEM_QUALIFICATION q; - q.value_type= Item::DECIMAL_ITEM; - curr_cond->ndb_item= new Ndb_item(NDB_VALUE, q, item); - if (! context->expecting_no_field_result()) - { - // We have not seen the field argument yet - context->expect_only(Item::FIELD_ITEM); - context->expect_only_field_result(DECIMAL_RESULT); - } - else - { - // Expect another logical expression - context->expect_only(Item::FUNC_ITEM); - context->expect(Item::COND_ITEM); - } - // Skip any arguments since we will evaluate function instead - DBUG_PRINT("info", ("Skip until end of arguments marker")); - context->skip= func_item->argument_count(); - break; - } - default: - break; - } + ndb_serialize_const(func_item->result_type(), item, curr_cond, + context); + + // Skip any arguments since we will evaluate function instead + DBUG_PRINT("info", ("Skip until end of arguments marker")); + context->skip= func_item->argument_count(); } else // Function does not return constant expression @@ -883,6 +891,19 @@ void ndb_serialize_cond(const Item *item, void *arg) } break; } + case Item::CACHE_ITEM: + { + DBUG_PRINT("info", ("CACHE_ITEM")); + if (item->const_item()) + { + ndb_serialize_const(((Item_cache*)item)->result_type(), item, + curr_cond, context); + } + else + context->supported= FALSE; + + break; + } default: { DBUG_PRINT("info", ("Found item of type %d", item->type())); diff --git a/sql/item.cc b/sql/item.cc index 1decb5ec426..24f57342668 100644 --- a/sql/item.cc +++ b/sql/item.cc @@ -5931,7 +5931,8 @@ bool Item::cache_const_expr_analyzer(uchar **arg) a subselect (they use their own cache). */ if (const_item() && - !(item->basic_const_item() || item->type() == Item::FIELD_ITEM || + !(basic_const_item() || item->basic_const_item() || + item->type() == Item::FIELD_ITEM || item->type() == SUBSELECT_ITEM || /* Do not cache GET_USER_VAR() function as its const_item() may diff --git a/sql/item.h b/sql/item.h index c7a97ca716a..d1957c46d25 100644 --- a/sql/item.h +++ b/sql/item.h @@ -3266,6 +3266,12 @@ public: bool basic_const_item() const { return test(example && example->basic_const_item());} virtual void clear() { null_value= TRUE; value_cached= FALSE; } + Item_result result_type() const + { + if (!example) + return INT_RESULT; + return Field::result_merge_type(example->field_type()); + } }; @@ -3335,7 +3341,9 @@ public: is_varbinary(item->type() == FIELD_ITEM && cached_field_type == MYSQL_TYPE_VARCHAR && !((const Item_field *) item)->field->has_charset()) - {} + { + collation.set(const_cast<DTCollation&>(item->collation)); + } double val_real(); longlong val_int(); String* val_str(String *); |