#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__); \
+ } \
+}
+
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"
Attachment: [text/bzr-bundle] bzr/ole.john.aske@oracle.com-20101026092110-o4zkofqugr7etdbr.bundle