List:Commits« Previous MessageNext Message »
From:Magnus Blåudd Date:October 27 2010 9:15am
Subject:Re: bzr commit into mysql-5.1-telco-7.0-spj-scan-vs-scan branch (ole.john.aske:3323)
View as plain text  
On 10/26/2010 02:15 PM, Ole John Aske wrote:
> On 10/26/10 01:27 PM, Magnus Blåudd wrote:
>> Hi,
>>
>> good looks greate, just one question inline.
>>
>>
>> / Magnus
>>
>> On 10/26/2010 11:21 AM, Ole John Aske wrote:
>>> #At
>>>
> file:///net/fimafeng09/export/home/tmp/oleja/mysql/mysql-5.1-telco-7.0-spj-scan-scan/
>>> based on
>>> revid:ole.john.aske@stripped
>>>
>>> 3323 Ole John Aske 2010-10-26
>>> spj-svs: Added EXPLAIN EXTENDED functionality which add info as
>>> warnings about why (parts of) a query is not pushed:
>>>
>>> Usage:
>>> set ndb_join_pushdown = true
>>>
>>> EXPLAIN EXTENDED<query>;
>>> SHOW WARNINGS;
>>>
>>> modified:
>>> sql/ha_ndbcluster.cc
>>> sql/ha_ndbcluster.h
>>> sql/share/errmsg.txt
>>> === modified file 'sql/ha_ndbcluster.cc'
>>> --- a/sql/ha_ndbcluster.cc 2010-10-21 08:31:51 +0000
>>> +++ b/sql/ha_ndbcluster.cc 2010-10-26 09:21:10 +0000
>>> @@ -306,6 +306,14 @@ static int ndb_to_mysql_error(const NdbE
>>> code= ndb_to_mysql_error(&tmp); \
>>> }
>>>
>>> +#define EXPLAIN_NO_PUSH(msgfmt, ...) \
>>> +{ \
>>> + if (unlikely((current_thd->lex->describe& DESCRIBE_EXTENDED))) \
>>> + { \
>>> + explain_no_push ((msgfmt), __VA_ARGS__); \
>>> + } \
>>> +}
>>
>> magnus: reacted on this since using defines are not really
>> recommended. I suspect that you don't want to call a function
>> just to check the if and return?
>>
>> But, why not declare 'explain_no_push' as "static inline" the function
>> would be inlined, right?
>
> Yes, the function itself would have been inlined, but the arguments to
> explain_no_push() are
> functions themself and they would have been evaluated - Like in:
>
> + EXPLAIN_NO_PUSH("Can't push table %s as child of %s, implementation
> limitations for outer joins",
> + table->get_table()->alias, join_root()->get_table()->alias);
>
> This extra overhead is avoided by testing for DESCRIBE_EXTENDED before
> this function is called.

OK, I see.

>
>
> OJ
>
>>
>>
>> Plus, if trying to avoid "expensive calls", why use 'current_thd'
>> macro (yes it is) and not pass THD* as first argument
>> to the function?
>
>
>>
>>
>>> +
>>> static int ndbcluster_inited= 0;
>>> int ndbcluster_terminating= 0;
>>>
>>> @@ -455,11 +463,21 @@ public:
>>> class ndb_pushed_builder_ctx
>>> {
>>> public:
>>> - ndb_pushed_builder_ctx(AQP::Join_plan& plan, const
>>> AQP::Table_access* const join_root)
>>> - : m_plan(plan), m_join_root(join_root), m_join_scope(join_root),
>>> m_const_scope()
>>> +
>>> + ndb_pushed_builder_ctx(AQP::Join_plan& plan)
>>> + : m_plan(plan), m_join_root(), m_join_scope(), m_const_scope()
>>> + { init_pushability();
>>> + }
>>> +
>>> + void set_root(const AQP::Table_access* const join_root)
>>> {
>>> + m_join_root= join_root;
>>> + m_join_scope.clear_all();
>>> + m_const_scope.clear_all();
>>> +
>>> + m_join_scope.add(join_root);
>>> for (uint i= 0; i<join_root->get_access_no(); i++)
>>> - m_const_scope.add(plan.get_table_access(i));
>>> + m_const_scope.add(m_plan.get_table_access(i));
>>> }
>>>
>>> const AQP::Join_plan& plan() const
>>> @@ -488,7 +506,10 @@ public:
>>> const ndb_table_access_map& old_parents,
>>> ndb_table_access_map& parents) const;
>>>
>>> - bool field_ref_is_join_pushable(
>>> + bool is_pushable_as_parent(
>>> + const AQP::Table_access* table);
>>> +
>>> + bool is_pushable_as_child(
>>> const AQP::Table_access* table,
>>> const Item* join_items[],
>>> const AQP::Table_access*& parent);
>>> @@ -506,9 +527,18 @@ public:
>>> return
>>> parents.is_overlapping(m_tables[table->get_access_no()].m_ancestors);
>>> }
>>>
>>> + enum pushability
>>> + {
>>> + PUSHABLE_AS_PARENT= 0x01,
>>> + PUSHABLE_AS_CHILD= 0x02
>>> + } enum_pushability;
>>> +
>>> +private:
>>> + void init_pushability();
>>> +
>>> private:
>>> const AQP::Join_plan& m_plan;
>>> - const AQP::Table_access* const m_join_root;
>>> + const AQP::Table_access* m_join_root;
>>>
>>> // Scope of tables covered by this pushed join
>>> ndb_table_access_map m_join_scope;
>>> @@ -520,12 +550,14 @@ private:
>>> struct pushed_tables
>>> {
>>> pushed_tables() :
>>> + m_maybe_pushable(PUSHABLE_AS_CHILD | PUSHABLE_AS_PARENT),
>>> m_parent(MAX_TABLES),
>>> m_ancestors(),
>>> m_last_scan_descendant(MAX_TABLES),
>>> op(NULL)
>>> {}
>>>
>>> + int m_maybe_pushable;
>>> uint m_parent;
>>> ndb_table_access_map m_ancestors;
>>> uint m_last_scan_descendant;
>>> @@ -672,6 +704,17 @@ static bool is_lookup_operation(AQP::enu
>>> accessType == AQP::AT_UNIQUE_KEY);
>>> }
>>>
>>> +static void
>>> +explain_no_push(const char* msgfmt, ...)
>>> +{
>>> + va_list args;
>>> + char wbuff[1024];
>>> + va_start(args,msgfmt);
>>> + (void) my_vsnprintf (wbuff, sizeof(wbuff), msgfmt, args);
>>> + va_end(args);
>>> + push_warning(current_thd, MYSQL_ERROR::WARN_LEVEL_NOTE,
>>> WARN_QUERY_NOT_PUSHED, wbuff);
>>> +} // explain_no_push();
>>> +
>>> void
>>> ndb_pushed_builder_ctx::add_pushed(
>>> const AQP::Table_access* table,
>>> @@ -682,6 +725,7 @@ ndb_pushed_builder_ctx::add_pushed(
>>> DBUG_ASSERT(table_no< MAX_TABLES);
>>> m_join_scope.add(table);
>>> m_tables[table_no].op= query_op;
>>> + m_tables[table_no].m_maybe_pushable= 0; // Exclude from further
>>> pushing
>>> if (likely(parent))
>>> {
>>> uint parent_no= parent->get_access_no();
>>> @@ -775,9 +819,69 @@ ndb_pushed_builder_ctx::add_parent_candi
>>> }
>>> } // ndb_pushed_builder_ctx::add_parent_candidate
>>>
>>> +/**
>>> + * Set up the 'm_maybe_pushable' property of each table from the
>>> 'Abstract Query Plan' associated
>>> + * with this ndb_pushed_builder_ctx. A table may be possibly
>>> pushable as both:
>>> + * PUSHABLE_AS_CHILD and/or PUSHABLE_AS_PARENT.
>>> + * When a table is annotated as not PUSHABLE_AS_... it will be
>>> excluded from further
>>> + * pushability investigation for this specific table.
>>> + */
>>> +void
>>> +ndb_pushed_builder_ctx::init_pushability()
>>> +{
>>> + for (uint i= 0; i< m_plan.get_access_count(); i++)
>>> + {
>>> + m_tables[i].m_maybe_pushable= 0;
>>> +
>>> + const TABLE* const table= m_plan.get_table_access(i)->get_table();
>>> + if (table->file->ht != ndbcluster_hton)
>>> + {
>>> + m_tables[i].m_maybe_pushable= 0;
>>> + EXPLAIN_NO_PUSH("Table %s not in Cluster engine, not pushable",
>>> table->alias);
>>> + continue;
>>> + }
>>> + m_tables[i].m_maybe_pushable=
>>> static_cast<ha_ndbcluster*>(table->file)->get_pushability();
>>> + }
>>> +
>>> + m_tables[0].m_maybe_pushable&= ~PUSHABLE_AS_CHILD;
>>> + m_tables[m_plan.get_access_count()-1].m_maybe_pushable&=
>>> ~PUSHABLE_AS_PARENT;
>>> +} // ndb_pushed_builder_ctx::init_pushability()
>>> +
>>> +
>>> +bool
>>> +ndb_pushed_builder_ctx::is_pushable_as_parent(const
>>> AQP::Table_access* table)
>>> +{
>>> + DBUG_ENTER("::is_pushable_as_parent");
>>> + uint table_no = table->get_access_no();
>>> + if ((m_tables[table_no].m_maybe_pushable& PUSHABLE_AS_PARENT) !=
>>> PUSHABLE_AS_PARENT)
>>> + {
>>> + DBUG_PRINT("info", ("Table %d already reported 'not
>>> pushable_as_parent'", table_no));
>>> + DBUG_RETURN(false);
>>> + }
>>> +
>>> + const AQP::enum_access_type access_type= table->get_access_type();
>>> + DBUG_ASSERT(access_type != AQP::AT_VOID);
>>> +
>>> + if (access_type == AQP::AT_OTHER)
>>> + {
>>> + EXPLAIN_NO_PUSH("Table %s is not pushable, unknown access 'type'",
>>> table->get_table()->alias);
>>> + m_tables[table_no].m_maybe_pushable&= ~PUSHABLE_AS_PARENT;
>>> + DBUG_RETURN(false);
>>> + }
>>> + if (access_type == AQP::AT_MULTI_UNIQUE_KEY)
>>> + {
>>> + EXPLAIN_NO_PUSH("Table %s is not pushable, access type
>>> 'MULTI_UNIQUE_KEY' not implemented",
>>> + table->get_table()->alias);
>>> + m_tables[table_no].m_maybe_pushable&= ~PUSHABLE_AS_PARENT;
>>> + DBUG_RETURN(false);
>>> + }
>>> +
>>> + DBUG_RETURN(true);
>>> +} // ndb_pushed_builder_ctx::is_pushable_as_parent()
>>> +
>>>
>>> /***************************************************************
>>> - * field_ref_is_join_pushable()
>>> + * is_pushable_as_child()
>>> *
>>> * Determines if the specified child ('table') can be appended to
>>> * an existing chain of previously pushed join operations.
>>> @@ -796,21 +900,48 @@ ndb_pushed_builder_ctx::add_parent_candi
>>> * join_items[] .
>>> ****************************************************************/
>>> bool
>>> -ndb_pushed_builder_ctx::field_ref_is_join_pushable(
>>> +ndb_pushed_builder_ctx::is_pushable_as_child(
>>> const AQP::Table_access* table,
>>> const Item* join_items[ndb_pushed_join::MAX_LINKED_KEYS+1],
>>> const AQP::Table_access*& parent)
>>> {
>>> - DBUG_ENTER("field_ref_is_join_pushable");
>>> + DBUG_ENTER("is_pushable_as_child");
>>> uint tab_no = table->get_access_no();
>>> parent= NULL;
>>>
>>> DBUG_ASSERT (join_root()< table);
>>>
>>> + if ((m_tables[tab_no].m_maybe_pushable& PUSHABLE_AS_CHILD) !=
>>> PUSHABLE_AS_CHILD)
>>> + {
>>> + DBUG_PRINT("info", ("Table %s already known 'not
>>> is_pushable_as_child'", table->get_table()->alias));
>>> + DBUG_RETURN(false);
>>> + }
>>> +
>>> + AQP::enum_access_type access_type= table->get_access_type();
>>> + AQP::enum_access_type root_type= join_root()->get_access_type();
>>> +
>>> + if (!(is_lookup_operation(access_type) ||
>>> access_type==AQP::AT_ORDERED_INDEX_SCAN))
>>> + {
>>> + EXPLAIN_NO_PUSH("Can't push table %s as child, 'type' must be a REF
>>> access",
>>> + table->get_table()->alias);
>>> + m_tables[tab_no].m_maybe_pushable&= ~PUSHABLE_AS_CHILD;
>>> + DBUG_RETURN(false);
>>> + }
>>> +
>>> + // Currently there is a limitation in not allowing LOOKUP -
>>> (index)SCAN operations
>>> + if (is_lookup_operation(root_type)&&
>>> access_type==AQP::AT_ORDERED_INDEX_SCAN)
>>> + {
>>> + EXPLAIN_NO_PUSH("Push of table %s as scan-child with lookup-root %s
>>> not implemented",
>>> + table->get_table()->alias, join_root()->get_table()->alias);
>>> + // 'table' may still be PUSHABLE_AS_CHILD with another parent
>>> + DBUG_RETURN(false);
>>> + }
>>> +
>>> if (table->get_no_of_key_fields()> ndb_pushed_join::MAX_LINKED_KEYS)
>>> {
>>> - DBUG_PRINT("info", (" 'key_parts>=
>>> ndb_pushed_join::MAX_LINKED_KEYS', "
>>> - "can't append table:%d", tab_no+1));
>>> + EXPLAIN_NO_PUSH("Can't push table %s as child; to many #REF'ed
>>> parent fields",
>>> + table->get_table()->alias);
>>> + m_tables[tab_no].m_maybe_pushable&= ~PUSHABLE_AS_CHILD; //
>>> Permanently dissable
>>> DBUG_RETURN(false);
>>> }
>>>
>>> @@ -841,7 +972,7 @@ ndb_pushed_builder_ctx::field_ref_is_joi
>>> {
>>> DBUG_PRINT("info", (" Item type:%d not join_pushable -> can't append
>>> table:%d",
>>> key_item->type(), tab_no+1));
>>> - DBUG_RETURN(false);
>>> + DBUG_RETURN(false); // TODO, handle gracefull -> continue?
>>> }
>>>
>>> const Item_field* const key_item_field
>>> @@ -855,7 +986,7 @@ ndb_pushed_builder_ctx::field_ref_is_joi
>>> ->eq_def(table->get_key_part_info(key_part_no)->field))
>>> {
>>> DBUG_PRINT("info", ("Item_field does not have same definition as
>>> REF'ed key"));
>>> - DBUG_RETURN(false);
>>> + DBUG_RETURN(false); // TODO, handle gracefull -> continue?
>>> }
>>>
>>> /**
>>> @@ -956,26 +1087,37 @@ ndb_pushed_builder_ctx::field_ref_is_joi
>>> }
>>> else
>>> {
>>> - DBUG_PRINT("info", ("Item_field %s.%s is outside scope of pushable
>>> join",
>>> - get_referred_table_access_name(key_item_field),
>>> - get_referred_field_name(key_item_field)));
>>> + EXPLAIN_NO_PUSH("Can't push table %s as child of %s, "
>>> + "Item_field '%s.%s' is outside scope of pushable join",
>>> + table->get_table()->alias, join_root()->get_table()->alias,
>>> + get_referred_table_access_name(key_item_field),
>>> + get_referred_field_name(key_item_field));
>>> DBUG_RETURN(false);
>>> }
>>> } // for (uint key_part_no= 0 ...
>>>
>>> join_items[table->get_no_of_key_fields()]= NULL;
>>>
>>> - if (m_const_scope.contain(current_parents))
>>> + if (current_parents.is_clear_all())
>>> + {
>>> + EXPLAIN_NO_PUSH("Can't push table %s as child; no usable REF'ed
>>> parent FIELD_ITEMs",
>>> + table->get_table()->alias);
>>> + m_tables[tab_no].m_maybe_pushable&= ~PUSHABLE_AS_CHILD; //
>>> Permanently disable as child
>>> + DBUG_RETURN(false);
>>> + }
>>> + else if (m_const_scope.contain(current_parents))
>>> {
>>> // NOTE: This is a constant table wrt. this instance of the pushed join.
>>> // It should be relatively simple to extend the SPJ block to
>>> // allow such tables to be included in the pushed join.
>>> - DBUG_PRINT("info", (" Contain only const/param REFs, -> can't
>>> append(yet) as 'const' wrt. pushed join:%d\n",tab_no+1));
>>> + EXPLAIN_NO_PUSH("Can't push table %s as child of %s, their
>>> dependency is 'const'",
>>> + table->get_table()->alias, join_root()->get_table()->alias);
>>> DBUG_RETURN(false);
>>> }
>>> else if (parents.is_clear_all())
>>> {
>>> - DBUG_PRINT("info", (" No common parents, -> can't append table to
>>> pushed joins:%d\n",tab_no+1));
>>> + EXPLAIN_NO_PUSH("Can't push table %s as child of %s, no parents
>>> found within scope",
>>> + table->get_table()->alias, join_root()->get_table()->alias);
>>> DBUG_RETURN(false);
>>> }
>>>
>>> @@ -1022,17 +1164,20 @@ ndb_pushed_builder_ctx::field_ref_is_joi
>>> if (scan_descendant->get_join_type(parent) == AQP::JT_OUTER_JOIN)
>>> {
>>> DBUG_PRINT("info", (" There are outer joins between parent and
>>> artificial parent -> can't append"));
>>> + EXPLAIN_NO_PUSH("Can't push table %s as child of %s, implementation
>>> limitations for outer joins",
>>> + table->get_table()->alias, join_root()->get_table()->alias);
>>> DBUG_RETURN(false);
>>> }
>>> parent_no= descendant_no;
>>> // parent= scan_descendant;
>>> - DBUG_PRINT("info", (" Force artificial grandparent dependency
>>> through scan-child %s",
>>> scan_descendant->get_table()->alias));
>>> + DBUG_PRINT("info", (" Force artificial grandparent dependency
>>> through scan-child %s",
>>> + scan_descendant->get_table()->alias));
>>>
>>> if (scan_descendant&&
>>> table->get_join_type(scan_descendant) == AQP::JT_OUTER_JOIN)
>>> {
>>> - DBUG_PRINT("info", (" Table scan %d is outer joined with
>>> scan-descendant %d, not pushable (yet)",
>>> - tab_no, descendant_no));
>>> + EXPLAIN_NO_PUSH("Can't push table %s as child of %s, outer join
>>> with scan-descendant %s not implemented",
>>> + table->get_table()->alias, join_root()->get_table()->alias,
>>> scan_descendant->get_table()->alias);
>>> DBUG_RETURN(false);
>>> }
>>> }
>>> @@ -1047,13 +1192,17 @@ ndb_pushed_builder_ctx::field_ref_is_joi
>>> uint ancestor_no= parent_no;
>>> while (ancestor_no != MAX_TABLES)
>>> {
>>> + scan_ancestor= m_plan.get_table_access(ancestor_no);
>>> if (m_tables[ancestor_no].m_last_scan_descendant< MAX_TABLES)
>>> {
>>> - DBUG_PRINT("info", (" Ancestor tab %d has scan descendants -> can't
>>> append", ancestor_no));
>>> + EXPLAIN_NO_PUSH("Can't push table %s as child of %s, "
>>> + "implementation limitations due to bushy scan with %s indirect
>>> through %s",
>>> + table->get_table()->alias, join_root()->get_table()->alias,
>>> +
>>>
> m_plan.get_table_access(m_tables[ancestor_no].m_last_scan_descendant)->get_table()->alias,
>>>
>>> + scan_ancestor->get_table()->alias);
>>> DBUG_RETURN(false);
>>> }
>>>
>>> - scan_ancestor= m_plan.get_table_access(ancestor_no);
>>> if (!is_lookup_operation(scan_ancestor->get_access_type()))
>>> {
>>> break; // As adding this scanop was prev. allowed, above ancestor
>>> can't be scan bushy
>>> @@ -1067,8 +1216,8 @@ ndb_pushed_builder_ctx::field_ref_is_joi
>>> if (scan_ancestor&&
>>> table->get_join_type(scan_ancestor) == AQP::JT_OUTER_JOIN)
>>> {
>>> - DBUG_PRINT("info", (" Table scan %d is outer joined with
>>> scan-ancestor %d, not pushable (yet)",
>>> - tab_no, ancestor_no));
>>> + EXPLAIN_NO_PUSH("Can't push table %s as child of %s, outer join
>>> with scan-ancestor %s not implemented",
>>> + table->get_table()->alias, join_root()->get_table()->alias,
>>> scan_ancestor->get_table()->alias);
>>> DBUG_RETURN(false);
>>> }
>>> }
>>> @@ -1152,7 +1301,7 @@ ndb_pushed_builder_ctx::field_ref_is_joi
>>> } // substitute
>>>
>>> DBUG_RETURN(true);
>>> -} // ndb_pushed_builder_ctx::field_ref_is_join_pushable
>>> +} // ndb_pushed_builder_ctx::is_pushable_as_child
>>>
>>>
>>> /**
>>> @@ -1210,44 +1359,20 @@ build_key_map(const NDBTAB* table, const
>>> } // build_key_map
>>>
>>> int
>>> -ha_ndbcluster::make_pushed_join(AQP::Join_plan& plan,
>>> +ha_ndbcluster::make_pushed_join(ndb_pushed_builder_ctx& context,
>>> const AQP::Table_access* const join_root)
>>> {
>>> DBUG_ENTER("make_pushed_join");
>>>
>>> - if (m_pushed_join_member) // Already member of another pushed join.
>>> - DBUG_RETURN(0);
>>> -
>>> - const AQP::enum_access_type access_type= join_root->get_access_type();
>>> - DBUG_ASSERT(access_type != AQP::AT_VOID);
>>> + DBUG_ASSERT (context.is_pushable_as_parent(join_root));
>>> + context.set_root(join_root);
>>> + const AQP::Join_plan& plan= context.plan();
>>>
>>> - DBUG_PRINT("enter", ("Investigating from table %d as root",
>>> join_root->get_access_no()));
>>> - if (access_type == AQP::AT_OTHER)
>>> - {
>>> - DBUG_PRINT("info", ("join_root->get_access_type() == AQP::AT_OTHER"
>>> - " -> not pushable"));
>>> - DBUG_RETURN(0);
>>> - }
>>> - if (access_type == AQP::AT_MULTI_UNIQUE_KEY)
>>> - {
>>> - DBUG_PRINT("info", ("join_root->get_access_type() ==
>>> AQP::AT_MULTI_KEY"
>>> - " -> not (yet) pushable"));
>>> - DBUG_RETURN(0);
>>> - }
>>> - if (uses_blob_value(table->read_set))
>>> - {
>>> - DBUG_PRINT("info", ("'read_set' contain BLOB columns -> not
>>> pushable"));
>>> - DBUG_RETURN(0);
>>> - }
>>> - if (m_user_defined_partitioning)
>>> - {
>>> - DBUG_PRINT("info", ("Tables has user defined partioning -> not
>>> pushable"));
>>> - DBUG_RETURN(0);
>>> - }
>>> -
>>> - DBUG_PRINT("info", ("join_root is pushable:"));
>>> + DBUG_PRINT("enter", ("Table %d as root is pushable",
>>> join_root->get_access_no()));
>>> DBUG_EXECUTE("info", join_root->dbug_print(););
>>>
>>> + const AQP::enum_access_type access_type= join_root->get_access_type();
>>> +
>>> /**
>>> * Past this point we know at least join_root to be join pushable
>>> * as parent operation. Search for tables to be appendable as child
>>> @@ -1256,7 +1381,6 @@ ha_ndbcluster::make_pushed_join(AQP::Joi
>>> * appendable child.
>>> */
>>> NdbQueryBuilder builder(*m_thd_ndb->ndb);
>>> - ndb_pushed_builder_ctx context(plan, join_root);
>>>
>>> uint push_cnt= 0;
>>> uint fld_refs= 0;
>>> @@ -1270,39 +1394,7 @@ ha_ndbcluster::make_pushed_join(AQP::Joi
>>> const AQP::Table_access* const join_tab=
>>> plan.get_table_access(join_cnt);
>>> const NdbQueryOperationDef* query_op= NULL;
>>>
>>> - if (join_tab->get_table()->file->ht != ht)
>>> - {
>>> - DBUG_PRINT("info", ("Table %d not same SE, not pushable", join_cnt));
>>> - continue;
>>> - }
>>> -
>>> - const ha_ndbcluster* const handler=
>>> - static_cast<ha_ndbcluster*>(join_tab->get_table()->file);
>>> -
>>> - if (handler->m_pushed_join_member)
>>> - {
>>> - DBUG_PRINT("info", ("Table %d already contained in another pushed
>>> join", join_cnt));
>>> - continue;
>>> - }
>>> - if (handler->uses_blob_value(join_tab->get_table()->read_set))
>>> - {
>>> - DBUG_PRINT("info", ("Table %d, 'read_set' contains BLOBs, not
>>> pushable", join_cnt));
>>> - continue;
>>> - }
>>> - if (handler->m_user_defined_partitioning)
>>> - {
>>> - DBUG_PRINT("info", ("Table %d has user defined partioning, not
>>> pushable", join_cnt));
>>> - continue;
>>> - }
>>> - AQP::enum_access_type child_type= join_tab->get_access_type();
>>> - if (!(is_lookup_operation(child_type) ||
>>> - // Currently there is a limitation in not allowing LOOKUP -
>>> (index)SCAN operations
>>> - (child_type==AQP::AT_ORDERED_INDEX_SCAN&&
>>> !is_lookup_operation(access_type))))
>>> - {
>>> - DBUG_PRINT("info", ("Table %d not a pushable access type", join_cnt));
>>> - continue;
>>> - }
>>> - if (!context.field_ref_is_join_pushable(join_tab, join_items,
>>> join_parent))
>>> + if (!context.is_pushable_as_child(join_tab, join_items, join_parent))
>>> {
>>> DBUG_PRINT("info", ("Table %d not REF-joined, not pushable", join_cnt));
>>> continue;
>>> @@ -1386,6 +1478,10 @@ ha_ndbcluster::make_pushed_join(AQP::Joi
>>> DBUG_PRINT("info", ("Appending child, join_cnt:%d, key_parts:%d",
>>> push_cnt,
>>> join_tab->get_no_of_key_fields()));
>>>
>>> + DBUG_ASSERT(join_tab->get_table()->file->ht == ht);
>>> + const ha_ndbcluster* const handler=
>>> + static_cast<ha_ndbcluster*>(join_tab->get_table()->file);
>>> +
>>> KEY *key=&handler->table->key_info[join_tab->get_index_no()];
>>>
>>> const NdbQueryOperand* linked_key[ndb_pushed_join::MAX_LINKED_KEYS]=
>>> {NULL};
>>> @@ -1428,7 +1524,7 @@ ha_ndbcluster::make_pushed_join(AQP::Joi
>>> if (field->is_real_null())
>>> {
>>> DBUG_PRINT("info", ("NULL constValues in key -> not pushable"));
>>> - DBUG_RETURN(0);
>>> + DBUG_RETURN(0); // TODO, handle gracefull -> continue?
>>> }
>>> const uchar* const ptr= (field->real_type() == MYSQL_TYPE_VARCHAR)
>>> ? field->ptr + ((Field_varstring*)field)->length_bytes
>>> @@ -1472,7 +1568,7 @@ ha_ndbcluster::make_pushed_join(AQP::Joi
>>> if (unlikely(fld_refs>= ndb_pushed_join::MAX_REFERRED_FIELDS))
>>> {
>>> DBUG_PRINT("info", ("Too many Field refs (>= MAX_REFERRED_FIELDS)
>>> encountered"));
>>> - DBUG_RETURN(0);
>>> + DBUG_RETURN(0); // TODO, handle gracefull -> continue?
>>> }
>>> referred_fields[fld_refs++]= field_item->field;
>>> linked_key[map[i]]= builder.paramValue();
>>> @@ -1556,6 +1652,25 @@ ha_ndbcluster::make_pushed_join(AQP::Joi
>>> } // ha_ndbcluster::make_pushed_join()
>>>
>>>
>>> +//ndb_pushed_builder_ctx::enum_pushability
>>> +int
>>> +ha_ndbcluster::get_pushability() const
>>> +{
>>> + if (uses_blob_value(table->read_set))
>>> + {
>>> + EXPLAIN_NO_PUSH("Table %s not pushable, 'read_set' contain BLOB
>>> columns", table->alias);
>>> + return 0;
>>> + }
>>> + if (m_user_defined_partitioning)
>>> + {
>>> + EXPLAIN_NO_PUSH("Table %s not pushable, has user defined
>>> partioning", table->alias);
>>> + return 0;
>>> + }
>>> + return (ndb_pushed_builder_ctx::PUSHABLE_AS_CHILD |
>>> + ndb_pushed_builder_ctx::PUSHABLE_AS_PARENT);
>>> +} // ha_ndbcluster::get_pushability()
>>> +
>>> +
>>> static
>>> int ndbcluster_make_pushed_join(handlerton *hton, THD* thd,
>>> AQP::Join_plan* plan)
>>> @@ -1565,15 +1680,16 @@ int ndbcluster_make_pushed_join(handlert
>>> if (!THDVAR(thd, join_pushdown))
>>> DBUG_RETURN(0);
>>>
>>> + ndb_pushed_builder_ctx context(*plan);
>>> for (uint i= 0; i< plan->get_access_count()-1; i++)
>>> {
>>> const AQP::Table_access* const join_root= plan->get_table_access(i);
>>> - if (join_root->get_table()->file->ht == ndbcluster_hton)
>>> + if (context.is_pushable_as_parent(join_root))
>>> {
>>> ha_ndbcluster* const handler=
>>> static_cast<ha_ndbcluster*>(join_root->get_table()->file);
>>>
>>> - int error= handler->make_pushed_join(*plan,join_root);
>>> + int error= handler->make_pushed_join(context,join_root);
>>> if (unlikely(error))
>>> {
>>> handler->print_error(error, MYF(0));
>>>
>>> === modified file 'sql/ha_ndbcluster.h'
>>> --- a/sql/ha_ndbcluster.h 2010-10-15 21:04:14 +0000
>>> +++ b/sql/ha_ndbcluster.h 2010-10-26 09:21:10 +0000
>>> @@ -417,6 +417,8 @@ class ha_ndbcluster: public handler
>>> ha_ndbcluster(handlerton *hton, TABLE_SHARE *table);
>>> ~ha_ndbcluster();
>>>
>>> + int get_pushability() const;
>>> +
>>> int ha_initialise();
>>> void column_bitmaps_signal(uint sig_type);
>>> int open(const char *name, int mode, uint test_if_locked);
>>> @@ -588,7 +590,7 @@ static void set_tabname(const char *path
>>> */
>>> void cond_pop();
>>>
>>> - int make_pushed_join(AQP::Join_plan& plan,
>>> + int make_pushed_join(class ndb_pushed_builder_ctx& context,
>>> const AQP::Table_access* const join_root);
>>>
>>> bool test_push_flag(enum ha_push_flag flag) const;
>>>
>>> === modified file 'sql/share/errmsg.txt'
>>> --- a/sql/share/errmsg.txt 2010-06-16 12:04:53 +0000
>>> +++ b/sql/share/errmsg.txt 2010-10-26 09:21:10 +0000
>>> @@ -6221,3 +6221,5 @@ ER_SLAVE_CONVERSION_FAILED
>>> eng "Column %d of table '%-.192s.%-.192s' cannot be converted from
>>> type '%-.32s' to type '%-.32s'"
>>> ER_SLAVE_CANT_CREATE_CONVERSION
>>> eng "Can't create conversion table for table '%-.192s.%-.192s'"
>>> +WARN_QUERY_NOT_PUSHED
>>> + eng "Table can't be part of pushed join"
>>>
>>>
>>>
>>>
>>>
>>
>

Thread
bzr commit into mysql-5.1-telco-7.0-spj-scan-vs-scan branch(ole.john.aske:3323) Ole John Aske26 Oct
  • Re: bzr commit into mysql-5.1-telco-7.0-spj-scan-vs-scan branch (ole.john.aske:3323)Magnus Blåudd26 Oct
Re: bzr commit into mysql-5.1-telco-7.0-spj-scan-vs-scan branch (ole.john.aske:3323)Magnus Blåudd27 Oct