List:Commits« Previous MessageNext Message »
From:Jonas Oreland Date:October 3 2011 8:04am
Subject:bzr push into mysql-5.5-cluster branch (jonas.oreland:3562 to 3564)
View as plain text  
 3564 Jonas Oreland	2011-10-03 [merge]
      ndb - merge 70-spj-scan-scan into 72

    modified:
      mysql-test/suite/ndb/r/ndb_join_pushdown.result
      mysql-test/suite/ndb/t/ndb_join_pushdown.test
 3563 Jonas Oreland	2011-10-03 [merge]
      ndb - merge 71 to 72

    added:
      storage/ndb/clusterj/clusterj-core/src/main/java/com/mysql/clusterj/core/query/IsNotNullPredicateImpl.java
      storage/ndb/clusterj/clusterj-core/src/main/java/com/mysql/clusterj/core/query/IsNullPredicateImpl.java
    modified:
      sql/ha_ndbcluster_binlog.cc
      storage/ndb/clusterj/clusterj-api/src/main/java/com/mysql/clusterj/query/PredicateOperand.java
      storage/ndb/clusterj/clusterj-core/src/main/java/com/mysql/clusterj/core/metadata/AbstractDomainFieldHandlerImpl.java
      storage/ndb/clusterj/clusterj-core/src/main/java/com/mysql/clusterj/core/query/ParameterImpl.java
      storage/ndb/clusterj/clusterj-core/src/main/java/com/mysql/clusterj/core/query/PredicateImpl.java
      storage/ndb/clusterj/clusterj-core/src/main/java/com/mysql/clusterj/core/query/PropertyImpl.java
      storage/ndb/clusterj/clusterj-core/src/main/java/com/mysql/clusterj/core/spi/DomainFieldHandler.java
      storage/ndb/clusterj/clusterj-core/src/main/java/com/mysql/clusterj/core/store/ScanFilter.java
      storage/ndb/clusterj/clusterj-test/src/main/java/testsuite/clusterj/AbstractQueryTest.java
      storage/ndb/clusterj/clusterj-test/src/main/java/testsuite/clusterj/QueryNotNullTest.java
      storage/ndb/clusterj/clusterj-test/src/main/java/testsuite/clusterj/QueryNullTest.java
      storage/ndb/clusterj/clusterj-tie/src/main/java/com/mysql/clusterj/tie/ScanFilterImpl.java
      storage/ndb/src/common/debugger/signaldata/ScanTab.cpp
      storage/ndb/src/kernel/blocks/dbdict/Dbdict.cpp
      storage/ndb/src/kernel/blocks/dbspj/Dbspj.hpp
      storage/ndb/src/kernel/blocks/dbspj/DbspjMain.cpp
      storage/ndb/src/ndbapi/NdbQueryBuilder.cpp
      storage/ndb/src/ndbapi/NdbQueryBuilderImpl.hpp
      storage/ndb/src/ndbjtie/test/test/MySqlUtilsCharsetMapTest.java
      storage/ndb/test/src/NDBT_Find.cpp
 3562 jonas oreland	2011-10-02
      ndb - remove some test from default.experimental, and add rpl_ndb_mixed_implicit_commit_binlog

    modified:
      mysql-test/collections/default.experimental
=== modified file 'mysql-test/suite/ndb/r/ndb_join_pushdown.result'
--- a/mysql-test/suite/ndb/r/ndb_join_pushdown.result	2011-09-28 10:55:58 +0000
+++ b/mysql-test/suite/ndb/r/ndb_join_pushdown.result	2011-10-03 08:02:28 +0000
@@ -4792,6 +4792,20 @@ join t3 as x3 on x3.a=x2.c
 join t1 as x4 on x4.a=x0.d and x4.b=x3.b;
 count(*)
 4800
+explain select straight_join count(*) from t1 as x1  
+join t1 as x2 on x1.c=x2.a and x2.d=2
+join t3 as x3 on x1.d=x3.a;
+id	select_type	table	type	possible_keys	key	key_len	ref	rows	Extra
+1	SIMPLE	x1	ALL	NULL	NULL	NULL	NULL	4	Parent of 3 pushed join@1
+1	SIMPLE	x2	ref	PRIMARY	PRIMARY	4	test.x1.c	1	Child of 'x1' in pushed join@1; Using where with pushed condition
+1	SIMPLE	x3	ref	PRIMARY	PRIMARY	4	test.x1.d	1	Child of 'x1' in pushed join@1
+select straight_join count(*) from t1 as x1  
+join t1 as x2 on x1.c=x2.a and x2.d=2
+join t3 as x3 on x1.d=x3.a;
+count(*)
+300
+Local_range_scans
+4
 drop table t1;
 drop table t2;
 drop table t3;
@@ -5471,11 +5485,11 @@ and spj_counts_at_end.counter_name <> 'R
        and spj_counts_at_end.counter_name <> 'SCAN_BATCHES_RETURNED';
 counter_name	spj_counts_at_end.val - spj_counts_at_startup.val
 CONST_PRUNED_RANGE_SCANS_RECEIVED	6
-LOCAL_TABLE_SCANS_SENT	248
+LOCAL_TABLE_SCANS_SENT	250
 PRUNED_RANGE_SCANS_RECEIVED	25
 RANGE_SCANS_RECEIVED	728
 READS_RECEIVED	58
-TABLE_SCANS_RECEIVED	248
+TABLE_SCANS_RECEIVED	250
 drop table spj_counts_at_startup;
 drop table spj_counts_at_end;
 scan_count_derived
@@ -5485,9 +5499,9 @@ pruned_scan_count
 sorted_scan_count
 10
 pushed_queries_defined
-399
+401
 pushed_queries_dropped
 11
 pushed_queries_executed
-547
+548
 set ndb_join_pushdown = @save_ndb_join_pushdown;

=== modified file 'mysql-test/suite/ndb/t/ndb_join_pushdown.test'
--- a/mysql-test/suite/ndb/t/ndb_join_pushdown.test	2011-09-27 13:02:41 +0000
+++ b/mysql-test/suite/ndb/t/ndb_join_pushdown.test	2011-09-29 13:11:52 +0000
@@ -3323,6 +3323,28 @@ select straight_join count(*) from t1 as
    join t3 as x3 on x3.a=x2.c
    join t1 as x4 on x4.a=x0.d and x4.b=x3.b;
 
+# If the first batch of an index scan has low parallelism and returns few rows,
+# there is a mechanism that will try to query the remaining fragments within
+# the same batch. This is done in order to avoid repeating other branches of 
+# a bushy scan whenever possible. This is a test of that mechanism. Scan
+# of x2 should return only one row. Therefore we should be able to fetch
+# x2 in one batch and scan x3 only once.
+
+let $scan_rows = query_get_value(select sum(val) as Value from ndbinfo.counters where block_name='DBSPJ' and counter_name='LOCAL_RANGE_SCANS_SENT', Value, 1);
+
+explain select straight_join count(*) from t1 as x1  
+   join t1 as x2 on x1.c=x2.a and x2.d=2
+   join t3 as x3 on x1.d=x3.a;  
+
+select straight_join count(*) from t1 as x1  
+   join t1 as x2 on x1.c=x2.a and x2.d=2
+   join t3 as x3 on x1.d=x3.a;
+
+--disable_query_log
+--eval select sum(val) - $scan_rows as Local_range_scans from ndbinfo.counters where block_name='DBSPJ' and counter_name='LOCAL_RANGE_SCANS_SENT';
+--enable_query_log
+
+
 connection ddl;
 drop table t1;
 drop table t2;

=== modified file 'sql/ha_ndbcluster_binlog.cc'
--- a/sql/ha_ndbcluster_binlog.cc	2011-09-28 14:55:31 +0000
+++ b/sql/ha_ndbcluster_binlog.cc	2011-10-03 07:22:29 +0000
@@ -3231,7 +3231,7 @@ ndb_binlog_index_table__open(THD *thd,
   if (open_and_lock_tables(thd, &tables, derived, flags))
   {
     if (thd->killed)
-      sql_print_error("NDB Binlog: Opening ndb_binlog_index: killed");
+      DBUG_PRINT("error", ("NDB Binlog: Opening ndb_binlog_index: killed"));
     else
       sql_print_error("NDB Binlog: Opening ndb_binlog_index: %d, '%s'",
                       thd_stmt_da(thd)->sql_errno(),
@@ -3271,7 +3271,10 @@ ndb_binlog_index_table__write_rows(THD *
 
   if (ndb_binlog_index_table__open(thd, &ndb_binlog_index))
   {
-    sql_print_error("NDB Binlog: Unable to open ndb_binlog_index table");
+    if (thd->killed)
+      DBUG_PRINT("error", ("NDB Binlog: Unable to lock table ndb_binlog_index, killed"));
+    else
+      sql_print_error("NDB Binlog: Unable to lock table ndb_binlog_index");
     error= -1;
     goto add_ndb_binlog_index_err;
   }
@@ -7217,6 +7220,7 @@ restart_cluster_failure:
               */
               if (thd->killed)
               {
+                DBUG_PRINT("error", ("Failed to write to ndb_binlog_index at shutdown, retrying"));
                 (void) mysql_mutex_lock(&LOCK_thread_count);
                 volatile THD::killed_state killed= thd->killed;
                 /* We are cleaning up, allow for flushing last epoch */

=== modified file 'storage/ndb/clusterj/clusterj-api/src/main/java/com/mysql/clusterj/query/PredicateOperand.java'
--- a/storage/ndb/clusterj/clusterj-api/src/main/java/com/mysql/clusterj/query/PredicateOperand.java	2011-05-26 21:04:45 +0000
+++ b/storage/ndb/clusterj/clusterj-api/src/main/java/com/mysql/clusterj/query/PredicateOperand.java	2011-10-02 21:20:50 +0000
@@ -88,4 +88,16 @@ public interface PredicateOperand {
      */
     Predicate like(PredicateOperand other);
 
+    /** Return a Predicate representing comparing this to null.
+     *
+     * @return a new Predicate
+     */
+    Predicate isNull();
+
+    /** Return a Predicate representing comparing this to not null.
+     *
+     * @return a new Predicate
+     */
+    Predicate isNotNull();
+
 }

=== modified file 'storage/ndb/clusterj/clusterj-core/src/main/java/com/mysql/clusterj/core/metadata/AbstractDomainFieldHandlerImpl.java'
--- a/storage/ndb/clusterj/clusterj-core/src/main/java/com/mysql/clusterj/core/metadata/AbstractDomainFieldHandlerImpl.java	2011-06-24 20:58:44 +0000
+++ b/storage/ndb/clusterj/clusterj-core/src/main/java/com/mysql/clusterj/core/metadata/AbstractDomainFieldHandlerImpl.java	2011-10-02 21:20:50 +0000
@@ -174,6 +174,14 @@ public abstract class AbstractDomainFiel
         }
     }
 
+    public void filterIsNull(ScanFilter filter) {
+        filter.isNull(storeColumn);
+    }
+
+    public void filterIsNotNull(ScanFilter filter) {
+        filter.isNotNull(storeColumn);
+    }
+
     public String getColumnName() {
         return columnName;
     }

=== added file 'storage/ndb/clusterj/clusterj-core/src/main/java/com/mysql/clusterj/core/query/IsNotNullPredicateImpl.java'
--- a/storage/ndb/clusterj/clusterj-core/src/main/java/com/mysql/clusterj/core/query/IsNotNullPredicateImpl.java	1970-01-01 00:00:00 +0000
+++ b/storage/ndb/clusterj/clusterj-core/src/main/java/com/mysql/clusterj/core/query/IsNotNullPredicateImpl.java	2011-10-02 21:20:50 +0000
@@ -0,0 +1,49 @@
+/*
+   Copyright (c) 2011, Oracle and/or its affiliates. All rights reserved.
+
+   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
+*/
+
+package com.mysql.clusterj.core.query;
+
+import com.mysql.clusterj.core.spi.QueryExecutionContext;
+import com.mysql.clusterj.core.store.ScanFilter;
+import com.mysql.clusterj.core.store.ScanOperation;
+
+public class IsNotNullPredicateImpl extends PredicateImpl {
+
+    /** My property */
+    protected PropertyImpl property;
+
+    /** Construct a new IsNotNull predicate
+     * 
+     * @param dobj the query domain object that owns this predicate
+     * @param property the property
+     */
+    public IsNotNullPredicateImpl(QueryDomainTypeImpl<?> dobj, PropertyImpl property) {
+        super(dobj);
+        this.property = property;
+    }
+
+    /** Set the condition into the filter.
+     * @param context the query execution context with the parameter values (ignored for isNotNull)
+     * @param op the operation
+     * @param filter the filter
+     */
+    @Override
+    public void filterCmpValue(QueryExecutionContext context, ScanOperation op, ScanFilter filter) {
+        property.filterIsNotNull(filter);
+    }
+
+}

=== added file 'storage/ndb/clusterj/clusterj-core/src/main/java/com/mysql/clusterj/core/query/IsNullPredicateImpl.java'
--- a/storage/ndb/clusterj/clusterj-core/src/main/java/com/mysql/clusterj/core/query/IsNullPredicateImpl.java	1970-01-01 00:00:00 +0000
+++ b/storage/ndb/clusterj/clusterj-core/src/main/java/com/mysql/clusterj/core/query/IsNullPredicateImpl.java	2011-10-02 21:20:50 +0000
@@ -0,0 +1,49 @@
+/*
+   Copyright (c) 2011, Oracle and/or its affiliates. All rights reserved.
+
+   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
+*/
+
+package com.mysql.clusterj.core.query;
+
+import com.mysql.clusterj.core.spi.QueryExecutionContext;
+import com.mysql.clusterj.core.store.ScanFilter;
+import com.mysql.clusterj.core.store.ScanOperation;
+
+public class IsNullPredicateImpl extends PredicateImpl {
+
+    /** My property */
+    protected PropertyImpl property;
+
+    /** Construct a new IsNull predicate
+     * 
+     * @param dobj the query domain object that owns this predicate
+     * @param property the property
+     */
+    public IsNullPredicateImpl(QueryDomainTypeImpl<?> dobj, PropertyImpl property) {
+        super(dobj);
+        this.property = property;
+    }
+
+    /** Set the condition into the filter.
+     * @param context the query execution context with the parameter values (ignored for isNull)
+     * @param op the operation
+     * @param filter the filter
+     */
+    @Override
+    public void filterCmpValue(QueryExecutionContext context, ScanOperation op, ScanFilter filter) {
+        property.filterIsNull(filter);
+    }
+
+}

=== modified file 'storage/ndb/clusterj/clusterj-core/src/main/java/com/mysql/clusterj/core/query/ParameterImpl.java'
--- a/storage/ndb/clusterj/clusterj-core/src/main/java/com/mysql/clusterj/core/query/ParameterImpl.java	2011-06-20 23:34:36 +0000
+++ b/storage/ndb/clusterj/clusterj-core/src/main/java/com/mysql/clusterj/core/query/ParameterImpl.java	2011-10-02 21:20:50 +0000
@@ -118,6 +118,16 @@ public class ParameterImpl implements Pr
                 local.message("ERR_NotImplemented"));
     }
 
+    public Predicate isNull() {
+        throw new UnsupportedOperationException(
+                local.message("ERR_NotImplemented"));
+    }
+
+    public Predicate isNotNull() {
+        throw new UnsupportedOperationException(
+                local.message("ERR_NotImplemented"));
+    }
+
     public void setProperty(PropertyImpl property) {
         if (this.property != null && this.property.fmd.getType() != property.fmd.getType()) {
             throw new ClusterJUserException(local.message("ERR_Multiple_Parameter_Usage", parameterName,

=== modified file 'storage/ndb/clusterj/clusterj-core/src/main/java/com/mysql/clusterj/core/query/PredicateImpl.java'
--- a/storage/ndb/clusterj/clusterj-core/src/main/java/com/mysql/clusterj/core/query/PredicateImpl.java	2011-06-20 23:34:36 +0000
+++ b/storage/ndb/clusterj/clusterj-core/src/main/java/com/mysql/clusterj/core/query/PredicateImpl.java	2011-10-02 21:20:50 +0000
@@ -81,8 +81,7 @@ public abstract class PredicateImpl impl
     }
 
     void markBoundsForCandidateIndices(QueryExecutionContext context, CandidateIndexImpl[] candidateIndices) {
-        throw new ClusterJFatalInternalException(
-                local.message("ERR_Implementation_Should_Not_Occur"));
+        // default is nothing to do
     }
 
     public void operationSetBounds(QueryExecutionContext context,
@@ -161,10 +160,14 @@ public abstract class PredicateImpl impl
     }
 
     /** Mark all parameters as being required. */
-    public abstract void markParameters();
+    public void markParameters() {
+        // default is nothing to do
+    }
 
     /** Unmark all parameters as being required. */
-    public abstract void unmarkParameters();
+    public  void unmarkParameters() {
+        // default is nothing to do
+    }
 
     private void assertPredicateImpl(Predicate other) {
         if (!(other instanceof PredicateImpl)) {

=== modified file 'storage/ndb/clusterj/clusterj-core/src/main/java/com/mysql/clusterj/core/query/PropertyImpl.java'
--- a/storage/ndb/clusterj/clusterj-core/src/main/java/com/mysql/clusterj/core/query/PropertyImpl.java	2011-06-20 23:34:36 +0000
+++ b/storage/ndb/clusterj/clusterj-core/src/main/java/com/mysql/clusterj/core/query/PropertyImpl.java	2011-10-02 21:20:50 +0000
@@ -83,7 +83,7 @@ public class PropertyImpl implements Pre
             throw new ClusterJUserException(
                     local.message("ERR_Only_Parameters", "equal"));
         }
-        return (Predicate) new EqualPredicateImpl(dobj, this, (ParameterImpl)other);
+        return new EqualPredicateImpl(dobj, this, (ParameterImpl)other);
     }
 
     public Predicate between(PredicateOperand lower, PredicateOperand upper) {
@@ -91,7 +91,7 @@ public class PropertyImpl implements Pre
             throw new ClusterJUserException(
                     local.message("ERR_Only_Parameters", "between"));
         }
-        return (Predicate) new BetweenPredicateImpl(dobj, this, (ParameterImpl)lower, (ParameterImpl)upper);
+        return new BetweenPredicateImpl(dobj, this, (ParameterImpl)lower, (ParameterImpl)upper);
     }
 
     public Predicate greaterThan(PredicateOperand other) {
@@ -99,7 +99,7 @@ public class PropertyImpl implements Pre
             throw new ClusterJUserException(
                     local.message("ERR_Only_Parameters", "greaterThan"));
         }
-        return (Predicate) new GreaterThanPredicateImpl(dobj, this, (ParameterImpl)other);
+        return new GreaterThanPredicateImpl(dobj, this, (ParameterImpl)other);
     }
 
     public Predicate greaterEqual(PredicateOperand other) {
@@ -107,7 +107,7 @@ public class PropertyImpl implements Pre
             throw new ClusterJUserException(
                     local.message("ERR_Only_Parameters", "greaterEqual"));
         }
-        return (Predicate) new GreaterEqualPredicateImpl(dobj, this, (ParameterImpl)other);
+        return new GreaterEqualPredicateImpl(dobj, this, (ParameterImpl)other);
     }
 
     public Predicate lessThan(PredicateOperand other) {
@@ -115,7 +115,7 @@ public class PropertyImpl implements Pre
             throw new ClusterJUserException(
                     local.message("ERR_Only_Parameters", "lessThan"));
         }
-        return (Predicate) new LessThanPredicateImpl(dobj, this, (ParameterImpl)other);
+        return new LessThanPredicateImpl(dobj, this, (ParameterImpl)other);
     }
 
     public Predicate lessEqual(PredicateOperand other) {
@@ -123,7 +123,7 @@ public class PropertyImpl implements Pre
             throw new ClusterJUserException(
                     local.message("ERR_Only_Parameters", "lessEqual"));
         }
-        return (Predicate) new LessEqualPredicateImpl(dobj, this, (ParameterImpl)other);
+        return new LessEqualPredicateImpl(dobj, this, (ParameterImpl)other);
     }
 
     public Predicate in(PredicateOperand other) {
@@ -131,7 +131,7 @@ public class PropertyImpl implements Pre
             throw new ClusterJUserException(
                     local.message("ERR_Only_Parameters", "in"));
         }
-        return (Predicate) new InPredicateImpl(dobj, this, (ParameterImpl)other);
+        return new InPredicateImpl(dobj, this, (ParameterImpl)other);
     }
 
     public Predicate like(PredicateOperand other) {
@@ -139,7 +139,15 @@ public class PropertyImpl implements Pre
             throw new ClusterJUserException(
                     local.message("ERR_Only_Parameters", "like"));
         }
-        return (Predicate) new LikePredicateImpl(dobj, this, (ParameterImpl)other);
+        return new LikePredicateImpl(dobj, this, (ParameterImpl)other);
+    }
+
+    public Predicate isNull() {
+        return new IsNullPredicateImpl(dobj, this);
+    }
+
+    public Predicate isNotNull() {
+        return new IsNotNullPredicateImpl(dobj, this);
     }
 
     void markLowerBound(CandidateIndexImpl[] candidateIndices, PredicateImpl predicate, boolean strict) {
@@ -167,4 +175,12 @@ public class PropertyImpl implements Pre
         }
     }
 
+    public void filterIsNull(ScanFilter filter) {
+        fmd.filterIsNull(filter);
+    }
+
+    public void filterIsNotNull(ScanFilter filter) {
+        fmd.filterIsNotNull(filter);
+    }
+
 }

=== modified file 'storage/ndb/clusterj/clusterj-core/src/main/java/com/mysql/clusterj/core/spi/DomainFieldHandler.java'
--- a/storage/ndb/clusterj/clusterj-core/src/main/java/com/mysql/clusterj/core/spi/DomainFieldHandler.java	2011-06-20 23:34:36 +0000
+++ b/storage/ndb/clusterj/clusterj-core/src/main/java/com/mysql/clusterj/core/spi/DomainFieldHandler.java	2011-10-02 21:20:50 +0000
@@ -78,4 +78,8 @@ public interface DomainFieldHandler {
 
     Object getValue(QueryExecutionContext context, String parameterName);
 
+    void filterIsNull(ScanFilter filter);
+
+    void filterIsNotNull(ScanFilter filter);
+
 }

=== modified file 'storage/ndb/clusterj/clusterj-core/src/main/java/com/mysql/clusterj/core/store/ScanFilter.java'
--- a/storage/ndb/clusterj/clusterj-core/src/main/java/com/mysql/clusterj/core/store/ScanFilter.java	2011-05-26 21:04:45 +0000
+++ b/storage/ndb/clusterj/clusterj-core/src/main/java/com/mysql/clusterj/core/store/ScanFilter.java	2011-10-02 21:20:50 +0000
@@ -59,6 +59,8 @@ public interface ScanFilter {
 
     public void isNull(Column storeColumn);
     
+    public void isNotNull(Column storeColumn);
+    
     public void delete();
 
 }

=== modified file 'storage/ndb/clusterj/clusterj-test/src/main/java/testsuite/clusterj/AbstractQueryTest.java'
--- a/storage/ndb/clusterj/clusterj-test/src/main/java/testsuite/clusterj/AbstractQueryTest.java	2011-07-05 22:11:45 +0000
+++ b/storage/ndb/clusterj/clusterj-test/src/main/java/testsuite/clusterj/AbstractQueryTest.java	2011-10-02 21:20:50 +0000
@@ -87,6 +87,8 @@ abstract public class AbstractQueryTest
         public PredicateOperand paramUpperPredicate;
         public PredicateOperand paramInPredicate;
         public Predicate equal;
+        public Predicate isNull;
+        public Predicate isNotNull;
         public Predicate equalOrEqual;
         public Predicate greaterThan;
         public Predicate greaterEqual;
@@ -117,6 +119,8 @@ abstract public class AbstractQueryTest
         public PredicateOperand extraParamInPredicate;
         public PredicateOperand extraProperty;
         public Predicate extraEqual;
+        public Predicate extraIsNull;
+        public Predicate extraIsNotNull;
         public Predicate extraGreaterThan;
         public Predicate extraGreaterEqual;
         public Predicate extraLessThan;
@@ -150,6 +154,8 @@ abstract public class AbstractQueryTest
             propertyPredicate = dobj.get(propertyName);
             // comparison operations
             equal = propertyPredicate.equal(paramEqualPredicate);
+            isNull = propertyPredicate.isNull();
+            isNotNull = propertyPredicate.isNotNull();
             greaterThan = propertyPredicate.greaterThan(paramLowerPredicate);
             greaterEqual = propertyPredicate.greaterEqual(paramLowerPredicate);
             lessThan = propertyPredicate.lessThan(paramUpperPredicate);
@@ -186,6 +192,8 @@ abstract public class AbstractQueryTest
             this.extraProperty = dobj.get(extraPropertyName);
             // comparison operations
             this.extraEqual = extraProperty.equal(extraParamEqualPredicate);
+            this.extraIsNull = extraProperty.isNull();
+            this.extraIsNotNull = extraProperty.isNotNull();
             this.extraGreaterThan = extraProperty.greaterThan(extraParamLowerPredicate);
             this.extraGreaterEqual = extraProperty.greaterEqual(extraParamLowerPredicate);
             this.extraLessThan = extraProperty.lessThan(extraParamUpperPredicate);
@@ -307,6 +315,26 @@ abstract public class AbstractQueryTest
             }
             };
                     
+    PredicateProvider extraIsNullPredicateProvider = 
+        new PredicateProvider() {
+            public Predicate getPredicate(QueryHolder holder) {
+                return holder.extraIsNull;
+                }
+            public String toString() {
+                return " isNull";
+            }
+            };
+                            
+    PredicateProvider extraIsNotNullPredicateProvider = 
+        new PredicateProvider() {
+            public Predicate getPredicate(QueryHolder holder) {
+                return holder.extraIsNotNull;
+                }
+            public String toString() {
+                return " isNotNull";
+            }
+            };
+                                    
     /** Print the result instance. Override this in a subclass if needed.
      * 
      * @param instance the instance to print if needed
@@ -330,6 +358,32 @@ abstract public class AbstractQueryTest
         tx.commit();
     }
 
+    public void isNullQuery(String propertyName, String expectedIndex, int... expected) {
+        tx.begin();
+        QueryHolder holder = new QueryHolder(getInstanceType(), propertyName, expectedIndex);
+        // specify the where clause
+        holder.dobj.where(holder.isNull);
+        // create the query
+        holder.createQuery(session);
+        // get the results
+        holder.setExpectedResultIds(expected);
+        holder.checkResults(propertyName + " isNull");
+        tx.commit();
+    }
+
+    public void isNotNullQuery(String propertyName, String expectedIndex, int... expected) {
+        tx.begin();
+        QueryHolder holder = new QueryHolder(getInstanceType(), propertyName, expectedIndex);
+        // specify the where clause
+        holder.dobj.where(holder.isNotNull);
+        // create the query
+        holder.createQuery(session);
+        // get the results
+        holder.setExpectedResultIds(expected);
+        holder.checkResults(propertyName + " isNotNull");
+        tx.commit();
+    }
+
     public void likeQuery(String propertyName, String expectedIndex,
             Object parameterValue, int... expected) {
         tx.begin();

=== modified file 'storage/ndb/clusterj/clusterj-test/src/main/java/testsuite/clusterj/QueryNotNullTest.java'
--- a/storage/ndb/clusterj/clusterj-test/src/main/java/testsuite/clusterj/QueryNotNullTest.java	2011-07-05 12:46:07 +0000
+++ b/storage/ndb/clusterj/clusterj-test/src/main/java/testsuite/clusterj/QueryNotNullTest.java	2011-10-03 07:22:29 +0000
@@ -1,6 +1,5 @@
 /*
-Copyright 2010 Sun Microsystems, Inc.
-All rights reserved. Use is subject to license terms.
+   Copyright (c) 2010, 2011, Oracle and/or its affiliates. All rights reserved.
 
 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
@@ -110,4 +109,36 @@ public class QueryNotNullTest extends Ab
         failOnError();        
     }
 
+    public void testExtraEqualIsNotNull() {
+        equalAnd1ExtraQuery("int_not_null_btree", 8, "int_null_none", extraIsNotNullPredicateProvider, "dummy unused value", "idx_int_not_null_btree", 8);
+        equalAnd1ExtraQuery("int_not_null_hash", 8, "int_null_none", extraIsNotNullPredicateProvider, "dummy unused value", "none", 8);
+        equalAnd1ExtraQuery("int_not_null_both", 8, "int_null_none", extraIsNotNullPredicateProvider, "dummy unused value", "idx_int_not_null_both", 8);
+        equalAnd1ExtraQuery("int_not_null_none", 8, "int_null_none", extraIsNotNullPredicateProvider, "dummy unused value", "none", 8);
+        failOnError();        
+    }
+
+    public void testBtreeIsNotNull() {
+        isNotNullQuery("int_not_null_btree", "none", 0, 1, 2, 3, 4, 5, 6, 7, 8, 9);
+        isNotNullQuery("int_null_btree", "none", 0, 1, 2, 3, 4, 5, 6, 7, 8, 9);
+        failOnError();        
+    }
+
+    public void testHashIsNotNull() {
+        isNotNullQuery("int_not_null_hash", "none", 0, 1, 2, 3, 4, 5, 6, 7, 8, 9);
+        isNotNullQuery("int_null_hash", "none", 0, 1, 2, 3, 4, 5, 6, 7, 8, 9);
+        failOnError();        
+    }
+
+    public void testBothIsNotNull() {
+        isNotNullQuery("int_not_null_both", "none", 0, 1, 2, 3, 4, 5, 6, 7, 8, 9);
+        isNotNullQuery("int_null_both", "none", 0, 1, 2, 3, 4, 5, 6, 7, 8, 9);
+        failOnError();        
+    }
+
+    public void testNoneIsNotNull() {
+        isNotNullQuery("int_not_null_none", "none", 0, 1, 2, 3, 4, 5, 6, 7, 8, 9);
+        isNotNullQuery("int_null_none", "none", 0, 1, 2, 3, 4, 5, 6, 7, 8, 9);
+        failOnError();        
+    }
+
 }

=== modified file 'storage/ndb/clusterj/clusterj-test/src/main/java/testsuite/clusterj/QueryNullTest.java'
--- a/storage/ndb/clusterj/clusterj-test/src/main/java/testsuite/clusterj/QueryNullTest.java	2011-07-05 12:46:07 +0000
+++ b/storage/ndb/clusterj/clusterj-test/src/main/java/testsuite/clusterj/QueryNullTest.java	2011-10-03 07:22:29 +0000
@@ -1,6 +1,5 @@
 /*
-Copyright 2010 Sun Microsystems, Inc.
-All rights reserved. Use is subject to license terms.
+   Copyright (c) 2010, 2011, Oracle and/or its affiliates. All rights reserved.
 
 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
@@ -113,6 +112,38 @@ public class QueryNullTest extends Abstr
         failOnError();        
     }
 
+    public void testExtraIsNull() {
+        equalAnd1ExtraQuery("int_not_null_btree", 8, "int_null_none", extraIsNullPredicateProvider, "dummy unused value", "idx_int_not_null_btree");
+        equalAnd1ExtraQuery("int_not_null_hash", 8, "int_null_none", extraIsNullPredicateProvider, "dummy unused value", "none");
+        equalAnd1ExtraQuery("int_not_null_both", 8, "int_null_none", extraIsNullPredicateProvider, "dummy unused value", "idx_int_not_null_both");
+        equalAnd1ExtraQuery("int_not_null_none", 8, "int_null_none", extraIsNullPredicateProvider, "dummy unused value", "none");
+        failOnError();        
+    }
+
+    public void testBtreeIsNull() {
+        isNullQuery("int_not_null_btree", "none");
+        isNullQuery("int_null_btree", "none");
+        failOnError();        
+    }
+
+    public void testHashIsNull() {
+        isNullQuery("int_not_null_hash", "none");
+        isNullQuery("int_null_hash", "none");
+        failOnError();        
+    }
+
+    public void testBothIsNull() {
+        isNullQuery("int_not_null_both", "none");
+        isNullQuery("int_null_both", "none");
+        failOnError();        
+    }
+
+    public void testNoneIsNull() {
+        isNullQuery("int_not_null_none", "none");
+        isNullQuery("int_null_none", "none");
+        failOnError();        
+    }
+
     public void testGreaterThanNull() {
         try {
             greaterThanQuery("int_not_null_btree", "none", null);

=== modified file 'storage/ndb/clusterj/clusterj-tie/src/main/java/com/mysql/clusterj/tie/ScanFilterImpl.java'
--- a/storage/ndb/clusterj/clusterj-tie/src/main/java/com/mysql/clusterj/tie/ScanFilterImpl.java	2011-07-05 12:46:07 +0000
+++ b/storage/ndb/clusterj/clusterj-tie/src/main/java/com/mysql/clusterj/tie/ScanFilterImpl.java	2011-10-03 07:22:29 +0000
@@ -160,6 +160,11 @@ class ScanFilterImpl implements ScanFilt
         handleError(returnCode, ndbScanFilter);
     }
 
+    public void isNotNull(Column storeColumn) {
+        int returnCode = ndbScanFilter.isnotnull(storeColumn.getColumnId());
+        handleError(returnCode, ndbScanFilter);
+    }
+
     public void end() {
         int returnCode = ndbScanFilter.end();
         handleError(returnCode, ndbScanFilter);

=== modified file 'storage/ndb/src/common/debugger/signaldata/ScanTab.cpp'
--- a/storage/ndb/src/common/debugger/signaldata/ScanTab.cpp	2011-09-02 09:16:56 +0000
+++ b/storage/ndb/src/common/debugger/signaldata/ScanTab.cpp	2011-10-03 08:02:28 +0000
@@ -78,9 +78,9 @@ printSCANTABCONF(FILE * output, const Ui
   size_t op_count= requestInfo & (~ScanTabConf::EndOfData);
   if (op_count)
   {
-    fprintf(output, " Operation(s) [api tc rows len]:\n");
     if (len == ScanTabConf::SignalLength + 4 * op_count)
     {
+      fprintf(output, " Operation(s) [api tc rows len]:\n");
       ScanTabConf::OpData * op = (ScanTabConf::OpData*)
         (theData + ScanTabConf::SignalLength);
       for(size_t i = 0; i<op_count; i++)
@@ -91,9 +91,9 @@ printSCANTABCONF(FILE * output, const Ui
         op++;
       }
     }
-    else
+    else if (len == ScanTabConf::SignalLength + 3 * op_count)
     {
-      assert(len == ScanTabConf::SignalLength + 3 * op_count);
+      fprintf(output, " Operation(s) [api tc rows len]:\n");      
       for(size_t i = 0; i<op_count; i++)
       {
         ScanTabConf::OpData * op = (ScanTabConf::OpData*)
@@ -104,6 +104,12 @@ printSCANTABCONF(FILE * output, const Ui
                 ScanTabConf::getLength(op->rows));
       }
     }
+    else
+    {
+      // ScanTabConf::OpData stored in section 0 of signal.
+      assert(len == ScanTabConf::SignalLength);
+      fprintf(output, " Long signal. Cannot print operations.");
+    }
     fprintf(output, "\n");
   }
   return false;

=== modified file 'storage/ndb/src/kernel/blocks/dbdict/Dbdict.cpp'
--- a/storage/ndb/src/kernel/blocks/dbdict/Dbdict.cpp	2011-09-02 09:16:56 +0000
+++ b/storage/ndb/src/kernel/blocks/dbdict/Dbdict.cpp	2011-10-03 07:22:29 +0000
@@ -442,6 +442,12 @@ void Dbdict::execDBINFO_SCANREQ(Signal *
         c_opRecordPool.getEntrySize(),
         c_opRecordPool.getUsedHi(),
         { 0,0,0,0 }},
+      { "Operation Data",
+        c_opSectionBufferPool.getUsed(),
+        c_opSectionBufferPool.getSize(),
+        c_opSectionBufferPool.getEntrySize(),
+        c_opSectionBufferPool.getUsedHi(),
+        { 0,0,0,0 }},
       { NULL, 0,0,0,0,{0,0,0,0}}
     };
 

=== modified file 'storage/ndb/src/kernel/blocks/dbspj/Dbspj.hpp'
--- a/storage/ndb/src/kernel/blocks/dbspj/Dbspj.hpp	2011-09-02 09:16:56 +0000
+++ b/storage/ndb/src/kernel/blocks/dbspj/Dbspj.hpp	2011-10-03 08:02:28 +0000
@@ -580,6 +580,8 @@ public:
     Uint32 m_fragCount;
     // The number of fragments that we scan in parallel.
     Uint32 m_parallelism;
+    // True if we are still receiving the first batch for this operation.
+    bool   m_firstBatch;
     /**
      * True if this is the first instantiation of this operation. A child
      * operation will be instantiated once for each batch of its parent.
@@ -1229,7 +1231,6 @@ private:
   void scanIndex_execSCAN_FRAGCONF(Signal*, Ptr<Request>, Ptr<TreeNode>, Ptr<ScanFragHandle>);
   void scanIndex_parent_row(Signal*,Ptr<Request>,Ptr<TreeNode>, const RowPtr&);
   void scanIndex_fixupBound(Ptr<ScanFragHandle> fragPtr, Uint32 ptrI, Uint32);
-  void scanIndex_send(Signal*,Ptr<Request>,Ptr<TreeNode>);
   void scanIndex_send(Signal* signal,
                       Ptr<Request> requestPtr,
                       Ptr<TreeNode> treeNodePtr,

=== modified file 'storage/ndb/src/kernel/blocks/dbspj/DbspjMain.cpp'
--- a/storage/ndb/src/kernel/blocks/dbspj/DbspjMain.cpp	2011-09-28 10:55:58 +0000
+++ b/storage/ndb/src/kernel/blocks/dbspj/DbspjMain.cpp	2011-10-03 08:02:28 +0000
@@ -5023,6 +5023,7 @@ Dbspj::scanIndex_parent_batch_complete(S
   const ScanFragReq * org = (const ScanFragReq*)data.m_scanFragReq;
   ndbrequire(org->batch_size_rows > 0);
 
+  data.m_firstBatch = true;
   if (treeNodePtr.p->m_bits & TreeNode::T_SCAN_PARALLEL)
   {
     jam();
@@ -5171,6 +5172,9 @@ Dbspj::scanIndex_send(Signal* signal,
                       Uint32 bs_rows,
                       Uint32& batchRange)
 {
+  jam();
+  ndbassert(bs_bytes > 0);
+  ndbassert(bs_rows > 0);
   /**
    * if (m_bits & prunemask):
    * - Range keys sliced out to each ScanFragHandle
@@ -5451,6 +5455,9 @@ Dbspj::scanIndex_execSCAN_FRAGCONF(Signa
 
   if (data.m_frags_outstanding == 0)
   {
+    const bool isFirstBatch = data.m_firstBatch;
+    data.m_firstBatch = false;
+
     const ScanFragReq * const org
       = reinterpret_cast<const ScanFragReq*>(data.m_scanFragReq);
 
@@ -5486,24 +5493,78 @@ Dbspj::scanIndex_execSCAN_FRAGCONF(Signa
     {
       jam();
       ndbrequire((requestPtr.p->m_state & Request::RS_ABORTING) != 0);
-    }
-    else if (! (data.m_rows_received == data.m_rows_expecting))
-    {
-      jam();
+      checkBatchComplete(signal, requestPtr, 1);
       return;
     }
-    else
+
+    if (isFirstBatch && data.m_frags_not_started > 0)
     {
-      if (treeNodePtr.p->m_bits & TreeNode::T_REPORT_BATCH_COMPLETE)
+      /**
+       * Check if we can expect to be able to fetch the entire result set by
+       * asking for more fragments within the same batch. This may improve 
+       * performance for bushy scans, as subsequent bushy branches must be
+       * re-executed for each batch of this scan.
+       */
+      
+      /**
+       * Find the maximal correlation value that we may have seen so far.
+       * Correlation value must be unique within batch and smaller than 
+       * org->batch_size_rows.
+       */
+      const Uint32 maxCorrVal = (data.m_totalRows) == 0 ? 0 :
+        org->batch_size_rows / data.m_parallelism * (data.m_parallelism - 1)
+        + data.m_totalRows;
+      
+      // Number of rows that we can still fetch in this batch.
+      const Int32 remainingRows 
+        = static_cast<Int32>(org->batch_size_rows - maxCorrVal);
+      
+      if (remainingRows >= data.m_frags_not_started &&
+          /**
+           * Check that (remaning row capacity)/(remaining fragments) is 
+           * greater or equal to (rows read so far)/(finished fragments).
+           */
+          remainingRows * static_cast<Int32>(data.m_parallelism) >=
+          static_cast<Int32>(data.m_totalRows * data.m_frags_not_started) &&
+          (org->batch_size_bytes - data.m_totalBytes) * data.m_parallelism >=
+          data.m_totalBytes * data.m_frags_not_started)
       {
         jam();
-        reportBatchComplete(signal, requestPtr, treeNodePtr);
+        Uint32 batchRange = maxCorrVal;
+        DEBUG("::scanIndex_execSCAN_FRAGCONF() first batch was not full."
+              " Asking for new batches from " << data.m_frags_not_started <<
+              " fragments with " << 
+              remainingRows / data.m_frags_not_started 
+              <<" rows and " << 
+              (org->batch_size_bytes - data.m_totalBytes)
+              / data.m_frags_not_started 
+              << " bytes.");
+        scanIndex_send(signal,
+                       requestPtr,
+                       treeNodePtr,
+                       data.m_frags_not_started,
+                       (org->batch_size_bytes - data.m_totalBytes)
+                       / data.m_frags_not_started,
+                       remainingRows / data.m_frags_not_started,
+                       batchRange);
+        return;
       }
     }
+    
+    if (data.m_rows_received != data.m_rows_expecting)
+    {
+      jam();
+      return;
+    }
+    
+    if (treeNodePtr.p->m_bits & TreeNode::T_REPORT_BATCH_COMPLETE)
+    {
+      jam();
+      reportBatchComplete(signal, requestPtr, treeNodePtr);
+    }
 
     checkBatchComplete(signal, requestPtr, 1);
-    return;
-  }
+  } // if (data.m_frags_outstanding == 0)
 }
 
 void

=== modified file 'storage/ndb/src/ndbapi/NdbQueryBuilder.cpp'
--- a/storage/ndb/src/ndbapi/NdbQueryBuilder.cpp	2011-09-14 13:56:17 +0000
+++ b/storage/ndb/src/ndbapi/NdbQueryBuilder.cpp	2011-10-03 08:02:28 +0000
@@ -343,7 +343,8 @@ NdbQueryDef::destroy() const
 void
 NdbQueryDef::print() const
 {
-  m_impl.getQueryOperation(0U).printTree(0, Bitmask<(NDB_SPJ_MAX_TREE_NODES+31)/32>());
+  m_impl.getQueryOperation(0U)
+    .printTree(0, NdbQueryOperationDefImpl::SiblingMask());
 }
 
 /*************************************************************************
@@ -1188,7 +1189,8 @@ NdbQueryBuilderImpl::prepare()
   if (doPrintQueryTree)
   {
     ndbout << "Query tree:" << endl;
-    def->getQueryOperation(0U).printTree(0, Bitmask<(NDB_SPJ_MAX_TREE_NODES+31)/32>());
+    def->getQueryOperation(0U)
+      .printTree(0, NdbQueryOperationDefImpl::SiblingMask());
   }
 
   return def;
@@ -2159,7 +2161,8 @@ NdbQueryOperationDefImpl::appendChildPro
  * that connect the tree nodes.
  */
 static void printMargin(Uint32 depth, 
-                        Bitmask<(NDB_SPJ_MAX_TREE_NODES+31)/32> hasMoreSiblingsMask, 
+                        NdbQueryOperationDefImpl::SiblingMask 
+                        hasMoreSiblingsMask, 
                         bool header)
 {
   if (depth > 0)
@@ -2193,11 +2196,10 @@ static void printMargin(Uint32 depth,
 
 void 
 NdbQueryOperationDefImpl::printTree(Uint32 depth, 
-                                    Bitmask<(NDB_SPJ_MAX_TREE_NODES+31)/32> 
-                                    hasMoreSiblingsMask) const
+                                    SiblingMask hasMoreSiblingsMask) const
 {
   // Print vertical line leading down to this node.
-  Bitmask<(NDB_SPJ_MAX_TREE_NODES+31)/32> firstLineMask = hasMoreSiblingsMask;
+  SiblingMask firstLineMask = hasMoreSiblingsMask;
   firstLineMask.set(depth);
   printMargin(depth, firstLineMask, false);
   ndbout << endl;
@@ -2214,22 +2216,24 @@ NdbQueryOperationDefImpl::printTree(Uint
     printMargin(depth, hasMoreSiblingsMask, false);
     ndbout << " index: " << getIndex()->getName() << endl; 
   }
-  /* For each child but the last one, use a mask with an extra bit set to
-   * indicate that there are more siblings.
-   */
-  hasMoreSiblingsMask.set(depth+1);
+
   for (int childNo = 0; 
-       childNo < static_cast<int>(getNoOfChildOperations()) - 1; 
+       childNo < static_cast<int>(getNoOfChildOperations()); 
        childNo++)
   {
-    getChildOperation(childNo).printTree(depth+1, hasMoreSiblingsMask);
-  }
-  if (getNoOfChildOperations() > 0)
-  {
-    // The last child has no more siblings.
-    hasMoreSiblingsMask.clear(depth+1);
-    getChildOperation(getNoOfChildOperations() - 1)
-      .printTree(depth+1, hasMoreSiblingsMask);
+    if (childNo == 0)
+    {
+      /* For each child but the last one, use a mask with an extra bit set to
+       * indicate that there are more siblings.
+       */
+      hasMoreSiblingsMask.set(depth+1);
+    }
+    if (childNo == static_cast<int>(getNoOfChildOperations()) - 1)
+    {
+      // The last child has no more siblings.
+      hasMoreSiblingsMask.clear(depth+1);
+    }
+    getChildOperation(childNo).printTree(depth+1, hasMoreSiblingsMask); 
   }
 } // NdbQueryOperationDefImpl::printTree()
 

=== modified file 'storage/ndb/src/ndbapi/NdbQueryBuilderImpl.hpp'
--- a/storage/ndb/src/ndbapi/NdbQueryBuilderImpl.hpp	2011-09-14 13:56:17 +0000
+++ b/storage/ndb/src/ndbapi/NdbQueryBuilderImpl.hpp	2011-10-03 08:02:28 +0000
@@ -429,6 +429,12 @@ public:
   // Get type of query operation
   virtual NdbQueryOperationDef::Type getType() const = 0;
 
+  /**
+   * Used for telling if parent at depth n has more siblings. (In that case
+   * we need to draw a horisontal line leading to that sibling.)
+   */
+  typedef Bitmask<(NDB_SPJ_MAX_TREE_NODES+31)/32> SiblingMask;
+
   /** Print query tree graph to trace file (using recursion).
    * @param depth Number of ancestor nodes that this node has.
    * @param hasMoreSiblingsMask The n'th bit should be set if the n'th ancestor
@@ -436,7 +442,7 @@ public:
    */
   void printTree(
            Uint32 depth, 
-           Bitmask<(NDB_SPJ_MAX_TREE_NODES+31)/32> hasMoreSiblingsMask) const;
+           SiblingMask hasMoreSiblingsMask) const;
 
 protected:
   // QueryTree building:

=== modified file 'storage/ndb/src/ndbjtie/test/test/MySqlUtilsCharsetMapTest.java'
--- a/storage/ndb/src/ndbjtie/test/test/MySqlUtilsCharsetMapTest.java	2011-02-02 09:52:33 +0000
+++ b/storage/ndb/src/ndbjtie/test/test/MySqlUtilsCharsetMapTest.java	2011-09-30 15:21:28 +0000
@@ -118,7 +118,7 @@ public class MySqlUtilsCharsetMapTest ex
         out.println("  <-- Test CharsetMap::getName()");
         
         /* Now we're going to recode. 
-         We test with the string "��lker", which begins with the character
+         We test with a string that begins with the character
          LATIN SMALL LETTER U WITH DIARESIS - unicode code point U+00FC.
          In the latin1 encoding this is a literal 0xFC,
          but in the UTF-8 representation it is 0xC3 0xBC.

=== modified file 'storage/ndb/test/src/NDBT_Find.cpp'
--- a/storage/ndb/test/src/NDBT_Find.cpp	2011-07-05 12:46:07 +0000
+++ b/storage/ndb/test/src/NDBT_Find.cpp	2011-10-03 07:22:29 +0000
@@ -83,7 +83,10 @@ NDBT_find_ndb_mgmd(BaseString& path)
 {
   NDBT_find_binary(path, "ndb_mgmd",
                    "../../src/mgmsrv",
-                   "../storage/ndb/src/mgmsrv/",
+                   "../storage/ndb/src/mgmsrv",
+                   "../libexec",
+                   "../sbin",
+                   "../bin",
                    NULL);
 }
 

No bundle (reason: useless for push emails).
Thread
bzr push into mysql-5.5-cluster branch (jonas.oreland:3562 to 3564) Jonas Oreland3 Oct