drill-commits mailing list archives

Site index · List index
Message view « Date » · « Thread »
Top « Date » · « Thread »
From par...@apache.org
Subject [2/4] drill git commit: DRILL-1062: Implemented null ordering (NULLS FIRST/NULLS LAST).
Date Mon, 23 Feb 2015 19:53:11 GMT
http://git-wip-us.apache.org/repos/asf/drill/blob/5efc7e68/exec/java-exec/src/main/java/org/apache/drill/exec/expr/fn/impl/ComparisonFunctionsNullable.java
----------------------------------------------------------------------
diff --git a/exec/java-exec/src/main/java/org/apache/drill/exec/expr/fn/impl/ComparisonFunctionsNullable.java b/exec/java-exec/src/main/java/org/apache/drill/exec/expr/fn/impl/ComparisonFunctionsNullable.java
deleted file mode 100644
index 570aaeb..0000000
--- a/exec/java-exec/src/main/java/org/apache/drill/exec/expr/fn/impl/ComparisonFunctionsNullable.java
+++ /dev/null
@@ -1,250 +0,0 @@
-/**
- * Licensed to the Apache Software Foundation (ASF) under one
- * or more contributor license agreements.  See the NOTICE file
- * distributed with this work for additional information
- * regarding copyright ownership.  The ASF licenses this file
- * to you under the Apache License, Version 2.0 (the
- * "License"); you may not use this file except in compliance
- * with the License.  You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-package org.apache.drill.exec.expr.fn.impl;
-
-import org.apache.drill.exec.expr.DrillSimpleFunc;
-import org.apache.drill.exec.expr.annotations.FunctionTemplate;
-import org.apache.drill.exec.expr.annotations.Output;
-import org.apache.drill.exec.expr.annotations.Param;
-import org.apache.drill.exec.expr.holders.BitHolder;
-import org.apache.drill.exec.expr.holders.NullableBigIntHolder;
-import org.apache.drill.exec.expr.holders.NullableIntHolder;
-import org.apache.drill.exec.record.RecordBatch;
-
-public class ComparisonFunctionsNullable {
-    static final org.slf4j.Logger logger = org.slf4j.LoggerFactory.getLogger(ComparisonFunctionsNullable.class);
-
-    private ComparisonFunctionsNullable() {}
-
-    @FunctionTemplate(names = {"equal", "=", "=="}, scope = FunctionTemplate.FunctionScope.SIMPLE)
-    public static class NullableIntEqual implements DrillSimpleFunc {
-
-        @Param NullableIntHolder left;
-        @Param NullableIntHolder right;
-        @Output BitHolder out;
-
-        public void setup(RecordBatch b) {}
-
-        public void eval() {
-            if (left.isSet  == 0 || right.isSet == 0) {
-                out.value = 0;
-            } else {
-                out.value = (left.value == right.value) ? 1 : 0;
-            }
-        }
-    }
-
-    @FunctionTemplate(names = {"equal", "=", "=="}, scope = FunctionTemplate.FunctionScope.SIMPLE)
-    public static class NullableBigIntEqual implements DrillSimpleFunc {
-
-        @Param NullableBigIntHolder left;
-        @Param NullableBigIntHolder right;
-        @Output BitHolder out;
-
-        public void setup(RecordBatch b) {}
-
-        public void eval() {
-            if (left.isSet  == 0 || right.isSet == 0) {
-                out.value = 0;
-            } else {
-                out.value = (left.value == right.value) ? 1 : 0;
-            }
-        }
-    }
-
-    @FunctionTemplate(names = {"not equal", "<>", "!="}, scope = FunctionTemplate.FunctionScope.SIMPLE)
-    public static class NullableIntNotEqual implements DrillSimpleFunc {
-
-        @Param NullableIntHolder left;
-        @Param NullableIntHolder right;
-        @Output BitHolder out;
-
-        public void setup(RecordBatch b) {}
-
-        public void eval() {
-            if (left.isSet  == 0 || right.isSet == 0) {
-                out.value = 0;
-            } else {
-                out.value = (left.value != right.value) ? 1 : 0;
-            }
-        }
-    }
-
-    @FunctionTemplate(names = {"not equal", "<>", "!="}, scope = FunctionTemplate.FunctionScope.SIMPLE)
-    public static class NullableBigIntNotEqual implements DrillSimpleFunc {
-
-        @Param NullableBigIntHolder left;
-        @Param NullableBigIntHolder right;
-        @Output BitHolder out;
-
-        public void setup(RecordBatch b) {}
-
-        public void eval() {
-            if (left.isSet  == 0 || right.isSet == 0) {
-                out.value = 0;
-            } else {
-                out.value = (left.value != right.value) ? 1 : 0;
-            }
-        }
-    }
-
-    @FunctionTemplate(names = {"less than","<"}, scope = FunctionTemplate.FunctionScope.SIMPLE)
-    public static class NullableIntLessThan implements DrillSimpleFunc {
-
-        @Param NullableIntHolder left;
-        @Param NullableIntHolder right;
-        @Output BitHolder out;
-
-        public void setup(RecordBatch b) {}
-
-        public void eval() {
-            if (left.isSet  == 0 || right.isSet == 0) {
-                out.value = 0;
-            } else {
-                out.value = (left.value < right.value) ? 1 : 0;
-            }
-        }
-    }
-
-    @FunctionTemplate(names = {"less than","<"}, scope = FunctionTemplate.FunctionScope.SIMPLE)
-    public static class NullableBigIntLessThan implements DrillSimpleFunc {
-
-        @Param NullableBigIntHolder left;
-        @Param NullableBigIntHolder right;
-        @Output BitHolder out;
-
-        public void setup(RecordBatch b) {}
-
-        public void eval() {
-            if (left.isSet  == 0 || right.isSet == 0) {
-                out.value = 0;
-            } else {
-                out.value = (left.value < right.value) ? 1 : 0;
-            }
-        }
-    }
-
-    @FunctionTemplate(names = {"less than or equal to","<="}, scope = FunctionTemplate.FunctionScope.SIMPLE)
-    public static class NullableIntLessThanEqual implements DrillSimpleFunc {
-
-        @Param NullableIntHolder left;
-        @Param NullableIntHolder right;
-        @Output BitHolder out;
-
-        public void setup(RecordBatch b) {}
-
-        public void eval() {
-            if (left.isSet  == 0 || right.isSet == 0) {
-                out.value = 0;
-            } else {
-                out.value = (left.value <= right.value) ? 1 : 0;
-            }
-        }
-    }
-
-    @FunctionTemplate(names = {"less than or equal to","<="}, scope = FunctionTemplate.FunctionScope.SIMPLE)
-    public static class NullableBigIntLessThanEqual implements DrillSimpleFunc {
-
-        @Param NullableBigIntHolder left;
-        @Param NullableBigIntHolder right;
-        @Output BitHolder out;
-
-        public void setup(RecordBatch b) {}
-
-        public void eval() {
-            if (left.isSet  == 0 || right.isSet == 0) {
-                out.value = 0;
-            } else {
-                out.value = (left.value <= right.value) ? 1 : 0;
-            }
-        }
-    }
-
-    @FunctionTemplate(names = {"greater than",">"}, scope = FunctionTemplate.FunctionScope.SIMPLE)
-    public static class NullableIntGreaterThan implements DrillSimpleFunc {
-
-        @Param NullableIntHolder left;
-        @Param NullableIntHolder right;
-        @Output BitHolder out;
-
-        public void setup(RecordBatch b) {}
-
-        public void eval() {
-            if (left.isSet  == 0 || right.isSet == 0) {
-                out.value = 0;
-            } else {
-                out.value = (left.value > right.value) ? 1 : 0;
-            }
-        }
-    }
-
-    @FunctionTemplate(names = {"greater than",">"}, scope = FunctionTemplate.FunctionScope.SIMPLE)
-    public static class NullableBigIntGreaterThan implements DrillSimpleFunc {
-
-        @Param NullableBigIntHolder left;
-        @Param NullableBigIntHolder right;
-        @Output BitHolder out;
-
-        public void setup(RecordBatch b) {}
-
-        public void eval() {
-            if (left.isSet  == 0 || right.isSet == 0) {
-                out.value = 0;
-            } else {
-                out.value = (left.value > right.value) ? 1 : 0;
-            }
-        }
-    }
-
-    @FunctionTemplate(names = {"greater than or equal to",">="}, scope = FunctionTemplate.FunctionScope.SIMPLE)
-    public static class NullableIntGreaterThanEqual implements DrillSimpleFunc {
-
-        @Param NullableIntHolder left;
-        @Param NullableIntHolder right;
-        @Output BitHolder out;
-
-        public void setup(RecordBatch b) {}
-
-        public void eval() {
-            if (left.isSet  == 0 || right.isSet == 0) {
-                out.value = 0;
-            } else {
-                out.value = (left.value >= right.value) ? 1 : 0;
-            }
-        }
-    }
-
-    @FunctionTemplate(names = {"greater than or equal to",">="},
-                      scope = FunctionTemplate.FunctionScope.SIMPLE)
-    public static class NullableBigIntGreaterThanEqual implements DrillSimpleFunc {
-
-        @Param NullableBigIntHolder left;
-        @Param NullableBigIntHolder right;
-        @Output BitHolder out;
-
-        public void setup(RecordBatch b) {}
-
-        public void eval() {
-            if (left.isSet  == 0 || right.isSet == 0) {
-                out.value = 0;
-            } else {
-                out.value = (left.value >= right.value) ? 1 : 0;
-            }
-        }
-    }
-}

http://git-wip-us.apache.org/repos/asf/drill/blob/5efc7e68/exec/java-exec/src/main/java/org/apache/drill/exec/physical/impl/TopN/TopNBatch.java
----------------------------------------------------------------------
diff --git a/exec/java-exec/src/main/java/org/apache/drill/exec/physical/impl/TopN/TopNBatch.java b/exec/java-exec/src/main/java/org/apache/drill/exec/physical/impl/TopN/TopNBatch.java
index 9829fc6..a73bdad 100644
--- a/exec/java-exec/src/main/java/org/apache/drill/exec/physical/impl/TopN/TopNBatch.java
+++ b/exec/java-exec/src/main/java/org/apache/drill/exec/physical/impl/TopN/TopNBatch.java
@@ -61,6 +61,7 @@ import org.apache.drill.exec.record.selection.SelectionVector4;
 import org.apache.drill.exec.vector.ValueVector;
 import org.apache.drill.exec.vector.complex.AbstractContainerVector;
 import org.eigenbase.rel.RelFieldCollation.Direction;
+import org.eigenbase.rel.RelFieldCollation.NullDirection;
 
 import com.google.common.base.Stopwatch;
 import com.google.common.collect.Lists;
@@ -324,7 +325,9 @@ public class TopNBatch extends AbstractRecordBatch<TopN> {
       g.setMappingSet(mainMapping);
 
       // next we wrap the two comparison sides and add the expression block for the comparison.
-      LogicalExpression fh = FunctionGenerationHelper.getComparator(left, right, context.getFunctionRegistry());
+      LogicalExpression fh =
+        FunctionGenerationHelper.getOrderingComparator(od.nullsSortHigh(), left, right,
+                                                       context.getFunctionRegistry());
       HoldingContainer out = g.addExpr(fh, false);
       JConditional jc = g.getEvalBlock()._if(out.getValue().ne(JExpr.lit(0)));
 

http://git-wip-us.apache.org/repos/asf/drill/blob/5efc7e68/exec/java-exec/src/main/java/org/apache/drill/exec/physical/impl/aggregate/StreamingAggBatch.java
----------------------------------------------------------------------
diff --git a/exec/java-exec/src/main/java/org/apache/drill/exec/physical/impl/aggregate/StreamingAggBatch.java b/exec/java-exec/src/main/java/org/apache/drill/exec/physical/impl/aggregate/StreamingAggBatch.java
index 860627d..4acf3d6 100644
--- a/exec/java-exec/src/main/java/org/apache/drill/exec/physical/impl/aggregate/StreamingAggBatch.java
+++ b/exec/java-exec/src/main/java/org/apache/drill/exec/physical/impl/aggregate/StreamingAggBatch.java
@@ -248,7 +248,9 @@ public class StreamingAggBatch extends AbstractRecordBatch<StreamingAggregate> {
       cg.setMappingSet(IS_SAME_I2);
       HoldingContainer second = cg.addExpr(expr, false);
 
-      LogicalExpression fh = FunctionGenerationHelper.getComparator(first, second, context.getFunctionRegistry());
+      LogicalExpression fh =
+          FunctionGenerationHelper
+          .getOrderingComparatorNullsHigh(first, second, context.getFunctionRegistry());
       HoldingContainer out = cg.addExpr(fh, false);
       cg.getEvalBlock()._if(out.getValue().ne(JExpr.lit(0)))._then()._return(JExpr.FALSE);
     }
@@ -269,7 +271,9 @@ public class StreamingAggBatch extends AbstractRecordBatch<StreamingAggregate> {
       cg.setMappingSet(ISA_B2);
       HoldingContainer second = cg.addExpr(expr, false);
 
-      LogicalExpression fh = FunctionGenerationHelper.getComparator(first, second, context.getFunctionRegistry());
+      LogicalExpression fh =
+          FunctionGenerationHelper
+          .getOrderingComparatorNullsHigh(first, second, context.getFunctionRegistry());
       HoldingContainer out = cg.addExpr(fh, false);
       cg.getEvalBlock()._if(out.getValue().ne(JExpr.lit(0)))._then()._return(JExpr.FALSE);
     }

http://git-wip-us.apache.org/repos/asf/drill/blob/5efc7e68/exec/java-exec/src/main/java/org/apache/drill/exec/physical/impl/common/ChainedHashTable.java
----------------------------------------------------------------------
diff --git a/exec/java-exec/src/main/java/org/apache/drill/exec/physical/impl/common/ChainedHashTable.java b/exec/java-exec/src/main/java/org/apache/drill/exec/physical/impl/common/ChainedHashTable.java
index ea19645..8f921f7 100644
--- a/exec/java-exec/src/main/java/org/apache/drill/exec/physical/impl/common/ChainedHashTable.java
+++ b/exec/java-exec/src/main/java/org/apache/drill/exec/physical/impl/common/ChainedHashTable.java
@@ -250,8 +250,10 @@ public class ChainedHashTable {
         jc._then()._return(JExpr.FALSE);
       }
 
-      // next we wrap the two comparison sides and add the expression block for the comparison.
-      LogicalExpression f = FunctionGenerationHelper.getComparator(left, right, context.getFunctionRegistry());
+      final LogicalExpression f =
+          FunctionGenerationHelper
+          .getOrderingComparatorNullsHigh(left, right, context.getFunctionRegistry());
+
       HoldingContainer out = cg.addExpr(f, false);
 
       // check if two values are not equal (comparator result != 0)

http://git-wip-us.apache.org/repos/asf/drill/blob/5efc7e68/exec/java-exec/src/main/java/org/apache/drill/exec/physical/impl/join/JoinStatus.java
----------------------------------------------------------------------
diff --git a/exec/java-exec/src/main/java/org/apache/drill/exec/physical/impl/join/JoinStatus.java b/exec/java-exec/src/main/java/org/apache/drill/exec/physical/impl/join/JoinStatus.java
index a7fa5aa..8dfc8f1 100644
--- a/exec/java-exec/src/main/java/org/apache/drill/exec/physical/impl/join/JoinStatus.java
+++ b/exec/java-exec/src/main/java/org/apache/drill/exec/physical/impl/join/JoinStatus.java
@@ -72,6 +72,29 @@ public final class JoinStatus {
     this.joinType = output.getJoinType();
   }
 
+  @Override
+  public String toString() {
+    return
+        super.toString()
+        + "["
+        + "leftPosition = " + leftPosition
+        + ", rightPosition = " + rightPosition
+        + ", svRightPosition = " + svRightPosition
+        + ", outputPosition = " + outputPosition
+        + ", lastLeft = " + lastLeft
+        + ", lastRight = " + lastRight
+        + ", rightSourceMode = " + rightSourceMode
+        + ", sv4 = " + sv4
+        + ", joinType = " + joinType
+        + ", ok = " + ok
+        + ", initialSet = " + initialSet
+        + ", leftRepeating = " + leftRepeating
+        + ", left = " + left
+        + ", right = " + right
+        + ", outputBatch = " + outputBatch
+        + "]";
+  }
+
   private final IterOutcome nextLeft() {
     return outputBatch.next(LEFT_INPUT, left);
   }

http://git-wip-us.apache.org/repos/asf/drill/blob/5efc7e68/exec/java-exec/src/main/java/org/apache/drill/exec/physical/impl/join/JoinTemplate.java
----------------------------------------------------------------------
diff --git a/exec/java-exec/src/main/java/org/apache/drill/exec/physical/impl/join/JoinTemplate.java b/exec/java-exec/src/main/java/org/apache/drill/exec/physical/impl/join/JoinTemplate.java
index 48a0996..4124e6d 100644
--- a/exec/java-exec/src/main/java/org/apache/drill/exec/physical/impl/join/JoinTemplate.java
+++ b/exec/java-exec/src/main/java/org/apache/drill/exec/physical/impl/join/JoinTemplate.java
@@ -155,7 +155,9 @@ public abstract class JoinTemplate implements JoinWorker {
           }
           status.advanceRight();
 
-        } while ((!status.isLeftRepeating() || status.isRightPositionInCurrentBatch()) && status.isRightPositionAllowed() && doCompare(status.getLeftPosition(), status.getRightPosition()) == 0);
+        } while ((!status.isLeftRepeating() || status.isRightPositionInCurrentBatch())
+                 && status.isRightPositionAllowed()
+                 && doCompare(status.getLeftPosition(), status.getRightPosition()) == 0);
 
         if (status.getRightPosition() > initialRightPosition &&
             (status.isLeftRepeating() || ! status.isNextLeftPositionInCurrentBatch())) {
@@ -204,8 +206,8 @@ public abstract class JoinTemplate implements JoinWorker {
   /**
    * Copy the data to the new record batch (if it fits).
    *
-   * @param leftIndex  position of batch (lower 16 bits) and record (upper 16 bits) in left SV4
-   * @param outIndex position of the output record batch
+   * @param  leftIndex   position of batch (lower 16 bits) and record (upper 16 bits) in left SV4
+   * @param  outIndex  position of the output record batch
    * @return Whether or not the data was copied.
    */
   public abstract void doCopyLeft(@Named("leftIndex") int leftIndex, @Named("outIndex") int outIndex);
@@ -228,8 +230,8 @@ public abstract class JoinTemplate implements JoinWorker {
 
   /**
    * Compare the current left key to the next left key, if it's within the batch.
-   * @return  0 if both keys are equal
-   *          1 if the keys are not equal
+   * @return  0 if both keys are equal,
+   *          1 if the keys are not equal, and
    *         -1 if there are no more keys in this batch
    */
   protected abstract int doCompareNextLeftKey(@Named("leftIndex") int leftIndex);

http://git-wip-us.apache.org/repos/asf/drill/blob/5efc7e68/exec/java-exec/src/main/java/org/apache/drill/exec/physical/impl/join/MergeJoinBatch.java
----------------------------------------------------------------------
diff --git a/exec/java-exec/src/main/java/org/apache/drill/exec/physical/impl/join/MergeJoinBatch.java b/exec/java-exec/src/main/java/org/apache/drill/exec/physical/impl/join/MergeJoinBatch.java
index 257b93e..8fce52e 100644
--- a/exec/java-exec/src/main/java/org/apache/drill/exec/physical/impl/join/MergeJoinBatch.java
+++ b/exec/java-exec/src/main/java/org/apache/drill/exec/physical/impl/join/MergeJoinBatch.java
@@ -313,12 +313,13 @@ public class MergeJoinBatch extends AbstractRecordBatch<MergeJoinPOP> {
 
       // check value equality
 
-      LogicalExpression gh = FunctionGenerationHelper.getComparator(compareThisLeftExprHolder,
-        compareNextLeftExprHolder,
-        context.getFunctionRegistry());
+      LogicalExpression gh =
+          FunctionGenerationHelper.getOrderingComparatorNullsHigh(compareThisLeftExprHolder,
+                                                                  compareNextLeftExprHolder,
+                                                                  context.getFunctionRegistry());
       HoldingContainer out = cg.addExpr(gh, false);
 
-      //If not 0, it means not equal. We return this out value.
+      // If not 0, it means not equal. We return this out value.
       JConditional jc = cg.getEvalBlock()._if(out.getValue().ne(JExpr.lit(0)));
       jc._then()._return(out.getValue());
     }
@@ -523,12 +524,13 @@ public class MergeJoinBatch extends AbstractRecordBatch<MergeJoinPOP> {
         cg.getSetupBlock().assign(JExpr._this().ref(incomingRecordBatch), JExpr._this().ref(incomingRightRecordBatch));
         ClassGenerator.HoldingContainer compareRightExprHolder = cg.addExpr(materializedRightExpr, false);
 
-        LogicalExpression fh = FunctionGenerationHelper.getComparator(compareLeftExprHolder,
-          compareRightExprHolder,
-          context.getFunctionRegistry());
+        LogicalExpression fh =
+            FunctionGenerationHelper.getOrderingComparatorNullsHigh(compareLeftExprHolder,
+                                                                    compareRightExprHolder,
+                                                                    context.getFunctionRegistry());
         HoldingContainer out = cg.addExpr(fh, false);
 
-        // If not 0, it means not equal. We return this out value.
+        // If not 0, it means not equal.
         // Null compares to Null should returns null (unknown). In such case, we return 1 to indicate they are not equal.
         if (compareLeftExprHolder.isOptional() && compareRightExprHolder.isOptional()
             && ! areNullsEqual) {

http://git-wip-us.apache.org/repos/asf/drill/blob/5efc7e68/exec/java-exec/src/main/java/org/apache/drill/exec/physical/impl/mergereceiver/MergingRecordBatch.java
----------------------------------------------------------------------
diff --git a/exec/java-exec/src/main/java/org/apache/drill/exec/physical/impl/mergereceiver/MergingRecordBatch.java b/exec/java-exec/src/main/java/org/apache/drill/exec/physical/impl/mergereceiver/MergingRecordBatch.java
index d78ba8e..804671e 100644
--- a/exec/java-exec/src/main/java/org/apache/drill/exec/physical/impl/mergereceiver/MergingRecordBatch.java
+++ b/exec/java-exec/src/main/java/org/apache/drill/exec/physical/impl/mergereceiver/MergingRecordBatch.java
@@ -76,6 +76,7 @@ import org.apache.drill.exec.vector.CopyUtil;
 import org.apache.drill.exec.vector.FixedWidthVector;
 import org.apache.drill.exec.vector.ValueVector;
 import org.eigenbase.rel.RelFieldCollation.Direction;
+import org.eigenbase.rel.RelFieldCollation.NullDirection;
 
 import parquet.Preconditions;
 
@@ -636,7 +637,9 @@ public class MergingRecordBatch extends AbstractRecordBatch<MergingReceiverPOP>
       g.setMappingSet(MAIN_MAPPING);
 
       // next we wrap the two comparison sides and add the expression block for the comparison.
-      LogicalExpression fh = FunctionGenerationHelper.getComparator(left, right, context.getFunctionRegistry());
+      LogicalExpression fh =
+          FunctionGenerationHelper.getOrderingComparator(od.nullsSortHigh(), left, right,
+                                                         context.getFunctionRegistry());
       HoldingContainer out = g.addExpr(fh, false);
       JConditional jc = g.getEvalBlock()._if(out.getValue().ne(JExpr.lit(0)));
 

http://git-wip-us.apache.org/repos/asf/drill/blob/5efc7e68/exec/java-exec/src/main/java/org/apache/drill/exec/physical/impl/orderedpartitioner/OrderedPartitionRecordBatch.java
----------------------------------------------------------------------
diff --git a/exec/java-exec/src/main/java/org/apache/drill/exec/physical/impl/orderedpartitioner/OrderedPartitionRecordBatch.java b/exec/java-exec/src/main/java/org/apache/drill/exec/physical/impl/orderedpartitioner/OrderedPartitionRecordBatch.java
index a062074..352e7ae 100644
--- a/exec/java-exec/src/main/java/org/apache/drill/exec/physical/impl/orderedpartitioner/OrderedPartitionRecordBatch.java
+++ b/exec/java-exec/src/main/java/org/apache/drill/exec/physical/impl/orderedpartitioner/OrderedPartitionRecordBatch.java
@@ -70,6 +70,7 @@ import org.apache.drill.exec.vector.AllocationHelper;
 import org.apache.drill.exec.vector.IntVector;
 import org.apache.drill.exec.vector.ValueVector;
 import org.eigenbase.rel.RelFieldCollation.Direction;
+import org.eigenbase.rel.RelFieldCollation.NullDirection;
 
 import com.google.common.base.Preconditions;
 import com.google.common.collect.Lists;
@@ -574,7 +575,10 @@ public class OrderedPartitionRecordBatch extends AbstractRecordBatch<OrderedPart
           new ValueVectorReadExpression(new TypedFieldId(expr.getMajorType(), count++)), false);
       cg.setMappingSet(mainMapping);
 
-      LogicalExpression fh = FunctionGenerationHelper.getComparator(left, right, context.getFunctionRegistry());
+      // next we wrap the two comparison sides and add the expression block for the comparison.
+      LogicalExpression fh =
+          FunctionGenerationHelper.getOrderingComparator(od.nullsSortHigh(), left, right,
+                                                         context.getFunctionRegistry());
       ClassGenerator.HoldingContainer out = cg.addExpr(fh, false);
       JConditional jc = cg.getEvalBlock()._if(out.getValue().ne(JExpr.lit(0)));
 

http://git-wip-us.apache.org/repos/asf/drill/blob/5efc7e68/exec/java-exec/src/main/java/org/apache/drill/exec/physical/impl/sort/SortBatch.java
----------------------------------------------------------------------
diff --git a/exec/java-exec/src/main/java/org/apache/drill/exec/physical/impl/sort/SortBatch.java b/exec/java-exec/src/main/java/org/apache/drill/exec/physical/impl/sort/SortBatch.java
index 19f5423..6f19e91 100644
--- a/exec/java-exec/src/main/java/org/apache/drill/exec/physical/impl/sort/SortBatch.java
+++ b/exec/java-exec/src/main/java/org/apache/drill/exec/physical/impl/sort/SortBatch.java
@@ -43,6 +43,7 @@ import org.apache.drill.exec.record.WritableBatch;
 import org.apache.drill.exec.record.selection.SelectionVector2;
 import org.apache.drill.exec.record.selection.SelectionVector4;
 import org.eigenbase.rel.RelFieldCollation.Direction;
+import org.eigenbase.rel.RelFieldCollation.NullDirection;
 
 import com.sun.codemodel.JConditional;
 import com.sun.codemodel.JExpr;
@@ -180,7 +181,9 @@ public class SortBatch extends AbstractRecordBatch<Sort> {
       g.setMappingSet(mainMapping);
 
       // next we wrap the two comparison sides and add the expression block for the comparison.
-      LogicalExpression fh = FunctionGenerationHelper.getComparator(left, right, context.getFunctionRegistry());
+      LogicalExpression fh =
+        FunctionGenerationHelper.getOrderingComparator(od.nullsSortHigh(), left, right,
+                                                       context.getFunctionRegistry());
       HoldingContainer out = g.addExpr(fh, false);
       JConditional jc = g.getEvalBlock()._if(out.getValue().ne(JExpr.lit(0)));
 

http://git-wip-us.apache.org/repos/asf/drill/blob/5efc7e68/exec/java-exec/src/main/java/org/apache/drill/exec/physical/impl/window/StreamingWindowFrameRecordBatch.java
----------------------------------------------------------------------
diff --git a/exec/java-exec/src/main/java/org/apache/drill/exec/physical/impl/window/StreamingWindowFrameRecordBatch.java b/exec/java-exec/src/main/java/org/apache/drill/exec/physical/impl/window/StreamingWindowFrameRecordBatch.java
index 26d23f2..87209eb 100644
--- a/exec/java-exec/src/main/java/org/apache/drill/exec/physical/impl/window/StreamingWindowFrameRecordBatch.java
+++ b/exec/java-exec/src/main/java/org/apache/drill/exec/physical/impl/window/StreamingWindowFrameRecordBatch.java
@@ -185,7 +185,9 @@ public class StreamingWindowFrameRecordBatch extends AbstractSingleRecordBatch<W
       cg.setMappingSet(ISA_B2);
       ClassGenerator.HoldingContainer second = cg.addExpr(expr, false);
 
-      LogicalExpression fh = FunctionGenerationHelper.getComparator(first, second, context.getFunctionRegistry());
+      LogicalExpression fh =
+          FunctionGenerationHelper
+          .getOrderingComparatorNullsHigh(first, second, context.getFunctionRegistry());
       ClassGenerator.HoldingContainer out = cg.addExpr(fh, false);
       cg.getEvalBlock()._if(out.getValue().ne(JExpr.lit(0)))._then()._return(JExpr.FALSE);
     }
@@ -205,7 +207,9 @@ public class StreamingWindowFrameRecordBatch extends AbstractSingleRecordBatch<W
       cg.setMappingSet(IS_SAME_I2);
       ClassGenerator.HoldingContainer second = cg.addExpr(expr, false);
 
-      LogicalExpression fh = FunctionGenerationHelper.getComparator(first, second, context.getFunctionRegistry());
+      LogicalExpression fh =
+          FunctionGenerationHelper
+          .getOrderingComparatorNullsHigh(first, second, context.getFunctionRegistry());
       ClassGenerator.HoldingContainer out = cg.addExpr(fh, false);
       cg.getEvalBlock()._if(out.getValue().ne(JExpr.lit(0)))._then()._return(JExpr.FALSE);
     }

http://git-wip-us.apache.org/repos/asf/drill/blob/5efc7e68/exec/java-exec/src/main/java/org/apache/drill/exec/physical/impl/xsort/ExternalSortBatch.java
----------------------------------------------------------------------
diff --git a/exec/java-exec/src/main/java/org/apache/drill/exec/physical/impl/xsort/ExternalSortBatch.java b/exec/java-exec/src/main/java/org/apache/drill/exec/physical/impl/xsort/ExternalSortBatch.java
index 9026661..f320bbb 100644
--- a/exec/java-exec/src/main/java/org/apache/drill/exec/physical/impl/xsort/ExternalSortBatch.java
+++ b/exec/java-exec/src/main/java/org/apache/drill/exec/physical/impl/xsort/ExternalSortBatch.java
@@ -65,6 +65,7 @@ import org.apache.drill.exec.vector.complex.AbstractContainerVector;
 import org.apache.hadoop.conf.Configuration;
 import org.apache.hadoop.fs.FileSystem;
 import org.eigenbase.rel.RelFieldCollation.Direction;
+import org.eigenbase.rel.RelFieldCollation.NullDirection;
 
 import com.google.common.base.Stopwatch;
 import com.google.common.collect.Iterators;
@@ -565,7 +566,9 @@ public class ExternalSortBatch extends AbstractRecordBatch<ExternalSort> {
       g.setMappingSet(mainMapping);
 
       // next we wrap the two comparison sides and add the expression block for the comparison.
-      LogicalExpression fh = FunctionGenerationHelper.getComparator(left, right, context.getFunctionRegistry());
+      LogicalExpression fh =
+          FunctionGenerationHelper.getOrderingComparator(od.nullsSortHigh(), left, right,
+                                                         context.getFunctionRegistry());
       HoldingContainer out = g.addExpr(fh, false);
       JConditional jc = g.getEvalBlock()._if(out.getValue().ne(JExpr.lit(0)));
 
@@ -612,7 +615,9 @@ public class ExternalSortBatch extends AbstractRecordBatch<ExternalSort> {
       g.setMappingSet(MAIN_MAPPING);
 
       // next we wrap the two comparison sides and add the expression block for the comparison.
-      LogicalExpression fh = FunctionGenerationHelper.getComparator(left, right, context.getFunctionRegistry());
+      LogicalExpression fh =
+          FunctionGenerationHelper.getOrderingComparator(od.nullsSortHigh(), left, right,
+                                                         context.getFunctionRegistry());
       HoldingContainer out = g.addExpr(fh, false);
       JConditional jc = g.getEvalBlock()._if(out.getValue().ne(JExpr.lit(0)));
 

http://git-wip-us.apache.org/repos/asf/drill/blob/5efc7e68/exec/java-exec/src/main/java/org/apache/drill/exec/physical/impl/xsort/MSorter.java
----------------------------------------------------------------------
diff --git a/exec/java-exec/src/main/java/org/apache/drill/exec/physical/impl/xsort/MSorter.java b/exec/java-exec/src/main/java/org/apache/drill/exec/physical/impl/xsort/MSorter.java
index e80d309..d97ffc0 100644
--- a/exec/java-exec/src/main/java/org/apache/drill/exec/physical/impl/xsort/MSorter.java
+++ b/exec/java-exec/src/main/java/org/apache/drill/exec/physical/impl/xsort/MSorter.java
@@ -24,6 +24,8 @@ import org.apache.drill.exec.ops.FragmentContext;
 import org.apache.drill.exec.record.VectorContainer;
 import org.apache.drill.exec.record.selection.SelectionVector4;
 
+// TODO:  Doc.:  What's an MSorter?  A sorter for merge join?  something else?
+// (What's the "M" part?  Actually, rename interface to clearer.
 public interface MSorter {
   public void setup(FragmentContext context, BufferAllocator allocator, SelectionVector4 vector4, VectorContainer hyperBatch) throws SchemaChangeException;
   public void sort(VectorContainer container);

http://git-wip-us.apache.org/repos/asf/drill/blob/5efc7e68/exec/java-exec/src/main/java/org/apache/drill/exec/planner/physical/ProjectPrule.java
----------------------------------------------------------------------
diff --git a/exec/java-exec/src/main/java/org/apache/drill/exec/planner/physical/ProjectPrule.java b/exec/java-exec/src/main/java/org/apache/drill/exec/planner/physical/ProjectPrule.java
index 732a345..72034ed 100644
--- a/exec/java-exec/src/main/java/org/apache/drill/exec/planner/physical/ProjectPrule.java
+++ b/exec/java-exec/src/main/java/org/apache/drill/exec/planner/physical/ProjectPrule.java
@@ -115,7 +115,7 @@ public class ProjectPrule extends Prule {
 
     for ( RelFieldCollation field : src.getFieldCollations()) {
       if (inToOut.containsKey(field.getFieldIndex())) {
-        newFields.add(new RelFieldCollation(inToOut.get(field.getFieldIndex()), field.getDirection()));
+        newFields.add(new RelFieldCollation(inToOut.get(field.getFieldIndex()), field.getDirection(), field.nullDirection));
       }
     }
 

http://git-wip-us.apache.org/repos/asf/drill/blob/5efc7e68/exec/java-exec/src/main/java/org/apache/drill/exec/rpc/user/QueryResultHandler.java
----------------------------------------------------------------------
diff --git a/exec/java-exec/src/main/java/org/apache/drill/exec/rpc/user/QueryResultHandler.java b/exec/java-exec/src/main/java/org/apache/drill/exec/rpc/user/QueryResultHandler.java
index 9015a16..b079428 100644
--- a/exec/java-exec/src/main/java/org/apache/drill/exec/rpc/user/QueryResultHandler.java
+++ b/exec/java-exec/src/main/java/org/apache/drill/exec/rpc/user/QueryResultHandler.java
@@ -65,7 +65,7 @@ public class QueryResultHandler {
     if (l == null) {
       BufferingListener bl = new BufferingListener();
       l = resultsListener.putIfAbsent(result.getQueryId(), bl);
-      // if we had a succesful insert, use that reference.  Otherwise, just throw away the new bufering listener.
+      // if we had a successful insert, use that reference.  Otherwise, just throw away the new bufering listener.
       if (l == null) {
         l = bl;
       }

http://git-wip-us.apache.org/repos/asf/drill/blob/5efc7e68/exec/java-exec/src/test/java/org/apache/drill/TestAggNullable.java
----------------------------------------------------------------------
diff --git a/exec/java-exec/src/test/java/org/apache/drill/TestAggNullable.java b/exec/java-exec/src/test/java/org/apache/drill/TestAggNullable.java
index 4c9617b..34850ba 100644
--- a/exec/java-exec/src/test/java/org/apache/drill/TestAggNullable.java
+++ b/exec/java-exec/src/test/java/org/apache/drill/TestAggNullable.java
@@ -47,12 +47,12 @@ public class TestAggNullable extends BaseTestQuery{
 
     enableAggr(true, false);
     actualRecordCount = testSql(query1);
-    assertEquals(String.format("Received unexepcted number of rows in output: expected=%d, received=%s",
+    assertEquals(String.format("Received unexpected number of rows in output: expected=%d, received=%s",
         expectedRecordCount, actualRecordCount), expectedRecordCount, actualRecordCount);
 
     expectedRecordCount = 4;
     actualRecordCount = testSql(query2);
-    assertEquals(String.format("Received unexepcted number of rows in output: expected=%d, received=%s",
+    assertEquals(String.format("Received unexpected number of rows in output: expected=%d, received=%s",
         expectedRecordCount, actualRecordCount), expectedRecordCount, actualRecordCount);
   }
 
@@ -68,12 +68,12 @@ public class TestAggNullable extends BaseTestQuery{
 
     enableAggr(false, true);
     actualRecordCount = testSql(query1);
-    assertEquals(String.format("Received unexepcted number of rows in output: expected=%d, received=%s",
+    assertEquals(String.format("Received unexpected number of rows in output: expected=%d, received=%s",
         expectedRecordCount, actualRecordCount), expectedRecordCount, actualRecordCount);
 
     expectedRecordCount = 4;
     actualRecordCount = testSql(query2);
-    assertEquals(String.format("Received unexepcted number of rows in output: expected=%d, received=%s",
+    assertEquals(String.format("Received unexpected number of rows in output: expected=%d, received=%s",
         expectedRecordCount, actualRecordCount), expectedRecordCount, actualRecordCount);
   }
 

http://git-wip-us.apache.org/repos/asf/drill/blob/5efc7e68/exec/java-exec/src/test/java/org/apache/drill/TestExampleQueries.java
----------------------------------------------------------------------
diff --git a/exec/java-exec/src/test/java/org/apache/drill/TestExampleQueries.java b/exec/java-exec/src/test/java/org/apache/drill/TestExampleQueries.java
index 55fb59f..a54200d 100644
--- a/exec/java-exec/src/test/java/org/apache/drill/TestExampleQueries.java
+++ b/exec/java-exec/src/test/java/org/apache/drill/TestExampleQueries.java
@@ -369,7 +369,7 @@ public class TestExampleQueries extends BaseTestQuery{
   public void testTopNWithSV2() throws Exception {
     int actualRecordCount = testSql("select N_NATIONKEY from cp.`tpch/nation.parquet` where N_NATIONKEY < 10 order by N_NATIONKEY limit 5");
     int expectedRecordCount = 5;
-    assertEquals(String.format("Received unexepcted number of rows in output: expected=%d, received=%s",
+    assertEquals(String.format("Received unexpected number of rows in output: expected=%d, received=%s",
         expectedRecordCount, actualRecordCount), expectedRecordCount, actualRecordCount);
   }
 
@@ -382,7 +382,7 @@ public class TestExampleQueries extends BaseTestQuery{
   public void testLikeEscape() throws Exception {
     int actualRecordCount = testSql("select id, name from cp.`jsoninput/specialchar.json` where name like '%#_%' ESCAPE '#'");
     int expectedRecordCount = 1;
-    assertEquals(String.format("Received unexepcted number of rows in output: expected=%d, received=%s",
+    assertEquals(String.format("Received unexpected number of rows in output: expected=%d, received=%s",
         expectedRecordCount, actualRecordCount), expectedRecordCount, actualRecordCount);
 
   }
@@ -391,7 +391,7 @@ public class TestExampleQueries extends BaseTestQuery{
   public void testSimilarEscape() throws Exception {
     int actualRecordCount = testSql("select id, name from cp.`jsoninput/specialchar.json` where name similar to '(N|S)%#_%' ESCAPE '#'");
     int expectedRecordCount = 1;
-    assertEquals(String.format("Received unexepcted number of rows in output: expected=%d, received=%s",
+    assertEquals(String.format("Received unexpected number of rows in output: expected=%d, received=%s",
         expectedRecordCount, actualRecordCount), expectedRecordCount, actualRecordCount);
   }
 
@@ -399,7 +399,7 @@ public class TestExampleQueries extends BaseTestQuery{
   public void testImplicitDownwardCast() throws Exception {
     int actualRecordCount = testSql("select o_totalprice from cp.`tpch/orders.parquet` where o_orderkey=60000 and o_totalprice=299402");
     int expectedRecordCount = 0;
-    assertEquals(String.format("Received unexepcted number of rows in output: expected=%d, received=%s",
+    assertEquals(String.format("Received unexpected number of rows in output: expected=%d, received=%s",
         expectedRecordCount, actualRecordCount), expectedRecordCount, actualRecordCount);
   }
 
@@ -408,26 +408,26 @@ public class TestExampleQueries extends BaseTestQuery{
     // cast from varchar with unknown length to a fixed length.
     int actualRecordCount = testSql("select first_name from cp.`employee.json` where cast(first_name as varchar(2)) = 'Sh'");
     int expectedRecordCount = 27;
-    assertEquals(String.format("Received unexepcted number of rows in output: expected=%d, received=%s",
+    assertEquals(String.format("Received unexpected number of rows in output: expected=%d, received=%s",
         expectedRecordCount, actualRecordCount), expectedRecordCount, actualRecordCount);
 
     // cast from varchar with unknown length to varchar(5), then to varchar(10), then to varchar(2). Should produce the same result as the first query.
     actualRecordCount = testSql("select first_name from cp.`employee.json` where cast(cast(cast(first_name as varchar(5)) as varchar(10)) as varchar(2)) = 'Sh'");
     expectedRecordCount = 27;
-    assertEquals(String.format("Received unexepcted number of rows in output: expected=%d, received=%s",
+    assertEquals(String.format("Received unexpected number of rows in output: expected=%d, received=%s",
         expectedRecordCount, actualRecordCount), expectedRecordCount, actualRecordCount);
 
 
     // this long nested cast expression should be essentially equal to substr(), meaning the query should return every row in the table.
     actualRecordCount = testSql("select first_name from cp.`employee.json` where cast(cast(cast(first_name as varchar(5)) as varchar(10)) as varchar(2)) = substr(first_name, 1, 2)");
     expectedRecordCount = 1155;
-    assertEquals(String.format("Received unexepcted number of rows in output: expected=%d, received=%s",
+    assertEquals(String.format("Received unexpected number of rows in output: expected=%d, received=%s",
         expectedRecordCount, actualRecordCount), expectedRecordCount, actualRecordCount);
 
     // cast is applied to a column from parquet file.
     actualRecordCount = testSql("select n_name from cp.`tpch/nation.parquet` where cast(n_name as varchar(2)) = 'UN'");
     expectedRecordCount = 2;
-    assertEquals(String.format("Received unexepcted number of rows in output: expected=%d, received=%s",
+    assertEquals(String.format("Received unexpected number of rows in output: expected=%d, received=%s",
         expectedRecordCount, actualRecordCount), expectedRecordCount, actualRecordCount);
   }
 
@@ -476,28 +476,28 @@ public class TestExampleQueries extends BaseTestQuery{
     // source is JSON
     actualRecordCount = testSql("select EMPID from ( select employee_id as empid from cp.`employee.json` limit 2)");
     expectedRecordCount = 2;
-    assertEquals(String.format("Received unexepcted number of rows in output: expected=%d, received=%s",
+    assertEquals(String.format("Received unexpected number of rows in output: expected=%d, received=%s",
         expectedRecordCount, actualRecordCount), expectedRecordCount, actualRecordCount);
 
     actualRecordCount = testSql("select EMPLOYEE_ID from ( select employee_id from cp.`employee.json` where Employee_id is not null limit 2)");
     expectedRecordCount = 2;
-    assertEquals(String.format("Received unexepcted number of rows in output: expected=%d, received=%s",
+    assertEquals(String.format("Received unexpected number of rows in output: expected=%d, received=%s",
         expectedRecordCount, actualRecordCount), expectedRecordCount, actualRecordCount);
 
     actualRecordCount = testSql("select x.EMPLOYEE_ID from ( select employee_id from cp.`employee.json` limit 2) X");
     expectedRecordCount = 2;
-    assertEquals(String.format("Received unexepcted number of rows in output: expected=%d, received=%s",
+    assertEquals(String.format("Received unexpected number of rows in output: expected=%d, received=%s",
         expectedRecordCount, actualRecordCount), expectedRecordCount, actualRecordCount);
 
     // source is PARQUET
     actualRecordCount = testSql("select NID from ( select n_nationkey as nid from cp.`tpch/nation.parquet`) where NID = 3");
     expectedRecordCount = 1;
-    assertEquals(String.format("Received unexepcted number of rows in output: expected=%d, received=%s",
+    assertEquals(String.format("Received unexpected number of rows in output: expected=%d, received=%s",
         expectedRecordCount, actualRecordCount), expectedRecordCount, actualRecordCount);
 
     actualRecordCount = testSql("select x.N_nationkey from ( select n_nationkey from cp.`tpch/nation.parquet`) X where N_NATIONKEY = 3");
     expectedRecordCount = 1;
-    assertEquals(String.format("Received unexepcted number of rows in output: expected=%d, received=%s",
+    assertEquals(String.format("Received unexpected number of rows in output: expected=%d, received=%s",
         expectedRecordCount, actualRecordCount), expectedRecordCount, actualRecordCount);
 
       // source is CSV
@@ -505,7 +505,7 @@ public class TestExampleQueries extends BaseTestQuery{
     String query = String.format("select rid, x.name from (select columns[0] as RID, columns[1] as NAME from dfs_test.`%s`) X where X.rid = 2", root);
     actualRecordCount = testSql(query);
     expectedRecordCount = 1;
-    assertEquals(String.format("Received unexepcted number of rows in output: expected=%d, received=%s",
+    assertEquals(String.format("Received unexpected number of rows in output: expected=%d, received=%s",
         expectedRecordCount, actualRecordCount), expectedRecordCount, actualRecordCount);
 
   }

http://git-wip-us.apache.org/repos/asf/drill/blob/5efc7e68/exec/java-exec/src/test/java/org/apache/drill/TestInList.java
----------------------------------------------------------------------
diff --git a/exec/java-exec/src/test/java/org/apache/drill/TestInList.java b/exec/java-exec/src/test/java/org/apache/drill/TestInList.java
index 03fbf97..b6218ec 100644
--- a/exec/java-exec/src/test/java/org/apache/drill/TestInList.java
+++ b/exec/java-exec/src/test/java/org/apache/drill/TestInList.java
@@ -33,7 +33,7 @@ public class TestInList extends BaseTestQuery{
         ")");
 
     int expectedRecordCount = 59;
-    assertEquals(String.format("Received unexepcted number of rows in output: expected=%d, received=%s",
+    assertEquals(String.format("Received unexpected number of rows in output: expected=%d, received=%s",
         expectedRecordCount, actualRecordCount), expectedRecordCount, actualRecordCount);
   }
 

http://git-wip-us.apache.org/repos/asf/drill/blob/5efc7e68/exec/java-exec/src/test/java/org/apache/drill/TestJoinNullable.java
----------------------------------------------------------------------
diff --git a/exec/java-exec/src/test/java/org/apache/drill/TestJoinNullable.java b/exec/java-exec/src/test/java/org/apache/drill/TestJoinNullable.java
index c49da6c..320a992 100644
--- a/exec/java-exec/src/test/java/org/apache/drill/TestJoinNullable.java
+++ b/exec/java-exec/src/test/java/org/apache/drill/TestJoinNullable.java
@@ -20,6 +20,7 @@ package org.apache.drill;
 import static org.junit.Assert.assertEquals;
 
 import org.apache.drill.common.util.TestTools;
+import org.junit.Ignore;
 import org.junit.Test;
 
 public class TestJoinNullable extends BaseTestQuery{
@@ -35,105 +36,382 @@ public class TestJoinNullable extends BaseTestQuery{
     test("alter session set `planner.slice_target` = 1");
   }
 
-  @Test  // InnerJoin on nullable cols, HashJoin
+  /** InnerJoin on nullable cols, HashJoin */
+  @Test
   public void testHashInnerJoinOnNullableColumns() throws Exception {
     String query = String.format("select t1.a1, t1.b1, t2.a2, t2.b2 from dfs_test.`%s/jsoninput/nullable1.json` t1, " +
-                   " dfs_test.`%s/jsoninput/nullable2.json` t2 where t1.b1 = t2.b2", TEST_RES_PATH ,TEST_RES_PATH);
-    int actualRecordCount;
-    int expectedRecordCount = 1;
+                   " dfs_test.`%s/jsoninput/nullable2.json` t2 where t1.b1 = t2.b2", TEST_RES_PATH, TEST_RES_PATH);
+    final int expectedRecordCount = 1;
 
     enableJoin(true, false);
-    actualRecordCount = testSql(query);
-    assertEquals(String.format("Received unexepcted number of rows in output: expected=%d, received=%s",
-        expectedRecordCount, actualRecordCount), expectedRecordCount, actualRecordCount);
+    final int actualRecordCount = testSql(query);
+    assertEquals("Number of output rows", expectedRecordCount, actualRecordCount);
   }
 
-  @Test // InnerJoin on nullable cols, MergeJoin
-  public void testMergeInnerJoinOnNullableColumns() throws Exception {
-    String query = String.format("select t1.a1, t1.b1, t2.a2, t2.b2 from dfs_test.`%s/jsoninput/nullable1.json` t1, " +
-                   " dfs_test.`%s/jsoninput/nullable2.json` t2 where t1.b1 = t2.b2", TEST_RES_PATH ,TEST_RES_PATH);
-    int actualRecordCount;
-    int expectedRecordCount = 1;
-
-    enableJoin(false, true);
-    actualRecordCount = testSql(query);
-    assertEquals(String.format("Received unexepcted number of rows in output: expected=%d, received=%s",
-        expectedRecordCount, actualRecordCount), expectedRecordCount, actualRecordCount);
-  }
-
-  @Test // LeftOuterJoin on nullable cols, HashJoin
+  /** LeftOuterJoin on nullable cols, HashJoin */
+  @Test
   public void testHashLOJOnNullableColumns() throws Exception {
     String query = String.format("select t1.a1, t1.b1, t2.a2, t2.b2 from dfs_test.`%s/jsoninput/nullable1.json` t1 " +
                       " left outer join dfs_test.`%s/jsoninput/nullable2.json` t2 " +
-                      " on t1.b1 = t2.b2", TEST_RES_PATH ,TEST_RES_PATH);
+                      " on t1.b1 = t2.b2", TEST_RES_PATH, TEST_RES_PATH);
 
-    int actualRecordCount;
-    int expectedRecordCount = 2;
+    final int expectedRecordCount = 2;
 
     enableJoin(true, false);
-    actualRecordCount = testSql(query);
-    assertEquals(String.format("Received unexepcted number of rows in output: expected=%d, received=%s",
-        expectedRecordCount, actualRecordCount), expectedRecordCount, actualRecordCount);
+    final int actualRecordCount = testSql(query);
+    assertEquals("Number of output rows", expectedRecordCount, actualRecordCount);
   }
 
-  @Test // RightOuterJoin on nullable cols, HashJoin
+  /** RightOuterJoin on nullable cols, HashJoin */
+  @Test
   public void testHashROJOnNullableColumns() throws Exception {
     String query = String.format("select t1.a1, t1.b1, t2.a2, t2.b2 from dfs_test.`%s/jsoninput/nullable1.json` t1 " +
                       " right outer join dfs_test.`%s/jsoninput/nullable2.json` t2 " +
-                      " on t1.b1 = t2.b2", TEST_RES_PATH ,TEST_RES_PATH);
+                      " on t1.b1 = t2.b2", TEST_RES_PATH, TEST_RES_PATH);
 
-    int actualRecordCount;
-    int expectedRecordCount = 4;
+    final int expectedRecordCount = 4;
 
     enableJoin(true, false);
-    actualRecordCount = testSql(query);
-    assertEquals(String.format("Received unexepcted number of rows in output: expected=%d, received=%s",
-        expectedRecordCount, actualRecordCount), expectedRecordCount, actualRecordCount);
+    final int actualRecordCount = testSql(query);
+    assertEquals("Number of output rows", expectedRecordCount, actualRecordCount);
   }
 
-  @Test // FullOuterJoin on nullable cols, HashJoin
+  /** FullOuterJoin on nullable cols, HashJoin */
+  @Test
   public void testHashFOJOnNullableColumns() throws Exception {
     String query = String.format("select t1.a1, t1.b1, t2.a2, t2.b2 from dfs_test.`%s/jsoninput/nullable1.json` t1 " +
                       " full outer join dfs_test.`%s/jsoninput/nullable2.json` t2 " +
-                      " on t1.b1 = t2.b2", TEST_RES_PATH ,TEST_RES_PATH);
+                      " on t1.b1 = t2.b2", TEST_RES_PATH, TEST_RES_PATH);
 
-    int actualRecordCount;
-    int expectedRecordCount = 5;
+    final int expectedRecordCount = +5;
 
     enableJoin(true, false);
-    actualRecordCount = testSql(query);
-    assertEquals(String.format("Received unexepcted number of rows in output: expected=%d, received=%s",
-        expectedRecordCount, actualRecordCount), expectedRecordCount, actualRecordCount);
+    final int actualRecordCount = testSql(query);
+    assertEquals("Number of output rows", expectedRecordCount, actualRecordCount);
   }
 
-  @Test // LeftOuterJoin on nullable cols, MergeJoin
-  public void testMergeLOJOnNullableColumns() throws Exception {
+  /** InnerJoin on nullable cols, MergeJoin */
+  @Test
+  public void testMergeInnerJoinOnNullableColumns() throws Exception {
+    String query =
+        String.format(
+            "select t1.a1, t1.b1, t2.a2, t2.b2 "
+            + "  from dfs_test.`%s/jsoninput/nullable1.json` t1, "
+            + "       dfs_test.`%s/jsoninput/nullable2.json` t2 "
+            + " where t1.b1 = t2.b2", TEST_RES_PATH, TEST_RES_PATH);
+    final int expectedRecordCount = 1;
+
+    enableJoin(false, true);
+    final int actualRecordCount = testSql(query);
+    assertEquals("Number of output rows", expectedRecordCount, actualRecordCount);
+  }
+
+  /** LeftOuterJoin on nullable cols, MergeJoin */
+  @Test
+  public void testMergeLOJNullable() throws Exception {
     String query = String.format("select t1.a1, t1.b1, t2.a2, t2.b2 from dfs_test.`%s/jsoninput/nullable1.json` t1 " +
                       " left outer join dfs_test.`%s/jsoninput/nullable2.json` t2 " +
-                      " on t1.b1 = t2.b2", TEST_RES_PATH ,TEST_RES_PATH);
+                      " on t1.b1 = t2.b2", TEST_RES_PATH, TEST_RES_PATH);
 
-    int actualRecordCount;
-    int expectedRecordCount = 2;
+    final int expectedRecordCount = 2;
 
     enableJoin(false, true);
-    actualRecordCount = testSql(query);
-    assertEquals(String.format("Received unexepcted number of rows in output: expected=%d, received=%s",
-        expectedRecordCount, actualRecordCount), expectedRecordCount, actualRecordCount);
+    final int actualRecordCount = testSql(query);
+    assertEquals("Number of output rows", expectedRecordCount, actualRecordCount);
   }
 
-  @Test // RightOuterJoin on nullable cols, MergeJoin
+  /** RightOuterJoin on nullable cols, MergeJoin */
+  @Test
   public void testMergeROJOnNullableColumns() throws Exception {
     String query = String.format("select t1.a1, t1.b1, t2.a2, t2.b2 from dfs_test.`%s/jsoninput/nullable1.json` t1 " +
                       " right outer join dfs_test.`%s/jsoninput/nullable2.json` t2 " +
-                      " on t1.b1 = t2.b2", TEST_RES_PATH ,TEST_RES_PATH);
+                      " on t1.b1 = t2.b2", TEST_RES_PATH, TEST_RES_PATH);
+
+    final int expectedRecordCount = 4;
+
+    enableJoin(false, true);
+    final int actualRecordCount = testSql(query);
+    assertEquals("Number of output rows", expectedRecordCount, actualRecordCount);
+  }
+
+
+  /** Left outer join, merge, nullable col. - unordered inputs. */
+  @Test
+  public void testMergeLOJNullableNoOrderedInputs() throws Exception {
+    String query =
+        String.format(
+            "SELECT * "
+            + "FROM               dfs_test.`%s/jsoninput/nullableOrdered1.json` t1 "
+            + "   left outer join dfs_test.`%s/jsoninput/nullableOrdered2.json` t2 "
+            + "      using ( key )",
+            TEST_RES_PATH, TEST_RES_PATH);
+    final int expectedRecordCount = 6;
+
+    enableJoin(false, true);
+    final int actualRecordCount = testSql(query);
+    assertEquals("Number of output rows", expectedRecordCount, actualRecordCount);
+  }
+
+  /** Left outer join, merge, nullable col. - ordered right, ASC NULLS FIRST (nulls low). */
+  @Test
+  public void testMergeLOJNullableOneOrderedInputAscNullsFirst() throws Exception {
+    String query =
+        String.format(
+            "SELECT * "
+            + "from         dfs_test.`%s/jsoninput/nullableOrdered1.json` t1 "
+            + "  LEFT OUTER JOIN "
+            + "    ( SELECT key, data "
+            + "        FROM dfs_test.`%s/jsoninput/nullableOrdered2.json` t2 "
+            + "        ORDER BY 1 ASC NULLS FIRST ) t2 "
+            + "    USING ( key )",
+            TEST_RES_PATH, TEST_RES_PATH);
+    final int expectedRecordCount = 6;
+
+    enableJoin(false, true);
+    final int actualRecordCount = testSql(query);
+    assertEquals("Number of output rows", expectedRecordCount, actualRecordCount);
+  }
+
+  /** Left outer join, merge, nullable col.  - ordered right, ASC NULLS LAST (nulls high). */
+  @Test
+  public void testMergeLOJNullableOneOrderedInputAscNullsLast() throws Exception {
+    String query =
+        String.format(
+            "SELECT * "
+            + "FROM         dfs_test.`%s/jsoninput/nullableOrdered1.json` t1 "
+            + "  LEFT OUTER JOIN "
+            + "    ( SELECT key, data "
+            + "        FROM dfs_test.`%s/jsoninput/nullableOrdered2.json` t2 "
+            + "        ORDER BY 1 ASC NULLS LAST ) t2 "
+            + "    USING ( key )",
+            TEST_RES_PATH, TEST_RES_PATH);
+    final int expectedRecordCount = 6;
+
+    enableJoin(false, true);
+    final int actualRecordCount = testSql(query);
+    assertEquals("Number of output rows", expectedRecordCount, actualRecordCount);
+  }
+
+  /** Left outer join, merge, nullable col. - ordered right, DESC NULLS FIRST (nulls high). */
+  @Test
+  public void testMergeLOJNullableOneOrderedInputDescNullsFirst() throws Exception {
+    String query =
+        String.format(
+            "SELECT * "
+            + "FROM         dfs_test.`%s/jsoninput/nullableOrdered1.json` t1 "
+            + "  LEFT OUTER JOIN "
+            + "    ( SELECT key, data "
+            + "        FROM dfs_test.`%s/jsoninput/nullableOrdered2.json` t2 "
+            + "        ORDER BY 1 DESC NULLS FIRST ) t2 "
+            + "    USING ( key )",
+            TEST_RES_PATH, TEST_RES_PATH);
+    final int expectedRecordCount = 6;
+
+    enableJoin(false, true);
+    final int actualRecordCount = testSql(query);
+    assertEquals("Number of output rows", expectedRecordCount, actualRecordCount);
+  }
+
+  /** Left outer join, merge, nullable col. - ordered right, DESC NULLS LAST (nulls low). */
+  @Test
+  public void testMergeLOJNullableOneOrderedInputDescNullsLast() throws Exception {
+    String query =
+        String.format(
+            "SELECT * "
+            + "FROM         dfs_test.`%s/jsoninput/nullableOrdered1.json` t1 "
+            + "  LEFT OUTER JOIN "
+            + "    ( SELECT key, data "
+            + "        FROM dfs_test.`%s/jsoninput/nullableOrdered2.json` t2 "
+            + "        ORDER BY 1 DESC NULLS LAST ) t2 "
+            + "    USING ( key )",
+            TEST_RES_PATH, TEST_RES_PATH);
+    final int expectedRecordCount = 6;
+
+    enableJoin(false, true);
+    final int actualRecordCount = testSql(query);
+    assertEquals("Number of output rows", expectedRecordCount, actualRecordCount);
+  }
+
+
+
+  /** Left outer join, merge, nullable col. - ordered inputs, both ASC NULLS FIRST (nulls low). */
+  @Test
+  public void testMergeLOJNullableBothInputsOrderedAscNullsFirstVsAscNullsFirst() throws Exception {
+    String query =
+        String.format(
+            "SELECT * "
+            + "from ( SELECT key, data "
+            + "         FROM dfs_test.`%s/jsoninput/nullableOrdered1.json` "
+            + "         ORDER BY 1 ASC NULLS FIRST ) t1 "
+            + "  LEFT OUTER JOIN "
+            + "     ( SELECT key, data "
+            + "         FROM dfs_test.`%s/jsoninput/nullableOrdered2.json` "
+            + "         ORDER BY 1 ASC NULLS FIRST ) t2 "
+            + "    USING ( key )",
+            TEST_RES_PATH, TEST_RES_PATH);
+    final int expectedRecordCount = 6;
+
+    enableJoin(false, true);
+    final int actualRecordCount = testSql(query);
+    assertEquals("Number of output rows", expectedRecordCount, actualRecordCount);
+  }
+
+  /** Left outer join, merge, nullable col. - ordered inputs, different null order. */
+  @Test
+  public void testMergeLOJNullableBothInputsOrderedAscNullsLastVsAscNullsFirst() throws Exception {
+    String query =
+        String.format(
+            "SELECT * "
+            + "from ( SELECT key, data "
+            + "         FROM dfs_test.`%s/jsoninput/nullableOrdered1.json` "
+            + "         ORDER BY 1 ASC NULLS LAST  ) t1 "
+            + "  LEFT OUTER JOIN "
+            + "     ( SELECT key, data "
+            + "         FROM dfs_test.`%s/jsoninput/nullableOrdered2.json` "
+            + "         ORDER BY 1 ASC NULLS FIRST ) t2 "
+            + "    USING ( key )",
+            TEST_RES_PATH, TEST_RES_PATH);
+    final int expectedRecordCount = 6;
+
+    enableJoin(false, true);
+    final int actualRecordCount = testSql(query);
+    assertEquals("Number of output rows", expectedRecordCount, actualRecordCount);
+  }
+
+  /** Left outer join, merge, nullable col. - ordered inputs, other different null order. */
+  @Test
+  public void testMergeLOJNullableBothInputsOrderedAscNullsFirstVsAscNullsLast() throws Exception {
+    String query =
+        String.format(
+            "SELECT * "
+            + "from ( SELECT key, data "
+            + "         FROM dfs_test.`%s/jsoninput/nullableOrdered1.json` "
+            + "         ORDER BY 1 ASC NULLS FIRST ) t1 "
+            + "  LEFT OUTER JOIN "
+            + "     ( SELECT key, data "
+            + "         FROM dfs_test.`%s/jsoninput/nullableOrdered2.json` "
+            + "         ORDER BY 1 ASC NULLS LAST  ) t2 "
+            + "    USING ( key )",
+            TEST_RES_PATH, TEST_RES_PATH);
+    final int expectedRecordCount = 6;
+
+    enableJoin(false, true);
+    final int actualRecordCount = testSql(query);
+    assertEquals("Number of output rows", expectedRecordCount, actualRecordCount);
+  }
+
+  /** Left outer join, merge, nullable col. - ordered inputs, both ASC NULLS LAST (nulls high) */
+  @Test
+  public void testMergeLOJNullableBothInputsOrderedAscNullsLastVsAscNullsLast() throws Exception {
+    String query =
+        String.format(
+            "SELECT * "
+            + "from ( SELECT key, data "
+            + "         FROM dfs_test.`%s/jsoninput/nullableOrdered1.json` "
+            + "         ORDER BY 1 ASC NULLS LAST  ) t1 "
+            + "  LEFT OUTER JOIN "
+            + "     ( SELECT key, data "
+            + "         FROM dfs_test.`%s/jsoninput/nullableOrdered2.json` "
+            + "         ORDER BY 1 ASC NULLS LAST  ) t2 "
+            + "    USING ( key )",
+            TEST_RES_PATH, TEST_RES_PATH);
+    final int expectedRecordCount = 6;
+
+    enableJoin(false, true);
+    final int actualRecordCount = testSql(query);
+    assertEquals("Number of output rows", expectedRecordCount, actualRecordCount);
+  }
+
+  /** Left outer join, merge, nullable col. - ordered inputs, DESC vs. ASC, NULLS
+      FIRST (nulls high vs. nulls low). */
+  @Test
+  public void testMergeLOJNullableBothInputsOrderedDescNullsFirstVsAscNullsFirst() throws Exception {
+    String query =
+        String.format(
+            "SELECT * "
+            + "from ( SELECT key, data "
+            + "         FROM dfs_test.`%s/jsoninput/nullableOrdered1.json` "
+            + "         ORDER BY 1 DESC NULLS FIRST ) t1 "
+            + "  LEFT OUTER JOIN "
+            + "     ( SELECT key, data "
+            + "         FROM dfs_test.`%s/jsoninput/nullableOrdered2.json` "
+            + "         ORDER BY 1 ASC NULLS FIRST ) t2 "
+            + "    USING ( key )",
+            TEST_RES_PATH, TEST_RES_PATH);
+    final int expectedRecordCount = 6;
+
+    enableJoin(false, true);
+    final int actualRecordCount = testSql(query);
+    assertEquals("Number of output rows", expectedRecordCount, actualRecordCount);
+  }
+
+  /** Left outer join, merge, nullable col. - ordered inputs, DESC vs. ASC, NULLS
+      LAST vs. FIRST (both nulls low). */
+  @Test
+  public void testMergeLOJNullableBothInputsOrderedDescNullsLastVsAscNullsFirst() throws Exception {
+    String query =
+        String.format(
+            "SELECT * "
+            + "from ( SELECT key, data "
+            + "         FROM dfs_test.`%s/jsoninput/nullableOrdered1.json` "
+            + "         ORDER BY 1 DESC NULLS LAST  ) t1 "
+            + "  LEFT OUTER JOIN "
+            + "     ( SELECT key, data "
+            + "         FROM dfs_test.`%s/jsoninput/nullableOrdered2.json` "
+            + "         ORDER BY 1 ASC NULLS FIRST ) t2 "
+            + "    USING ( key )",
+            TEST_RES_PATH, TEST_RES_PATH);
+    final int expectedRecordCount = 6;
+
+    enableJoin(false, true);
+    final int actualRecordCount = testSql(query);
+    assertEquals("Number of output rows", expectedRecordCount, actualRecordCount);
+  }
+
+  /** Left outer join, merge, nullable col. - ordered inputs, DESC vs. ASC, NULLS
+      FIRST vs. LAST (both nulls high). */
+  @Test
+  public void testMergeLOJNullableBothInputsOrderedDescNullsFirstVsAscNullsLast() throws Exception {
+    String query =
+        String.format(
+            "SELECT * "
+            + "from ( SELECT key, data "
+            + "         FROM dfs_test.`%s/jsoninput/nullableOrdered1.json` "
+            + "         ORDER BY 1 DESC NULLS FIRST ) t1 "
+            + "  LEFT OUTER JOIN "
+            + "     ( SELECT key, data "
+            + "         FROM dfs_test.`%s/jsoninput/nullableOrdered2.json` "
+            + "         ORDER BY 1 ASC NULLS LAST  ) t2 "
+            + "    USING ( key )",
+            TEST_RES_PATH, TEST_RES_PATH);
+    final int expectedRecordCount = 6;
+
+    enableJoin(false, true);
+    final int actualRecordCount = testSql(query);
+    assertEquals("Number of output rows", expectedRecordCount, actualRecordCount);
+  }
 
-    int actualRecordCount;
-    int expectedRecordCount = 4;
+  /** Left outer join, merge, nullable col. - ordered inputs, DESC vs. ASC, NULLS
+      LAST (nulls low vs. nulls high). */
+  @Test
+  public void testMergeLOJNullableBothInputsOrderedDescNullsLastVsAscNullsLast() throws Exception {
+    String query =
+        String.format(
+            "SELECT * "
+            + "from ( SELECT key, data "
+            + "         FROM dfs_test.`%s/jsoninput/nullableOrdered1.json` "
+            + "         ORDER BY 1 DESC NULLS LAST  ) t1 "
+            + "  LEFT OUTER JOIN "
+            + "     ( SELECT key, data "
+            + "         FROM dfs_test.`%s/jsoninput/nullableOrdered2.json` "
+            + "         ORDER BY 1 ASC NULLS LAST  ) t2 "
+            + "    USING ( key )",
+            TEST_RES_PATH, TEST_RES_PATH);
+    final int expectedRecordCount = 6;
 
     enableJoin(false, true);
-    actualRecordCount = testSql(query);
-    assertEquals(String.format("Received unexepcted number of rows in output: expected=%d, received=%s",
-        expectedRecordCount, actualRecordCount), expectedRecordCount, actualRecordCount);
+    final int actualRecordCount = testSql(query);
+    assertEquals("Number of output rows", expectedRecordCount, actualRecordCount);
   }
 
 }

http://git-wip-us.apache.org/repos/asf/drill/blob/5efc7e68/exec/java-exec/src/test/resources/jsoninput/nullableOrdered1.json
----------------------------------------------------------------------
diff --git a/exec/java-exec/src/test/resources/jsoninput/nullableOrdered1.json b/exec/java-exec/src/test/resources/jsoninput/nullableOrdered1.json
new file mode 100644
index 0000000..135d3a0
--- /dev/null
+++ b/exec/java-exec/src/test/resources/jsoninput/nullableOrdered1.json
@@ -0,0 +1,24 @@
+{
+ "key":"A",
+ "data":"L_A_1"
+}
+{
+ "key":"B",
+ "data":"L_B_1"
+}
+{
+ "key":null,
+ "data":"L_null_1"
+}
+{
+ "key":"A",
+ "data":"L_A_2"
+}
+{
+ "key":null,
+ "data":"L_null_2"
+}
+{
+ "key":"B",
+ "data":"L_B_2"
+}

http://git-wip-us.apache.org/repos/asf/drill/blob/5efc7e68/exec/java-exec/src/test/resources/jsoninput/nullableOrdered2.json
----------------------------------------------------------------------
diff --git a/exec/java-exec/src/test/resources/jsoninput/nullableOrdered2.json b/exec/java-exec/src/test/resources/jsoninput/nullableOrdered2.json
new file mode 100644
index 0000000..ebaedd1
--- /dev/null
+++ b/exec/java-exec/src/test/resources/jsoninput/nullableOrdered2.json
@@ -0,0 +1,16 @@
+{
+ "key":null,
+ "data":"R_null_1"
+}
+{
+ "key":"A",
+ "data":"R_A_1"
+}
+{
+ "key":null,
+ "data":"R_null_2"
+}
+{
+ "key":null,
+ "data":"R_null_3"
+}

http://git-wip-us.apache.org/repos/asf/drill/blob/5efc7e68/exec/jdbc/src/main/java/org/apache/drill/jdbc/DrillDatabaseMetaData.java
----------------------------------------------------------------------
diff --git a/exec/jdbc/src/main/java/org/apache/drill/jdbc/DrillDatabaseMetaData.java b/exec/jdbc/src/main/java/org/apache/drill/jdbc/DrillDatabaseMetaData.java
new file mode 100644
index 0000000..ca1648d
--- /dev/null
+++ b/exec/jdbc/src/main/java/org/apache/drill/jdbc/DrillDatabaseMetaData.java
@@ -0,0 +1,53 @@
+/**
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.drill.jdbc;
+
+import net.hydromatic.avatica.AvaticaConnection;
+import net.hydromatic.avatica.AvaticaDatabaseMetaData;
+
+public class DrillDatabaseMetaData extends AvaticaDatabaseMetaData {
+
+  protected DrillDatabaseMetaData( AvaticaConnection connection ) {
+    super( connection );
+  }
+
+
+  // For omitted NULLS FIRST/NULLS HIGH, Drill sort NULL sorts as highest value:
+
+  @Override
+  public boolean nullsAreSortedHigh() {
+    return true;
+  }
+
+  @Override
+  public boolean nullsAreSortedLow() {
+    return false;
+  }
+
+  @Override
+  public boolean nullsAreSortedAtStart() {
+    return false;
+  }
+
+  @Override
+  public boolean nullsAreSortedAtEnd() {
+    return false;
+  }
+
+
+}

http://git-wip-us.apache.org/repos/asf/drill/blob/5efc7e68/exec/jdbc/src/main/java/org/apache/drill/jdbc/DrillFactory.java
----------------------------------------------------------------------
diff --git a/exec/jdbc/src/main/java/org/apache/drill/jdbc/DrillFactory.java b/exec/jdbc/src/main/java/org/apache/drill/jdbc/DrillFactory.java
index 9b9eb7b..c674f8e 100644
--- a/exec/jdbc/src/main/java/org/apache/drill/jdbc/DrillFactory.java
+++ b/exec/jdbc/src/main/java/org/apache/drill/jdbc/DrillFactory.java
@@ -38,14 +38,17 @@ public abstract class DrillFactory implements AvaticaFactory {
     this.minor = minor;
   }
 
+  @Override
   public int getJdbcMajorVersion() {
     return major;
   }
 
+  @Override
   public int getJdbcMinorVersion() {
     return minor;
   }
 
+  @Override
   public final AvaticaConnection newConnection(UnregisteredDriver driver, AvaticaFactory factory, String url,
       Properties info)  throws SQLException{
     return newDrillConnection((Driver) driver, (DrillFactory) factory, url, info);

http://git-wip-us.apache.org/repos/asf/drill/blob/5efc7e68/exec/jdbc/src/main/java/org/apache/drill/jdbc/DrillJdbc41Factory.java
----------------------------------------------------------------------
diff --git a/exec/jdbc/src/main/java/org/apache/drill/jdbc/DrillJdbc41Factory.java b/exec/jdbc/src/main/java/org/apache/drill/jdbc/DrillJdbc41Factory.java
index 7fb0a34..4da26e9 100644
--- a/exec/jdbc/src/main/java/org/apache/drill/jdbc/DrillJdbc41Factory.java
+++ b/exec/jdbc/src/main/java/org/apache/drill/jdbc/DrillJdbc41Factory.java
@@ -57,16 +57,20 @@ public class DrillJdbc41Factory extends DrillFactory {
     return new DrillJdbc41Connection((Driver) driver, factory, url, info);
   }
 
+  @Override
   public DrillJdbc41DatabaseMetaData newDatabaseMetaData(AvaticaConnection connection) {
     return new DrillJdbc41DatabaseMetaData((DrillConnectionImpl) connection);
   }
 
+
+  @Override
   public DrillJdbc41Statement newStatement(AvaticaConnection connection, int resultSetType, int resultSetConcurrency,
       int resultSetHoldability) {
     return new DrillJdbc41Statement((DrillConnectionImpl) connection, resultSetType, resultSetConcurrency,
         resultSetHoldability);
   }
 
+  @Override
   public AvaticaPreparedStatement newPreparedStatement(AvaticaConnection connection,
       AvaticaPrepareResult prepareResult, int resultSetType, int resultSetConcurrency, int resultSetHoldability)
       throws SQLException {
@@ -74,11 +78,13 @@ public class DrillJdbc41Factory extends DrillFactory {
         resultSetType, resultSetConcurrency, resultSetHoldability);
   }
 
+  @Override
   public DrillResultSet newResultSet(AvaticaStatement statement, AvaticaPrepareResult prepareResult, TimeZone timeZone) {
     final ResultSetMetaData metaData = newResultSetMetaData(statement, prepareResult.getColumnList());
     return new DrillResultSet(statement, (DrillPrepareResult) prepareResult, metaData, timeZone);
   }
 
+  @Override
   public ResultSetMetaData newResultSetMetaData(AvaticaStatement statement, List<ColumnMetaData> columnMetaDataList) {
     return new AvaticaResultSetMetaData(statement, null, columnMetaDataList);
   }
@@ -176,7 +182,7 @@ public class DrillJdbc41Factory extends DrillFactory {
     }
   }
 
-  private static class DrillJdbc41DatabaseMetaData extends AvaticaDatabaseMetaData {
+  private static class DrillJdbc41DatabaseMetaData extends DrillDatabaseMetaData {
     DrillJdbc41DatabaseMetaData(DrillConnectionImpl connection) {
       super(connection);
     }


Mime
View raw message