You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@tajo.apache.org by hy...@apache.org on 2013/09/30 05:22:37 UTC
git commit: TAJO-212: Implement type cast expresion. (hyunsik)
Updated Branches:
refs/heads/master bc19cc2f8 -> 135b27a6a
TAJO-212: Implement type cast expresion. (hyunsik)
Project: http://git-wip-us.apache.org/repos/asf/incubator-tajo/repo
Commit: http://git-wip-us.apache.org/repos/asf/incubator-tajo/commit/135b27a6
Tree: http://git-wip-us.apache.org/repos/asf/incubator-tajo/tree/135b27a6
Diff: http://git-wip-us.apache.org/repos/asf/incubator-tajo/diff/135b27a6
Branch: refs/heads/master
Commit: 135b27a6ae481faeb0953fbe53baf81fd54a4628
Parents: bc19cc2
Author: Hyunsik Choi <hy...@apache.org>
Authored: Mon Sep 30 12:18:38 2013 +0900
Committer: Hyunsik Choi <hy...@apache.org>
Committed: Mon Sep 30 12:18:38 2013 +0900
----------------------------------------------------------------------
CHANGES.txt | 2 +
.../java/org/apache/tajo/algebra/CastExpr.java | 44 ++++++
.../org/apache/tajo/algebra/CreateTable.java | 42 ++----
.../java/org/apache/tajo/algebra/DataType.java | 68 +++++++++
.../java/org/apache/tajo/algebra/OpType.java | 4 +-
.../org/apache/tajo/datum/BooleanDatum.java | 5 +
.../java/org/apache/tajo/datum/Float4Datum.java | 5 +
.../java/org/apache/tajo/datum/Float8Datum.java | 5 +
.../java/org/apache/tajo/datum/Int2Datum.java | 5 +
.../java/org/apache/tajo/datum/Int4Datum.java | 7 +-
.../java/org/apache/tajo/datum/Int8Datum.java | 5 +
.../org/apache/tajo/engine/parser/SQLLexer.g4 | 9 +-
.../org/apache/tajo/engine/parser/SQLParser.g4 | 25 +++-
.../org/apache/tajo/engine/eval/CastEval.java | 119 +++++++++++++++
.../org/apache/tajo/engine/eval/EvalNode.java | 6 +-
.../org/apache/tajo/engine/eval/EvalType.java | 5 +-
.../apache/tajo/engine/parser/SQLAnalyzer.java | 138 ++++++++----------
.../apache/tajo/engine/planner/LogicalPlan.java | 7 +-
.../tajo/engine/planner/LogicalPlanner.java | 54 +++----
.../tajo/engine/planner/TargetListManager.java | 12 +-
.../apache/tajo/engine/eval/ExprTestBase.java | 143 ++++++++++++++++++
.../tajo/engine/eval/TestSQLExpression.java | 71 +++++++++
.../tajo/engine/function/ExprTestBase.java | 145 -------------------
.../function/TestPatternMatchingPredicates.java | 1 +
.../TestStringOperatorsAndFunctions.java | 1 +
25 files changed, 624 insertions(+), 304 deletions(-)
----------------------------------------------------------------------
http://git-wip-us.apache.org/repos/asf/incubator-tajo/blob/135b27a6/CHANGES.txt
----------------------------------------------------------------------
diff --git a/CHANGES.txt b/CHANGES.txt
index a373870..419e492 100644
--- a/CHANGES.txt
+++ b/CHANGES.txt
@@ -4,6 +4,8 @@ Release 0.2.0 - unreleased
NEW FEATURES
+ TAJO-212: Implement type cast expresion. (hyunsik)
+
TAJO-206: Implement String concatenation operator (||). (hyunsik)
TAJO-213: NULL characters in meta of csv table should be supported.
http://git-wip-us.apache.org/repos/asf/incubator-tajo/blob/135b27a6/tajo-algebra/src/main/java/org/apache/tajo/algebra/CastExpr.java
----------------------------------------------------------------------
diff --git a/tajo-algebra/src/main/java/org/apache/tajo/algebra/CastExpr.java b/tajo-algebra/src/main/java/org/apache/tajo/algebra/CastExpr.java
new file mode 100644
index 0000000..349617f
--- /dev/null
+++ b/tajo-algebra/src/main/java/org/apache/tajo/algebra/CastExpr.java
@@ -0,0 +1,44 @@
+/**
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.apache.tajo.algebra;
+
+public class CastExpr extends Expr {
+ private Expr operand;
+ private DataType target;
+
+ public CastExpr(Expr operand, DataType target) {
+ super(OpType.Cast);
+ this.operand = operand;
+ this.target = target;
+ }
+
+ public Expr getOperand() {
+ return operand;
+ }
+
+ public DataType getTarget() {
+ return target;
+ }
+
+ @Override
+ boolean equalsTo(Expr expr) {
+ CastExpr another = (CastExpr) expr;
+ return operand.equals(another.operand) && target.equals(another.target);
+ }
+}
http://git-wip-us.apache.org/repos/asf/incubator-tajo/blob/135b27a6/tajo-algebra/src/main/java/org/apache/tajo/algebra/CreateTable.java
----------------------------------------------------------------------
diff --git a/tajo-algebra/src/main/java/org/apache/tajo/algebra/CreateTable.java b/tajo-algebra/src/main/java/org/apache/tajo/algebra/CreateTable.java
index 1552467..5f96d00 100644
--- a/tajo-algebra/src/main/java/org/apache/tajo/algebra/CreateTable.java
+++ b/tajo-algebra/src/main/java/org/apache/tajo/algebra/CreateTable.java
@@ -124,47 +124,33 @@ public class CreateTable extends Expr {
TUtil.checkEquals(params, another.params);
}
- public static class ColumnDefinition {
+ public static class ColumnDefinition extends DataType {
String col_name;
- String data_type;
- Integer length_or_precision;
- Integer scale;
public ColumnDefinition(String columnName, String dataType) {
+ super(dataType);
this.col_name = columnName;
- this.data_type = dataType;
}
- public String getColumnName() {
- return this.col_name;
- }
-
- public String getDataType() {
- return this.data_type;
- }
-
- public void setLengthOrPrecision(int lengthOrPrecision) {
- this.length_or_precision = lengthOrPrecision;
- }
-
- public Integer getLengthOrPrecision() {
- return this.length_or_precision;
- }
-
- public void setScale(int scale) {
- this.scale = scale;
+ public ColumnDefinition(String columnName, DataType dataType) {
+ super(dataType.getTypeName());
+ if (dataType.hasLengthOrPrecision()) {
+ setLengthOrPrecision(dataType.lengthOrPrecision);
+ if (dataType.hasScale()) {
+ setScale(dataType.scale);
+ }
+ }
+ this.col_name = columnName;
}
- public Integer getScale() {
- return this.scale;
+ public String getColumnName() {
+ return this.col_name;
}
public boolean equals(Object obj) {
if (obj instanceof ColumnDefinition) {
ColumnDefinition another = (ColumnDefinition) obj;
- return col_name.equals(another.col_name) && data_type.equals(another.data_type) &&
- TUtil.checkEquals(length_or_precision, another.length_or_precision) &&
- TUtil.checkEquals(scale, another.scale);
+ return col_name.equals(another.col_name) && super.equals(another);
}
return false;
http://git-wip-us.apache.org/repos/asf/incubator-tajo/blob/135b27a6/tajo-algebra/src/main/java/org/apache/tajo/algebra/DataType.java
----------------------------------------------------------------------
diff --git a/tajo-algebra/src/main/java/org/apache/tajo/algebra/DataType.java b/tajo-algebra/src/main/java/org/apache/tajo/algebra/DataType.java
new file mode 100644
index 0000000..ed8a4a6
--- /dev/null
+++ b/tajo-algebra/src/main/java/org/apache/tajo/algebra/DataType.java
@@ -0,0 +1,68 @@
+/**
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.apache.tajo.algebra;
+
+import org.apache.tajo.util.TUtil;
+
+public class DataType extends Expr {
+ String typeName;
+ Integer lengthOrPrecision;
+ Integer scale;
+
+ public DataType(String typeName) {
+ super(OpType.DataType);
+ this.typeName = typeName;
+ }
+
+ public String getTypeName() {
+ return this.typeName;
+ }
+
+ public boolean hasLengthOrPrecision() {
+ return lengthOrPrecision != null;
+ }
+
+ public void setLengthOrPrecision(int lengthOrPrecision) {
+ this.lengthOrPrecision = lengthOrPrecision;
+ }
+
+ public Integer getLengthOrPrecision() {
+ return this.lengthOrPrecision;
+ }
+
+ public boolean hasScale() {
+ return this.scale != null;
+ }
+
+ public void setScale(int scale) {
+ this.scale = scale;
+ }
+
+ public Integer getScale() {
+ return this.scale;
+ }
+
+ @Override
+ boolean equalsTo(Expr expr) {
+ DataType another = (DataType) expr;
+ return typeName.equals(another.typeName) &&
+ TUtil.checkEquals(lengthOrPrecision, another.lengthOrPrecision) &&
+ TUtil.checkEquals(scale, another.scale);
+ }
+}
http://git-wip-us.apache.org/repos/asf/incubator-tajo/blob/135b27a6/tajo-algebra/src/main/java/org/apache/tajo/algebra/OpType.java
----------------------------------------------------------------------
diff --git a/tajo-algebra/src/main/java/org/apache/tajo/algebra/OpType.java b/tajo-algebra/src/main/java/org/apache/tajo/algebra/OpType.java
index ab4e403..145c52c 100644
--- a/tajo-algebra/src/main/java/org/apache/tajo/algebra/OpType.java
+++ b/tajo-algebra/src/main/java/org/apache/tajo/algebra/OpType.java
@@ -89,9 +89,11 @@ public enum OpType {
CountRowsFunction(CountRowsFunctionExpr.class),
GeneralSetFunction(GeneralSetFunctionExpr.class),
+ Cast(CastExpr.class),
+ ScalarSubQuery(ScalarSubQuery.class),
Literal(LiteralValue.class),
Null(NullValue.class),
- ScalarSubQuery(ScalarSubQuery.class);
+ DataType(org.apache.tajo.algebra.DataType.class);
private Class baseClass;
http://git-wip-us.apache.org/repos/asf/incubator-tajo/blob/135b27a6/tajo-common/src/main/java/org/apache/tajo/datum/BooleanDatum.java
----------------------------------------------------------------------
diff --git a/tajo-common/src/main/java/org/apache/tajo/datum/BooleanDatum.java b/tajo-common/src/main/java/org/apache/tajo/datum/BooleanDatum.java
index e7c4d39..aeab5aa 100644
--- a/tajo-common/src/main/java/org/apache/tajo/datum/BooleanDatum.java
+++ b/tajo-common/src/main/java/org/apache/tajo/datum/BooleanDatum.java
@@ -56,6 +56,11 @@ public class BooleanDatum extends Datum {
public void setValue(boolean val) {
this.val = val;
}
+
+ @Override
+ public char asChar() {
+ return val ? 't' : 'f';
+ }
@Override
public short asInt2() {
http://git-wip-us.apache.org/repos/asf/incubator-tajo/blob/135b27a6/tajo-common/src/main/java/org/apache/tajo/datum/Float4Datum.java
----------------------------------------------------------------------
diff --git a/tajo-common/src/main/java/org/apache/tajo/datum/Float4Datum.java b/tajo-common/src/main/java/org/apache/tajo/datum/Float4Datum.java
index 84245b2..97e608a 100644
--- a/tajo-common/src/main/java/org/apache/tajo/datum/Float4Datum.java
+++ b/tajo-common/src/main/java/org/apache/tajo/datum/Float4Datum.java
@@ -48,6 +48,11 @@ public class Float4Datum extends Datum implements NumericDatum {
public boolean asBool() {
throw new InvalidCastException();
}
+
+ @Override
+ public char asChar() {
+ return asChars().charAt(0);
+ }
@Override
public short asInt2() {
http://git-wip-us.apache.org/repos/asf/incubator-tajo/blob/135b27a6/tajo-common/src/main/java/org/apache/tajo/datum/Float8Datum.java
----------------------------------------------------------------------
diff --git a/tajo-common/src/main/java/org/apache/tajo/datum/Float8Datum.java b/tajo-common/src/main/java/org/apache/tajo/datum/Float8Datum.java
index d9389f4..d531942 100644
--- a/tajo-common/src/main/java/org/apache/tajo/datum/Float8Datum.java
+++ b/tajo-common/src/main/java/org/apache/tajo/datum/Float8Datum.java
@@ -46,6 +46,11 @@ public class Float8Datum extends Datum implements NumericDatum {
ByteBuffer bb = ByteBuffer.wrap(bytes);
this.val = bb.getDouble();
}
+
+ @Override
+ public char asChar() {
+ return asChars().charAt(0);
+ }
@Override
public short asInt2() {
http://git-wip-us.apache.org/repos/asf/incubator-tajo/blob/135b27a6/tajo-common/src/main/java/org/apache/tajo/datum/Int2Datum.java
----------------------------------------------------------------------
diff --git a/tajo-common/src/main/java/org/apache/tajo/datum/Int2Datum.java b/tajo-common/src/main/java/org/apache/tajo/datum/Int2Datum.java
index 4101e12..b34031f 100644
--- a/tajo-common/src/main/java/org/apache/tajo/datum/Int2Datum.java
+++ b/tajo-common/src/main/java/org/apache/tajo/datum/Int2Datum.java
@@ -43,6 +43,11 @@ public class Int2Datum extends Datum implements NumericDatum {
ByteBuffer bb = ByteBuffer.wrap(bytes);
this.val = bb.getShort();
}
+
+ @Override
+ public char asChar() {
+ return asChars().charAt(0);
+ }
@Override
public short asInt2() {
http://git-wip-us.apache.org/repos/asf/incubator-tajo/blob/135b27a6/tajo-common/src/main/java/org/apache/tajo/datum/Int4Datum.java
----------------------------------------------------------------------
diff --git a/tajo-common/src/main/java/org/apache/tajo/datum/Int4Datum.java b/tajo-common/src/main/java/org/apache/tajo/datum/Int4Datum.java
index 0b95229..1422187 100644
--- a/tajo-common/src/main/java/org/apache/tajo/datum/Int4Datum.java
+++ b/tajo-common/src/main/java/org/apache/tajo/datum/Int4Datum.java
@@ -45,6 +45,11 @@ public class Int4Datum extends Datum implements NumericDatum {
this.val = bb.getInt();
}
+ @Override
+ public char asChar() {
+ return asChars().charAt(0);
+ }
+
@Override
public short asInt2() {
return (short) val;
@@ -62,7 +67,7 @@ public class Int4Datum extends Datum implements NumericDatum {
@Override
public byte asByte() {
- throw new InvalidCastException();
+ return (byte) val;
}
@Override
http://git-wip-us.apache.org/repos/asf/incubator-tajo/blob/135b27a6/tajo-common/src/main/java/org/apache/tajo/datum/Int8Datum.java
----------------------------------------------------------------------
diff --git a/tajo-common/src/main/java/org/apache/tajo/datum/Int8Datum.java b/tajo-common/src/main/java/org/apache/tajo/datum/Int8Datum.java
index dd00cb4..689adbc 100644
--- a/tajo-common/src/main/java/org/apache/tajo/datum/Int8Datum.java
+++ b/tajo-common/src/main/java/org/apache/tajo/datum/Int8Datum.java
@@ -49,6 +49,11 @@ public class Int8Datum extends Datum implements NumericDatum {
public boolean asBool() {
throw new InvalidCastException();
}
+
+ @Override
+ public char asChar() {
+ return asChars().charAt(0);
+ }
@Override
public short asInt2() {
http://git-wip-us.apache.org/repos/asf/incubator-tajo/blob/135b27a6/tajo-core/tajo-core-backend/src/main/antlr4/org/apache/tajo/engine/parser/SQLLexer.g4
----------------------------------------------------------------------
diff --git a/tajo-core/tajo-core-backend/src/main/antlr4/org/apache/tajo/engine/parser/SQLLexer.g4 b/tajo-core/tajo-core-backend/src/main/antlr4/org/apache/tajo/engine/parser/SQLLexer.g4
index 46384c8..26bcb67 100644
--- a/tajo-core/tajo-core-backend/src/main/antlr4/org/apache/tajo/engine/parser/SQLLexer.g4
+++ b/tajo-core/tajo-core-backend/src/main/antlr4/org/apache/tajo/engine/parser/SQLLexer.g4
@@ -124,6 +124,7 @@ AVG : A V G;
BY : B Y;
CASE : C A S E;
+CAST : C A S T;
CHARACTER : C H A R A C T E R;
COALESCE : C O A L E S C E;
COUNT : C O U N T;
@@ -305,8 +306,14 @@ Not_Similar_To : '!~';
Similar_To_Case_Insensitive : '~*';
Not_Similar_To_Case_Insensitive : '!~*';
+// Cast Operator
+CAST_EXPRESSION
+ : COLON COLON
+ ;
+
ASSIGN : ':=';
EQUAL : '=';
+COLON : ':';
SEMI_COLON : ';';
COMMA : ',';
CONCATENATION_OPERATOR : VERTICAL_BAR VERTICAL_BAR;
@@ -357,7 +364,7 @@ Identifier
;
Regular_Identifier
- : ('a'..'z'|'A'..'Z'|'_') ('a'..'z'|'A'..'Z'|Digit|'_'|':')*
+ : ('a'..'z'|'A'..'Z'|'_') ('a'..'z'|'A'..'Z'|Digit|'_')*
;
/*
http://git-wip-us.apache.org/repos/asf/incubator-tajo/blob/135b27a6/tajo-core/tajo-core-backend/src/main/antlr4/org/apache/tajo/engine/parser/SQLParser.g4
----------------------------------------------------------------------
diff --git a/tajo-core/tajo-core-backend/src/main/antlr4/org/apache/tajo/engine/parser/SQLParser.g4 b/tajo-core/tajo-core-backend/src/main/antlr4/org/apache/tajo/engine/parser/SQLParser.g4
index 2c52b70..823dfd5 100644
--- a/tajo-core/tajo-core-backend/src/main/antlr4/org/apache/tajo/engine/parser/SQLParser.g4
+++ b/tajo-core/tajo-core-backend/src/main/antlr4/org/apache/tajo/engine/parser/SQLParser.g4
@@ -52,7 +52,7 @@ predefined_type
character_string_type
: CHARACTER type_length?
- | CHAR type_length? |
+ | CHAR type_length?
| CHARACTER VARYING type_length?
| CHAR VARYING type_length?
| VARCHAR type_length?
@@ -593,6 +593,10 @@ null_ordering
*/
boolean_value_expression
+ : or_predicate (CAST_EXPRESSION data_type)?
+ ;
+
+or_predicate
: and_predicate (OR and_predicate)*
;
@@ -796,6 +800,7 @@ numeric_primary
| set_function_specification
| routine_invocation
| scalar_subquery
+ | cast_specification
| LEFT_PAREN numeric_value_expression RIGHT_PAREN
;
@@ -863,4 +868,22 @@ else_clause
result
: numeric_value_expression | NULL
+ ;
+
+/*
+===============================================================================
+ cast_specification
+===============================================================================
+*/
+
+cast_specification
+ : CAST LEFT_PAREN cast_operand AS cast_target RIGHT_PAREN
+ ;
+
+cast_operand
+ : boolean_value_expression
+ ;
+
+cast_target
+ : data_type
;
\ No newline at end of file
http://git-wip-us.apache.org/repos/asf/incubator-tajo/blob/135b27a6/tajo-core/tajo-core-backend/src/main/java/org/apache/tajo/engine/eval/CastEval.java
----------------------------------------------------------------------
diff --git a/tajo-core/tajo-core-backend/src/main/java/org/apache/tajo/engine/eval/CastEval.java b/tajo-core/tajo-core-backend/src/main/java/org/apache/tajo/engine/eval/CastEval.java
new file mode 100644
index 0000000..96ac630
--- /dev/null
+++ b/tajo-core/tajo-core-backend/src/main/java/org/apache/tajo/engine/eval/CastEval.java
@@ -0,0 +1,119 @@
+/**
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.apache.tajo.engine.eval;
+
+import com.google.gson.annotations.Expose;
+import org.apache.tajo.catalog.Schema;
+import org.apache.tajo.datum.Datum;
+import org.apache.tajo.datum.DatumFactory;
+import org.apache.tajo.storage.Tuple;
+
+import static org.apache.tajo.common.TajoDataTypes.DataType;
+
+public class CastEval extends EvalNode {
+ @Expose private EvalNode operand;
+ @Expose private DataType target;
+
+ public CastEval(EvalNode operand, DataType target) {
+ super(EvalType.CAST);
+ this.operand = operand;
+ this.target = target;
+ }
+
+ @Override
+ public EvalContext newContext() {
+ CastContext castContext = new CastContext();
+ castContext.childCtx = operand.newContext();
+ return castContext;
+ }
+
+ @Override
+ public DataType[] getValueType() {
+ return new DataType[] {target};
+ }
+
+ @Override
+ public String getName() {
+ return target.getType().name();
+ }
+
+ public void eval(EvalContext ctx, Schema schema, Tuple tuple) {
+ CastContext castContext = (CastContext) ctx;
+ operand.eval(castContext.childCtx , schema, tuple);
+ }
+
+ @Override
+ public Datum terminate(EvalContext ctx) {
+ CastContext castContext = (CastContext) ctx;
+ switch (target.getType()) {
+ case BOOLEAN:
+ return DatumFactory.createBool(operand.terminate(castContext.childCtx).asBool());
+ case CHAR:
+ return DatumFactory.createChar(operand.terminate(castContext.childCtx).asChar());
+ case INT1:
+ case INT2:
+ return DatumFactory.createInt2(operand.terminate(castContext.childCtx).asInt2());
+ case INT4:
+ return DatumFactory.createInt4(operand.terminate(castContext.childCtx).asInt4());
+ case INT8:
+ return DatumFactory.createInt8(operand.terminate(castContext.childCtx).asInt8());
+ case FLOAT4:
+ return DatumFactory.createFloat4(operand.terminate(castContext.childCtx).asFloat4());
+ case FLOAT8:
+ return DatumFactory.createFloat8(operand.terminate(castContext.childCtx).asFloat8());
+ case TEXT:
+ return DatumFactory.createText(operand.terminate(castContext.childCtx).asTextBytes());
+ case BLOB:
+ return DatumFactory.createBlob(operand.terminate(castContext.childCtx).asByteArray());
+ default:
+ throw new InvalidCastException("Cannot cast " + operand.getValueType()[0].getType() + " to "
+ + target.getType());
+ }
+ }
+
+ public String toString() {
+ return "CAST (" + operand + " AS " + target.getType() + ")";
+ }
+
+ @Override
+ public boolean equals(Object obj) {
+ boolean valid = obj != null && obj instanceof CastEval;
+ if (valid) {
+ CastEval another = (CastEval) obj;
+ return operand.equals(another.operand) && target.equals(another.target);
+ } else {
+ return false;
+ }
+ }
+
+ @Override
+ public void preOrder(EvalNodeVisitor visitor) {
+ visitor.visit(this);
+ visitor.visit(operand);
+ }
+
+ public void postOrder(EvalNodeVisitor visitor) {
+ visitor.visit(operand);
+ visitor.visit(this);
+ }
+
+ static class CastContext implements EvalContext {
+ EvalContext childCtx;
+ }
+}
http://git-wip-us.apache.org/repos/asf/incubator-tajo/blob/135b27a6/tajo-core/tajo-core-backend/src/main/java/org/apache/tajo/engine/eval/EvalNode.java
----------------------------------------------------------------------
diff --git a/tajo-core/tajo-core-backend/src/main/java/org/apache/tajo/engine/eval/EvalNode.java b/tajo-core/tajo-core-backend/src/main/java/org/apache/tajo/engine/eval/EvalNode.java
index c6f0f2d..dec9c4a 100644
--- a/tajo-core/tajo-core-backend/src/main/java/org/apache/tajo/engine/eval/EvalNode.java
+++ b/tajo-core/tajo-core-backend/src/main/java/org/apache/tajo/engine/eval/EvalNode.java
@@ -78,7 +78,7 @@ public abstract class EvalNode implements Cloneable, GsonObject {
public abstract String getName();
public String toString() {
- return "("+this.type+"("+leftExpr.toString()+" "+rightExpr.toString()+"))";
+ return "(" + this.type + "(" + leftExpr.toString() + " " + rightExpr.toString() + "))";
}
@Override
@@ -90,12 +90,14 @@ public abstract class EvalNode implements Cloneable, GsonObject {
public abstract Datum terminate(EvalContext ctx);
+ @Deprecated
public void preOrder(EvalNodeVisitor visitor) {
visitor.visit(this);
leftExpr.preOrder(visitor);
rightExpr.preOrder(visitor);
}
-
+
+ @Deprecated
public void postOrder(EvalNodeVisitor visitor) {
leftExpr.postOrder(visitor);
rightExpr.postOrder(visitor);
http://git-wip-us.apache.org/repos/asf/incubator-tajo/blob/135b27a6/tajo-core/tajo-core-backend/src/main/java/org/apache/tajo/engine/eval/EvalType.java
----------------------------------------------------------------------
diff --git a/tajo-core/tajo-core-backend/src/main/java/org/apache/tajo/engine/eval/EvalType.java b/tajo-core/tajo-core-backend/src/main/java/org/apache/tajo/engine/eval/EvalType.java
index f5a9e56..9f81b05 100644
--- a/tajo-core/tajo-core-backend/src/main/java/org/apache/tajo/engine/eval/EvalType.java
+++ b/tajo-core/tajo-core-backend/src/main/java/org/apache/tajo/engine/eval/EvalType.java
@@ -54,9 +54,10 @@ public enum EvalType {
IN(InEval.class),
// Value or Reference
+ CAST(CastEval.class),
+ ROW_CONSTANT(RowConstantEval.class),
FIELD(FieldEval.class),
- CONST(ConstEval.class),
- ROW_CONSTANT(RowConstantEval.class);
+ CONST(ConstEval.class);
private Class<? extends EvalNode> baseClass;
private String operatorName;
http://git-wip-us.apache.org/repos/asf/incubator-tajo/blob/135b27a6/tajo-core/tajo-core-backend/src/main/java/org/apache/tajo/engine/parser/SQLAnalyzer.java
----------------------------------------------------------------------
diff --git a/tajo-core/tajo-core-backend/src/main/java/org/apache/tajo/engine/parser/SQLAnalyzer.java b/tajo-core/tajo-core-backend/src/main/java/org/apache/tajo/engine/parser/SQLAnalyzer.java
index b173037..e9773fc 100644
--- a/tajo-core/tajo-core-backend/src/main/java/org/apache/tajo/engine/parser/SQLAnalyzer.java
+++ b/tajo-core/tajo-core-backend/src/main/java/org/apache/tajo/engine/parser/SQLAnalyzer.java
@@ -453,31 +453,39 @@ public class SQLAnalyzer extends SQLParserBaseVisitor<Expr> {
}
@Override
- public Expr visitAnd_predicate(SQLParser.And_predicateContext ctx) {
- Expr current = visitBoolean_factor(ctx.boolean_factor(0));
+ public Expr visitBoolean_value_expression(SQLParser.Boolean_value_expressionContext ctx) {
+ Expr current = visitOr_predicate(ctx.or_predicate());
+ if (checkIfExist(ctx.CAST_EXPRESSION())) {
+ current = new CastExpr(current, visitData_type(ctx.data_type()));
+ }
+ return current;
+ }
+
+ @Override
+ public Expr visitOr_predicate(SQLParser.Or_predicateContext ctx) {
+ Expr current = visitAnd_predicate(ctx.and_predicate(0));
Expr left;
Expr right;
- for (int i = 1; i < ctx.boolean_factor().size(); i++) {
+ for (int i = 1; i < ctx.and_predicate().size(); i++) {
left = current;
- right = visitBoolean_factor(ctx.boolean_factor(i));
- current = new BinaryOperator(OpType.And, left, right);
+ right = visitAnd_predicate(ctx.and_predicate(i));
+ current = new BinaryOperator(OpType.Or, left, right);
}
return current;
}
@Override
- public Expr visitBoolean_value_expression(SQLParser.Boolean_value_expressionContext ctx) {
-
- Expr current = visitAnd_predicate(ctx.and_predicate(0));
+ public Expr visitAnd_predicate(SQLParser.And_predicateContext ctx) {
+ Expr current = visitBoolean_factor(ctx.boolean_factor(0));
Expr left;
Expr right;
- for (int i = 1; i < ctx.and_predicate().size(); i++) {
+ for (int i = 1; i < ctx.boolean_factor().size(); i++) {
left = current;
- right = visitAnd_predicate(ctx.and_predicate(i));
- current = new BinaryOperator(OpType.Or, left, right);
+ right = visitBoolean_factor(ctx.boolean_factor(i));
+ current = new BinaryOperator(OpType.And, left, right);
}
return current;
@@ -814,26 +822,18 @@ public class SQLAnalyzer extends SQLParserBaseVisitor<Expr> {
CreateTable.ColumnDefinition [] elements = new CreateTable.ColumnDefinition[size];
for (int i = 0; i < size; i++) {
String name = ctx.field_element(i).name.getText();
- TypeDefinition typeDef = getDataType(ctx.field_element(i).field_type().data_type());
- String type = typeDef.getType();
- elements[i] = new CreateTable.ColumnDefinition(name, type);
- if (typeDef.getLengthOrPrecision() != null) {
- elements[i].setLengthOrPrecision(typeDef.getLengthOrPrecision());
-
- if (typeDef.getScale() != null) {
- elements[i].setScale(typeDef.getScale());
- }
- }
-
+ DataType typeDef = visitData_type(ctx.field_element(i).field_type().data_type());
+ elements[i] = new CreateTable.ColumnDefinition(name, typeDef);
}
return elements;
}
- private TypeDefinition getDataType(SQLParser.Data_typeContext type) {
- SQLParser.Predefined_typeContext predefined_type = type.predefined_type();
+ @Override
+ public DataType visitData_type(SQLParser.Data_typeContext ctx) {
+ SQLParser.Predefined_typeContext predefined_type = ctx.predefined_type();
- TypeDefinition typeDefinition = null;
+ DataType typeDefinition = null;
if (predefined_type.character_string_type() != null) {
SQLParser.Character_string_typeContext character_string_type =
predefined_type.character_string_type();
@@ -841,7 +841,7 @@ public class SQLAnalyzer extends SQLParserBaseVisitor<Expr> {
if ((character_string_type.CHARACTER() != null || character_string_type.CHAR() != null) &&
character_string_type.VARYING() == null) {
- typeDefinition = new TypeDefinition(Type.CHAR.name());
+ typeDefinition = new DataType(Type.CHAR.name());
if (character_string_type.type_length() != null) {
typeDefinition.setLengthOrPrecision(
@@ -851,7 +851,7 @@ public class SQLAnalyzer extends SQLParserBaseVisitor<Expr> {
} else if (character_string_type.VARCHAR() != null
|| character_string_type.VARYING() != null) {
- typeDefinition = new TypeDefinition(Type.VARCHAR.name());
+ typeDefinition = new DataType(Type.VARCHAR.name());
if (character_string_type.type_length() != null) {
typeDefinition.setLengthOrPrecision(
@@ -859,7 +859,7 @@ public class SQLAnalyzer extends SQLParserBaseVisitor<Expr> {
}
} else if (character_string_type.TEXT() != null) {
- typeDefinition = new TypeDefinition(Type.TEXT.name());
+ typeDefinition = new DataType(Type.TEXT.name());
}
} else if (predefined_type.national_character_string_type() != null) {
@@ -867,9 +867,9 @@ public class SQLAnalyzer extends SQLParserBaseVisitor<Expr> {
predefined_type.national_character_string_type();
if ((nchar_type.CHAR() != null || nchar_type.CHARACTER() != null
|| nchar_type.NCHAR() != null) && nchar_type.VARYING() == null) {
- typeDefinition = new TypeDefinition(Type.NCHAR.name());
+ typeDefinition = new DataType(Type.NCHAR.name());
} else if (nchar_type.NVARCHAR() != null || nchar_type.VARYING() != null) {
- typeDefinition = new TypeDefinition(Type.NVARCHAR.name());
+ typeDefinition = new DataType(Type.NVARCHAR.name());
}
if (nchar_type.type_length() != null) {
@@ -880,7 +880,7 @@ public class SQLAnalyzer extends SQLParserBaseVisitor<Expr> {
} else if (predefined_type.binary_large_object_string_type() != null) {
SQLParser.Binary_large_object_string_typeContext blob_type =
predefined_type.binary_large_object_string_type();
- typeDefinition = new TypeDefinition(Type.BLOB.name());
+ typeDefinition = new DataType(Type.BLOB.name());
if (blob_type.type_length() != null) {
typeDefinition.setLengthOrPrecision(
Integer.parseInt(blob_type.type_length().NUMBER().getText()));
@@ -891,22 +891,22 @@ public class SQLAnalyzer extends SQLParserBaseVisitor<Expr> {
SQLParser.Exact_numeric_typeContext exactType =
predefined_type.numeric_type().exact_numeric_type();
if (exactType.TINYINT() != null || exactType.INT1() != null) {
- typeDefinition = new TypeDefinition(Type.INT1.name());
+ typeDefinition = new DataType(Type.INT1.name());
} else if (exactType.INT2() != null || exactType.SMALLINT() != null) {
- typeDefinition = new TypeDefinition(Type.INT2.name());
+ typeDefinition = new DataType(Type.INT2.name());
} else if (exactType.INT4() != null || exactType.INTEGER() != null ||
exactType.INT() != null) {
- typeDefinition = new TypeDefinition(Type.INT4.name());
+ typeDefinition = new DataType(Type.INT4.name());
} else if (exactType.INT8() != null || exactType.BIGINT() != null) {
- typeDefinition = new TypeDefinition(Type.INT8.name());
+ typeDefinition = new DataType(Type.INT8.name());
} else if (exactType.NUMERIC() != null) {
- typeDefinition = new TypeDefinition(Type.NUMERIC.name());
+ typeDefinition = new DataType(Type.NUMERIC.name());
} else if (exactType.DECIMAL() != null || exactType.DEC() != null) {
- typeDefinition = new TypeDefinition(Type.DECIMAL.name());
+ typeDefinition = new DataType(Type.DECIMAL.name());
}
- if (typeDefinition.getType().equals(Type.NUMERIC.name()) ||
- typeDefinition.getType().equals(Type.DECIMAL.name())) {
+ if (typeDefinition.getTypeName().equals(Type.NUMERIC.name()) ||
+ typeDefinition.getTypeName().equals(Type.DECIMAL.name())) {
if (exactType.precision_param() != null) {
if (exactType.precision_param().scale != null) {
typeDefinition.setScale(
@@ -921,34 +921,34 @@ public class SQLAnalyzer extends SQLParserBaseVisitor<Expr> {
predefined_type.numeric_type().approximate_numeric_type();
if (approximateType.FLOAT() != null || approximateType.FLOAT4() != null
|| approximateType.REAL() != null) {
- typeDefinition = new TypeDefinition(Type.FLOAT4.name());
+ typeDefinition = new DataType(Type.FLOAT4.name());
} else if (approximateType.FLOAT8() != null || approximateType.DOUBLE() != null) {
- typeDefinition = new TypeDefinition(Type.FLOAT8.name());
+ typeDefinition = new DataType(Type.FLOAT8.name());
}
}
} else if (predefined_type.boolean_type() != null) {
- typeDefinition = new TypeDefinition(Type.BOOLEAN.name());
+ typeDefinition = new DataType(Type.BOOLEAN.name());
} else if (predefined_type.datetime_type() != null) {
SQLParser.Datetime_typeContext dateTimeType = predefined_type.datetime_type();
if (dateTimeType.DATE() != null) {
- typeDefinition = new TypeDefinition(Type.DATE.name());
+ typeDefinition = new DataType(Type.DATE.name());
} else if (dateTimeType.TIME(0) != null && dateTimeType.ZONE() == null) {
- typeDefinition = new TypeDefinition(Type.TIME.name());
+ typeDefinition = new DataType(Type.TIME.name());
} else if ((dateTimeType.TIME(0) != null && dateTimeType.ZONE() != null) ||
dateTimeType.TIMETZ() != null) {
- typeDefinition = new TypeDefinition(Type.TIMEZ.name());
+ typeDefinition = new DataType(Type.TIMEZ.name());
} else if (dateTimeType.TIMESTAMP() != null && dateTimeType.ZONE() == null) {
- typeDefinition = new TypeDefinition(Type.TIMESTAMP.name());
+ typeDefinition = new DataType(Type.TIMESTAMP.name());
} else if ((dateTimeType.TIMESTAMP() != null && dateTimeType.ZONE() != null) ||
dateTimeType.TIMESTAMPTZ() != null) {
- typeDefinition = new TypeDefinition(Type.TIMESTAMPZ.name());
+ typeDefinition = new DataType(Type.TIMESTAMPZ.name());
}
} else if (predefined_type.bit_type() != null) {
SQLParser.Bit_typeContext bitType = predefined_type.bit_type();
if (bitType.VARBIT() != null || bitType.VARYING() != null) {
- typeDefinition = new TypeDefinition(Type.VARBIT.name());
+ typeDefinition = new DataType(Type.VARBIT.name());
} else {
- typeDefinition = new TypeDefinition(Type.BIT.name());
+ typeDefinition = new DataType(Type.BIT.name());
}
if (bitType.type_length() != null) {
typeDefinition.setLengthOrPrecision(
@@ -957,9 +957,9 @@ public class SQLAnalyzer extends SQLParserBaseVisitor<Expr> {
} else if (predefined_type.binary_type() != null) {
SQLParser.Binary_typeContext binaryType = predefined_type.binary_type();
if (binaryType.VARBINARY() != null || binaryType.VARYING() != null) {
- typeDefinition = new TypeDefinition(Type.VARBINARY.name());
+ typeDefinition = new DataType(Type.VARBINARY.name());
} else {
- typeDefinition = new TypeDefinition(Type.BINARY.name());
+ typeDefinition = new DataType(Type.BINARY.name());
}
if (binaryType.type_length() != null) {
@@ -971,36 +971,6 @@ public class SQLAnalyzer extends SQLParserBaseVisitor<Expr> {
return typeDefinition;
}
- public static class TypeDefinition {
- private String type;
- private Integer length_or_precision;
- private Integer scale;
-
- TypeDefinition(String type) {
- this.type = type;
- }
-
- String getType() {
- return type;
- }
-
- public void setLengthOrPrecision(Integer length_or_precision) {
- this.length_or_precision = length_or_precision;
- }
-
- public Integer getLengthOrPrecision() {
- return length_or_precision;
- }
-
- void setScale(Integer scale) {
- this.scale = scale;
- }
-
- public Integer getScale() {
- return this.scale;
- }
- }
-
@Override
public Expr visitInsert_statement(SQLParser.Insert_statementContext ctx) {
Insert insertExpr = new Insert();
@@ -1085,4 +1055,10 @@ public class SQLAnalyzer extends SQLParserBaseVisitor<Expr> {
private static String stripQuote(String str) {
return str.substring(1, str.length() - 1);
}
+
+ @Override public Expr visitCast_specification(SQLParser.Cast_specificationContext ctx) {
+ Expr operand = visitChildren(ctx.cast_operand());
+ DataType castTarget = visitData_type(ctx.cast_target().data_type());
+ return new CastExpr(operand, castTarget);
+ }
}
http://git-wip-us.apache.org/repos/asf/incubator-tajo/blob/135b27a6/tajo-core/tajo-core-backend/src/main/java/org/apache/tajo/engine/planner/LogicalPlan.java
----------------------------------------------------------------------
diff --git a/tajo-core/tajo-core-backend/src/main/java/org/apache/tajo/engine/planner/LogicalPlan.java b/tajo-core/tajo-core-backend/src/main/java/org/apache/tajo/engine/planner/LogicalPlan.java
index 3ab98f0..286b3b2 100644
--- a/tajo-core/tajo-core-backend/src/main/java/org/apache/tajo/engine/planner/LogicalPlan.java
+++ b/tajo-core/tajo-core-backend/src/main/java/org/apache/tajo/engine/planner/LogicalPlan.java
@@ -75,8 +75,8 @@ public class LogicalPlan {
return newAndGetBlock(NONAME_BLOCK_PREFIX + (noNameBlockId++));
}
- public String newNonameColumnName() {
- return "?_" + (noNameColumnId++);
+ public String newNonameColumnName(String prefix) {
+ return "?" + prefix + "_" + (noNameColumnId++);
}
/**
@@ -735,7 +735,8 @@ public class LogicalPlan {
} else {
Target [] addedTargets = new Target[aggrFunctions.size()];
for (int i = 0; i < aggrFunctions.size(); i++) {
- Target aggrFunctionTarget = new Target(aggrFunctions.get(i), newNonameColumnName());
+ Target aggrFunctionTarget = new Target(aggrFunctions.get(i),
+ newNonameColumnName(aggrFunctions.get(i).getName()));
addedTargets[i] = aggrFunctionTarget;
EvalTreeUtil.replace(havingCondition, aggrFunctions.get(i),
new FieldEval(aggrFunctionTarget.getColumnSchema()));
http://git-wip-us.apache.org/repos/asf/incubator-tajo/blob/135b27a6/tajo-core/tajo-core-backend/src/main/java/org/apache/tajo/engine/planner/LogicalPlanner.java
----------------------------------------------------------------------
diff --git a/tajo-core/tajo-core-backend/src/main/java/org/apache/tajo/engine/planner/LogicalPlanner.java b/tajo-core/tajo-core-backend/src/main/java/org/apache/tajo/engine/planner/LogicalPlanner.java
index f08855a..d6b644b 100644
--- a/tajo-core/tajo-core-backend/src/main/java/org/apache/tajo/engine/planner/LogicalPlanner.java
+++ b/tajo-core/tajo-core-backend/src/main/java/org/apache/tajo/engine/planner/LogicalPlanner.java
@@ -807,35 +807,19 @@ public class LogicalPlanner extends BaseAlgebraVisitor<LogicalPlanner.PlanContex
return schema;
}
- private Column convertColumn(ColumnDefinition columnDefinition) {
- TajoDataTypes.Type type = TajoDataTypes.Type.valueOf(columnDefinition.getDataType());
- Column column;
- switch (type) {
- case CHAR:
- case VARCHAR:
- case NCHAR:
- case NVARCHAR:
- column = new Column(columnDefinition.getColumnName(),
- TajoDataTypes.Type.valueOf(columnDefinition.getDataType()),
- columnDefinition.getLengthOrPrecision());
- break;
- case FLOAT4:
- case FLOAT8:
- // TODO: support precision
- column = new Column(columnDefinition.getColumnName(),
- TajoDataTypes.Type.valueOf(columnDefinition.getDataType()));
- break;
- case NUMERIC:
- case DECIMAL:
- // TODO: support precision and scale
- column = new Column(columnDefinition.getColumnName(),
- TajoDataTypes.Type.valueOf(columnDefinition.getDataType()));
- break;
- default:
- column = new Column(columnDefinition.getColumnName(),
- TajoDataTypes.Type.valueOf(columnDefinition.getDataType()));
+ private DataType convertDataType(org.apache.tajo.algebra.DataType dataType) {
+ TajoDataTypes.Type type = TajoDataTypes.Type.valueOf(dataType.getTypeName());
+
+ DataType.Builder builder = DataType.newBuilder();
+ builder.setType(type);
+ if (dataType.hasLengthOrPrecision()) {
+ builder.setLength(dataType.getLengthOrPrecision());
}
- return column;
+ return builder.build();
+ }
+
+ private Column convertColumn(ColumnDefinition columnDefinition) {
+ return new Column(columnDefinition.getColumnName(), convertDataType(columnDefinition));
}
protected LogicalNode visitInsert(PlanContext context, Stack<OpType> stack, Insert expr) throws PlanningException {
@@ -941,6 +925,11 @@ public class LogicalPlanner extends BaseAlgebraVisitor<LogicalPlanner.PlanContex
throw new RuntimeException("Unsupported type: " + literal.getValueType());
}
+ case Cast:
+ CastExpr cast = (CastExpr) expr;
+ return new CastEval(createEvalTree(plan, block, cast.getOperand()),
+ convertDataType(cast.getTarget()));
+
case ValueList: {
ValueListExpr valueList = (ValueListExpr) expr;
Datum[] values = new Datum[valueList.getValues().length];
@@ -1182,12 +1171,11 @@ public class LogicalPlanner extends BaseAlgebraVisitor<LogicalPlanner.PlanContex
for(Target t : targets) {
DataType type = t.getEvalTree().getValueType()[0];
String name;
- if (t.hasAlias()) {
+ if (t.hasAlias() || t.getEvalTree().getType() == EvalType.FIELD) {
+ name = t.getCanonicalName();
+ } else { // if an alias is not given or this target is an expression
+ t.setAlias(plan.newNonameColumnName(t.getEvalTree().getName()));
name = t.getAlias();
- } else if (t.getEvalTree().getName().equals("?")) {
- name = plan.newNonameColumnName();
- } else {
- name = t.getEvalTree().getName();
}
projected.addColumn(name,type);
}
http://git-wip-us.apache.org/repos/asf/incubator-tajo/blob/135b27a6/tajo-core/tajo-core-backend/src/main/java/org/apache/tajo/engine/planner/TargetListManager.java
----------------------------------------------------------------------
diff --git a/tajo-core/tajo-core-backend/src/main/java/org/apache/tajo/engine/planner/TargetListManager.java b/tajo-core/tajo-core-backend/src/main/java/org/apache/tajo/engine/planner/TargetListManager.java
index ccb64ce..205b1b7 100644
--- a/tajo-core/tajo-core-backend/src/main/java/org/apache/tajo/engine/planner/TargetListManager.java
+++ b/tajo-core/tajo-core-backend/src/main/java/org/apache/tajo/engine/planner/TargetListManager.java
@@ -22,6 +22,7 @@ import org.apache.tajo.algebra.Projection;
import org.apache.tajo.catalog.Column;
import org.apache.tajo.catalog.Schema;
import org.apache.tajo.engine.eval.EvalTreeUtil;
+import org.apache.tajo.engine.eval.EvalType;
import org.apache.tajo.engine.eval.FieldEval;
import java.util.Collection;
@@ -152,12 +153,11 @@ public class TargetListManager {
public Column getResolvedTargetToColumn(int id) {
Target t = targets[id];
String name;
- if (t.hasAlias()) {
- name = t.getAlias();
- } else if (t.getEvalTree().getName().equals("?")) {
- name = plan.newNonameColumnName();
- } else {
- name = t.getEvalTree().getName();
+ if (t.hasAlias() || t.getEvalTree().getType() == EvalType.FIELD) {
+ name = t.getCanonicalName();
+ } else { // if alias name is not given or target is an expression
+ t.setAlias(plan.newNonameColumnName(t.getEvalTree().getName()));
+ name = t.getCanonicalName();
}
return new Column(name, t.getEvalTree().getValueType()[0]);
}
http://git-wip-us.apache.org/repos/asf/incubator-tajo/blob/135b27a6/tajo-core/tajo-core-backend/src/test/java/org/apache/tajo/engine/eval/ExprTestBase.java
----------------------------------------------------------------------
diff --git a/tajo-core/tajo-core-backend/src/test/java/org/apache/tajo/engine/eval/ExprTestBase.java b/tajo-core/tajo-core-backend/src/test/java/org/apache/tajo/engine/eval/ExprTestBase.java
new file mode 100644
index 0000000..dd1f894
--- /dev/null
+++ b/tajo-core/tajo-core-backend/src/test/java/org/apache/tajo/engine/eval/ExprTestBase.java
@@ -0,0 +1,143 @@
+/**
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.apache.tajo.engine.eval;
+
+import org.apache.hadoop.fs.Path;
+import org.apache.tajo.TajoTestingCluster;
+import org.apache.tajo.algebra.Expr;
+import org.apache.tajo.catalog.*;
+import org.apache.tajo.catalog.proto.CatalogProtos;
+import org.apache.tajo.datum.NullDatum;
+import org.apache.tajo.datum.TextDatum;
+import org.apache.tajo.engine.json.CoreGsonHelper;
+import org.apache.tajo.engine.parser.SQLAnalyzer;
+import org.apache.tajo.engine.planner.LogicalPlan;
+import org.apache.tajo.engine.planner.LogicalPlanner;
+import org.apache.tajo.engine.planner.PlanningException;
+import org.apache.tajo.engine.planner.Target;
+import org.apache.tajo.master.TajoMaster;
+import org.apache.tajo.storage.LazyTuple;
+import org.apache.tajo.storage.Tuple;
+import org.apache.tajo.storage.VTuple;
+import org.apache.tajo.util.Bytes;
+import org.junit.AfterClass;
+import org.junit.BeforeClass;
+
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertTrue;
+
+public class ExprTestBase {
+ private static TajoTestingCluster util;
+ private static CatalogService cat;
+ private static SQLAnalyzer analyzer;
+ private static LogicalPlanner planner;
+
+ @BeforeClass
+ public static void setUp() throws Exception {
+ util = new TajoTestingCluster();
+ util.startCatalogCluster();
+ cat = util.getMiniCatalogCluster().getCatalog();
+ for (FunctionDesc funcDesc : TajoMaster.initBuiltinFunctions()) {
+ cat.createFunction(funcDesc);
+ }
+
+ analyzer = new SQLAnalyzer();
+ planner = new LogicalPlanner(cat);
+ }
+
+ @AfterClass
+ public static void tearDown() throws Exception {
+ util.shutdownCatalogCluster();
+ }
+
+ private static void assertJsonSerDer(EvalNode expr) {
+ String json = expr.toJson();
+ EvalNode fromJson = CoreGsonHelper.fromJson(json, EvalNode.class);
+ assertEquals(expr, fromJson);
+ }
+
+ private static Target[] getRawTargets(String query) throws PlanningException {
+ Expr expr = analyzer.parse(query);
+ LogicalPlan plan = planner.createPlan(expr);
+ Target [] targets = plan.getRootBlock().getTargetListManager().getUnresolvedTargets();
+ if (targets == null) {
+ throw new PlanningException("Wrong query statement or query plan: " + query);
+ }
+ for (Target t : targets) {
+ assertJsonSerDer(t.getEvalTree());
+ }
+ return targets;
+ }
+
+ public void testSimpleEval(String query, String [] expected) {
+ testEval(null, null, null, query, expected);
+ }
+
+ public void testEval(Schema schema, String tableName, String csvTuple, String query, String [] expected) {
+ LazyTuple lazyTuple;
+ VTuple vtuple = null;
+ Schema inputSchema = null;
+ if (schema != null) {
+ inputSchema = (Schema) schema.clone();
+ inputSchema.setQualifier(tableName, true);
+
+ int targetIdx [] = new int[inputSchema.getColumnNum()];
+ for (int i = 0; i < targetIdx.length; i++) {
+ targetIdx[i] = i;
+ }
+
+ lazyTuple = new LazyTuple(inputSchema, Bytes.splitPreserveAllTokens(csvTuple.getBytes(), ',', targetIdx), 0);
+ vtuple = new VTuple(inputSchema.getColumnNum());
+ for (int i = 0; i < inputSchema.getColumnNum(); i++) {
+ // If null value occurs, null datum is manually inserted to an input tuple.
+ if (lazyTuple.get(i) instanceof TextDatum && lazyTuple.getText(i).asChars().equals("")) {
+ vtuple.put(i, NullDatum.get());
+ } else {
+ vtuple.put(i, lazyTuple.get(i));
+ }
+ }
+ cat.addTable(new TableDescImpl(tableName, inputSchema, CatalogProtos.StoreType.CSV, new Options(), new Path("/")));
+ }
+
+ Target [] targets = null;
+
+ try {
+ targets = getRawTargets(query);
+ } catch (PlanningException e) {
+ assertTrue("Wrong query statement: " + query, false);
+ }
+
+ EvalContext [] evalContexts = new EvalContext[targets.length];
+ Tuple outTuple = new VTuple(targets.length);
+ for (int i = 0; i < targets.length; i++) {
+ EvalNode eval = targets[i].getEvalTree();
+ evalContexts[i] = eval.newContext();
+ eval.eval(evalContexts[i], inputSchema, vtuple);
+ outTuple.put(i, eval.terminate(evalContexts[i]));
+ }
+
+ if (schema != null) {
+ cat.deleteTable(tableName);
+ }
+
+ for (int i = 0; i < expected.length; i++) {
+ assertEquals(query, expected[i], outTuple.get(i).asChars());
+ }
+ }
+}
http://git-wip-us.apache.org/repos/asf/incubator-tajo/blob/135b27a6/tajo-core/tajo-core-backend/src/test/java/org/apache/tajo/engine/eval/TestSQLExpression.java
----------------------------------------------------------------------
diff --git a/tajo-core/tajo-core-backend/src/test/java/org/apache/tajo/engine/eval/TestSQLExpression.java b/tajo-core/tajo-core-backend/src/test/java/org/apache/tajo/engine/eval/TestSQLExpression.java
new file mode 100644
index 0000000..21a94f2
--- /dev/null
+++ b/tajo-core/tajo-core-backend/src/test/java/org/apache/tajo/engine/eval/TestSQLExpression.java
@@ -0,0 +1,71 @@
+/**
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.apache.tajo.engine.eval;
+
+import org.apache.tajo.catalog.Schema;
+import org.junit.Test;
+
+import static org.apache.tajo.common.TajoDataTypes.Type.TEXT;
+
+public class TestSQLExpression extends ExprTestBase {
+
+ @Test
+ public void testCast() {
+ testSimpleEval("select cast (1 as char)", new String[] {"1"});
+ testSimpleEval("select cast (119 as char)", new String[] {"1"});
+
+ testSimpleEval("select cast (1 as int2)", new String[ ]{"1"});
+ testSimpleEval("select cast (1 as int4)", new String[] {"1"});
+ testSimpleEval("select cast (1 as int8)", new String[] {"1"});
+ testSimpleEval("select cast (1 as float)", new String[] {"1.0"});
+ testSimpleEval("select cast (1 as double)", new String[] {"1.0"});
+ testSimpleEval("select cast (1 as text)", new String[] {"1"});
+
+ testSimpleEval("select cast ('123' as int2)", new String[] {"123"});
+ testSimpleEval("select cast ('123' as int4)", new String[] {"123"});
+ testSimpleEval("select cast ('123' as int8)", new String[] {"123"});
+ testSimpleEval("select cast ('123' as float)", new String[] {"123.0"});
+ testSimpleEval("select cast ('123' as double)", new String[] {"123.0"});
+ testSimpleEval("select cast ('123' as text)", new String[] {"123"});
+
+ testSimpleEval("select 123::int2", new String[] {"123"});
+ testSimpleEval("select 123::int4", new String[] {"123"});
+ testSimpleEval("select 123::int8", new String[] {"123"});
+ testSimpleEval("select 123::float", new String[] {"123.0"});
+ testSimpleEval("select 123::double", new String[] {"123.0"});
+ testSimpleEval("select 123::text", new String[] {"123"});
+
+ testSimpleEval("select 123.0::float", new String[] {"123.0"});
+ testSimpleEval("select 123.0::double", new String[] {"123.0"});
+
+ testSimpleEval("select '123'::int", new String[] {"123"});
+ testSimpleEval("select '123'::double", new String[] {"123.0"});
+ }
+
+ @Test
+ public void testCastFromTable() {
+ Schema schema = new Schema();
+ schema.addColumn("col1", TEXT);
+ schema.addColumn("col2", TEXT);
+ testEval(schema, "table1", "123,234", "select cast(col1 as float) as b, cast(col2 as float) as a from table1",
+ new String[]{"123.0", "234.0"});
+ testEval(schema, "table1", "123,234", "select col1::float, col2::float from table1",
+ new String[]{"123.0", "234.0"});
+ }
+}
http://git-wip-us.apache.org/repos/asf/incubator-tajo/blob/135b27a6/tajo-core/tajo-core-backend/src/test/java/org/apache/tajo/engine/function/ExprTestBase.java
----------------------------------------------------------------------
diff --git a/tajo-core/tajo-core-backend/src/test/java/org/apache/tajo/engine/function/ExprTestBase.java b/tajo-core/tajo-core-backend/src/test/java/org/apache/tajo/engine/function/ExprTestBase.java
deleted file mode 100644
index c3e5d00..0000000
--- a/tajo-core/tajo-core-backend/src/test/java/org/apache/tajo/engine/function/ExprTestBase.java
+++ /dev/null
@@ -1,145 +0,0 @@
-/**
- * Licensed to the Apache Software Foundation (ASF) under one
- * or more contributor license agreements. See the NOTICE file
- * distributed with this work for additional information
- * regarding copyright ownership. The ASF licenses this file
- * to you under the Apache License, Version 2.0 (the
- * "License"); you may not use this file except in compliance
- * with the License. You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package org.apache.tajo.engine.function;
-
-import org.apache.hadoop.fs.Path;
-import org.apache.tajo.TajoTestingCluster;
-import org.apache.tajo.algebra.Expr;
-import org.apache.tajo.catalog.*;
-import org.apache.tajo.catalog.proto.CatalogProtos;
-import org.apache.tajo.datum.NullDatum;
-import org.apache.tajo.datum.TextDatum;
-import org.apache.tajo.engine.eval.EvalContext;
-import org.apache.tajo.engine.eval.EvalNode;
-import org.apache.tajo.engine.json.CoreGsonHelper;
-import org.apache.tajo.engine.parser.SQLAnalyzer;
-import org.apache.tajo.engine.planner.LogicalPlan;
-import org.apache.tajo.engine.planner.LogicalPlanner;
-import org.apache.tajo.engine.planner.PlanningException;
-import org.apache.tajo.engine.planner.Target;
-import org.apache.tajo.master.TajoMaster;
-import org.apache.tajo.storage.LazyTuple;
-import org.apache.tajo.storage.Tuple;
-import org.apache.tajo.storage.VTuple;
-import org.apache.tajo.util.Bytes;
-import org.junit.AfterClass;
-import org.junit.BeforeClass;
-
-import static org.junit.Assert.assertEquals;
-import static org.junit.Assert.assertTrue;
-
-public class ExprTestBase {
- private static TajoTestingCluster util;
- private static CatalogService cat;
- private static SQLAnalyzer analyzer;
- private static LogicalPlanner planner;
-
- @BeforeClass
- public static void setUp() throws Exception {
- util = new TajoTestingCluster();
- util.startCatalogCluster();
- cat = util.getMiniCatalogCluster().getCatalog();
- for (FunctionDesc funcDesc : TajoMaster.initBuiltinFunctions()) {
- cat.createFunction(funcDesc);
- }
-
- analyzer = new SQLAnalyzer();
- planner = new LogicalPlanner(cat);
- }
-
- @AfterClass
- public static void tearDown() throws Exception {
- util.shutdownCatalogCluster();
- }
-
- private static void assertJsonSerDer(EvalNode expr) {
- String json = expr.toJson();
- EvalNode fromJson = CoreGsonHelper.fromJson(json, EvalNode.class);
- assertEquals(expr, fromJson);
- }
-
- private static Target[] getRawTargets(String query) throws PlanningException {
- Expr expr = analyzer.parse(query);
- LogicalPlan plan = planner.createPlan(expr);
- Target [] targets = plan.getRootBlock().getTargetListManager().getUnresolvedTargets();
- if (targets == null) {
- throw new PlanningException("Wrong query statement or query plan: " + query);
- }
- for (Target t : targets) {
- assertJsonSerDer(t.getEvalTree());
- }
- return targets;
- }
-
- public void testSimpleEval(String query, String [] expected) {
- testEval(null, null, null, query, expected);
- }
-
- public void testEval(Schema schema, String tableName, String csvTuple, String query, String [] expected) {
- LazyTuple lazyTuple;
- VTuple vtuple = null;
- Schema inputSchema = null;
- if (schema != null) {
- inputSchema = (Schema) schema.clone();
- inputSchema.setQualifier(tableName, true);
-
- int targetIdx [] = new int[inputSchema.getColumnNum()];
- for (int i = 0; i < targetIdx.length; i++) {
- targetIdx[i] = i;
- }
-
- lazyTuple = new LazyTuple(inputSchema, Bytes.splitPreserveAllTokens(csvTuple.getBytes(), ',', targetIdx), 0);
- vtuple = new VTuple(inputSchema.getColumnNum());
- for (int i = 0; i < inputSchema.getColumnNum(); i++) {
- // If null value occurs, null datum is manually inserted to an input tuple.
- if (lazyTuple.get(i) instanceof TextDatum && lazyTuple.getText(i).asChars().equals("")) {
- vtuple.put(i, NullDatum.get());
- } else {
- vtuple.put(i, lazyTuple.get(i));
- }
- }
- cat.addTable(new TableDescImpl(tableName, inputSchema, CatalogProtos.StoreType.CSV, new Options(), new Path("/")));
- }
-
- Target [] targets = null;
-
- try {
- targets = getRawTargets(query);
- } catch (PlanningException e) {
- assertTrue("Wrong query statement: " + query, false);
- }
-
- EvalContext [] evalContexts = new EvalContext[targets.length];
- Tuple outTuple = new VTuple(targets.length);
- for (int i = 0; i < targets.length; i++) {
- EvalNode eval = targets[i].getEvalTree();
- evalContexts[i] = eval.newContext();
- eval.eval(evalContexts[i], inputSchema, vtuple);
- outTuple.put(i, eval.terminate(evalContexts[i]));
- }
-
- if (schema != null) {
- cat.deleteTable(tableName);
- }
-
- for (int i = 0; i < expected.length; i++) {
- assertEquals(query, expected[i], outTuple.get(i).asChars());
- }
- }
-}
http://git-wip-us.apache.org/repos/asf/incubator-tajo/blob/135b27a6/tajo-core/tajo-core-backend/src/test/java/org/apache/tajo/engine/function/TestPatternMatchingPredicates.java
----------------------------------------------------------------------
diff --git a/tajo-core/tajo-core-backend/src/test/java/org/apache/tajo/engine/function/TestPatternMatchingPredicates.java b/tajo-core/tajo-core-backend/src/test/java/org/apache/tajo/engine/function/TestPatternMatchingPredicates.java
index 2b43795..3a930d4 100644
--- a/tajo-core/tajo-core-backend/src/test/java/org/apache/tajo/engine/function/TestPatternMatchingPredicates.java
+++ b/tajo-core/tajo-core-backend/src/test/java/org/apache/tajo/engine/function/TestPatternMatchingPredicates.java
@@ -19,6 +19,7 @@
package org.apache.tajo.engine.function;
import org.apache.tajo.catalog.Schema;
+import org.apache.tajo.engine.eval.ExprTestBase;
import org.junit.Test;
import static org.apache.tajo.common.TajoDataTypes.Type.TEXT;
http://git-wip-us.apache.org/repos/asf/incubator-tajo/blob/135b27a6/tajo-core/tajo-core-backend/src/test/java/org/apache/tajo/engine/function/TestStringOperatorsAndFunctions.java
----------------------------------------------------------------------
diff --git a/tajo-core/tajo-core-backend/src/test/java/org/apache/tajo/engine/function/TestStringOperatorsAndFunctions.java b/tajo-core/tajo-core-backend/src/test/java/org/apache/tajo/engine/function/TestStringOperatorsAndFunctions.java
index 9c2a68c..6f080f0 100644
--- a/tajo-core/tajo-core-backend/src/test/java/org/apache/tajo/engine/function/TestStringOperatorsAndFunctions.java
+++ b/tajo-core/tajo-core-backend/src/test/java/org/apache/tajo/engine/function/TestStringOperatorsAndFunctions.java
@@ -20,6 +20,7 @@ package org.apache.tajo.engine.function;
import org.apache.tajo.catalog.Schema;
+import org.apache.tajo.engine.eval.ExprTestBase;
import org.junit.Test;
import static org.apache.tajo.common.TajoDataTypes.Type.FLOAT8;