You are viewing a plain text version of this content. The canonical link for it is here.
Posted to dev@drill.apache.org by td...@apache.org on 2012/12/02 00:47:45 UTC
[6/7] git commit: Initial work on logical plan parser and expressions
Initial work on logical plan parser and expressions
Project: http://git-wip-us.apache.org/repos/asf/incubator-drill/repo
Commit: http://git-wip-us.apache.org/repos/asf/incubator-drill/commit/78940e78
Tree: http://git-wip-us.apache.org/repos/asf/incubator-drill/tree/78940e78
Diff: http://git-wip-us.apache.org/repos/asf/incubator-drill/diff/78940e78
Branch: refs/heads/DRILL-3
Commit: 78940e78dd20ca9b304def7cab3868014fae3d4a
Parents: 408168c
Author: Jacques Nadeau <ja...@gmail.com>
Authored: Fri Nov 23 22:51:02 2012 -0800
Committer: Jacques Nadeau <ja...@gmail.com>
Committed: Fri Nov 23 22:51:02 2012 -0800
----------------------------------------------------------------------
.gitignore | 28 +--
sandbox/prototype/common/pom.xml | 77 ++++++
.../drill/common/expression/parser/ExprLexer.g | 93 ++++++++
.../drill/common/expression/parser/ExprParser.g | 183 +++++++++++++++
.../drill/common/expression/BooleanFunctions.java | 129 ++++++++++
.../org/apache/drill/common/expression/Cast.java | 27 +++
.../apache/drill/common/expression/DataType.java | 30 +++
.../common/expression/ExpressionFunction.java | 70 ++++++
.../expression/ExpressionValidationError.java | 22 ++
.../drill/common/expression/FieldReference.java | 57 +++++
.../drill/common/expression/FunctionBase.java | 87 +++++++
.../drill/common/expression/FunctionName.java | 12 +
.../drill/common/expression/IfExpression.java | 87 +++++++
.../drill/common/expression/LogicalExpression.java | 97 ++++++++
.../common/expression/LogicalExpressionBase.java | 64 +++++
.../drill/common/expression/MathFunction.java | 84 +++++++
.../drill/common/expression/StringFunctions.java | 55 +++++
.../drill/common/expression/TypeFunctions.java | 31 +++
.../drill/common/expression/UnaryFunctions.java | 57 +++++
.../drill/common/expression/ValueExpressions.java | 87 +++++++
.../expression/aggregate/BasicAggregates.java | 5 +
.../common/expression/visitors/BasicEvaluator.java | 5 +
.../expression/visitors/FunctionVisitor.java | 11 +
.../common/expression/visitors/GetIdentifiers.java | 11 +
.../org/apache/drill/common/logical/FieldName.java | 5 +
.../org/apache/drill/common/logical/FlowInput.java | 5 +
.../apache/drill/common/logical/FlowOutput.java | 5 +
.../apache/drill/common/logical/LogicalPlan.java | 47 ++++
.../drill/common/logical/OperatorRegistry.java | 5 +
.../drill/common/logical/OperatorResolver.java | 5 +
.../drill/common/logical/PlanProperties.java | 14 ++
.../drill/common/logical/ValidationError.java | 5 +
.../apache/drill/common/logical/data/Combine.java | 12 +
.../apache/drill/common/logical/data/Explode.java | 18 ++
.../apache/drill/common/logical/data/Filter.java | 11 +
.../apache/drill/common/logical/data/Flatten.java | 12 +
.../apache/drill/common/logical/data/Group.java | 13 +
.../org/apache/drill/common/logical/data/Join.java | 21 ++
.../drill/common/logical/data/LogicalOperator.java | 24 ++
.../common/logical/data/LogicalOperatorBase.java | 25 ++
.../org/apache/drill/common/logical/data/Nest.java | 17 ++
.../logical/data/OperatorListDeserializer.java | 108 +++++++++
.../apache/drill/common/logical/data/Order.java | 19 ++
.../apache/drill/common/logical/data/Project.java | 13 +
.../org/apache/drill/common/logical/data/Scan.java | 10 +
.../apache/drill/common/logical/data/Sequence.java | 117 +++++++++
.../common/logical/data/SingleInputOperator.java | 17 ++
.../drill/common/logical/data/Transform.java | 19 ++
.../apache/drill/common/logical/data/Union.java | 9 +
.../common/logical/data/ZeroInputOperator.java | 5 +
.../drill/common/logical/sources/DataSource.java | 12 +
.../common/logical/sources/DataSourceBase.java | 12 +
.../apache/drill/common/logical/sources/Mongo.java | 8 +
.../apache/drill/common/logical/sources/Mysql.java | 8 +
.../apache/drill/common/logical/sources/Text.java | 16 ++
.../logical/sources/record/FirstRowMaker.java | 8 +
.../common/logical/sources/record/RecordMaker.java | 9 +
.../logical/sources/record/RecordMakerBase.java | 5 +
.../apache/drill/common/physical/Partitioner.java | 6 +
.../drill/common/physical/PhysicalOperator.java | 25 ++
.../apache/drill/common/physical/PhysicalPlan.java | 5 +
.../common/physical/RowBatchReceiverSource.java | 6 +
.../drill/common/physical/RowBatchSenderSink.java | 5 +
.../apache/drill/common/physical/StreamSink.java | 5 +
.../apache/drill/common/physical/StreamSource.java | 5 +
.../drill/common/physical/operators/Dump.java | 5 +
.../common/physical/operators/HashAggregate.java | 5 +
.../drill/common/physical/operators/HashJoin.java | 5 +
.../drill/common/physical/operators/Limit.java | 5 +
.../drill/common/physical/operators/MergeJoin.java | 5 +
.../drill/common/physical/operators/RowRotate.java | 12 +
.../drill/common/physical/operators/Scan.java | 5 +
.../drill/common/physical/operators/Sort.java | 5 +
.../drill/common/physical/operators/Store.java | 5 +
.../physical/operators/StreamingAggregate.java | 5 +
.../common/physical/operators/StreamingSort.java | 5 +
.../drill/common/physical/operators/Union.java | 5 +
.../apache/drill/common/storage/FieldSchema.java | 30 +++
.../drill/common/storage/ReaderCapabilities.java | 6 +
.../apache/drill/common/storage/StorageEngine.java | 6 +
.../apache/drill/common/storage/StorageReader.java | 25 ++
.../apache/drill/common/storage/TreeHolder.java | 12 +
.../apache/drill/common/storage/ValueCapturer.java | 25 ++
.../apache/drill/common/storage/ValueHolder.java | 17 ++
.../apache/drill/common/storage/ValueModifier.java | 6 +
.../test/java/org/apache/drill/ExpressionTest.java | 14 ++
.../drill/common/expression/parser/TreeTest.java | 45 ++++
.../common/src/test/resources/example1.sql | 61 +++++
.../common/src/test/resources/example2.sql | 55 +++++
.../common/src/test/resources/logical_plan1.json | 139 +++++++++++
.../common/src/test/resources/simple_plan.json | 113 +++++++++
sandbox/prototype/contrib/pom.xml | 28 +++
sandbox/prototype/contrib/storage-hbase/pom.xml | 24 ++
.../src/main/java/org/apache/drill/App.java | 13 +
.../src/test/java/org/apache/drill/AppTest.java | 38 +++
sandbox/prototype/exec/java-exec/pom.xml | 24 ++
.../src/main/java/org/apache/drill/App.java | 13 +
.../src/test/java/org/apache/drill/AppTest.java | 38 +++
sandbox/prototype/exec/pom.xml | 28 +++
sandbox/prototype/planner/pom.xml | 24 ++
.../src/main/java/org/apache/drill/App.java | 13 +
.../src/test/java/org/apache/drill/AppTest.java | 38 +++
sandbox/prototype/pom.xml | 53 +++++
sandbox/prototype/sqlparser/pom.xml | 24 ++
.../src/main/java/org/apache/drill/App.java | 13 +
.../src/test/java/org/apache/drill/AppTest.java | 38 +++
106 files changed, 3114 insertions(+), 21 deletions(-)
----------------------------------------------------------------------
http://git-wip-us.apache.org/repos/asf/incubator-drill/blob/78940e78/.gitignore
----------------------------------------------------------------------
diff --git a/.gitignore b/.gitignore
index 95d2008..4f8967e 100644
--- a/.gitignore
+++ b/.gitignore
@@ -1,21 +1,7 @@
-sandbox/**/target
-sandbox/plan-parser/basic-interpreter/.idea/*
-sandbox/plan-parser/.idea/.name
-sandbox/plan-parser/.idea/compiler.xml
-sandbox/plan-parser/.idea/copyright/profiles_settings.xml
-sandbox/plan-parser/.idea/encodings.xml
-sandbox/plan-parser/.idea/libraries/Maven__antlr_antlr_2_7_7.xml
-sandbox/plan-parser/.idea/libraries/Maven__com_google_code_findbugs_jsr305_1_3_9.xml
-sandbox/plan-parser/.idea/libraries/Maven__com_google_guava_guava_10_0_1.xml
-sandbox/plan-parser/.idea/libraries/Maven__junit_junit_4_8_2.xml
-sandbox/plan-parser/.idea/libraries/Maven__org_antlr_ST4_4_0_4.xml
-sandbox/plan-parser/.idea/libraries/Maven__org_antlr_antlr_3_4.xml
-sandbox/plan-parser/.idea/libraries/Maven__org_antlr_antlr_runtime_3_4.xml
-sandbox/plan-parser/.idea/libraries/Maven__org_antlr_stringtemplate_3_2_1.xml
-sandbox/plan-parser/.idea/misc.xml
-sandbox/plan-parser/.idea/modules.xml
-sandbox/plan-parser/.idea/scopes/scope_settings.xml
-sandbox/plan-parser/.idea/uiDesigner.xml
-sandbox/plan-parser/.idea/vcs.xml
-sandbox/plan-parser/.idea/workspace.xml
-sandbox/plan-parser/basic-interpreter.iml
+.project
+.buildpath
+.classpath
+.settings/
+.idea/
+*.iml
+target/
http://git-wip-us.apache.org/repos/asf/incubator-drill/blob/78940e78/sandbox/prototype/common/pom.xml
----------------------------------------------------------------------
diff --git a/sandbox/prototype/common/pom.xml b/sandbox/prototype/common/pom.xml
new file mode 100644
index 0000000..531c08e
--- /dev/null
+++ b/sandbox/prototype/common/pom.xml
@@ -0,0 +1,77 @@
+<?xml version="1.0"?>
+<project
+ xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"
+ xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
+ <modelVersion>4.0.0</modelVersion>
+ <parent>
+ <artifactId>prototype-parent</artifactId>
+ <groupId>org.apache.drill</groupId>
+ <version>1.0-SNAPSHOT</version>
+ </parent>
+ <artifactId>common</artifactId>
+ <packaging>jar</packaging>
+ <name>common</name>
+ <url>http://maven.apache.org</url>
+ <properties>
+ <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
+ </properties>
+ <dependencies>
+
+ <dependency>
+ <groupId>ch.qos.logback</groupId>
+ <artifactId>logback-classic</artifactId>
+ <version>1.0.7</version>
+ <scope>provided</scope>
+ </dependency>
+ <dependency>
+ <version>1.7.2</version>
+ <groupId>org.slf4j</groupId>
+ <artifactId>slf4j-api</artifactId>
+ </dependency>
+ <dependency>
+ <groupId>com.google.guava</groupId>
+ <artifactId>guava</artifactId>
+ <version>13.0.1</version>
+ </dependency>
+
+ <dependency>
+ <groupId>com.fasterxml.jackson.core</groupId>
+ <artifactId>jackson-annotations</artifactId>
+ <version>2.1.1</version>
+ </dependency>
+
+ <dependency>
+ <groupId>com.fasterxml.jackson.core</groupId>
+ <artifactId>jackson-databind</artifactId>
+ <version>2.1.1</version>
+ </dependency>
+ <dependency>
+ <groupId>org.antlr</groupId>
+ <artifactId>antlr-runtime</artifactId>
+ <version>3.4</version>
+ </dependency>
+ <dependency>
+ <groupId>junit</groupId>
+ <artifactId>junit</artifactId>
+ <version>4.11</version>
+ <scope>test</scope>
+ </dependency>
+ </dependencies>
+
+ <build>
+ <plugins>
+ <plugin>
+ <groupId>org.antlr</groupId>
+ <artifactId>antlr3-maven-plugin</artifactId>
+ <version>3.4</version>
+ <executions>
+ <execution>
+ <goals>
+ <goal>antlr</goal>
+ </goals>
+ </execution>
+ </executions>
+ </plugin>
+ </plugins>
+ </build>
+</project>
http://git-wip-us.apache.org/repos/asf/incubator-drill/blob/78940e78/sandbox/prototype/common/src/main/antlr3/org/apache/drill/common/expression/parser/ExprLexer.g
----------------------------------------------------------------------
diff --git a/sandbox/prototype/common/src/main/antlr3/org/apache/drill/common/expression/parser/ExprLexer.g b/sandbox/prototype/common/src/main/antlr3/org/apache/drill/common/expression/parser/ExprLexer.g
new file mode 100644
index 0000000..3eeeca3
--- /dev/null
+++ b/sandbox/prototype/common/src/main/antlr3/org/apache/drill/common/expression/parser/ExprLexer.g
@@ -0,0 +1,93 @@
+lexer grammar ExprLexer;
+
+options {
+ language=Java;
+}
+
+@header {
+ package org.apache.drill.common.expression.parser;
+}
+
+If : 'if';
+Else : 'else';
+Return : 'return';
+Then : 'then';
+End : 'end';
+In : 'in';
+Case : 'case';
+When : 'when';
+
+
+Or : '||';
+And : '&&';
+Equals : '==';
+NEquals : '!=';
+GTEquals : '>=';
+LTEquals : '<=';
+Caret : '^';
+Excl : '!';
+GT : '>';
+LT : '<';
+Plus : '+';
+Minus : '-';
+Asterisk : '*';
+ForwardSlash : '/';
+Percent : '%';
+OBrace : '{';
+CBrace : '}';
+OBracket : '[';
+CBracket : ']';
+OParen : '(';
+CParen : ')';
+SColon : ';';
+Comma : ',';
+QMark : '?';
+Colon : ':';
+SingleQuote: '\'';
+
+Bool
+ : 'true'
+ | 'false'
+ ;
+
+Number
+ : Int ('.' Digit*)? ('e' ('+' | '-')? Digit*)?
+ ;
+
+//Float
+// : Int ('.' Digit*)? ('e' ('+' | '-')? Digit*)?
+// ;
+//
+//Integer
+// : Digit Digit*
+// ;
+
+Identifier
+ : ('a'..'z' | 'A'..'Z' | '_') ('a'..'z' | 'A'..'Z' | '_' | Digit)* ('.' ('a'..'z' | 'A'..'Z' | '_') ('a'..'z' | 'A'..'Z' | '_' | Digit)*)*
+ ;
+
+String
+@after {
+ setText(getText().substring(1, getText().length()-1).replaceAll("\\\\(.)", "$1"));
+}
+ : '"' (~('"' | '\\') | '\\' ('\\' | '"'))* '"'
+ | '\'' (~('\'' | '\\') | '\\' ('\\' | '\''))* '\''
+ ;
+
+Comment
+ : '//' ~('\r' | '\n')* {skip();}
+ | '/*' .* '*/' {skip();}
+ ;
+
+Space
+ : (' ' | '\t' | '\r' | '\n' | '\u000C') {skip();}
+ ;
+
+fragment Int
+ : '1'..'9' Digit*
+ | '0'
+ ;
+
+fragment Digit
+ : '0'..'9'
+ ;
http://git-wip-us.apache.org/repos/asf/incubator-drill/blob/78940e78/sandbox/prototype/common/src/main/antlr3/org/apache/drill/common/expression/parser/ExprParser.g
----------------------------------------------------------------------
diff --git a/sandbox/prototype/common/src/main/antlr3/org/apache/drill/common/expression/parser/ExprParser.g b/sandbox/prototype/common/src/main/antlr3/org/apache/drill/common/expression/parser/ExprParser.g
new file mode 100644
index 0000000..4d4d24c
--- /dev/null
+++ b/sandbox/prototype/common/src/main/antlr3/org/apache/drill/common/expression/parser/ExprParser.g
@@ -0,0 +1,183 @@
+parser grammar ExprParser;
+
+options{
+ output=AST;
+ language=Java;
+ tokenVocab=ExprLexer;
+ backtrack=true;
+ memoize=true;
+}
+
+
+
+@header {
+ package org.apache.drill.common.expression.parser;
+
+ //Explicit import...
+ import org.antlr.runtime.BitSet;
+ import java.util.*;
+ import org.apache.drill.common.expression.*;
+}
+
+@members{
+ public static void p(String s){
+ System.out.println(s);
+ }
+}
+
+parse returns [LogicalExpression e]
+ : expression EOF {$e = $expression.e; }
+ ;
+
+functionCall returns [LogicalExpression e]
+ : Identifier OParen exprList? CParen {$e = ExpressionFunction.create($Identifier.text, $exprList.listE); }
+ ;
+
+ifStatement returns [LogicalExpression e]
+ @init {
+ IfExpression.Builder s = IfExpression.newBuilder();
+ }
+ @after {
+ $e = s.build();
+ }
+ : i1=ifStat {s.addCondition($i1.i); } (elseIfStat { s.addCondition($elseIfStat.i); } )* Else expression { s.setElse($expression.e); }End
+ ;
+
+ifStat returns [IfExpression.IfCondition i]
+ : If e1=expression Then e2=expression { $i = new IfExpression.IfCondition($e1.e, $e2.e); }
+ ;
+elseIfStat returns [IfExpression.IfCondition i]
+ : Else If e1=expression Then e2=expression { $i = new IfExpression.IfCondition($e1.e, $e2.e); }
+ ;
+
+caseStatement returns [LogicalExpression e]
+ @init {
+ IfExpression.Builder s = IfExpression.newBuilder();
+ }
+ @after {
+ $e = s.build();
+ }
+ : Case (caseWhenStat {s.addCondition($caseWhenStat.i); }) + caseElseStat { s.setElse($caseElseStat.e); } End
+ ;
+
+caseWhenStat returns [IfExpression.IfCondition i]
+ : When e1=expression Then e2=expression {$i = new IfExpression.IfCondition($e1.e, $e2.e); }
+ ;
+
+caseElseStat returns [LogicalExpression e]
+ : Else expression {$e = $expression.e; }
+ ;
+
+exprList returns [List<LogicalExpression> listE]
+ @init{
+ $listE = new ArrayList<LogicalExpression>();
+ }
+ : e1=expression {$listE.add($e1.e); } (Comma e2=expression {$listE.add($e2.e); } )*
+ ;
+
+expression returns [LogicalExpression e]
+ : ifStatement {$e = $ifStatement.e; }
+ | caseStatement {$e = $caseStatement.e; }
+ | condExpr {$e = $condExpr.e; }
+ ;
+
+condExpr returns [LogicalExpression e]
+ : orExpr {$e = $orExpr.e; }
+ ;
+
+orExpr returns [LogicalExpression e]
+ @init{
+ List<LogicalExpression> exprs = new ArrayList<LogicalExpression>();
+ }
+ @after{
+ if(exprs.size() == 1){
+ $e = exprs.get(0);
+ }else{
+ $e = new BooleanFunctions.Or(exprs);
+ }
+ }
+ : a1=andExpr { exprs.add($a1.e); } (Or^ a2=andExpr { exprs.add($a2.e); })*
+ ;
+
+andExpr returns [LogicalExpression e]
+ @init{
+ List<LogicalExpression> exprs = new ArrayList<LogicalExpression>();
+ }
+ @after{
+ if(exprs.size() == 1){
+ $e = exprs.get(0);
+ }else{
+ $e = new BooleanFunctions.And(exprs);
+ }
+ }
+ : e1=equExpr { exprs.add($e1.e); } (And^ e2=equExpr { exprs.add($e2.e); })*
+ ;
+
+equExpr returns [LogicalExpression e]
+ @init{
+ List<LogicalExpression> exprs = new ArrayList<LogicalExpression>();
+ List<String> cmps = new ArrayList();
+ }
+ @after{
+ $e = BooleanFunctions.Comparison.create(exprs, cmps);
+ }
+ : r1=relExpr {exprs.add($r1.e);} ( cmpr= (Equals | NEquals ) r2=relExpr {exprs.add($r2.e); cmps.add($cmpr.text); })*
+ ;
+
+relExpr returns [LogicalExpression e]
+ : left=addExpr {$e = $left.e; } (cmpr = (GTEquals | LTEquals | GT | LT) right=addExpr {$e = new BooleanFunctions.Comparison($cmpr.text, $left.e, $right.e); } )?
+ ;
+
+addExpr returns [LogicalExpression e]
+ @init{
+ List<LogicalExpression> exprs = new ArrayList<LogicalExpression>();
+ List<String> ops = new ArrayList();
+ }
+ @after{
+ $e = MathFunction.create(exprs, ops);
+ }
+ : m1=mulExpr {exprs.add($m1.e);} ( op=(Plus|Minus) m2=mulExpr {exprs.add($m2.e); ops.add($op.text); })*
+ ;
+
+mulExpr returns [LogicalExpression e]
+ @init{
+ List<LogicalExpression> exprs = new ArrayList<LogicalExpression>();
+ List<String> ops = new ArrayList();
+ }
+ @after{
+ $e = MathFunction.create(exprs, ops);
+ }
+ : p1=powExpr {exprs.add($p1.e);} (op=(Asterisk|ForwardSlash|Percent) p2=powExpr {exprs.add($p2.e); ops.add($op.text); } )*
+ ;
+
+powExpr returns [LogicalExpression e]
+ @init{
+ List<LogicalExpression> exprs = new ArrayList<LogicalExpression>();
+ List<String> ops = new ArrayList();
+ }
+ @after{
+ $e = MathFunction.create(exprs, ops);
+ }
+ : u1=unaryExpr {exprs.add($u1.e);} (Caret u2=unaryExpr {exprs.add($u2.e); ops.add($Caret.text);} )*
+ ;
+
+unaryExpr returns [LogicalExpression e]
+ : Minus atom {$e = new UnaryFunctions.Negative($atom.e); }
+ | Excl atom {$e= new UnaryFunctions.Not($atom.e); }
+ | atom {$e = $atom.e; }
+ ;
+
+atom returns [LogicalExpression e]
+ : Number {$e = new ValueExpressions.NumberExpression($Number.text); }
+ | Bool {$e = new ValueExpressions.BooleanExpression( $Bool.text ); }
+ | lookup {$e = $lookup.e; }
+ ;
+
+
+lookup returns [LogicalExpression e]
+ : functionCall {$e = $functionCall.e ;}
+ | Identifier {$e = new ValueExpressions.Identifier($Identifier.text); }
+ | String {$e = new ValueExpressions.QuotedString($String.text); }
+ | OParen expression CParen {$e = $expression.e; }
+ | SingleQuote Identifier SingleQuote {$e = new ValueExpressions.Identifier($Identifier.text); }
+ ;
http://git-wip-us.apache.org/repos/asf/incubator-drill/blob/78940e78/sandbox/prototype/common/src/main/java/org/apache/drill/common/expression/BooleanFunctions.java
----------------------------------------------------------------------
diff --git a/sandbox/prototype/common/src/main/java/org/apache/drill/common/expression/BooleanFunctions.java b/sandbox/prototype/common/src/main/java/org/apache/drill/common/expression/BooleanFunctions.java
new file mode 100644
index 0000000..4a33148
--- /dev/null
+++ b/sandbox/prototype/common/src/main/java/org/apache/drill/common/expression/BooleanFunctions.java
@@ -0,0 +1,129 @@
+package org.apache.drill.common.expression;
+
+import java.util.List;
+
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+public class BooleanFunctions {
+
+ static final Logger logger = LoggerFactory.getLogger(BooleanFunctions.class);
+
+ public static final Class<?>[] SUB_TYPES = { Or.class, And.class };
+
+ private static abstract class BooleanFunctionBase extends FunctionBase {
+
+ protected BooleanFunctionBase(List<LogicalExpression> expressions) {
+ super(expressions);
+ }
+
+
+
+ @Override
+ public DataType getDataType() {
+ return DataType.BOOLEAN;
+ }
+ }
+
+ public static class Or extends BooleanFunctionBase {
+ public Or(List<LogicalExpression> expressions) {
+ super(expressions);
+ }
+
+ @Override
+ public void addToString(StringBuilder sb) {
+ this.opToString(sb, "||");
+ }
+
+
+
+ }
+
+ public static class And extends BooleanFunctionBase {
+ public And(List<LogicalExpression> expressions) {
+ super(expressions);
+ }
+
+ @Override
+ public void addToString(StringBuilder sb) {
+ this.opToString(sb, "&&");
+ }
+
+ }
+
+ @FunctionName("isNull")
+ public static class IsNull extends BooleanFunctionBase {
+ public IsNull(List<LogicalExpression> expressions) {
+ super(expressions);
+ }
+
+ @Override
+ public void addToString(StringBuilder sb) {
+ this.funcToString(sb, "isNull");
+ }
+
+ }
+
+ public static class Comparison extends LogicalExpressionBase {
+
+ public final ComparisonType type;
+ public final LogicalExpression left;
+ public final LogicalExpression right;
+
+ public static enum ComparisonType {
+ GT(">"), LT("<"), EQ("=="), NOTEQ("!="), GTE(">="), LTE("<=");
+ public final String val;
+
+ ComparisonType(String str) {
+ this.val = str;
+ }
+ }
+
+
+ public Comparison(String s, LogicalExpression left, LogicalExpression right) {
+ this.left = left;
+ this.right = right;
+ ComparisonType temp = null;
+ for (ComparisonType ct : ComparisonType.values()) {
+ if (ct.val.equals(s)) {
+ temp = ct;
+ break;
+ }
+ }
+ if (temp == null)
+ throw new IllegalArgumentException("Unknown comparison type of " + s);
+ type = temp;
+
+ }
+
+ @Override
+ public void addToString(StringBuilder sb) {
+ sb.append(" ( ");
+ left.addToString(sb);
+ sb.append(" ");
+ sb.append(type.val);
+ sb.append(" ");
+ right.addToString(sb);
+ sb.append(" ) ");
+ }
+
+ public static LogicalExpression create(List<LogicalExpression> expressions, List<String> comparisonTypes) {
+ logger.debug("Generating new comparison expressions.");
+ if (expressions.size() == 1) {
+ return expressions.get(0);
+ }
+
+ if (expressions.size() - 1 != comparisonTypes.size())
+ throw new IllegalArgumentException("Must receive one more expression then the provided number of comparisons.");
+
+ LogicalExpression first = expressions.get(0);
+ LogicalExpression second;
+ for (int i = 0; i < comparisonTypes.size(); i++) {
+ second = expressions.get(i + 1);
+ first = new Comparison(comparisonTypes.get(i), first, second);
+ }
+ return first;
+ }
+ }
+
+}
http://git-wip-us.apache.org/repos/asf/incubator-drill/blob/78940e78/sandbox/prototype/common/src/main/java/org/apache/drill/common/expression/Cast.java
----------------------------------------------------------------------
diff --git a/sandbox/prototype/common/src/main/java/org/apache/drill/common/expression/Cast.java b/sandbox/prototype/common/src/main/java/org/apache/drill/common/expression/Cast.java
new file mode 100644
index 0000000..b2546df
--- /dev/null
+++ b/sandbox/prototype/common/src/main/java/org/apache/drill/common/expression/Cast.java
@@ -0,0 +1,27 @@
+package org.apache.drill.common.expression;
+
+
+@FunctionName("cast")
+public class Cast extends LogicalExpressionBase {
+ private DataType outputType;
+ private LogicalExpression sub;
+
+ public Cast(LogicalExpression subExpression, DataType outputType) throws ExpressionValidationError {
+ if (!sub.getDataType().canCastTo(outputType))
+ throw new ExpressionValidationError();
+ this.sub = subExpression;
+ this.outputType = outputType;
+ }
+
+ @Override
+ public DataType getDataType() {
+ return outputType;
+ }
+
+ @Override
+ public void addToString(StringBuilder sb) {
+ }
+
+
+
+}
http://git-wip-us.apache.org/repos/asf/incubator-drill/blob/78940e78/sandbox/prototype/common/src/main/java/org/apache/drill/common/expression/DataType.java
----------------------------------------------------------------------
diff --git a/sandbox/prototype/common/src/main/java/org/apache/drill/common/expression/DataType.java b/sandbox/prototype/common/src/main/java/org/apache/drill/common/expression/DataType.java
new file mode 100644
index 0000000..d07e5b7
--- /dev/null
+++ b/sandbox/prototype/common/src/main/java/org/apache/drill/common/expression/DataType.java
@@ -0,0 +1,30 @@
+package org.apache.drill.common.expression;
+
+import java.util.Arrays;
+
+public enum DataType{ // roughly taken from sql
+ INVALID, BOOLEAN, BYTES, NVARCHAR, INTEGER, SMALLINT, VARBIT, FLOAT, DOUBLE, DATE, TIME, DATETIME, UNKNOWN;
+
+ private DataType[] castable;
+ DataType(DataType... castToDataTypes){
+ castable = castToDataTypes;
+ Arrays.sort(castable);
+ }
+ public boolean canCastTo(DataType dt){
+ if(dt == this) return true;
+ for(int i =0; i < castable.length; i++){
+ if(dt.equals(castable[i])) return true;
+ }
+ return false;
+ }
+
+ public static DataType getCombinedCast(DataType a, DataType b){
+ if(a == b) return a;
+
+ if(a.canCastTo(b)) return b;
+ if(b.canCastTo(a)) return a;
+ return null;
+ }
+
+
+}
\ No newline at end of file
http://git-wip-us.apache.org/repos/asf/incubator-drill/blob/78940e78/sandbox/prototype/common/src/main/java/org/apache/drill/common/expression/ExpressionFunction.java
----------------------------------------------------------------------
diff --git a/sandbox/prototype/common/src/main/java/org/apache/drill/common/expression/ExpressionFunction.java b/sandbox/prototype/common/src/main/java/org/apache/drill/common/expression/ExpressionFunction.java
new file mode 100644
index 0000000..dee571a
--- /dev/null
+++ b/sandbox/prototype/common/src/main/java/org/apache/drill/common/expression/ExpressionFunction.java
@@ -0,0 +1,70 @@
+package org.apache.drill.common.expression;
+
+import java.lang.reflect.Constructor;
+import java.lang.reflect.Type;
+import java.util.List;
+
+import org.apache.drill.common.expression.BooleanFunctions.IsNull;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import com.google.common.collect.ImmutableMap;
+import com.google.common.reflect.TypeToken;
+
+
+@SuppressWarnings("unchecked")
+public class ExpressionFunction {
+ final static Logger logger = LoggerFactory.getLogger(ExpressionFunction.class);
+
+ @SuppressWarnings("serial")
+ final static Type EXPR_LIST = (new TypeToken<List<LogicalExpression>>() {}).getType();
+
+ private static final Class<?>[] FUNCTIONS = {
+ BooleanFunctions.And.class, BooleanFunctions.Or.class, StringFunctions.Regex.class, StringFunctions.StartsWith.class, IsNull.class
+ };
+
+ private static final ImmutableMap<String, Constructor<LogicalExpression>> FUNCTION_MAP;
+
+ static {
+ ImmutableMap.Builder<String, Constructor<LogicalExpression>> builder = ImmutableMap.builder();
+ for(Class<?> c : FUNCTIONS){
+
+ logger.debug("Adding {} and function", c);
+ if(!LogicalExpression.class.isAssignableFrom(c)){
+ logger.error("The provided Class [{}] does not derive from LogicalExpression. Skipping inclusion in registry.", c);
+ continue;
+ }
+ FunctionName fn = c.getAnnotation(FunctionName.class);
+ if(fn == null){
+ logger.error("The provided Class [{}] did not have a FunctionName annotation. Skipping inclusion in registry.", c);
+ continue;
+ }
+ String name = fn.value();
+ try{
+ Constructor<LogicalExpression> m = (Constructor<LogicalExpression>) c.getConstructor(List.class);
+ if(!EXPR_LIST.equals(m.getGenericParameterTypes()[0])){
+ logger.error("The constructor for each function must have a argument list that only contains a List<LogicalExpression>. The class[{}] has an inccorect List<{}> argument.", c, m.getGenericParameterTypes()[0]);
+ continue;
+ }
+
+ builder.put(name, m);
+ }catch(Exception e){
+ logger.error("Failure while attempting to retrieve Logical Expression list constructor on class [{}]. Functions must have one of these.", c, e);
+ }
+
+ }
+
+ FUNCTION_MAP = builder.build();
+ }
+
+
+ public static LogicalExpression create(String functionName, List<LogicalExpression> expressions) throws ExpressionValidationError{
+ logger.debug("Requesting generation of new function with name {}.", functionName);
+ if(!FUNCTION_MAP.containsKey(functionName)) throw new ExpressionValidationError(String.format("Unknown function with name '%s'", functionName));
+ try {
+ return FUNCTION_MAP.get(functionName).newInstance(expressions);
+ } catch (Exception e) {
+ throw new ExpressionValidationError("Failure while attempting to build type of " + functionName, e);
+ }
+ }
+}
http://git-wip-us.apache.org/repos/asf/incubator-drill/blob/78940e78/sandbox/prototype/common/src/main/java/org/apache/drill/common/expression/ExpressionValidationError.java
----------------------------------------------------------------------
diff --git a/sandbox/prototype/common/src/main/java/org/apache/drill/common/expression/ExpressionValidationError.java b/sandbox/prototype/common/src/main/java/org/apache/drill/common/expression/ExpressionValidationError.java
new file mode 100644
index 0000000..51ba2d2
--- /dev/null
+++ b/sandbox/prototype/common/src/main/java/org/apache/drill/common/expression/ExpressionValidationError.java
@@ -0,0 +1,22 @@
+package org.apache.drill.common.expression;
+
+
+public class ExpressionValidationError extends RuntimeException{
+
+ public ExpressionValidationError() {
+ super();
+ }
+
+ public ExpressionValidationError(String arg0, Throwable arg1) {
+ super(arg0, arg1);
+ }
+
+ public ExpressionValidationError(String arg0) {
+ super(arg0);
+ }
+
+ public ExpressionValidationError(Throwable arg0) {
+ super(arg0);
+ }
+
+}
http://git-wip-us.apache.org/repos/asf/incubator-drill/blob/78940e78/sandbox/prototype/common/src/main/java/org/apache/drill/common/expression/FieldReference.java
----------------------------------------------------------------------
diff --git a/sandbox/prototype/common/src/main/java/org/apache/drill/common/expression/FieldReference.java b/sandbox/prototype/common/src/main/java/org/apache/drill/common/expression/FieldReference.java
new file mode 100644
index 0000000..5cf6d00
--- /dev/null
+++ b/sandbox/prototype/common/src/main/java/org/apache/drill/common/expression/FieldReference.java
@@ -0,0 +1,57 @@
+package org.apache.drill.common.expression;
+
+import java.io.IOException;
+
+import org.apache.drill.common.expression.FieldReference.De;
+import org.apache.drill.common.expression.FieldReference.Se;
+
+import com.fasterxml.jackson.core.JsonGenerationException;
+import com.fasterxml.jackson.core.JsonGenerator;
+import com.fasterxml.jackson.core.JsonParser;
+import com.fasterxml.jackson.core.JsonProcessingException;
+import com.fasterxml.jackson.databind.DeserializationContext;
+import com.fasterxml.jackson.databind.SerializerProvider;
+import com.fasterxml.jackson.databind.annotation.JsonDeserialize;
+import com.fasterxml.jackson.databind.annotation.JsonSerialize;
+import com.fasterxml.jackson.databind.deser.std.StdDeserializer;
+import com.fasterxml.jackson.databind.ser.std.StdSerializer;
+
+@JsonSerialize(using=Se.class)
+@JsonDeserialize(using=De.class)
+public class FieldReference extends ValueExpressions.Identifier {
+ private String refName;
+
+ public FieldReference(String value) {
+ super(value);
+ }
+
+ public static class De extends StdDeserializer<FieldReference> {
+
+ public De() {
+ super(FieldReference.class);
+ }
+
+ @Override
+ public FieldReference deserialize(JsonParser jp, DeserializationContext ctxt) throws IOException,
+ JsonProcessingException {
+ String s = jp.getText();
+ return new FieldReference(s);
+ }
+
+ }
+
+ public static class Se extends StdSerializer<FieldReference> {
+
+ public Se() {
+ super(FieldReference.class);
+ }
+
+ @Override
+ public void serialize(FieldReference value, JsonGenerator jgen, SerializerProvider provider) throws IOException,
+ JsonGenerationException {
+ jgen.writeString(value.refName);
+ }
+
+ }
+
+}
http://git-wip-us.apache.org/repos/asf/incubator-drill/blob/78940e78/sandbox/prototype/common/src/main/java/org/apache/drill/common/expression/FunctionBase.java
----------------------------------------------------------------------
diff --git a/sandbox/prototype/common/src/main/java/org/apache/drill/common/expression/FunctionBase.java b/sandbox/prototype/common/src/main/java/org/apache/drill/common/expression/FunctionBase.java
new file mode 100644
index 0000000..f87c73c
--- /dev/null
+++ b/sandbox/prototype/common/src/main/java/org/apache/drill/common/expression/FunctionBase.java
@@ -0,0 +1,87 @@
+package org.apache.drill.common.expression;
+
+import java.util.Collection;
+import java.util.Iterator;
+import java.util.List;
+
+import org.apache.drill.common.expression.visitors.FunctionVisitor;
+import org.apache.drill.common.logical.ValidationError;
+
+import com.fasterxml.jackson.annotation.JsonIgnore;
+import com.google.common.collect.ImmutableList;
+
+
+public abstract class FunctionBase extends LogicalExpressionBase implements Iterable<LogicalExpression>{
+ public final ImmutableList<LogicalExpression> expressions;
+
+
+ protected void funcToString(StringBuilder sb, String functionName) {
+ sb.append(" ");
+ sb.append(functionName);
+ sb.append("( ");
+ for(int i= 0; i < expressions.size(); i++){
+ if(i != 0) sb.append(", ");
+ expressions.get(i).addToString(sb);
+ }
+ sb.append(" ) ");
+ }
+
+ protected void opToString(StringBuilder sb, String operator) {
+ sb.append(" ( ");
+ expressions.get(0).addToString(sb);
+ for(int i =1; i < expressions.size(); i++){
+ sb.append(operator);
+ expressions.get(i).addToString(sb);
+ }
+ sb.append(" ) ");
+ }
+
+ public FunctionBase(List<LogicalExpression> expressions){
+ if( !(expressions instanceof ImmutableList)){
+ expressions = ImmutableList.copyOf(expressions);
+ }
+ this.expressions = (ImmutableList<LogicalExpression>) expressions;
+ }
+
+ public static DataType getJointType(String parentName, LogicalExpression expr1, LogicalExpression expr2) throws ExpressionValidationError{
+ DataType dt = DataType.getCombinedCast(expr1.getDataType(), expr2.getDataType());
+ if(dt == null) throw new ExpressionValidationError();
+
+ return dt;
+ }
+
+ public LogicalExpression wrapWithCastIfNecessary(DataType dt) throws ExpressionValidationError{
+ if(this.getDataType() != dt) return new Cast(this, dt);
+ return this;
+ }
+
+
+ @Override
+ public Void accept(FunctionVisitor visitor) {
+ visitor.visit(this);
+ return null;
+ }
+
+ @Override
+ public Iterator<LogicalExpression> iterator() {
+ return expressions.iterator();
+ }
+
+ @Override
+ @JsonIgnore
+ public DataType getDataType() {
+ throw new UnsupportedOperationException();
+ }
+
+ @Override
+ public void resolveAndValidate(List<LogicalExpression> expressions,
+ Collection<ValidationError> errors) {
+ throw new UnsupportedOperationException();
+ }
+
+
+
+
+
+
+}
http://git-wip-us.apache.org/repos/asf/incubator-drill/blob/78940e78/sandbox/prototype/common/src/main/java/org/apache/drill/common/expression/FunctionName.java
----------------------------------------------------------------------
diff --git a/sandbox/prototype/common/src/main/java/org/apache/drill/common/expression/FunctionName.java b/sandbox/prototype/common/src/main/java/org/apache/drill/common/expression/FunctionName.java
new file mode 100644
index 0000000..3cbca7d
--- /dev/null
+++ b/sandbox/prototype/common/src/main/java/org/apache/drill/common/expression/FunctionName.java
@@ -0,0 +1,12 @@
+package org.apache.drill.common.expression;
+
+import java.lang.annotation.ElementType;
+import java.lang.annotation.Retention;
+import java.lang.annotation.RetentionPolicy;
+import java.lang.annotation.Target;
+
+@Retention(RetentionPolicy.RUNTIME)
+@Target({ElementType.TYPE})
+public @interface FunctionName {
+ String value();
+}
http://git-wip-us.apache.org/repos/asf/incubator-drill/blob/78940e78/sandbox/prototype/common/src/main/java/org/apache/drill/common/expression/IfExpression.java
----------------------------------------------------------------------
diff --git a/sandbox/prototype/common/src/main/java/org/apache/drill/common/expression/IfExpression.java b/sandbox/prototype/common/src/main/java/org/apache/drill/common/expression/IfExpression.java
new file mode 100644
index 0000000..52d45c2
--- /dev/null
+++ b/sandbox/prototype/common/src/main/java/org/apache/drill/common/expression/IfExpression.java
@@ -0,0 +1,87 @@
+package org.apache.drill.common.expression;
+
+import java.util.ArrayList;
+import java.util.List;
+
+import org.apache.drill.common.expression.IfExpression.IfCondition;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import com.google.common.collect.ImmutableList;
+import com.google.common.collect.UnmodifiableIterator;
+
+public class IfExpression extends LogicalExpressionBase implements Iterable<IfCondition>{
+ static final Logger logger = LoggerFactory.getLogger(IfExpression.class);
+
+ public final ImmutableList<IfCondition> conditions;
+ public final LogicalExpression elseExpression;
+
+ private IfExpression(List<IfCondition> conditions, LogicalExpression elseExpression){
+ this.conditions = ImmutableList.copyOf(conditions);
+ this.elseExpression = elseExpression;
+ };
+
+
+ public static class IfCondition{
+ public final LogicalExpression condition;
+ public final LogicalExpression expression;
+
+ public IfCondition(LogicalExpression condition,
+ LogicalExpression expression) {
+ logger.debug("Generating IfCondition {}, {}", condition, expression);
+
+ this.condition = condition;
+ this.expression = expression;
+ }
+
+ }
+
+ public static class Builder{
+ List<IfCondition> conditions = new ArrayList<IfCondition>();
+ private LogicalExpression elseExpression;
+
+ public void addCondition(IfCondition condition){
+ conditions.add(condition);
+ }
+
+ public void setElse(LogicalExpression elseExpression) {
+ this.elseExpression = elseExpression;
+ }
+
+ public IfExpression build(){
+ return new IfExpression(conditions, elseExpression);
+ }
+
+ }
+
+
+
+
+ @Override
+ public void addToString(StringBuilder sb) {
+ sb.append(" ( ");
+ for(int i =0; i < conditions.size(); i++){
+ IfCondition c = conditions.get(i);
+ if(i !=0) sb.append(" else ");
+ sb.append("if (");
+ c.condition.addToString(sb);
+ sb.append(" ) then (");
+ c.expression.addToString(sb);
+ sb.append(" ) ");
+ }
+ sb.append(" end ");
+ sb.append(" ) ");
+ }
+
+
+ public static Builder newBuilder(){
+ return new Builder();
+ }
+
+
+ @Override
+ public UnmodifiableIterator<IfCondition> iterator() {
+ return conditions.iterator();
+ }
+
+}
http://git-wip-us.apache.org/repos/asf/incubator-drill/blob/78940e78/sandbox/prototype/common/src/main/java/org/apache/drill/common/expression/LogicalExpression.java
----------------------------------------------------------------------
diff --git a/sandbox/prototype/common/src/main/java/org/apache/drill/common/expression/LogicalExpression.java b/sandbox/prototype/common/src/main/java/org/apache/drill/common/expression/LogicalExpression.java
new file mode 100644
index 0000000..bfdd6cc
--- /dev/null
+++ b/sandbox/prototype/common/src/main/java/org/apache/drill/common/expression/LogicalExpression.java
@@ -0,0 +1,97 @@
+package org.apache.drill.common.expression;
+
+import java.io.IOException;
+import java.util.Collection;
+import java.util.List;
+
+import org.antlr.runtime.ANTLRStringStream;
+import org.antlr.runtime.CommonTokenStream;
+import org.antlr.runtime.RecognitionException;
+import org.apache.drill.common.expression.parser.ExprLexer;
+import org.apache.drill.common.expression.parser.ExprParser;
+import org.apache.drill.common.expression.parser.ExprParser.parse_return;
+import org.apache.drill.common.expression.visitors.FunctionVisitor;
+import org.apache.drill.common.logical.ValidationError;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import com.fasterxml.jackson.annotation.JsonIgnore;
+import com.fasterxml.jackson.core.JsonGenerationException;
+import com.fasterxml.jackson.core.JsonGenerator;
+import com.fasterxml.jackson.core.JsonParser;
+import com.fasterxml.jackson.core.JsonProcessingException;
+import com.fasterxml.jackson.databind.DeserializationContext;
+import com.fasterxml.jackson.databind.SerializerProvider;
+import com.fasterxml.jackson.databind.annotation.JsonDeserialize;
+import com.fasterxml.jackson.databind.annotation.JsonSerialize;
+import com.fasterxml.jackson.databind.deser.std.StdDeserializer;
+import com.fasterxml.jackson.databind.ser.std.StdSerializer;
+
+@JsonDeserialize(using=LogicalExpression.De.class)
+@JsonSerialize(using=LogicalExpression.Se.class)
+//@JsonTypeInfo(use = JsonTypeInfo.Id.MINIMAL_CLASS, include = JsonTypeInfo.As.PROPERTY, property = "fn")
+public interface LogicalExpression {
+ static final Logger logger = LoggerFactory.getLogger(LogicalExpression.class);
+
+ public static final Class<?>[] SUB_TYPES = {};
+
+ LogicalExpression wrapWithCastIfNecessary(DataType dt)
+ throws ExpressionValidationError;
+
+ @JsonIgnore
+ public abstract DataType getDataType();
+
+
+ public void addToString(StringBuilder sb);
+ public void resolveAndValidate(List<LogicalExpression> expressions,
+ Collection<ValidationError> errors);
+
+ public Object accept(FunctionVisitor visitor);
+
+ public static class De extends StdDeserializer<LogicalExpression> {
+
+
+ public De() {
+ super(LogicalExpression.class);
+ }
+
+ @Override
+ public LogicalExpression deserialize(JsonParser jp,
+ DeserializationContext ctxt) throws IOException,
+ JsonProcessingException {
+ String expr = jp.getText();
+
+ if(expr == null || expr.isEmpty()) return null;
+ try {
+ logger.debug("Parsing expression string '{}'", expr);
+ ExprLexer lexer = new ExprLexer(new ANTLRStringStream(expr));
+
+ CommonTokenStream tokens = new CommonTokenStream(lexer);
+ ExprParser parser = new ExprParser(tokens);
+ parse_return ret = parser.parse();
+ logger.debug("Found expression '{}'", ret.e);
+ return ret.e;
+ } catch (RecognitionException e) {
+ throw new RuntimeException(e);
+ }
+ }
+
+ }
+
+ public static class Se extends StdSerializer<LogicalExpression> {
+
+ protected Se() {
+ super(LogicalExpression.class);
+ }
+
+ @Override
+ public void serialize(LogicalExpression value, JsonGenerator jgen, SerializerProvider provider) throws IOException,
+ JsonGenerationException {
+ StringBuilder sb = new StringBuilder();
+ value.addToString(sb);
+ jgen.writeString(sb.toString());
+ }
+
+ }
+
+}
http://git-wip-us.apache.org/repos/asf/incubator-drill/blob/78940e78/sandbox/prototype/common/src/main/java/org/apache/drill/common/expression/LogicalExpressionBase.java
----------------------------------------------------------------------
diff --git a/sandbox/prototype/common/src/main/java/org/apache/drill/common/expression/LogicalExpressionBase.java b/sandbox/prototype/common/src/main/java/org/apache/drill/common/expression/LogicalExpressionBase.java
new file mode 100644
index 0000000..e742d63
--- /dev/null
+++ b/sandbox/prototype/common/src/main/java/org/apache/drill/common/expression/LogicalExpressionBase.java
@@ -0,0 +1,64 @@
+package org.apache.drill.common.expression;
+
+import java.util.Collection;
+import java.util.List;
+
+import org.apache.drill.common.expression.visitors.FunctionVisitor;
+import org.apache.drill.common.logical.ValidationError;
+
+import com.fasterxml.jackson.annotation.JsonIgnore;
+import com.fasterxml.jackson.annotation.JsonProperty;
+import com.fasterxml.jackson.annotation.JsonPropertyOrder;
+
+
+@JsonPropertyOrder({ "type" })
+public abstract class LogicalExpressionBase implements LogicalExpression{
+
+
+ public static DataType getJointType(String parentName, LogicalExpression expr1, LogicalExpression expr2) throws ExpressionValidationError{
+ DataType dt = DataType.getCombinedCast(expr1.getDataType(), expr2.getDataType());
+ if(dt == null) throw new ExpressionValidationError();
+
+ return dt;
+ }
+
+ public LogicalExpression wrapWithCastIfNecessary(DataType dt) throws ExpressionValidationError{
+ if(this.getDataType() != dt) return new Cast(this, dt);
+ return this;
+ }
+
+
+ protected void i(StringBuilder sb, int indent){
+ for(int i = 0; i < indent; i++){
+ sb.append(" ");
+ }
+ }
+
+ @Override
+ public Void accept(FunctionVisitor visitor) {
+ visitor.visit(this);
+ return null;
+ }
+
+ @Override
+ @JsonIgnore
+ public DataType getDataType() {
+ throw new UnsupportedOperationException();
+ }
+
+ @Override
+ public void resolveAndValidate(List<LogicalExpression> expressions,
+ Collection<ValidationError> errors) {
+
+
+ }
+
+ @JsonProperty("type")
+ public String getDescription(){
+ return this.getClass().getSimpleName();
+ }
+
+
+
+
+}
http://git-wip-us.apache.org/repos/asf/incubator-drill/blob/78940e78/sandbox/prototype/common/src/main/java/org/apache/drill/common/expression/MathFunction.java
----------------------------------------------------------------------
diff --git a/sandbox/prototype/common/src/main/java/org/apache/drill/common/expression/MathFunction.java b/sandbox/prototype/common/src/main/java/org/apache/drill/common/expression/MathFunction.java
new file mode 100644
index 0000000..31da768
--- /dev/null
+++ b/sandbox/prototype/common/src/main/java/org/apache/drill/common/expression/MathFunction.java
@@ -0,0 +1,84 @@
+package org.apache.drill.common.expression;
+
+import java.util.Collection;
+import java.util.List;
+
+import org.apache.drill.common.logical.ValidationError;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import com.fasterxml.jackson.annotation.JsonIgnore;
+
+
+
+public class MathFunction extends LogicalExpressionBase{
+
+ static final Logger logger = LoggerFactory.getLogger(MathFunction.class);
+
+ public final Method method;
+ public final LogicalExpression left;
+ public final LogicalExpression right;
+
+ public MathFunction(Method method, LogicalExpression left, LogicalExpression right) throws ExpressionValidationError {
+ this.method = method;
+ this.left = left;
+ this.right = right;
+ }
+
+ public MathFunction(String methodString, LogicalExpression left, LogicalExpression right) throws ExpressionValidationError {
+ logger.debug("{}|{} Generating new Math expression of type " + methodString, left, right);
+ Method temp = null;
+ for(Method m : Method.values()){
+ if(m.expr.equals(methodString)){
+ temp = m;
+ break;
+ }
+ }
+ if(temp == null) throw new IllegalArgumentException("Unknown match operator: " + methodString);
+ this.method = temp;
+ this.left = left;
+ this.right = right;
+ }
+
+ @Override
+ public void addToString(StringBuilder sb) {
+ sb.append(" ( ");
+ left.addToString(sb);
+ sb.append(" ");
+ sb.append(method.expr);
+ sb.append(" ");
+ right.addToString(sb);
+ sb.append(" ) ");
+ }
+
+
+ public static enum Method{
+ ADD("+"), DIVIDE("/"), MULTIPLY("*"), SUBSTRACT("-"), POWER("^"), MOD("%");
+ public final String expr;
+
+ Method(String expr){
+ this.expr = expr;
+ }
+ }
+
+
+ public static LogicalExpression create(List<LogicalExpression> expressions, List<String> operators){
+
+ if(expressions.size() == 1){
+ return expressions.get(0);
+ }
+
+ if(expressions.size()-1 != operators.size()) throw new IllegalArgumentException("Must receive one more expression then the provided number of operators.");
+
+ LogicalExpression first = expressions.get(0);
+ LogicalExpression second;
+ for(int i=0; i < operators.size(); i ++){
+ second = expressions.get(i+1);
+ first = new MathFunction(operators.get(i), first, second );
+ }
+ return first;
+ }
+
+
+
+}
http://git-wip-us.apache.org/repos/asf/incubator-drill/blob/78940e78/sandbox/prototype/common/src/main/java/org/apache/drill/common/expression/StringFunctions.java
----------------------------------------------------------------------
diff --git a/sandbox/prototype/common/src/main/java/org/apache/drill/common/expression/StringFunctions.java b/sandbox/prototype/common/src/main/java/org/apache/drill/common/expression/StringFunctions.java
new file mode 100644
index 0000000..7f29e27
--- /dev/null
+++ b/sandbox/prototype/common/src/main/java/org/apache/drill/common/expression/StringFunctions.java
@@ -0,0 +1,55 @@
+package org.apache.drill.common.expression;
+
+import java.util.Collection;
+import java.util.List;
+
+import org.apache.drill.common.logical.ValidationError;
+
+public class StringFunctions {
+
+ public static final Class<?>[] SUB_TYPES = {Regex.class, StartsWith.class};
+
+ @FunctionName("regex")
+ public static class Regex extends FunctionBase{
+
+
+ public Regex(List<LogicalExpression> expressions) {
+ super(expressions);
+
+ }
+
+ @Override
+ public DataType getDataType() {
+ return DataType.NVARCHAR;
+ }
+
+
+ @Override
+ public void addToString(StringBuilder sb) {
+ this.funcToString(sb, "regex");
+ }
+
+ }
+
+ @FunctionName("startsWith")
+ public static class StartsWith extends FunctionBase{
+
+ public StartsWith(List<LogicalExpression> expressions) {
+ super(expressions);
+ }
+
+ @Override
+ public DataType getDataType() {
+ return DataType.BOOLEAN;
+ }
+
+ @Override
+ public void addToString(StringBuilder sb) {
+ this.funcToString(sb, "startsWith");
+ }
+
+
+
+ }
+
+}
http://git-wip-us.apache.org/repos/asf/incubator-drill/blob/78940e78/sandbox/prototype/common/src/main/java/org/apache/drill/common/expression/TypeFunctions.java
----------------------------------------------------------------------
diff --git a/sandbox/prototype/common/src/main/java/org/apache/drill/common/expression/TypeFunctions.java b/sandbox/prototype/common/src/main/java/org/apache/drill/common/expression/TypeFunctions.java
new file mode 100644
index 0000000..0476533
--- /dev/null
+++ b/sandbox/prototype/common/src/main/java/org/apache/drill/common/expression/TypeFunctions.java
@@ -0,0 +1,31 @@
+package org.apache.drill.common.expression;
+
+import java.util.List;
+
+import com.fasterxml.jackson.annotation.JsonTypeName;
+
+public class TypeFunctions {
+ public static final Class<?>[] SUB_TYPES = {IsANumber.class};
+
+
+
+ @JsonTypeName("isNumber")
+ public static class IsANumber extends FunctionBase{
+
+ public IsANumber(List<LogicalExpression> expressions) {
+ super(expressions);
+ }
+
+ @Override
+ public DataType getDataType() {
+ return DataType.BOOLEAN;
+ }
+
+ @Override
+ public void addToString(StringBuilder sb) {
+ this.funcToString(sb, "isNumber");
+ }
+
+
+ }
+}
http://git-wip-us.apache.org/repos/asf/incubator-drill/blob/78940e78/sandbox/prototype/common/src/main/java/org/apache/drill/common/expression/UnaryFunctions.java
----------------------------------------------------------------------
diff --git a/sandbox/prototype/common/src/main/java/org/apache/drill/common/expression/UnaryFunctions.java b/sandbox/prototype/common/src/main/java/org/apache/drill/common/expression/UnaryFunctions.java
new file mode 100644
index 0000000..f3a0a17
--- /dev/null
+++ b/sandbox/prototype/common/src/main/java/org/apache/drill/common/expression/UnaryFunctions.java
@@ -0,0 +1,57 @@
+package org.apache.drill.common.expression;
+
+
+public class UnaryFunctions {
+
+
+
+
+ public static abstract class UnaryLogicalExpressionBase extends LogicalExpressionBase{
+ protected final LogicalExpression input1;
+
+ protected UnaryLogicalExpressionBase(LogicalExpression input1){
+ this.input1 = input1;
+ }
+
+ protected void unaryToString(StringBuilder sb, String expr) {
+ sb.append(" ");
+ sb.append(expr);
+ sb.append("( ");
+ input1.addToString(sb);
+ sb.append(" ) ");
+ }
+
+ }
+
+ public static class Not extends UnaryLogicalExpressionBase{
+
+ public Not(LogicalExpression input1) {
+ super(input1);
+ }
+
+ @Override
+ public void addToString(StringBuilder sb) {
+ unaryToString(sb, "!");
+ }
+
+
+ }
+
+ public static class Negative extends UnaryLogicalExpressionBase{
+
+ public Negative(LogicalExpression input1) {
+ super(input1);
+ }
+
+ @Override
+ public void addToString(StringBuilder sb) {
+ unaryToString(sb, "-");
+ }
+
+
+ @Override
+ public DataType getDataType() {
+ return input1.getDataType();
+ }
+ }
+}
http://git-wip-us.apache.org/repos/asf/incubator-drill/blob/78940e78/sandbox/prototype/common/src/main/java/org/apache/drill/common/expression/ValueExpressions.java
----------------------------------------------------------------------
diff --git a/sandbox/prototype/common/src/main/java/org/apache/drill/common/expression/ValueExpressions.java b/sandbox/prototype/common/src/main/java/org/apache/drill/common/expression/ValueExpressions.java
new file mode 100644
index 0000000..6df2782
--- /dev/null
+++ b/sandbox/prototype/common/src/main/java/org/apache/drill/common/expression/ValueExpressions.java
@@ -0,0 +1,87 @@
+package org.apache.drill.common.expression;
+
+
+public class ValueExpressions {
+
+ protected static abstract class ValueExpression<V> extends
+ LogicalExpressionBase {
+ public final V value;
+
+ protected ValueExpression(String value) {
+ this.value = parseValue(value);
+ }
+
+ protected abstract V parseValue(String s);
+
+
+ }
+
+ public static class BooleanExpression extends ValueExpression<Boolean> {
+ public BooleanExpression(String value) {
+ super(value);
+ }
+
+ @Override
+ protected Boolean parseValue(String s) {
+ return Boolean.parseBoolean(s);
+ }
+
+ @Override
+ public void addToString(StringBuilder sb) {
+ sb.append(value.toString());
+ }
+
+ }
+
+ public static class NumberExpression extends ValueExpression<Number> {
+ public NumberExpression(String value) {
+ super(value);
+ }
+
+ @Override
+ protected Number parseValue(String s) {
+ return Integer.parseInt(s);
+ }
+
+ @Override
+ public void addToString(StringBuilder sb) {
+ sb.append(value.toString());
+ }
+ }
+
+ public static class QuotedString extends ValueExpression<String> {
+ public QuotedString(String value) {
+ super(value);
+ }
+
+ @Override
+ protected String parseValue(String s) {
+ return s;
+ }
+
+ @Override
+ public void addToString(StringBuilder sb) {
+ sb.append("\"");
+ sb.append(value.toString());
+ sb.append("\"");
+ }
+ }
+
+ public static class Identifier extends ValueExpression<String> {
+ public Identifier(String value) {
+ super(value);
+ }
+
+ @Override
+ protected String parseValue(String s) {
+ return s;
+ }
+
+ @Override
+ public void addToString(StringBuilder sb) {
+ sb.append("'");
+ sb.append(value.toString());
+ sb.append("'");
+ }
+ }
+}
http://git-wip-us.apache.org/repos/asf/incubator-drill/blob/78940e78/sandbox/prototype/common/src/main/java/org/apache/drill/common/expression/aggregate/BasicAggregates.java
----------------------------------------------------------------------
diff --git a/sandbox/prototype/common/src/main/java/org/apache/drill/common/expression/aggregate/BasicAggregates.java b/sandbox/prototype/common/src/main/java/org/apache/drill/common/expression/aggregate/BasicAggregates.java
new file mode 100644
index 0000000..f336772
--- /dev/null
+++ b/sandbox/prototype/common/src/main/java/org/apache/drill/common/expression/aggregate/BasicAggregates.java
@@ -0,0 +1,5 @@
+package org.apache.drill.common.expression.aggregate;
+
+public class BasicAggregates {
+
+}
http://git-wip-us.apache.org/repos/asf/incubator-drill/blob/78940e78/sandbox/prototype/common/src/main/java/org/apache/drill/common/expression/visitors/BasicEvaluator.java
----------------------------------------------------------------------
diff --git a/sandbox/prototype/common/src/main/java/org/apache/drill/common/expression/visitors/BasicEvaluator.java b/sandbox/prototype/common/src/main/java/org/apache/drill/common/expression/visitors/BasicEvaluator.java
new file mode 100644
index 0000000..e0ce4d2
--- /dev/null
+++ b/sandbox/prototype/common/src/main/java/org/apache/drill/common/expression/visitors/BasicEvaluator.java
@@ -0,0 +1,5 @@
+package org.apache.drill.common.expression.visitors;
+
+public class BasicEvaluator extends FunctionVisitor{
+
+}
http://git-wip-us.apache.org/repos/asf/incubator-drill/blob/78940e78/sandbox/prototype/common/src/main/java/org/apache/drill/common/expression/visitors/FunctionVisitor.java
----------------------------------------------------------------------
diff --git a/sandbox/prototype/common/src/main/java/org/apache/drill/common/expression/visitors/FunctionVisitor.java b/sandbox/prototype/common/src/main/java/org/apache/drill/common/expression/visitors/FunctionVisitor.java
new file mode 100644
index 0000000..e65244e
--- /dev/null
+++ b/sandbox/prototype/common/src/main/java/org/apache/drill/common/expression/visitors/FunctionVisitor.java
@@ -0,0 +1,11 @@
+package org.apache.drill.common.expression.visitors;
+
+import org.apache.drill.common.expression.LogicalExpression;
+
+public abstract class FunctionVisitor {
+
+ public final void visit(LogicalExpression e){
+ throw new UnsupportedOperationException("The current visitor doesn't support the provided LogicalExpression of " + e.getClass().getSimpleName());
+ }
+
+}
http://git-wip-us.apache.org/repos/asf/incubator-drill/blob/78940e78/sandbox/prototype/common/src/main/java/org/apache/drill/common/expression/visitors/GetIdentifiers.java
----------------------------------------------------------------------
diff --git a/sandbox/prototype/common/src/main/java/org/apache/drill/common/expression/visitors/GetIdentifiers.java b/sandbox/prototype/common/src/main/java/org/apache/drill/common/expression/visitors/GetIdentifiers.java
new file mode 100644
index 0000000..7f3ebee
--- /dev/null
+++ b/sandbox/prototype/common/src/main/java/org/apache/drill/common/expression/visitors/GetIdentifiers.java
@@ -0,0 +1,11 @@
+package org.apache.drill.common.expression.visitors;
+
+import java.util.HashSet;
+
+import org.apache.drill.common.expression.ValueExpressions;
+
+public class GetIdentifiers extends FunctionVisitor{
+ private HashSet<ValueExpressions.Identifier> identifiers = new HashSet<ValueExpressions.Identifier>();
+
+
+}
http://git-wip-us.apache.org/repos/asf/incubator-drill/blob/78940e78/sandbox/prototype/common/src/main/java/org/apache/drill/common/logical/FieldName.java
----------------------------------------------------------------------
diff --git a/sandbox/prototype/common/src/main/java/org/apache/drill/common/logical/FieldName.java b/sandbox/prototype/common/src/main/java/org/apache/drill/common/logical/FieldName.java
new file mode 100644
index 0000000..86fa403
--- /dev/null
+++ b/sandbox/prototype/common/src/main/java/org/apache/drill/common/logical/FieldName.java
@@ -0,0 +1,5 @@
+package org.apache.drill.common.logical;
+
+public class FieldName {
+ public String name;
+}
http://git-wip-us.apache.org/repos/asf/incubator-drill/blob/78940e78/sandbox/prototype/common/src/main/java/org/apache/drill/common/logical/FlowInput.java
----------------------------------------------------------------------
diff --git a/sandbox/prototype/common/src/main/java/org/apache/drill/common/logical/FlowInput.java b/sandbox/prototype/common/src/main/java/org/apache/drill/common/logical/FlowInput.java
new file mode 100644
index 0000000..386807f
--- /dev/null
+++ b/sandbox/prototype/common/src/main/java/org/apache/drill/common/logical/FlowInput.java
@@ -0,0 +1,5 @@
+package org.apache.drill.common.logical;
+
+public class FlowInput {
+
+}
http://git-wip-us.apache.org/repos/asf/incubator-drill/blob/78940e78/sandbox/prototype/common/src/main/java/org/apache/drill/common/logical/FlowOutput.java
----------------------------------------------------------------------
diff --git a/sandbox/prototype/common/src/main/java/org/apache/drill/common/logical/FlowOutput.java b/sandbox/prototype/common/src/main/java/org/apache/drill/common/logical/FlowOutput.java
new file mode 100644
index 0000000..7844a30
--- /dev/null
+++ b/sandbox/prototype/common/src/main/java/org/apache/drill/common/logical/FlowOutput.java
@@ -0,0 +1,5 @@
+package org.apache.drill.common.logical;
+
+public class FlowOutput {
+
+}
http://git-wip-us.apache.org/repos/asf/incubator-drill/blob/78940e78/sandbox/prototype/common/src/main/java/org/apache/drill/common/logical/LogicalPlan.java
----------------------------------------------------------------------
diff --git a/sandbox/prototype/common/src/main/java/org/apache/drill/common/logical/LogicalPlan.java b/sandbox/prototype/common/src/main/java/org/apache/drill/common/logical/LogicalPlan.java
new file mode 100644
index 0000000..28624cf
--- /dev/null
+++ b/sandbox/prototype/common/src/main/java/org/apache/drill/common/logical/LogicalPlan.java
@@ -0,0 +1,47 @@
+package org.apache.drill.common.logical;
+
+import java.io.File;
+import java.util.ArrayList;
+import java.util.List;
+
+import org.apache.drill.common.logical.data.LogicalOperator;
+import org.apache.drill.common.logical.data.Transform;
+import org.apache.drill.common.logical.sources.DataSource;
+import org.apache.drill.common.logical.sources.record.RecordMaker;
+
+import com.fasterxml.jackson.annotation.JsonProperty;
+import com.fasterxml.jackson.annotation.JsonPropertyOrder;
+import com.fasterxml.jackson.core.JsonParser.Feature;
+import com.fasterxml.jackson.databind.ObjectMapper;
+import com.fasterxml.jackson.databind.SerializationFeature;
+import com.google.common.base.Charsets;
+import com.google.common.io.Files;
+
+@JsonPropertyOrder({"head", "sources", "query"})
+public class LogicalPlan {
+ @JsonProperty("head") public PlanProperties properties = new PlanProperties();
+ @JsonProperty("sources") public List<DataSource> dataSources = new ArrayList<DataSource>();
+ @JsonProperty("query") public List<LogicalOperator> operators = new ArrayList<LogicalOperator>();
+
+ public static void main(String[] args) throws Exception {
+
+
+ ObjectMapper mapper = new ObjectMapper();
+
+ mapper.enable(SerializationFeature.INDENT_OUTPUT);
+ mapper.configure(Feature.ALLOW_UNQUOTED_FIELD_NAMES, true);
+ mapper.configure(Feature.ALLOW_COMMENTS, true);
+
+ mapper.registerSubtypes(LogicalOperator.SUB_TYPES);
+ mapper.registerSubtypes(DataSource.SUB_TYPES);
+ mapper.registerSubtypes(RecordMaker.SUB_TYPES);
+
+ String externalPlan = Files.toString(new File("src/test/resources/simple_plan.json"), Charsets.UTF_8);
+ LogicalPlan plan = mapper.readValue(externalPlan, LogicalPlan.class);
+ System.out.println(mapper.writeValueAsString(((Transform) plan.operators.get(1)).input));
+ System.out.println(mapper.writeValueAsString(plan));
+ }
+
+
+
+}
http://git-wip-us.apache.org/repos/asf/incubator-drill/blob/78940e78/sandbox/prototype/common/src/main/java/org/apache/drill/common/logical/OperatorRegistry.java
----------------------------------------------------------------------
diff --git a/sandbox/prototype/common/src/main/java/org/apache/drill/common/logical/OperatorRegistry.java b/sandbox/prototype/common/src/main/java/org/apache/drill/common/logical/OperatorRegistry.java
new file mode 100644
index 0000000..85eda7f
--- /dev/null
+++ b/sandbox/prototype/common/src/main/java/org/apache/drill/common/logical/OperatorRegistry.java
@@ -0,0 +1,5 @@
+package org.apache.drill.common.logical;
+
+public class OperatorRegistry {
+
+}
http://git-wip-us.apache.org/repos/asf/incubator-drill/blob/78940e78/sandbox/prototype/common/src/main/java/org/apache/drill/common/logical/OperatorResolver.java
----------------------------------------------------------------------
diff --git a/sandbox/prototype/common/src/main/java/org/apache/drill/common/logical/OperatorResolver.java b/sandbox/prototype/common/src/main/java/org/apache/drill/common/logical/OperatorResolver.java
new file mode 100644
index 0000000..36d7193
--- /dev/null
+++ b/sandbox/prototype/common/src/main/java/org/apache/drill/common/logical/OperatorResolver.java
@@ -0,0 +1,5 @@
+package org.apache.drill.common.logical;
+
+public class OperatorResolver {
+
+}
http://git-wip-us.apache.org/repos/asf/incubator-drill/blob/78940e78/sandbox/prototype/common/src/main/java/org/apache/drill/common/logical/PlanProperties.java
----------------------------------------------------------------------
diff --git a/sandbox/prototype/common/src/main/java/org/apache/drill/common/logical/PlanProperties.java b/sandbox/prototype/common/src/main/java/org/apache/drill/common/logical/PlanProperties.java
new file mode 100644
index 0000000..7a224d6
--- /dev/null
+++ b/sandbox/prototype/common/src/main/java/org/apache/drill/common/logical/PlanProperties.java
@@ -0,0 +1,14 @@
+package org.apache.drill.common.logical;
+
+
+public class PlanProperties {
+ public String type = "apache_drill_logical_plan";
+ public int version;
+ public Generator generator = new Generator();
+
+
+ public static class Generator{
+ public String type;
+ public String info;
+ }
+}
http://git-wip-us.apache.org/repos/asf/incubator-drill/blob/78940e78/sandbox/prototype/common/src/main/java/org/apache/drill/common/logical/ValidationError.java
----------------------------------------------------------------------
diff --git a/sandbox/prototype/common/src/main/java/org/apache/drill/common/logical/ValidationError.java b/sandbox/prototype/common/src/main/java/org/apache/drill/common/logical/ValidationError.java
new file mode 100644
index 0000000..dd6b9bd
--- /dev/null
+++ b/sandbox/prototype/common/src/main/java/org/apache/drill/common/logical/ValidationError.java
@@ -0,0 +1,5 @@
+package org.apache.drill.common.logical;
+
+public class ValidationError {
+
+}
http://git-wip-us.apache.org/repos/asf/incubator-drill/blob/78940e78/sandbox/prototype/common/src/main/java/org/apache/drill/common/logical/data/Combine.java
----------------------------------------------------------------------
diff --git a/sandbox/prototype/common/src/main/java/org/apache/drill/common/logical/data/Combine.java b/sandbox/prototype/common/src/main/java/org/apache/drill/common/logical/data/Combine.java
new file mode 100644
index 0000000..a14eb3c
--- /dev/null
+++ b/sandbox/prototype/common/src/main/java/org/apache/drill/common/logical/data/Combine.java
@@ -0,0 +1,12 @@
+package org.apache.drill.common.logical.data;
+
+import com.fasterxml.jackson.annotation.JsonTypeName;
+
+
+@JsonTypeName("combine")
+public class Combine extends SingleInputOperator{
+
+ public String name;
+
+
+}
http://git-wip-us.apache.org/repos/asf/incubator-drill/blob/78940e78/sandbox/prototype/common/src/main/java/org/apache/drill/common/logical/data/Explode.java
----------------------------------------------------------------------
diff --git a/sandbox/prototype/common/src/main/java/org/apache/drill/common/logical/data/Explode.java b/sandbox/prototype/common/src/main/java/org/apache/drill/common/logical/data/Explode.java
new file mode 100644
index 0000000..ac09a54
--- /dev/null
+++ b/sandbox/prototype/common/src/main/java/org/apache/drill/common/logical/data/Explode.java
@@ -0,0 +1,18 @@
+package org.apache.drill.common.logical.data;
+
+import org.apache.drill.common.expression.FieldReference;
+
+import com.fasterxml.jackson.annotation.JsonProperty;
+import com.fasterxml.jackson.annotation.JsonTypeName;
+
+/**
+ * The explode operator
+ */
+@JsonTypeName("explode")
+public class Explode extends SingleInputOperator{
+
+ @JsonProperty("ref") public FieldReference reference;
+
+ public Explode(){}
+
+}
http://git-wip-us.apache.org/repos/asf/incubator-drill/blob/78940e78/sandbox/prototype/common/src/main/java/org/apache/drill/common/logical/data/Filter.java
----------------------------------------------------------------------
diff --git a/sandbox/prototype/common/src/main/java/org/apache/drill/common/logical/data/Filter.java b/sandbox/prototype/common/src/main/java/org/apache/drill/common/logical/data/Filter.java
new file mode 100644
index 0000000..108782d
--- /dev/null
+++ b/sandbox/prototype/common/src/main/java/org/apache/drill/common/logical/data/Filter.java
@@ -0,0 +1,11 @@
+package org.apache.drill.common.logical.data;
+
+import org.apache.drill.common.expression.LogicalExpression;
+
+import com.fasterxml.jackson.annotation.JsonTypeName;
+
+@JsonTypeName("filter")
+public class Filter extends LogicalOperatorBase{
+ public int input;
+ public LogicalExpression expr;
+}
http://git-wip-us.apache.org/repos/asf/incubator-drill/blob/78940e78/sandbox/prototype/common/src/main/java/org/apache/drill/common/logical/data/Flatten.java
----------------------------------------------------------------------
diff --git a/sandbox/prototype/common/src/main/java/org/apache/drill/common/logical/data/Flatten.java b/sandbox/prototype/common/src/main/java/org/apache/drill/common/logical/data/Flatten.java
new file mode 100644
index 0000000..d87e5f3
--- /dev/null
+++ b/sandbox/prototype/common/src/main/java/org/apache/drill/common/logical/data/Flatten.java
@@ -0,0 +1,12 @@
+package org.apache.drill.common.logical.data;
+
+import java.util.List;
+
+import org.apache.drill.common.expression.LogicalExpression;
+
+import com.fasterxml.jackson.annotation.JsonProperty;
+
+public class Flatten {
+ @JsonProperty("input") public int inputNode;
+ public List<LogicalExpression> exprs;
+}
http://git-wip-us.apache.org/repos/asf/incubator-drill/blob/78940e78/sandbox/prototype/common/src/main/java/org/apache/drill/common/logical/data/Group.java
----------------------------------------------------------------------
diff --git a/sandbox/prototype/common/src/main/java/org/apache/drill/common/logical/data/Group.java b/sandbox/prototype/common/src/main/java/org/apache/drill/common/logical/data/Group.java
new file mode 100644
index 0000000..ac1ea7b
--- /dev/null
+++ b/sandbox/prototype/common/src/main/java/org/apache/drill/common/logical/data/Group.java
@@ -0,0 +1,13 @@
+package org.apache.drill.common.logical.data;
+
+import java.util.List;
+
+import org.apache.drill.common.expression.LogicalExpression;
+
+import com.fasterxml.jackson.annotation.JsonTypeName;
+
+@JsonTypeName("group")
+public class Group extends LogicalOperatorBase{
+ public int input;
+ public List<LogicalExpression> exprs;
+}
http://git-wip-us.apache.org/repos/asf/incubator-drill/blob/78940e78/sandbox/prototype/common/src/main/java/org/apache/drill/common/logical/data/Join.java
----------------------------------------------------------------------
diff --git a/sandbox/prototype/common/src/main/java/org/apache/drill/common/logical/data/Join.java b/sandbox/prototype/common/src/main/java/org/apache/drill/common/logical/data/Join.java
new file mode 100644
index 0000000..7187108
--- /dev/null
+++ b/sandbox/prototype/common/src/main/java/org/apache/drill/common/logical/data/Join.java
@@ -0,0 +1,21 @@
+package org.apache.drill.common.logical.data;
+
+import java.util.List;
+
+import org.apache.drill.common.expression.LogicalExpression;
+
+import com.fasterxml.jackson.annotation.JsonProperty;
+import com.fasterxml.jackson.annotation.JsonTypeName;
+
+@JsonTypeName("join")
+public class Join extends LogicalOperatorBase{
+ public int left;
+ public int right;
+ public List<JoinCondition> conditions;
+
+ public static class JoinCondition{
+ public String relationship;
+ @JsonProperty("left-expr") public LogicalExpression leftExpression;
+ @JsonProperty("right-expr") public LogicalExpression rightExpression;
+ }
+}
http://git-wip-us.apache.org/repos/asf/incubator-drill/blob/78940e78/sandbox/prototype/common/src/main/java/org/apache/drill/common/logical/data/LogicalOperator.java
----------------------------------------------------------------------
diff --git a/sandbox/prototype/common/src/main/java/org/apache/drill/common/logical/data/LogicalOperator.java b/sandbox/prototype/common/src/main/java/org/apache/drill/common/logical/data/LogicalOperator.java
new file mode 100644
index 0000000..83e9c61
--- /dev/null
+++ b/sandbox/prototype/common/src/main/java/org/apache/drill/common/logical/data/LogicalOperator.java
@@ -0,0 +1,24 @@
+package org.apache.drill.common.logical.data;
+
+import java.util.Collection;
+import java.util.List;
+
+import org.apache.drill.common.logical.ValidationError;
+
+import com.fasterxml.jackson.annotation.JsonIdentityInfo;
+import com.fasterxml.jackson.annotation.JsonInclude;
+import com.fasterxml.jackson.annotation.JsonInclude.Include;
+import com.fasterxml.jackson.annotation.JsonTypeInfo;
+import com.fasterxml.jackson.annotation.ObjectIdGenerators;
+
+@JsonIdentityInfo(generator=ObjectIdGenerators.IntSequenceGenerator.class, property="@id")
+@JsonTypeInfo(use = JsonTypeInfo.Id.NAME, include = JsonTypeInfo.As.PROPERTY, property="op")
+@JsonInclude(Include.NON_DEFAULT)
+public interface LogicalOperator {
+
+ public static final Class<?>[] SUB_TYPES = {Sequence.class, Combine.class, Explode.class, Filter.class, Group.class, Join.class, Nest.class, Order.class, Project.class, Scan.class, Transform.class, Union.class};
+
+ public void registerAsSubscriber(LogicalOperator operator);
+ public void setupAndValidate(List<LogicalOperator> operators, Collection<ValidationError> errors);
+
+}
http://git-wip-us.apache.org/repos/asf/incubator-drill/blob/78940e78/sandbox/prototype/common/src/main/java/org/apache/drill/common/logical/data/LogicalOperatorBase.java
----------------------------------------------------------------------
diff --git a/sandbox/prototype/common/src/main/java/org/apache/drill/common/logical/data/LogicalOperatorBase.java b/sandbox/prototype/common/src/main/java/org/apache/drill/common/logical/data/LogicalOperatorBase.java
new file mode 100644
index 0000000..5632e84
--- /dev/null
+++ b/sandbox/prototype/common/src/main/java/org/apache/drill/common/logical/data/LogicalOperatorBase.java
@@ -0,0 +1,25 @@
+package org.apache.drill.common.logical.data;
+
+import java.util.ArrayList;
+import java.util.Collection;
+import java.util.List;
+
+import org.apache.drill.common.logical.ValidationError;
+
+public abstract class LogicalOperatorBase implements LogicalOperator{
+ private List<LogicalOperator> children = new ArrayList<LogicalOperator>();
+
+ public LogicalOperatorBase(){}
+
+ @Override
+ public void setupAndValidate(List<LogicalOperator> operators, Collection<ValidationError> errors) {
+ }
+
+ @Override
+ public void registerAsSubscriber(LogicalOperator operator) {
+ children.add(operator);
+ }
+
+
+
+}
http://git-wip-us.apache.org/repos/asf/incubator-drill/blob/78940e78/sandbox/prototype/common/src/main/java/org/apache/drill/common/logical/data/Nest.java
----------------------------------------------------------------------
diff --git a/sandbox/prototype/common/src/main/java/org/apache/drill/common/logical/data/Nest.java b/sandbox/prototype/common/src/main/java/org/apache/drill/common/logical/data/Nest.java
new file mode 100644
index 0000000..534a562
--- /dev/null
+++ b/sandbox/prototype/common/src/main/java/org/apache/drill/common/logical/data/Nest.java
@@ -0,0 +1,17 @@
+package org.apache.drill.common.logical.data;
+
+import java.util.List;
+
+import org.apache.drill.common.expression.LogicalExpression;
+
+import com.fasterxml.jackson.annotation.JsonTypeName;
+
+@JsonTypeName("nest")
+public class Nest extends LogicalOperatorBase{
+
+
+ public LogicalOperator input;
+ public String name;
+ public List<LogicalExpression> exprs;
+
+}
http://git-wip-us.apache.org/repos/asf/incubator-drill/blob/78940e78/sandbox/prototype/common/src/main/java/org/apache/drill/common/logical/data/OperatorListDeserializer.java
----------------------------------------------------------------------
diff --git a/sandbox/prototype/common/src/main/java/org/apache/drill/common/logical/data/OperatorListDeserializer.java b/sandbox/prototype/common/src/main/java/org/apache/drill/common/logical/data/OperatorListDeserializer.java
new file mode 100644
index 0000000..a6cec8a
--- /dev/null
+++ b/sandbox/prototype/common/src/main/java/org/apache/drill/common/logical/data/OperatorListDeserializer.java
@@ -0,0 +1,108 @@
+package org.apache.drill.common.logical.data;
+
+import java.io.IOException;
+
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import com.fasterxml.jackson.core.JsonLocation;
+import com.fasterxml.jackson.core.JsonParseException;
+import com.fasterxml.jackson.core.JsonParser;
+import com.fasterxml.jackson.core.JsonProcessingException;
+import com.fasterxml.jackson.core.JsonToken;
+import com.fasterxml.jackson.databind.DeserializationContext;
+import com.fasterxml.jackson.databind.JavaType;
+import com.fasterxml.jackson.databind.JsonDeserializer;
+
+public class OperatorListDeserializer {
+ static final Logger logger = LoggerFactory.getLogger(OperatorListDeserializer.class);
+
+ public LogicalOperator deserializeSequence(JsonParser jp, DeserializationContext ctxt) throws IOException,
+ JsonProcessingException {
+
+ final JavaType tp = ctxt.constructType(LogicalOperator.class);
+ final JsonDeserializer<Object> d = ctxt.findRootValueDeserializer(tp);
+ final JsonLocation start = jp.getCurrentLocation();
+
+ JsonToken t = jp.getCurrentToken();
+ LogicalOperator parent = null;
+ LogicalOperator first = null;
+ LogicalOperator prev = null;
+
+ while (true) {
+ String token = jp.getText();
+ logger.debug("Working on token '{}'", token);
+ jp.nextToken();
+ switch (token) { // switch on field names.
+ case "input":
+
+ parent = (LogicalOperator) d.deserialize(jp, ctxt);
+ break;
+ case "do":
+ if (!jp.isExpectedStartArrayToken())
+ throwE(
+ jp,
+ "The do parameter of sequence should be an array of SimpleOperators. Expected a JsonToken.START_ARRAY token but received a "
+ + t.name() + "token.");
+
+ int pos = 0;
+ while ((t = jp.nextToken()) != JsonToken.END_ARRAY) {
+ logger.debug("Reading sequence child {}.", pos);
+ JsonLocation l = jp.getCurrentLocation(); // get current location
+ // first so we can correctly
+ // reference the start of
+ // the object in the case
+ // that the type is wrong.
+ LogicalOperator o = jp.readValueAs(LogicalOperator.class);
+
+ if (pos == 0) {
+ if (!(o instanceof SingleInputOperator) && !(o instanceof ZeroInputOperator))
+ throwE(
+ l,
+ "The first operator in a sequence must be either a ZeroInput or SingleInput operator. The provided first operator was not. It was of type "
+ + o.getClass().getName());
+ first = o;
+ } else {
+ if (!(o instanceof SingleInputOperator))
+ throwE(l, "All operators after the first must be single input operators. The operator at position "
+ + pos + " was not. It was of type " + o.getClass().getName());
+ SingleInputOperator now = (SingleInputOperator) o;
+ now.setInput(prev);
+ }
+ prev = o;
+
+ pos++;
+ }
+ break;
+ default:
+ throwE(jp, "Unknown field name provided for Sequence: " + jp.getText());
+ }
+
+ t = jp.nextToken();
+ if (t == JsonToken.END_OBJECT) {
+ break;
+ }
+ }
+
+ if (first == null)
+ throwE(start, "A sequence must include at least one operator.");
+ if ((parent == null && first instanceof SingleInputOperator)
+ || (parent != null && first instanceof ZeroInputOperator))
+ throwE(start,
+ "A sequence must either start with a ZeroInputOperator or have a provided input. It cannot have both or neither.");
+
+ if (parent != null && first instanceof SingleInputOperator) {
+ ((SingleInputOperator) first).setInput(parent);
+ }
+
+ return first;
+ }
+
+ private static void throwE(JsonLocation l, String e) throws JsonParseException {
+ throw new JsonParseException(e, l);
+ }
+
+ private static void throwE(JsonParser jp, String e) throws JsonParseException {
+ throw new JsonParseException(e, jp.getCurrentLocation());
+ }
+}
http://git-wip-us.apache.org/repos/asf/incubator-drill/blob/78940e78/sandbox/prototype/common/src/main/java/org/apache/drill/common/logical/data/Order.java
----------------------------------------------------------------------
diff --git a/sandbox/prototype/common/src/main/java/org/apache/drill/common/logical/data/Order.java b/sandbox/prototype/common/src/main/java/org/apache/drill/common/logical/data/Order.java
new file mode 100644
index 0000000..3680056
--- /dev/null
+++ b/sandbox/prototype/common/src/main/java/org/apache/drill/common/logical/data/Order.java
@@ -0,0 +1,19 @@
+package org.apache.drill.common.logical.data;
+
+import java.util.List;
+
+import org.apache.drill.common.expression.LogicalExpression;
+
+import com.fasterxml.jackson.annotation.JsonProperty;
+import com.fasterxml.jackson.annotation.JsonTypeName;
+
+@JsonTypeName("order")
+public class Order extends LogicalOperatorBase{
+ public int input;
+ @JsonProperty("orders") public List<Ordering> orderings;
+
+ public static class Ordering {
+ public String direction;
+ public LogicalExpression expr;
+ }
+}
http://git-wip-us.apache.org/repos/asf/incubator-drill/blob/78940e78/sandbox/prototype/common/src/main/java/org/apache/drill/common/logical/data/Project.java
----------------------------------------------------------------------
diff --git a/sandbox/prototype/common/src/main/java/org/apache/drill/common/logical/data/Project.java b/sandbox/prototype/common/src/main/java/org/apache/drill/common/logical/data/Project.java
new file mode 100644
index 0000000..3943421
--- /dev/null
+++ b/sandbox/prototype/common/src/main/java/org/apache/drill/common/logical/data/Project.java
@@ -0,0 +1,13 @@
+package org.apache.drill.common.logical.data;
+
+import java.util.List;
+
+import org.apache.drill.common.expression.LogicalExpression;
+
+import com.fasterxml.jackson.annotation.JsonTypeName;
+
+@JsonTypeName("project")
+public class Project extends LogicalOperatorBase{
+ public int input;
+ public List<LogicalExpression>[] exprs;
+}
http://git-wip-us.apache.org/repos/asf/incubator-drill/blob/78940e78/sandbox/prototype/common/src/main/java/org/apache/drill/common/logical/data/Scan.java
----------------------------------------------------------------------
diff --git a/sandbox/prototype/common/src/main/java/org/apache/drill/common/logical/data/Scan.java b/sandbox/prototype/common/src/main/java/org/apache/drill/common/logical/data/Scan.java
new file mode 100644
index 0000000..fb02159
--- /dev/null
+++ b/sandbox/prototype/common/src/main/java/org/apache/drill/common/logical/data/Scan.java
@@ -0,0 +1,10 @@
+package org.apache.drill.common.logical.data;
+
+import com.fasterxml.jackson.annotation.JsonTypeName;
+
+@JsonTypeName("scan")
+public class Scan extends LogicalOperatorBase{
+ public String source;
+ public String name;
+ public String table;
+}
http://git-wip-us.apache.org/repos/asf/incubator-drill/blob/78940e78/sandbox/prototype/common/src/main/java/org/apache/drill/common/logical/data/Sequence.java
----------------------------------------------------------------------
diff --git a/sandbox/prototype/common/src/main/java/org/apache/drill/common/logical/data/Sequence.java b/sandbox/prototype/common/src/main/java/org/apache/drill/common/logical/data/Sequence.java
new file mode 100644
index 0000000..99814aa
--- /dev/null
+++ b/sandbox/prototype/common/src/main/java/org/apache/drill/common/logical/data/Sequence.java
@@ -0,0 +1,117 @@
+package org.apache.drill.common.logical.data;
+
+import java.io.IOException;
+
+import org.apache.drill.common.logical.data.Sequence.De;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import com.fasterxml.jackson.annotation.JsonProperty;
+import com.fasterxml.jackson.annotation.JsonTypeName;
+import com.fasterxml.jackson.annotation.ObjectIdGenerator;
+import com.fasterxml.jackson.annotation.ObjectIdGenerators;
+import com.fasterxml.jackson.core.JsonLocation;
+import com.fasterxml.jackson.core.JsonParseException;
+import com.fasterxml.jackson.core.JsonParser;
+import com.fasterxml.jackson.core.JsonProcessingException;
+import com.fasterxml.jackson.core.JsonToken;
+import com.fasterxml.jackson.databind.DeserializationContext;
+import com.fasterxml.jackson.databind.JavaType;
+import com.fasterxml.jackson.databind.JsonDeserializer;
+import com.fasterxml.jackson.databind.annotation.JsonDeserialize;
+import com.fasterxml.jackson.databind.deser.impl.ReadableObjectId;
+import com.fasterxml.jackson.databind.deser.std.StdDeserializer;
+
+/**
+ * Describes a list of operators where each operator only has one input and that
+ * input is the operator that came before.
+ *
+ */
+@JsonDeserialize(using = De.class)
+@JsonTypeName("sequence")
+public class Sequence extends LogicalOperatorBase {
+ static final Logger logger = LoggerFactory.getLogger(Sequence.class);
+
+ public boolean openTop;
+ public LogicalOperator input;
+ @JsonProperty("do")
+ public LogicalOperator[] stream;
+
+ public static class De extends StdDeserializer<LogicalOperator> {
+
+ protected De() {
+ super(Sequence.class);
+ }
+
+ @Override
+ public LogicalOperator deserialize(JsonParser jp, DeserializationContext ctxt) throws IOException, JsonProcessingException {
+
+ JsonLocation start = jp.getCurrentLocation();
+ JsonToken t = jp.getCurrentToken();
+ LogicalOperator parent = null;
+ LogicalOperator first = null;
+ LogicalOperator prev = null;
+
+ while(true){
+ String token = jp.getText();
+ logger.debug("Working on token '{}'", token);
+ jp.nextToken();
+ switch(token){ // switch on field names.
+ case "input":
+ JavaType tp = ctxt.constructType(LogicalOperator.class);
+ JsonDeserializer<Object> d = ctxt.findRootValueDeserializer(tp);
+ parent = (LogicalOperator) d.deserialize(jp, ctxt);
+ break;
+ case "do":
+ if(!jp.isExpectedStartArrayToken()) throwE(jp, "The do parameter of sequence should be an array of SimpleOperators. Expected a JsonToken.START_ARRAY token but received a " + t.name() + "token.");
+
+ int pos = 0;
+ while( (t = jp.nextToken()) != JsonToken.END_ARRAY){
+ logger.debug("Reading sequence child {}.", pos);
+ JsonLocation l = jp.getCurrentLocation(); // get current location first so we can correctly reference the start of the object in the case that the type is wrong.
+ LogicalOperator o = jp.readValueAs(LogicalOperator.class);
+
+ if(pos == 0){
+ if( !(o instanceof SingleInputOperator) && !(o instanceof ZeroInputOperator)) throwE(l, "The first operator in a sequence must be either a ZeroInput or SingleInput operator. The provided first operator was not. It was of type " + o.getClass().getName());
+ first = o;
+ }else{
+ if( !(o instanceof SingleInputOperator)) throwE(l, "All operators after the first must be single input operators. The operator at position " + pos + " was not. It was of type " + o.getClass().getName());
+ SingleInputOperator now = (SingleInputOperator) o;
+ now.setInput(prev);
+ }
+ prev = o;
+
+ pos++;
+ }
+ break;
+ default:
+ throwE(jp, "Unknown field name provided for Sequence: " + jp.getText());
+ }
+
+ t = jp.nextToken();
+ if(t == JsonToken.END_OBJECT){
+ break;
+ }
+ }
+
+ if(first == null) throwE(start, "A sequence must include at least one operator.");
+ if( (parent == null && first instanceof SingleInputOperator) ||
+ (parent != null && first instanceof ZeroInputOperator) )
+ throwE(start, "A sequence must either start with a ZeroInputOperator or have a provided input. It cannot have both or neither.");
+
+ if(parent != null && first instanceof SingleInputOperator){
+ ((SingleInputOperator) first).setInput(parent);
+ }
+
+ return first;
+ }
+
+
+ }
+ private static void throwE(JsonLocation l, String e) throws JsonParseException{
+ throw new JsonParseException(e, l);
+ }
+ private static void throwE(JsonParser jp, String e) throws JsonParseException{
+ throw new JsonParseException(e, jp.getCurrentLocation());
+ }
+}