List:Commits« Previous MessageNext Message »
From:Ole John Aske Date:September 22 2010 7:44am
Subject:bzr commit into mysql-5.1-telco-7.0-spj-scan-vs-scan branch
(ole.john.aske:3287)
View as plain text  
#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

 3287 Ole John Aske	2010-09-22
      sps-svs: AQP::get_join_type() was not always correct about the join_type it reported: 
      I some circumstances it reported an 'outer join' instead of an 'inner join'
      
      There is no testcase for this fix as it does not affect the correctnes of the result.
      Reporting an outer join instead of an inner join will only cause the 'client side inner join'
      implementation to not remove inner joins before presenting result to mysqld. 'mysqld' will
      then later remove these unwanted NULL rows itself.
       

    modified:
      sql/abstract_query_plan.cc
      sql/abstract_query_plan.h
      sql/ha_ndbcluster.cc
=== modified file 'sql/abstract_query_plan.cc'
--- a/sql/abstract_query_plan.cc	2010-07-06 13:26:52 +0000
+++ b/sql/abstract_query_plan.cc	2010-09-22 07:44:06 +0000
@@ -144,13 +144,38 @@ namespace AQP
     return (m_order_by_filesort_is_skippable == true);
   }
 
-
-  enum_join_type Table_access::get_join_type() const
+  /**
+   Determine join type between this table and its parent table.
+  */
+  enum_join_type Table_access::get_join_type(const Table_access* parent) const
   {
-    if (get_join_tab()->table->maybe_null)
-      return JT_OUTER_JOIN;
-    else
-      return JT_INNER_JOIN;
+    const TABLE_LIST *this_table=   this->get_join_tab()->table->pos_in_table_list;
+    const TABLE_LIST *parent_table= parent->get_join_tab()->table->pos_in_table_list;
+
+    /**
+     Itterate the join-nest until we reach the same join level as the parent.
+     If we find 'outer_join' inbetween, the join of this table wrt. parent
+     is reported as JT_OUTER_JOIN.
+    */
+    const TABLE_LIST *join_item = this_table;
+    for (join_item = this_table; join_item!=NULL; join_item = join_item->embedding)
+    {
+      if (join_item->outer_join)
+      {
+        DBUG_PRINT("info", ("JT_OUTER_JOIN"));
+        return JT_OUTER_JOIN;
+      }
+      else if (join_item->embedding == parent_table->embedding)
+      {
+        DBUG_PRINT("info", ("at parent -> JT_INNER_JOIN"));
+        return JT_INNER_JOIN;
+      }
+    }
+
+    /* Unable to determine jointype, default to OUTER which is the 'most covering' */
+    DBUG_PRINT("info", ("fall through -> JT_OUTER_JOIN"));
+    DBUG_ASSERT(false);
+    return JT_OUTER_JOIN;
   }
 
   /**

=== modified file 'sql/abstract_query_plan.h'
--- a/sql/abstract_query_plan.h	2010-06-27 21:13:29 +0000
+++ b/sql/abstract_query_plan.h	2010-09-22 07:44:06 +0000
@@ -189,7 +189,7 @@ namespace AQP
 
     enum_access_type get_access_type() const;
 
-    enum_join_type get_join_type() const;
+    enum_join_type get_join_type(const Table_access* parent) const;
 
     uint get_no_of_key_fields() const;
 

=== modified file 'sql/ha_ndbcluster.cc'
--- a/sql/ha_ndbcluster.cc	2010-09-21 11:41:05 +0000
+++ b/sql/ha_ndbcluster.cc	2010-09-22 07:44:06 +0000
@@ -1007,22 +1007,20 @@ ndb_pushed_builder_ctx::field_ref_is_joi
      *        As a longer term solution bushy scans should be nativily supported by SPJ.
      */
 
+    // 'm_last_scan_descendant' is the candidate to be added as an artificial grandparent.
     if (m_tables[parent_no].m_last_scan_descendant < MAX_TABLES)
     {
       uint descendant_no= m_tables[parent_no].m_last_scan_descendant;
-      while (descendant_no != MAX_TABLES && descendant_no != parent_no)
-      {
-        const AQP::Table_access* const descendant= m_plan.get_table_access(descendant_no);
-        if (descendant->get_join_type() != AQP::JT_INNER_JOIN)
-        {
-          DBUG_PRINT("info", ("  There are outer joins between parent and artificial parent -> can't append"));
-          DBUG_RETURN(false);
-        }
-        descendant_no= m_tables[descendant_no].m_parent;
-      } // while
 
-      parent_no= m_tables[parent_no].m_last_scan_descendant;
+      const AQP::Table_access* const scan_descendant = m_plan.get_table_access(descendant_no);
       parent= m_plan.get_table_access(parent_no);
+      if (scan_descendant->get_join_type(parent) != AQP::JT_INNER_JOIN)
+      {
+        DBUG_PRINT("info", ("  There are outer joins between parent and artificial parent -> can't append"));
+        DBUG_RETURN(false);
+      }
+      parent_no= descendant_no;
+//    parent= scan_descendant;
       DBUG_PRINT("info", ("  Force artificial grandparent dependency through scan-child %s", parent->get_table()->alias));
     }
     else
@@ -1459,11 +1457,12 @@ ha_ndbcluster::make_pushed_join(AQP::Joi
     const NdbDictionary::Table* const table= handler->m_table;
  
     NdbQueryOptions options;
-    if (join_tab->get_join_type() == AQP::JT_INNER_JOIN)
+    DBUG_ASSERT(join_parent!=NULL);
+    if (join_tab->get_join_type(join_parent) == AQP::JT_INNER_JOIN)
     {
       options.setMatchType(NdbQueryOptions::MatchNonNull);
     }
-    if (need_explicit_parent && join_parent!=NULL)
+    if (need_explicit_parent)
     {
       const NdbQueryOperationDef* parent_op= context.get_query_operation(join_parent);
       DBUG_ASSERT(parent_op != NULL);


Attachment: [text/bzr-bundle] bzr/ole.john.aske@sun.com-20100922074406-9524eq2bu81k0av7.bundle
Thread
bzr commit into mysql-5.1-telco-7.0-spj-scan-vs-scan branch(ole.john.aske:3287) Ole John Aske22 Sep