From: magnus.blaudd Date: September 30 2011 10:30am Subject: bzr push into mysql-trunk-cluster branch (magnus.blaudd:3390 to 3392) List-Archive: http://lists.mysql.com/commits/141230 Message-Id: <201109301030.p8UAUhuW024961@acsmt356.oracle.com> MIME-Version: 1.0 Content-Type: text/plain; charset="us-ascii" Content-Transfer-Encoding: 7bit 3392 magnus.blaudd@stripped 2011-09-30 ndb - remove abstract_query_plan.h/cc, should be added to trunk as part of it's own WL# removed: sql/abstract_query_plan.cc sql/abstract_query_plan.h 3391 magnus.blaudd@stripped 2011-09-30 [merge] Merge modified: sql/abstract_query_plan.cc sql/ha_ndbcluster.cc sql/ha_ndbcluster.h sql/ha_ndbcluster_cond.cc sql/ha_ndbcluster_cond.h sql/ha_ndbcluster_connection.cc sql/ha_ndbcluster_push.cc sql/ha_ndbcluster_push.h storage/ndb/CMakeLists.txt 3390 magnus.blaudd@stripped 2011-09-28 [merge] Merge === removed file 'sql/abstract_query_plan.cc' --- a/sql/abstract_query_plan.cc 2011-09-28 19:25:31 +0000 +++ b/sql/abstract_query_plan.cc 1970-01-01 00:00:00 +0000 @@ -1,573 +0,0 @@ -/* - Copyright 2010 Sun Microsystems, Inc. - All rights reserved. Use is subject to license terms. - - This program is free software; you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation; version 2 of the License. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with this program; if not, write to the Free Software - Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA -*/ - -#ifdef USE_PRAGMA_IMPLEMENTATION -#pragma implementation // gcc: Class implementation -#endif - -#ifndef MYSQL_SERVER -#define MYSQL_SERVER -#endif - -#include "sql_priv.h" -#include "sql_select.h" -#include "abstract_query_plan.h" - - -#ifdef NDB_WITHOUT_JOIN_PUSHDOWN -static bool -test_if_skip_sort_order(JOIN_TAB *tab,ORDER *order,ha_rows select_limit, - bool no_changes, const key_map *map) -{ - // Stub used when compiling AQP as part of ndbcluster, never called - assert(false); - return false; -} -#endif - -namespace AQP -{ - - /** - @param join_tab Array of access methods constituting the nested loop join. - @param access_count Length of array. - */ - Join_plan::Join_plan(const JOIN* join) - : m_join_tabs(join->join_tab), - m_access_count(join->tables), - m_table_accesses(NULL) - { - /* - This combination is assumed not to appear. If it does, code must - be written to handle it. - */ - DBUG_ASSERT((m_join_tabs[0].use_quick != 2) - || (m_join_tabs[0].type == JT_ALL) - || (m_join_tabs[0].select == NULL) - || (m_join_tabs[0].select->quick == NULL)); - - m_table_accesses= new Table_access[m_access_count]; - for(uint i= 0; i < m_access_count; i++) - { - m_table_accesses[i].m_join_plan= this; - m_table_accesses[i].m_tab_no= i; - } - } - - Join_plan::~Join_plan() - { - delete[] m_table_accesses; - m_table_accesses= NULL; - } - - /** Get the JOIN_TAB of the n'th table access operation.*/ - const JOIN_TAB* Join_plan::get_join_tab(uint join_tab_no) const - { - DBUG_ASSERT(join_tab_no < m_access_count); - return m_join_tabs + join_tab_no; - } - - void - Join_plan::find_skippabable_group_or_order() const - { - const - JOIN* const join= m_join_tabs->join; - - if (join->const_tables < join->tables) - { - JOIN_TAB* join_head= join->join_tab+join->const_tables; - - m_group_by_filesort_is_skippable= join->group_optimized_away; - m_order_by_filesort_is_skippable= join->skip_sort_order; - - /* A single row don't have to be sorted */ - if (join_head->type == JT_CONST || - join_head->type == JT_SYSTEM || - join_head->type == JT_EQ_REF) - { - m_group_by_filesort_is_skippable= true; - m_order_by_filesort_is_skippable= true; - } - else if (join->select_options & SELECT_BIG_RESULT) - { - /* Excluded from ordered index optimization */ - } - else if (join->group_list && !m_group_by_filesort_is_skippable) - { - if (!join->tmp_table_param.quick_group || join->procedure) - { - /* Unsure how to handle - Is disabled in ::compute_type_and_index() */ - } - if (join->simple_group) - { - /** - test_if_skip_sort_order(...group_list...) already done by JOIN::optimize(). - As we still have a 'simple_group', GROUP BY has been optimized through an - access path providing an ordered sequence as required by GROUP BY: - - Verify this assumption in ASSERT below: - */ - DBUG_ASSERT(test_if_skip_sort_order(join_head, join->group_list, - join->unit->select_limit_cnt, true, - &join_head->table->keys_in_use_for_group_by)); - m_group_by_filesort_is_skippable= true; - } - } - else if (join->order && !m_order_by_filesort_is_skippable) - { - if (join->simple_order) - { - m_order_by_filesort_is_skippable= - test_if_skip_sort_order(join_head, - join->order, - join->unit->select_limit_cnt, false, - &join_head->table->keys_in_use_for_order_by); - } - } - } - } - - bool - Join_plan::group_by_filesort_is_skippable() const - { - return (m_group_by_filesort_is_skippable == true); - } - - bool - Join_plan::order_by_filesort_is_skippable() const - { - return (m_order_by_filesort_is_skippable == true); - } - - /** - Determine join type between this table access and some other table - access that preceeds it in the join plan.. - */ - enum_join_type - Table_access::get_join_type(const Table_access* predecessor) const - { - DBUG_ENTER("get_join_type"); - DBUG_ASSERT(get_access_no() > predecessor->get_access_no()); - - if (get_join_tab()->table->pos_in_table_list->outer_join != 0) - { - /* - This cover unnested outer joins such as - 'select * from t1 left join t2 on t1.attr=t1.pk'. - */ - DBUG_PRINT("info", ("JT_OUTER_JOIN between %s and %s", - predecessor->get_join_tab()->table->alias, - get_join_tab()->table->alias)); - DBUG_RETURN(JT_OUTER_JOIN); - } - - const TABLE_LIST* const child_embedding= - get_join_tab()->table->pos_in_table_list->embedding; - - if (child_embedding == NULL) - { - // 'this' is not on the inner side of any left join. - DBUG_PRINT("info", ("JT_INNER_JOIN between %s and %s", - predecessor->get_join_tab()->table->alias, - get_join_tab()->table->alias)); - DBUG_RETURN(JT_INNER_JOIN); - } - - DBUG_ASSERT(child_embedding->outer_join != 0); - - const TABLE_LIST *predecessor_embedding= - predecessor->get_join_tab()->table->pos_in_table_list->embedding; - - /* - This covers the nested join case, i.e: - LEFT JOIN (). - - TABLE_LIST objects form a tree where TABLE_LIST::emebedding points to - the parent object. Now if child_embedding is non null and not an - ancestor of predecessor_embedding in the embedding tree, then 'this' - must be on the inner side of some left join where 'predecessor' is on - the outer side. - */ - while (true) - { - if (predecessor_embedding == child_embedding) - { - DBUG_PRINT("info", ("JT_INNER_JOIN between %s and %s", - predecessor->get_join_tab()->table->alias, - get_join_tab()->table->alias)); - DBUG_RETURN(JT_INNER_JOIN); - } - else if (predecessor_embedding == NULL) - { - /* - We reached the root of the tree without finding child_embedding, - so it must be in another branch and hence on the inner side of some - left join where 'predecessor' is on the outer side. - */ - DBUG_PRINT("info", ("JT_OUTER_JOIN between %s and %s", - predecessor->get_join_tab()->table->alias, - get_join_tab()->table->alias)); - DBUG_RETURN(JT_OUTER_JOIN); - } - // Iterate through ancestors of predecessor_embedding. - predecessor_embedding = predecessor_embedding->embedding; - } - } - - /** - Get the number of key values for this operation. It is an error - to call this method on an operation that is not an index lookup - operation. - */ - uint Table_access::get_no_of_key_fields() const - { - DBUG_ASSERT(m_access_type == AT_PRIMARY_KEY || - m_access_type == AT_UNIQUE_KEY || - m_access_type == AT_MULTI_PRIMARY_KEY || - m_access_type == AT_MULTI_UNIQUE_KEY || - m_access_type == AT_ORDERED_INDEX_SCAN); // Used as 'range scan' - return get_join_tab()->ref.key_parts; - } - - /** - Get the field_no'th key values for this operation. It is an error - to call this method on an operation that is not an index lookup - operation. - */ - const Item* Table_access::get_key_field(uint field_no) const - { - DBUG_ASSERT(field_no < get_no_of_key_fields()); - return get_join_tab()->ref.items[field_no]; - } - - /** - Get the field_no'th KEY_PART_INFO for this operation. It is an error - to call this method on an operation that is not an index lookup - operation. - */ - const KEY_PART_INFO* Table_access::get_key_part_info(uint field_no) const - { - DBUG_ASSERT(field_no < get_no_of_key_fields()); - const KEY* key= &get_join_tab()->table->key_info[get_join_tab()->ref.key]; - return &key->key_part[field_no]; - } - - /** - Get the table that this operation accesses. - */ - TABLE* Table_access::get_table() const - { - return get_join_tab()->table; - } - - /** Get the JOIN_TAB object that corresponds to this operation.*/ - const JOIN_TAB* Table_access::get_join_tab() const - { - return m_join_plan->get_join_tab(m_tab_no); - } - - /** Get the Item_equal's set relevant for the specified 'Item_field' */ - Item_equal* - Table_access::get_item_equal(const Item_field* field_item) const - { - DBUG_ASSERT(field_item->type() == Item::FIELD_ITEM); - - COND_EQUAL* const cond_equal = get_join_tab()->join->cond_equal; - if (cond_equal!=NULL) - { - return (field_item->item_equal != NULL) - ? field_item->item_equal - : const_cast(field_item)->find_item_equal(cond_equal); - } - return NULL; - } - - /** - Write an entry in the trace file about the contents of this object. - */ - void Table_access::dbug_print() const - { - DBUG_PRINT("info", ("type:%d", get_join_tab()->type)); - DBUG_PRINT("info", ("ref.key:%d", get_join_tab()->ref.key)); - DBUG_PRINT("info", ("ref.key_parts:%d", get_join_tab()->ref.key_parts)); - DBUG_PRINT("info", ("ref.key_length:%d", get_join_tab()->ref.key_length)); - - DBUG_PRINT("info", ("order:%p", get_join_tab()->join->order)); - DBUG_PRINT("info", ("skip_sort_order:%d", - get_join_tab()->join->skip_sort_order)); - DBUG_PRINT("info", ("no_order:%d", get_join_tab()->join->no_order)); - DBUG_PRINT("info", ("simple_order:%d", get_join_tab()->join->simple_order)); - - DBUG_PRINT("info", ("group:%d", get_join_tab()->join->group)); - DBUG_PRINT("info", ("group_list:%p", get_join_tab()->join->group_list)); - DBUG_PRINT("info", ("simple_group:%d", get_join_tab()->join->simple_group)); - DBUG_PRINT("info", ("group_optimized_away:%d", - get_join_tab()->join->group_optimized_away)); - - DBUG_PRINT("info", ("full_join:%d", get_join_tab()->join->full_join)); - DBUG_PRINT("info", ("need_tmp:%d", get_join_tab()->join->need_tmp)); - DBUG_PRINT("info", ("select_distinct:%d", - get_join_tab()->join->select_distinct)); - - DBUG_PRINT("info", ("use_quick:%d", get_join_tab()->use_quick)); - DBUG_PRINT("info", ("index:%d", get_join_tab()->index)); - DBUG_PRINT("info", ("quick:%p", get_join_tab()->quick)); - DBUG_PRINT("info", ("select:%p", get_join_tab()->select)); - if (get_join_tab()->select && get_join_tab()->select->quick) - { - DBUG_PRINT("info", ("select->quick->get_type():%d", - get_join_tab()->select->quick->get_type())); - } - } - - - /** - Compute the access type and index (if apliccable) of this operation . - */ - void Table_access::compute_type_and_index() const - { - DBUG_ENTER("Table_access::compute_type_and_index"); - const JOIN_TAB* const join_tab= get_join_tab(); - JOIN* const join= join_tab->join; - - /** - * There are some JOIN arguments we don't fully understand or has - * not yet invested time into exploring pushability of: - */ - if (join->procedure) - { - m_access_type= AT_OTHER; - m_other_access_reason = - "'PROCEDURE'-clause post processing cannot be pushed."; - DBUG_VOID_RETURN; - } - - if (join->group_list && !join->tmp_table_param.quick_group) - { - m_access_type= AT_OTHER; - m_other_access_reason = - "GROUP BY cannot be done using index on grouped columns."; - DBUG_VOID_RETURN; - } - - /* Tables below 'const_tables' has been const'ified, or entirely - * optimized away due to 'impossible WHERE/ON' - */ - if (join_tab < join->join_tab+join->const_tables) - { - DBUG_PRINT("info", ("Operation %d is const-optimized.", m_tab_no)); - m_access_type= AT_FIXED; - DBUG_VOID_RETURN; - } - - /* First non-const table may provide 'simple' ordering for entire join */ - if (join_tab == join->join_tab+join->const_tables) - { - m_join_plan->find_skippabable_group_or_order(); - } - - /* - Identify the type of access operation and the index to use (if any). - */ - switch (join_tab->type) - { - case JT_EQ_REF: - case JT_CONST: - m_index_no= join_tab->ref.key; - - if (m_index_no == static_cast(join_tab->table->s->primary_key)) - { - DBUG_PRINT("info", ("Operation %d is a primary key lookup.", m_tab_no)); - m_access_type= AT_PRIMARY_KEY; - } - else - { - DBUG_PRINT("info", ("Operation %d is a unique index lookup.", - m_tab_no)); - m_access_type= AT_UNIQUE_KEY; - } - break; - - case JT_REF: - { - DBUG_ASSERT(join_tab->ref.key >= 0); - DBUG_ASSERT(join_tab->ref.key < MAX_KEY); - m_index_no= join_tab->ref.key; - - /* - All parts of a key are specified for an unique index -> access is a key lookup. - */ - const KEY *key_info= join_tab->table->s->key_info; - if (key_info[m_index_no].key_parts == join_tab->ref.key_parts && - key_info[m_index_no].flags & HA_NOSAME) - { - m_access_type= - (m_index_no == static_cast(join_tab->table->s->primary_key)) - ? AT_PRIMARY_KEY - : AT_UNIQUE_KEY; - DBUG_PRINT("info", ("Operation %d is an unique key referrence.", m_tab_no)); - } - else - { - DBUG_ASSERT(join_tab->ref.key_parts > 0); - DBUG_ASSERT(join_tab->ref.key_parts <= key_info[m_index_no].key_parts); - m_access_type= AT_ORDERED_INDEX_SCAN; - DBUG_PRINT("info", ("Operation %d is an ordered index scan.", m_tab_no)); - } - break; - } - case JT_NEXT: - DBUG_ASSERT(join_tab->index < MAX_KEY); - m_index_no= join_tab->index; - m_access_type= AT_ORDERED_INDEX_SCAN; - DBUG_PRINT("info", ("Operation %d is an ordered index scan.", m_tab_no)); - break; - - case JT_ALL: - if (join_tab->use_quick == 2) - { - /* - use_quick == 2 means that the decision on which access method to use - will be taken late (as rows from the preceeding operation arrive). - This operation is therefor not pushable. - */ - DBUG_PRINT("info", - ("Operation %d has 'use_quick == 2' -> not pushable", - m_tab_no)); - m_access_type= AT_UNDECIDED; - m_index_no= -1; - } - else - { - if (join_tab->select != NULL && - join_tab->select->quick != NULL) - { - QUICK_SELECT_I *quick= join_tab->select->quick; - - /** QUICK_SELECT results in execution of MRR (Multi Range Read). - * Depending on each range, it may require execution of - * either a PK-lookup or a range scan. To cover both of - * these we may need to prepare both a pushed lookup join - * and a pushed range scan. Currently we handle it as - * a range scan and convert e PK lookup to a (closed-) range - * whenever required. - **/ - - const KEY *key_info= join_tab->table->s->key_info; - DBUG_EXECUTE("info", quick->dbug_dump(0, TRUE);); - - // Temporary assert as we are still investigation the relation between - // 'quick->index == MAX_KEY' and the different quick_types - DBUG_ASSERT ((quick->index == MAX_KEY) == - ((quick->get_type() == QUICK_SELECT_I::QS_TYPE_INDEX_MERGE) || - (quick->get_type() == QUICK_SELECT_I::QS_TYPE_ROR_INTERSECT) || - (quick->get_type() == QUICK_SELECT_I::QS_TYPE_ROR_UNION))); - - // JT_INDEX_MERGE: We have a set of qualifying PKs as root of pushed joins - if (quick->index == MAX_KEY) - { - m_index_no= join_tab->table->s->primary_key; - m_access_type= AT_MULTI_PRIMARY_KEY; // Multiple PKs are produced by merge - } - - // Else JT_RANGE: May be both exact PK and/or index scans when sorted index available - else if (quick->index == join_tab->table->s->primary_key) - { - m_index_no= quick->index; - if (key_info[m_index_no].algorithm == HA_KEY_ALG_HASH) - m_access_type= AT_MULTI_PRIMARY_KEY; // MRR w/ multiple PK's - else - m_access_type= AT_MULTI_MIXED; // MRR w/ both range and PKs - } - else - { - m_index_no= quick->index; - if (key_info[m_index_no].algorithm == HA_KEY_ALG_HASH) - m_access_type= AT_MULTI_UNIQUE_KEY; // MRR with multiple unique keys - else - m_access_type= AT_MULTI_MIXED; // MRR w/ both range and unique keys - } - } - else - { - DBUG_PRINT("info", ("Operation %d is a table scan.", m_tab_no)); - m_access_type= AT_TABLE_SCAN; - } - } - break; - - default: - /* - Other join_types either cannot be pushed or the code analyze them is - not yet in place. - */ - DBUG_PRINT("info", - ("Operation %d has join_type %d. -> Not pushable.", - m_tab_no, join_tab->type)); - m_access_type= AT_OTHER; - m_index_no= -1; - m_other_access_reason = "This table access method can not be pushed."; - break; - } - DBUG_VOID_RETURN; - } - // Table_access::compute_type_and_index() - - - Table_access::Table_access() - :m_join_plan(NULL), - m_tab_no(0), - m_access_type(AT_VOID), - m_other_access_reason(NULL), - m_index_no(-1) - {} - - /** - @return True iff ordered index access is *required* from this operation. - */ - bool Table_access::is_fixed_ordered_index() const - { - const JOIN_TAB* const join_tab= get_join_tab(); - - /* For the QUICK_SELECT_I classes we can disable ordered index usage by - * setting 'QUICK_SELECT_I::sorted = false'. - * However, QUICK_SELECT_I::QS_TYPE_RANGE_DESC is special as its - * internal implementation requires its 'multi-ranges' to be retrieved - * in (descending) sorted order from the underlying table. - */ - if (join_tab->select != NULL && - join_tab->select->quick != NULL) - { - QUICK_SELECT_I *quick= join_tab->select->quick; - return (quick->get_type() == QUICK_SELECT_I::QS_TYPE_RANGE_DESC); - } - return false; - } - - /** - Check if the results from this operation will joined with results - from the next operation using a join buffer (instead of plain nested loop). - @return True if using a join buffer. - */ - bool Table_access::uses_join_cache() const - { - return get_join_tab()->next_select == sub_select_cache; - } - -}; -// namespace AQP === removed file 'sql/abstract_query_plan.h' --- a/sql/abstract_query_plan.h 2011-09-28 19:25:31 +0000 +++ b/sql/abstract_query_plan.h 1970-01-01 00:00:00 +0000 @@ -1,315 +0,0 @@ -/* - Copyright 2010 Sun Microsystems, Inc. - All rights reserved. Use is subject to license terms. - - This program is free software; you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation; version 2 of the License. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with this program; if not, write to the Free Software - Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA -*/ - -#ifndef ABSTRACT_QUERY_PLAN_H_INCLUDED -#define ABSTRACT_QUERY_PLAN_H_INCLUDED - -struct TABLE; -struct st_join_table; -typedef st_join_table JOIN_TAB; -class JOIN; -class Item; -class Item_field; -class Item_equal_iterator; - -/** - Abstract query plan (AQP) is an interface for examining certain aspects of - query plans without accessing mysqld internal classes (JOIN_TAB, SQL_SELECT - etc.) directly. - - AQP maps join execution plans, as represented by mysqld internals, to a set - of facade classes. Non-join operations such as sorting and aggregation is - currently *not* modelled in the AQP. - - The AQP models an n-way join as a sequence of the n table access operations - that the MySQL server would execute as part of its nested loop join - execution. (Each such table access operation is a scan of a table or index, - or an index lookup.) For each lookup operation, it is possible to examine - the expression that represents each field in the key. - - A storage enging will typically use the AQP for finding sections of a join - execution plan that may be executed in the engine rather than in mysqld. By - using the AQP rather than the mysqld internals directly, the coupling between - the engine and mysqld is reduced. -*/ -namespace AQP -{ - class Table_access; - - /** - This class represents a query plan for an n-way join, in the form a - sequence of n table access operations that will execute as a nested loop - join. - */ - class Join_plan - { - friend class Equal_set_iterator; - friend class Table_access; - public: - - explicit Join_plan(const JOIN* join); - - ~Join_plan(); - - const Table_access* get_table_access(uint access_no) const; - - uint get_access_count() const; - - /** - Can filesort(), normally required by execution of GROUP BY - or ORDER BY, be skipped due to the columns already being - accessible in required sorted order. - */ - bool group_by_filesort_is_skippable() const; - bool order_by_filesort_is_skippable() const; - - private: - /** - Array of the JOIN_TABs that are the internal representation of table - access operations. - */ - const JOIN_TAB* const m_join_tabs; - - /** Number of table access operations. */ - const uint m_access_count; - Table_access* m_table_accesses; - - mutable bool m_group_by_filesort_is_skippable; - mutable bool m_order_by_filesort_is_skippable; - - void find_skippabable_group_or_order() const; - - const JOIN_TAB* get_join_tab(uint join_tab_no) const; - - // No copying. - Join_plan(const Join_plan&); - Join_plan& operator=(const Join_plan&); - }; - // class Join_plan - - - /** - This class is an iterator for iterating over sets of fields (columns) that - should have the same value. For example, if the query is - SELECT * FROM T1, T2, T3 WHERE T1.b = T2.a AND T2.a = T3.a - then there would be such a set of {T1.b, T2.a, T3.a}. - */ - class Equal_set_iterator - { - public: - explicit Equal_set_iterator(Item_equal& item_equal) - : m_iterator(item_equal) {} - - const Item_field* next() - { return m_iterator++; } - - private: - /** - This class is implemented in terms of this mysqld internal class. - */ - Item_equal_iterator m_iterator; - - // No copying. - Equal_set_iterator(const Equal_set_iterator&); - Equal_set_iterator& operator=(const Equal_set_iterator&); - }; - // class Equal_set_iterator - - /** The type of a table access operation. */ - enum enum_access_type - { - /** For default initialization.*/ - AT_VOID, - /** Value has already been fetched / determined by optimizer.*/ - AT_FIXED, - /** Do a lookup of a single primary key.*/ - AT_PRIMARY_KEY, - /** Do a lookup of a single unique index key.*/ - AT_UNIQUE_KEY, - /** Scan an ordered index with a single upper and lower bound pair.*/ - AT_ORDERED_INDEX_SCAN, - /** Do a multi range read for a set of primary keys.*/ - AT_MULTI_PRIMARY_KEY, - /** Do a multi range read for a set of unique index keys.*/ - AT_MULTI_UNIQUE_KEY, - /** - Do a multi range read for a mix of ranges (for which there is an - ordered index), and either primary keys or unique index keys. - */ - AT_MULTI_MIXED, - /** Scan a table. (No index is assumed to be used.) */ - AT_TABLE_SCAN, - /** Access method will not be chosen before the execution phase.*/ - AT_UNDECIDED, - /** - The access method has properties that prevents it from being pushed to a - storage engine. - */ - AT_OTHER - }; - - /** The type of join operation require */ - enum enum_join_type - { - JT_OUTER_JOIN, - JT_INNER_JOIN, - JT_SEMI_JOIN - }; - - /** - This class represents an access operation on a table, such as a table - scan, or a scan or lookup via an index. A Table_access object is always - owned by a Join_plan object, such that the life time of the Table_access - object ends when the life time of the owning Join_plan object ends. - */ - class Table_access - { - friend class Join_plan; - friend inline bool equal(const Table_access*, const Table_access*); - public: - - const Join_plan* get_join_plan() const; - - enum_access_type get_access_type() const; - - const char* get_other_access_reason() const; - - enum_join_type get_join_type(const Table_access* parent) const; - - uint get_no_of_key_fields() const; - - const Item* get_key_field(uint field_no) const; - - const KEY_PART_INFO* get_key_part_info(uint field_no) const; - - uint get_access_no() const; - - int get_index_no() const; - - TABLE* get_table() const; - - Item_equal* get_item_equal(const Item_field* field_item) const; - - void dbug_print() const; - - bool is_fixed_ordered_index() const; - - bool uses_join_cache() const; - - private: - - /** Backref. to the Join_plan which this Table_access is part of */ - const Join_plan* m_join_plan; - - /** This operation corresponds to m_root_tab[m_tab_no].*/ - uint m_tab_no; - - /** The type of this operation.*/ - mutable enum_access_type m_access_type; - - /** - The reason for getting m_access_type==AT_OTHER. Used for explain extended. - */ - mutable const char* m_other_access_reason; - - /** The index to use for this operation (if applicable )*/ - mutable int m_index_no; - - explicit Table_access(); - - const JOIN_TAB* get_join_tab() const; - - void compute_type_and_index() const; - - /** No copying*/ - Table_access(const Table_access&); - Table_access& operator=(const Table_access&); - }; - // class Table_access - - /** - Get the n'th table access operation. - @param access_no The index of the table access operation to fetch. - @return The access_no'th table access operation. - */ - inline const Table_access* Join_plan::get_table_access(uint access_no) const - { - DBUG_ASSERT(access_no < m_access_count); - return m_table_accesses + access_no; - } - - /** - @return The number of table access operations in the nested loop join. - */ - inline uint Join_plan::get_access_count() const - { - return m_access_count; - } - - /** Get the Join_plan that this Table_access belongs to.*/ - inline const Join_plan* Table_access::get_join_plan() const - { - return m_join_plan; - } - - /** Get the type of this operation.*/ - inline enum_access_type Table_access::get_access_type() const - { - if (m_access_type == AT_VOID) - compute_type_and_index(); - return m_access_type; - } - - /** - Get a description of the reason for getting access_type==AT_OTHER. To be - used for informational messages. - @return A string that should be assumed to have the same life time as the - Table_access object. - */ - inline const char* Table_access::get_other_access_reason() const - { - if (m_access_type == AT_VOID) - compute_type_and_index(); - return m_other_access_reason; - } - - /** - @return The number of the index to use for this access operation ( - or -1 for non-index operations). - */ - inline int Table_access::get_index_no() const - { - if (m_access_type == AT_VOID) - compute_type_and_index(); - - return m_index_no; - } - - /** - Get the number of this Table_access within the enclosing Join_plan. - (This number will be in the range 0 to Join_plan::get_access_count() - 1.) - */ - inline uint Table_access::get_access_no() const - { - return m_tab_no; - } - -}; -// namespace AQP - -#endif === modified file 'sql/ha_ndbcluster.cc' --- a/sql/ha_ndbcluster.cc 2011-09-28 19:11:28 +0000 +++ b/sql/ha_ndbcluster.cc 2011-09-30 10:24:10 +0000 @@ -21,10 +21,6 @@ MySQL and NDB Cluster */ -#ifdef USE_PRAGMA_IMPLEMENTATION -#pragma implementation // gcc: Class implementation -#endif - #include "ha_ndbcluster_glue.h" #ifdef WITH_NDBCLUSTER_STORAGE_ENGINE @@ -45,7 +41,9 @@ #include "ndb_table_guard.h" #include "ndb_global_schema_lock.h" #include "ndb_global_schema_lock_guard.h" +#ifndef NDB_WITHOUT_JOIN_PUSHDOWN #include "abstract_query_plan.h" +#endif #include "ndb_dist_priv_util.h" #include "ha_ndb_index_stat.h" @@ -3139,7 +3137,7 @@ ha_ndbcluster::primary_key_is_clustered( get_index_type_from_table(table->s->primary_key); return (idx_type == PRIMARY_KEY_ORDERED_INDEX || idx_type == UNIQUE_ORDERED_INDEX || - idx_type == ORDERED_INDEX); + idx_type == ORDERED_INDEX); } bool ha_ndbcluster::check_index_fields_in_write_set(uint keyno) @@ -3180,6 +3178,7 @@ int ha_ndbcluster::pk_read(const uchar * NdbOperation::LockMode lm= get_ndb_lock_mode(m_lock.type); +#ifndef NDB_WITHOUT_JOIN_PUSHDOWN if (check_if_pushable(NdbQueryOperationDef::PrimaryKeyAccess, table->s->primary_key)) { // Is parent of pushed join @@ -3213,6 +3212,7 @@ int ha_ndbcluster::pk_read(const uchar * } } else +#endif { if (m_pushed_join_operation == PUSHED_ROOT) { @@ -3594,6 +3594,7 @@ int ha_ndbcluster::unique_index_read(con NdbOperation::LockMode lm= get_ndb_lock_mode(m_lock.type); +#ifndef NDB_WITHOUT_JOIN_PUSHDOWN if (check_if_pushable(NdbQueryOperationDef::UniqueIndexAccess, active_index)) { DBUG_ASSERT(lm == NdbOperation::LM_CommittedRead); @@ -3624,6 +3625,7 @@ int ha_ndbcluster::unique_index_read(con } } else +#endif { if (m_pushed_join_operation == PUSHED_ROOT) { @@ -3984,6 +3986,7 @@ ha_ndbcluster::pk_unique_index_read_key( extern void sql_print_information(const char *format, ...); +#ifndef NDB_WITHOUT_JOIN_PUSHDOWN static bool is_shrinked_varchar(const Field *field) @@ -4063,8 +4066,9 @@ ha_ndbcluster::pk_unique_index_read_key_ const int ret= create_pushed_join(paramValues, key_def->key_parts); DBUG_RETURN(ret); -} // ha_ndbcluster::pk_unique_index_read_key_pushed +} +#endif /** Count number of columns in key part. */ static uint @@ -4226,6 +4230,7 @@ int ha_ndbcluster::ordered_index_scan(co pbound = &bound; } +#ifndef NDB_WITHOUT_JOIN_PUSHDOWN if (check_if_pushable(NdbQueryOperationDef::OrderedIndexScan, active_index, sorted)) { @@ -4254,7 +4259,8 @@ int ha_ndbcluster::ordered_index_scan(co DBUG_ASSERT(!uses_blob_value(table->read_set)); // Can't have BLOB in pushed joins (yet) } - else // if (check_if_pushable(NdbQueryOperationDef::OrderedIndexScan)) + else +#endif { if (m_pushed_join_operation == PUSHED_ROOT) { @@ -4419,6 +4425,7 @@ int ha_ndbcluster::full_table_scan(const if (table_share->primary_key == MAX_KEY) get_hidden_fields_scan(&options, gets); +#ifndef NDB_WITHOUT_JOIN_PUSHDOWN if (check_if_pushable(NdbQueryOperationDef::TableScan)) { const int error= create_pushed_join(); @@ -4428,7 +4435,8 @@ int ha_ndbcluster::full_table_scan(const m_thd_ndb->m_scan_count++; DBUG_ASSERT(!uses_blob_value(table->read_set)); // Can't have BLOB in pushed joins (yet) } - else // if (check_if_pushable(NdbQueryOperationDef::TableScan)) + else +#endif { if (m_pushed_join_operation == PUSHED_ROOT) { @@ -7215,6 +7223,7 @@ int ha_ndbcluster::reset() { m_cond->cond_clear(); } +#ifndef NDB_WITHOUT_JOIN_PUSHDOWN DBUG_ASSERT(m_active_query == NULL); if (m_pushed_join_operation==PUSHED_ROOT) // Root of pushed query { @@ -7223,6 +7232,7 @@ int ha_ndbcluster::reset() m_pushed_join_member= NULL; m_pushed_join_operation= -1; m_disable_pushed_join= FALSE; +#endif #if 0 // Magnus, disble this "hack" until it's possible to test if @@ -10610,8 +10620,6 @@ ha_ndbcluster::~ha_ndbcluster() release_blobs_buffer(); // Check for open cursor/transaction - DBUG_ASSERT(m_active_cursor == NULL); - DBUG_ASSERT(m_active_query == NULL); DBUG_ASSERT(m_thd_ndb == NULL); // Discard any generated condition @@ -10622,12 +10630,15 @@ ha_ndbcluster::~ha_ndbcluster() m_cond= NULL; } DBUG_PRINT("info", ("Deleting pushed joins")); +#ifndef NDB_WITHOUT_JOIN_PUSHDOWN DBUG_ASSERT(m_active_query == NULL); + DBUG_ASSERT(m_active_cursor == NULL); if (m_pushed_join_operation==PUSHED_ROOT) { delete m_pushed_join_member; // Also delete QueryDef } m_pushed_join_member= NULL; +#endif DBUG_VOID_RETURN; } @@ -13783,6 +13794,7 @@ ha_ndbcluster::read_multi_range_first(KE break; } +#ifndef NDB_WITHOUT_JOIN_PUSHDOWN /* Create the scan operation for the first scan range. */ if (check_if_pushable(NdbQueryOperationDef::OrderedIndexScan, active_index, @@ -13799,9 +13811,10 @@ ha_ndbcluster::read_multi_range_first(KE query->getQueryOperation((uint)PUSHED_ROOT)->setOrdering(NdbQueryOptions::ScanOrdering_ascending)) ERR_RETURN(query->getNdbError()); } - } // check_if_pushable() - - else if (!m_multi_cursor) + } + else +#endif + if (!m_multi_cursor) { if (m_pushed_join_operation == PUSHED_ROOT) { @@ -14353,7 +14366,7 @@ int ndbcluster_make_pushed_join(handlert } } DBUG_RETURN(0); -} // ndbcluster_make_pushed_join +} #endif @@ -14382,7 +14395,7 @@ ha_ndbcluster::assign_pushed_join(const pushed_join->get_operation_count()-1)); DBUG_RETURN(0); -} // ha_ndbcluster::assign_pushed_join() +} /** @@ -14425,7 +14438,7 @@ ha_ndbcluster::maybe_pushable_join(const } return true; -} // ha_ndbcluster::is_pushable() +} /** * Check if this table access operation (and a number of succeding operation) @@ -14441,6 +14454,7 @@ ha_ndbcluster::maybe_pushable_join(const * with sorted results. * @return True if the operation may be pushed. */ +#ifndef NDB_WITHOUT_JOIN_PUSHDOWN bool ha_ndbcluster::check_if_pushable(int type, //NdbQueryOperationDef::Type, uint idx, @@ -14499,7 +14513,8 @@ ha_ndbcluster::create_pushed_join(const m_thd_ndb->m_pushed_queries_executed++; DBUG_RETURN(0); -} // ha_ndbcluster::create_pushed_join +} +#endif /** === modified file 'sql/ha_ndbcluster.h' --- a/sql/ha_ndbcluster.h 2011-09-28 19:11:28 +0000 +++ b/sql/ha_ndbcluster.h 2011-09-30 10:24:10 +0000 @@ -21,10 +21,6 @@ */ -#ifdef USE_PRAGMA_INTERFACE -#pragma interface /* gcc class implementation */ -#endif - /* Blob tables and events are internal to NDB and must never be accessed */ #define IS_NDB_BLOB_PREFIX(A) is_prefix(A, "NDB$BLOB") === modified file 'sql/ha_ndbcluster_cond.cc' --- a/sql/ha_ndbcluster_cond.cc 2011-09-07 10:08:09 +0000 +++ b/sql/ha_ndbcluster_cond.cc 2011-09-30 10:24:10 +0000 @@ -20,10 +20,6 @@ This file defines the NDB Cluster handler engine_condition_pushdown */ -#ifdef USE_PRAGMA_IMPLEMENTATION -#pragma implementation // gcc: Class implementation -#endif - #include "ha_ndbcluster_glue.h" #ifdef WITH_NDBCLUSTER_STORAGE_ENGINE === modified file 'sql/ha_ndbcluster_cond.h' --- a/sql/ha_ndbcluster_cond.h 2011-07-08 09:34:07 +0000 +++ b/sql/ha_ndbcluster_cond.h 2011-09-30 10:24:10 +0000 @@ -21,10 +21,6 @@ the NDB Cluster handler */ -#ifdef USE_PRAGMA_INTERFACE -#pragma interface /* gcc class implementation */ -#endif - typedef enum ndb_item_type { NDB_VALUE = 0, // Qualified more with Item::Type NDB_FIELD = 1, // Qualified from table definition === modified file 'sql/ha_ndbcluster_connection.cc' --- a/sql/ha_ndbcluster_connection.cc 2011-07-05 12:46:07 +0000 +++ b/sql/ha_ndbcluster_connection.cc 2011-09-30 10:24:10 +0000 @@ -16,10 +16,6 @@ Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA */ -#ifdef USE_PRAGMA_IMPLEMENTATION -#pragma implementation // gcc: Class implementation -#endif - #include "ha_ndbcluster_glue.h" #ifdef WITH_NDBCLUSTER_STORAGE_ENGINE === modified file 'sql/ha_ndbcluster_push.cc' --- a/sql/ha_ndbcluster_push.cc 2011-09-07 10:08:09 +0000 +++ b/sql/ha_ndbcluster_push.cc 2011-09-30 10:24:10 +0000 @@ -22,14 +22,9 @@ to the ndb data node (for execution by the SPJ block). */ -#ifdef USE_PRAGMA_IMPLEMENTATION -#pragma implementation // gcc: Class implementation -#endif #include "ha_ndbcluster_glue.h" -#include "rpl_mi.h" - #ifdef WITH_NDBCLUSTER_STORAGE_ENGINE #include "ha_ndbcluster.h" @@ -45,12 +40,6 @@ #include - -#ifdef ndb_dynamite -#undef assert -#define assert(x) do { if(x) break; ::printf("%s %d: assert failed: %s\n", __FILE__, __LINE__, #x); ::fflush(stdout); ::signal(SIGABRT,SIG_DFL); ::abort(); ::kill(::getpid(),6); ::kill(::getpid(),9); } while (0) -#endif - #define EXPLAIN_NO_PUSH(msgfmt, ...) \ do \ { \ === modified file 'sql/ha_ndbcluster_push.h' --- a/sql/ha_ndbcluster_push.h 2011-07-04 08:38:03 +0000 +++ b/sql/ha_ndbcluster_push.h 2011-09-30 10:24:10 +0000 @@ -15,10 +15,6 @@ Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA */ -#ifdef USE_PRAGMA_INTERFACE -#pragma interface /* gcc class implementation */ -#endif - #include "sql_bitmap.h" class NdbTransaction; === modified file 'storage/ndb/CMakeLists.txt' --- a/storage/ndb/CMakeLists.txt 2011-09-28 19:36:09 +0000 +++ b/storage/ndb/CMakeLists.txt 2011-09-30 10:26:18 +0000 @@ -67,7 +67,6 @@ NDB_CHECK_MYSQL_CLUSTER(${VERSION}) SET(NDBCLUSTER_SOURCES ../../sql/ha_ndbcluster.cc ../../sql/ha_ndbcluster_cond.cc - ../../sql/ha_ndbcluster_push.cc ../../sql/ha_ndbcluster_connection.cc ../../sql/ha_ndbcluster_binlog.cc ../../sql/ha_ndb_index_stat.cc @@ -93,10 +92,6 @@ IF(NOT MYSQL_CLUSTER_VERSION) # Pushdown of join queries not supported in non # MySQL Cluster version yet, compile ndbcluster without it ADD_DEFINITIONS(-DNDB_WITHOUT_JOIN_PUSHDOWN) - # Since the MySQL Server has no AQP support, compile - # that into ndbcluster instead - SET(NDBCLUSTER_SOURCES ${NDBCLUSTER_SOURCES} - ../../sql/abstract_query_plan.cc) ENDIF() # NDB is DEFAULT plugin in MySQL Cluster No bundle (reason: useless for push emails).