You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@storm.apache.org by sr...@apache.org on 2015/11/10 19:39:51 UTC
[2/3] storm git commit: Implement nullable semantics for AND,
OR and NOT operators.
Implement nullable semantics for AND, OR and NOT operators.
Project: http://git-wip-us.apache.org/repos/asf/storm/repo
Commit: http://git-wip-us.apache.org/repos/asf/storm/commit/8890de3e
Tree: http://git-wip-us.apache.org/repos/asf/storm/tree/8890de3e
Diff: http://git-wip-us.apache.org/repos/asf/storm/diff/8890de3e
Branch: refs/heads/STORM-1040
Commit: 8890de3e098b759d0a2938e06b4841d371066b7e
Parents: 183b5ac
Author: Haohui Mai <wh...@apache.org>
Authored: Wed Nov 4 09:24:32 2015 -0800
Committer: Haohui Mai <wh...@apache.org>
Committed: Wed Nov 4 09:24:32 2015 -0800
----------------------------------------------------------------------
.../apache/storm/sql/compiler/ExprCompiler.java | 101 +++++++++++++++----
.../storm/sql/compiler/TestExprSemantic.java | 49 ++++++---
2 files changed, 119 insertions(+), 31 deletions(-)
----------------------------------------------------------------------
http://git-wip-us.apache.org/repos/asf/storm/blob/8890de3e/external/sql/storm-sql-core/src/jvm/org/apache/storm/sql/compiler/ExprCompiler.java
----------------------------------------------------------------------
diff --git a/external/sql/storm-sql-core/src/jvm/org/apache/storm/sql/compiler/ExprCompiler.java b/external/sql/storm-sql-core/src/jvm/org/apache/storm/sql/compiler/ExprCompiler.java
index fd3a614..db97d43 100644
--- a/external/sql/storm-sql-core/src/jvm/org/apache/storm/sql/compiler/ExprCompiler.java
+++ b/external/sql/storm-sql-core/src/jvm/org/apache/storm/sql/compiler/ExprCompiler.java
@@ -17,7 +17,9 @@
*/
package org.apache.storm.sql.compiler;
+import com.google.common.base.Joiner;
import com.google.common.collect.ImmutableMap;
+import org.apache.calcite.adapter.enumerable.CallImplementor;
import org.apache.calcite.adapter.enumerable.RexImpTable;
import org.apache.calcite.adapter.java.JavaTypeFactory;
import org.apache.calcite.rel.type.RelDataType;
@@ -67,9 +69,9 @@ import static org.apache.calcite.sql.fun.SqlStdOperatorTable.PLUS;
*/
class ExprCompiler implements RexVisitor<String> {
private final PrintWriter pw;
- private final Map<RexNode, String> expr = new IdentityHashMap<>();
private final JavaTypeFactory typeFactory;
private static final ImpTable IMP_TABLE = new ImpTable();
+ private int nameCount;
ExprCompiler(PrintWriter pw, JavaTypeFactory typeFactory) {
this.pw = pw;
@@ -78,14 +80,10 @@ class ExprCompiler implements RexVisitor<String> {
@Override
public String visitInputRef(RexInputRef rexInputRef) {
- if (expr.containsKey(rexInputRef)) {
- return expr.get(rexInputRef);
- }
String name = reserveName(rexInputRef);
String typeName = javaTypeName(rexInputRef);
pw.print(String.format("%s %s = (%s)(_data.get(%d));\n", typeName, name,
typeName, rexInputRef.getIndex()));
- expr.put(rexInputRef, name);
return name;
}
@@ -167,8 +165,7 @@ class ExprCompiler implements RexVisitor<String> {
}
private String reserveName(RexNode node) {
- String name = "t" + expr.size();
- expr.put(node, name);
+ String name = "t" + ++nameCount;
return name;
}
@@ -285,6 +282,9 @@ class ExprCompiler implements RexVisitor<String> {
}
+ // If any of the arguments are false, result is false;
+ // else if any arguments are null, result is null;
+ // else true.
private static final CallExprPrinter AND_EXPR = new CallExprPrinter() {
@Override
public String translate(
@@ -293,15 +293,40 @@ class ExprCompiler implements RexVisitor<String> {
PrintWriter pw = compiler.pw;
pw.print(String.format("final %s %s;\n", compiler.javaTypeName(call),
val));
- String lhs = call.getOperands().get(0).accept(compiler);
- pw.print(String.format("if (!(%2$s)) { %1$s = false; }\n", val, lhs));
- pw.print("else {\n");
- String rhs = call.getOperands().get(1).accept(compiler);
- pw.print(String.format(" %1$s = %2$s;\n}\n", val, rhs));
+ RexNode op0 = call.getOperands().get(0);
+ RexNode op1 = call.getOperands().get(1);
+ boolean lhsNullable = op0.getType().isNullable();
+ boolean rhsNullable = op1.getType().isNullable();
+ String lhs = op0.accept(compiler);
+ if (!lhsNullable) {
+ pw.print(String.format("if (!(%2$s)) { %1$s = false; }\n", val, lhs));
+ pw.print("else {\n");
+ String rhs = op1.accept(compiler);
+ pw.print(String.format(" %1$s = %2$s;\n}\n", val, rhs));
+ } else {
+ String foldedLHS = foldNullExpr(
+ String.format("%1$s == null || %1$s", lhs), "true", lhs);
+ pw.print(String.format("if (%s) {\n", foldedLHS));
+ String rhs = op1.accept(compiler);
+ String s;
+ if (rhsNullable) {
+ s = foldNullExpr(
+ String.format("(%2$s != null && !(%2$s)) ? false : %1$s", lhs,
+ rhs),
+ "null", rhs);
+ } else {
+ s = String.format("!(%2$s) ? false : %1$s", lhs, rhs);
+ }
+ pw.print(String.format(" %1$s = %2$s;\n", val, s));
+ pw.print(String.format("} else { %1$s = false; }\n", val));
+ }
return val;
}
};
+ // If any of the arguments are true, result is true;
+ // else if any arguments are null, result is null;
+ // else false.
private static final CallExprPrinter OR_EXPR = new CallExprPrinter() {
@Override
public String translate(
@@ -310,11 +335,32 @@ class ExprCompiler implements RexVisitor<String> {
PrintWriter pw = compiler.pw;
pw.print(String.format("final %s %s;\n", compiler.javaTypeName(call),
val));
- String lhs = call.getOperands().get(0).accept(compiler);
- pw.print(String.format("if (%2$s) { %1$s = true; }\n", val, lhs));
- pw.print("else {\n");
- String rhs = call.getOperands().get(1).accept(compiler);
- pw.print(String.format(" %1$s = %2$s;\n}\n", val, rhs));
+ RexNode op0 = call.getOperands().get(0);
+ RexNode op1 = call.getOperands().get(1);
+ boolean lhsNullable = op0.getType().isNullable();
+ boolean rhsNullable = op1.getType().isNullable();
+ String lhs = op0.accept(compiler);
+ if (!lhsNullable) {
+ pw.print(String.format("if (%2$s) { %1$s = true; }\n", val, lhs));
+ pw.print("else {\n");
+ String rhs = op1.accept(compiler);
+ pw.print(String.format(" %1$s = %2$s;\n}\n", val, rhs));
+ } else {
+ String foldedLHS = foldNullExpr(
+ String.format("%1$s == null || !(%1$s)", lhs), "true", lhs);
+ pw.print(String.format("if (%s) {\n", foldedLHS));
+ String rhs = op1.accept(compiler);
+ String s;
+ if (rhsNullable) {
+ s = foldNullExpr(
+ String.format("(%2$s != null && %2$s) ? true : %1$s", lhs, rhs),
+ "null", rhs);
+ } else {
+ s = String.format("%2$s ? %2$s : %1$s", lhs, rhs);
+ }
+ pw.print(String.format(" %1$s = %2$s;\n", val, s));
+ pw.print(String.format("} else { %1$s = true; }\n", val));
+ }
return val;
}
};
@@ -325,13 +371,30 @@ class ExprCompiler implements RexVisitor<String> {
ExprCompiler compiler, RexCall call) {
String val = compiler.reserveName(call);
PrintWriter pw = compiler.pw;
- String lhs = call.getOperands().get(0).accept(compiler);
+ RexNode op = call.getOperands().get(0);
+ String lhs = op.accept(compiler);
+ boolean nullable = call.getType().isNullable();
pw.print(String.format("final %s %s;\n", compiler.javaTypeName(call),
val));
- pw.print(String.format("%1$s = !(%2$s);\n", val, lhs));
+ if (!nullable) {
+ pw.print(String.format("%1$s = !(%2$s);\n", val, lhs));
+ } else {
+ String s = foldNullExpr(
+ String.format("%1$s == null ? null : !(%1$s)", lhs), "null", lhs);
+ pw.print(String.format("%1$s = %2$s;\n", val, s));
+ }
return val;
}
};
+
+ private static String foldNullExpr(String notNullExpr, String
+ nullExpr, String op) {
+ if (op.equals("null")) {
+ return nullExpr;
+ } else {
+ return notNullExpr;
+ }
+ }
}
}
http://git-wip-us.apache.org/repos/asf/storm/blob/8890de3e/external/sql/storm-sql-core/src/test/org/apache/storm/sql/compiler/TestExprSemantic.java
----------------------------------------------------------------------
diff --git a/external/sql/storm-sql-core/src/test/org/apache/storm/sql/compiler/TestExprSemantic.java b/external/sql/storm-sql-core/src/test/org/apache/storm/sql/compiler/TestExprSemantic.java
index bda9e00..7bde092 100644
--- a/external/sql/storm-sql-core/src/test/org/apache/storm/sql/compiler/TestExprSemantic.java
+++ b/external/sql/storm-sql-core/src/test/org/apache/storm/sql/compiler/TestExprSemantic.java
@@ -43,8 +43,7 @@ public class TestExprSemantic {
public void testLogicalExpr() throws Exception {
Values v = testExpr(
Lists.newArrayList("ID > 0 OR ID < 1", "ID > 0 AND ID < 1",
- "NOT (ID > 0 AND ID < 1)"),
- "WHERE ID > 0 AND ID < 2");
+ "NOT (ID > 0 AND ID < 1)"));
assertEquals(new Values(true, false, true), v);
}
@@ -58,12 +57,42 @@ public class TestExprSemantic {
assertEquals(new Values(true, false, false, true, false, true, false), v);
}
- private Values testExpr(List<String> exprs, String additionalCaluse)
- throws Exception {
- String sql = "SELECT " + Joiner.on(',').join(exprs) + " FROM FOO";
- if (additionalCaluse != null) {
- sql += " " + additionalCaluse;
- }
+ @Test
+ public void testNotWithNull() throws Exception {
+ Values v = testExpr(
+ Lists.newArrayList(
+ "NOT TRUE", "NOT FALSE", "NOT UNKNOWN"
+ ));
+ assertEquals(new Values(false, true, null), v);
+ }
+
+ @Test
+ public void testAndWithNull() throws Exception {
+ Values v = testExpr(
+ Lists.newArrayList(
+ "UNKNOWN AND TRUE", "UNKNOWN AND FALSE", "UNKNOWN AND UNKNOWN",
+ "TRUE AND TRUE", "TRUE AND FALSE", "TRUE AND UNKNOWN",
+ "FALSE AND TRUE", "FALSE AND FALSE", "FALSE AND UNKNOWN"
+ ));
+ assertEquals(new Values(null, false, null, true, false, null, false,
+ false, false), v);
+ }
+
+ @Test
+ public void testOrWithNull() throws Exception {
+ Values v = testExpr(
+ Lists.newArrayList(
+ "UNKNOWN OR TRUE", "UNKNOWN OR FALSE", "UNKNOWN OR UNKNOWN",
+ "TRUE OR TRUE", "TRUE OR FALSE", "TRUE OR UNKNOWN",
+ "FALSE OR TRUE", "FALSE OR FALSE", "FALSE OR UNKNOWN"
+ ));
+ assertEquals(new Values(true, null, null, true, true, true, true,
+ false, null), v);
+ }
+
+ private Values testExpr(List<String> exprs) throws Exception {
+ String sql = "SELECT " + Joiner.on(',').join(exprs) + " FROM FOO" +
+ " WHERE ID > 0 AND ID < 2";
TestUtils.CalciteState state = TestUtils.sqlOverDummyTable(sql);
PlanCompiler compiler = new PlanCompiler(typeFactory);
AbstractValuesProcessor proc = compiler.compile(state.tree);
@@ -75,8 +104,4 @@ public class TestExprSemantic {
return values.get(0);
}
- private Values testExpr(List<String> exprs) throws Exception {
- return testExpr(exprs, null);
- }
-
}