Merge branch 'master' of https://git-wip-us.apache.org/repos/asf/tajo into window_function
Conflicts:
tajo-core/src/main/java/org/apache/tajo/engine/parser/HiveQLAnalyzer.java
diff --git a/CHANGES b/CHANGES
index c7ea93f..3dd67a9 100644
--- a/CHANGES
+++ b/CHANGES
@@ -68,6 +68,10 @@
TAJO-789: Improve shuffle URI. (jinho)
TAJO-769: A minor improvements for HCatalogStore (Fengdong Yu via hyunsik)
+
+ SUB TASKS:
+
+ TAJO-757: Add parser rule and algebraic expression for window function. (hyunsik)
TAJO-734: Arrange TajoCli output message. (hyoungjunkim via jihoon)
diff --git a/tajo-algebra/src/main/java/org/apache/tajo/algebra/Expr.java b/tajo-algebra/src/main/java/org/apache/tajo/algebra/Expr.java
index daf59b6..26e0831 100644
--- a/tajo-algebra/src/main/java/org/apache/tajo/algebra/Expr.java
+++ b/tajo-algebra/src/main/java/org/apache/tajo/algebra/Expr.java
@@ -26,8 +26,8 @@
import java.lang.reflect.Type;
public abstract class Expr implements JsonSerializable {
+ @Expose @SerializedName("type")
private static final String SERIALIZED_NAME_OF_OP_TYPE = "OpType";
-
@Expose @SerializedName(SERIALIZED_NAME_OF_OP_TYPE)
protected OpType opType;
diff --git a/tajo-algebra/src/main/java/org/apache/tajo/algebra/GeneralSetFunctionExpr.java b/tajo-algebra/src/main/java/org/apache/tajo/algebra/GeneralSetFunctionExpr.java
index fcb48df..3d812e7 100644
--- a/tajo-algebra/src/main/java/org/apache/tajo/algebra/GeneralSetFunctionExpr.java
+++ b/tajo-algebra/src/main/java/org/apache/tajo/algebra/GeneralSetFunctionExpr.java
@@ -42,10 +42,10 @@
*
* @param signature Function name
* @param distinct True if this function is a distinct aggregation function
- * @param param Function parameter
+ * @param params Function parameters
*/
- public GeneralSetFunctionExpr(String signature, boolean distinct, Expr param) {
- this(OpType.GeneralSetFunction, signature, distinct, new Expr [] {param});
+ public GeneralSetFunctionExpr(String signature, boolean distinct, Expr[] params) {
+ this(OpType.GeneralSetFunction, signature, distinct, params);
}
/**
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 0ba087a..bc6e89b 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
@@ -41,6 +41,7 @@
Relation(Relation.class),
ScalarSubQuery(ScalarSubQuery.class),
Explain(Explain.class),
+ Window(Window.class),
// Data definition language
CreateDatabase(CreateDatabase.class),
@@ -93,6 +94,8 @@
Column(ColumnReferenceExpr.class),
Target(NamedExpr.class),
Function(FunctionExpr.class),
+ WindowFunction(WindowFunctionExpr.class),
+ WindowSpec(WindowSpecExpr.class),
Asterisk(QualifiedAsteriskExpr.class),
// Set Functions
diff --git a/tajo-algebra/src/main/java/org/apache/tajo/algebra/Window.java b/tajo-algebra/src/main/java/org/apache/tajo/algebra/Window.java
new file mode 100644
index 0000000..e9cd21c
--- /dev/null
+++ b/tajo-algebra/src/main/java/org/apache/tajo/algebra/Window.java
@@ -0,0 +1,64 @@
+/**
+ * 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 com.google.common.base.Objects;
+import org.apache.tajo.util.TUtil;
+
+public class Window extends UnaryOperator {
+ private WindowDefinition [] definitions;
+
+ public Window(WindowDefinition [] definitions) {
+ super(OpType.Window);
+ this.definitions = definitions;
+ }
+
+ public WindowDefinition [] getWindowDefinitions() {
+ return definitions;
+ }
+
+ @Override
+ public int hashCode() {
+ return Objects.hashCode(definitions);
+ }
+
+ @Override
+ boolean equalsTo(Expr expr) {
+ Window another = (Window) expr;
+ return TUtil.checkEquals(definitions, another.definitions);
+ }
+
+ public static class WindowDefinition {
+ private String windowName;
+ private WindowSpecExpr windowSpec;
+
+ public WindowDefinition(String windowName, WindowSpecExpr spec) {
+ this.windowName = windowName;
+ this.windowSpec = spec;
+ }
+
+ public String getWindowName() {
+ return windowName;
+ }
+
+ public WindowSpecExpr getWindowSpec() {
+ return windowSpec;
+ }
+ }
+}
diff --git a/tajo-algebra/src/main/java/org/apache/tajo/algebra/WindowFunctionExpr.java b/tajo-algebra/src/main/java/org/apache/tajo/algebra/WindowFunctionExpr.java
new file mode 100644
index 0000000..517ec0f
--- /dev/null
+++ b/tajo-algebra/src/main/java/org/apache/tajo/algebra/WindowFunctionExpr.java
@@ -0,0 +1,70 @@
+/**
+ * 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 com.google.common.base.Objects;
+import org.apache.tajo.util.TUtil;
+
+public class WindowFunctionExpr extends Expr {
+ // set function
+ GeneralSetFunctionExpr function;
+
+ // over clause - only one of both is used.
+ private String windowName;
+ private WindowSpecExpr windowSpec;
+
+ public WindowFunctionExpr(GeneralSetFunctionExpr function) {
+ super(OpType.WindowFunction);
+ this.function = function;
+ }
+
+ public boolean hasWindowName() {
+ return windowName != null;
+ }
+
+ public void setWindowName(String windowName) {
+ this.windowName = windowName;
+ }
+
+ public String getWindowName() {
+ return this.windowName;
+ }
+
+ public boolean hasWidowSpec() {
+ return windowSpec != null;
+ }
+
+ public void setWindowSpec(WindowSpecExpr windowSpec) {
+ this.windowSpec = windowSpec;
+ }
+
+ public WindowSpecExpr getWindowSpec() {
+ return this.windowSpec;
+ }
+
+ @Override
+ public int hashCode() {
+ return Objects.hashCode(windowName, windowSpec);
+ }
+
+ @Override
+ boolean equalsTo(Expr expr) {
+ return TUtil.checkEquals(windowName, windowSpec);
+ }
+}
diff --git a/tajo-algebra/src/main/java/org/apache/tajo/algebra/WindowSpecExpr.java b/tajo-algebra/src/main/java/org/apache/tajo/algebra/WindowSpecExpr.java
new file mode 100644
index 0000000..37c2ff1
--- /dev/null
+++ b/tajo-algebra/src/main/java/org/apache/tajo/algebra/WindowSpecExpr.java
@@ -0,0 +1,181 @@
+/**
+ * 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 com.google.common.base.Objects;
+import org.apache.tajo.util.TUtil;
+
+public class WindowSpecExpr extends Expr {
+ private String windowName;
+ private Expr [] partitionKeys; // OVER (PARTITION BY ?,...,?)
+ private Sort.SortSpec [] sortSpecs; // OVER (... ORDER BY ?,...,?)
+ private WindowFrame windowFrame;
+
+ public WindowSpecExpr() {
+ super(OpType.WindowSpec);
+ }
+
+ public boolean hasWindowName() {
+ return windowName != null;
+ }
+
+ public void setWindowName(String windowName) {
+ this.windowName = windowName;
+ }
+
+ public String getWindowName() {
+ return this.windowName;
+ }
+
+ public boolean hasPartitionBy() {
+ return this.partitionKeys != null;
+ }
+
+ public void setPartitionKeys(Expr[] partitionKeys) {
+ this.partitionKeys = partitionKeys;
+ }
+
+ public Expr [] getPartitionKeys() {
+ return this.partitionKeys;
+ }
+
+ public boolean hasOrderBy() {
+ return this.sortSpecs != null;
+ }
+
+ public void setSortSpecs(Sort.SortSpec [] sortSpecs) {
+ this.sortSpecs = sortSpecs;
+ }
+
+ public Sort.SortSpec [] getSortSpecs() {
+ return this.sortSpecs;
+ }
+
+ public boolean hasWindowFrame() {
+ return windowFrame != null;
+ }
+
+ public void setWindowFrame(WindowFrame frame) {
+ this.windowFrame = frame;
+ }
+
+ public WindowFrame getWindowFrame() {
+ return windowFrame;
+ }
+
+ @Override
+ public int hashCode() {
+ return Objects.hashCode(windowName, partitionKeys, sortSpecs);
+ }
+
+ @Override
+ boolean equalsTo(Expr expr) {
+ WindowSpecExpr another = (WindowSpecExpr) expr;
+ return TUtil.checkEquals(windowName, another.windowName) &&
+ TUtil.checkEquals(partitionKeys, another.partitionKeys) &&
+ TUtil.checkEquals(sortSpecs, another.sortSpecs);
+ }
+
+ public static enum WindowFrameUnit {
+ ROW,
+ RANGE
+ }
+
+ public static enum WindowFrameStartBoundType {
+ UNBOUNDED_PRECEDING,
+ CURRENT_ROW,
+ PRECEDING
+ }
+
+ public static enum WindowFrameEndBoundType {
+ UNBOUNDED_FOLLOWING,
+ CURRENT_ROW,
+ FOLLOWING
+ }
+
+ public static class WindowFrame {
+ WindowFrameUnit unit;
+ private WindowStartBound startBound;
+ private WindowEndBound endBound;
+
+ public WindowFrame(WindowFrameUnit unit, WindowStartBound startBound) {
+ this.unit = unit;
+ this.startBound = startBound;
+ }
+
+ public WindowFrame(WindowFrameUnit unit, WindowStartBound startBound, WindowEndBound endBound) {
+ this(unit, startBound);
+ this.endBound = endBound;
+ }
+
+ public WindowStartBound getStartBound() {
+ return startBound;
+ }
+
+ public boolean hasEndBound() {
+ return endBound != null;
+ }
+
+ public WindowEndBound getEndBound() {
+ return endBound;
+ }
+ }
+
+ public static class WindowStartBound {
+ private WindowFrameStartBoundType boundType;
+ private Expr number;
+
+ public WindowStartBound(WindowFrameStartBoundType type) {
+ this.boundType = type;
+ }
+
+ public WindowFrameStartBoundType getBoundType() {
+ return boundType;
+ }
+
+ public void setNumber(Expr number) {
+ this.number = number;
+ }
+
+ public Expr getNumber() {
+ return number;
+ }
+ }
+
+ public static class WindowEndBound {
+ private WindowFrameEndBoundType boundType;
+ private Expr number;
+
+ public WindowEndBound(WindowFrameEndBoundType type) {
+ this.boundType = type;
+ }
+
+ public WindowFrameEndBoundType getBoundType() {
+ return boundType;
+ }
+
+ public Expr setNumber(Expr number) {
+ return number;
+ }
+
+ public Expr getNumber() {
+ return number;
+ }
+ }
+}
diff --git a/tajo-catalog/tajo-catalog-common/src/main/java/org/apache/tajo/catalog/CatalogUtil.java b/tajo-catalog/tajo-catalog-common/src/main/java/org/apache/tajo/catalog/CatalogUtil.java
index 4f86028..ae00084 100644
--- a/tajo-catalog/tajo-catalog-common/src/main/java/org/apache/tajo/catalog/CatalogUtil.java
+++ b/tajo-catalog/tajo-catalog-common/src/main/java/org/apache/tajo/catalog/CatalogUtil.java
@@ -729,8 +729,9 @@
"RIGHT",
"SELECT", "SOME", "SYMMETRIC",
"TABLE", "THEN", "TRAILING", "TRUE",
+ "OVER",
"UNION", "UNIQUE", "USING",
- "WHEN", "WHERE", "WITH"
+ "WHEN", "WHERE", "WINDOW", "WITH"
};
static {
diff --git a/tajo-core/src/main/antlr4/org/apache/tajo/engine/parser/SQLLexer.g4 b/tajo-core/src/main/antlr4/org/apache/tajo/engine/parser/SQLLexer.g4
index da5f355..4bdbc3d 100644
--- a/tajo-core/src/main/antlr4/org/apache/tajo/engine/parser/SQLLexer.g4
+++ b/tajo-core/src/main/antlr4/org/apache/tajo/engine/parser/SQLLexer.g4
@@ -167,9 +167,10 @@
NULL : N U L L;
ON : O N;
-OUTER : O U T E R;
OR : O R;
ORDER : O R D E R;
+OUTER : O U T E R;
+OVER : O V E R;
RIGHT : R I G H T;
SELECT : S E L E C T;
SOME : S O M E;
@@ -187,6 +188,7 @@
WHEN : W H E N;
WHERE : W H E R E;
WITH : W I T H;
+WINDOW : W I N D O W;
/*
===============================================================================
@@ -207,17 +209,21 @@
COLUMN : C O L U M N;
COUNT : C O U N T;
CUBE : C U B E;
+CUME_DIST : C U M E UNDERLINE D I S T;
+CURRENT : C U R R E N T;
DAY : D A Y;
DATABASE : D A T A B A S E;
DEC : D E C;
DECADE : D E C A D E;
+DENSE_RANK : D E N S E UNDERLINE R A N K;
DOW : D O W;
DOY : D O Y;
DROP : D R O P;
EPOCH : E P O C H;
EVERY : E V E R Y;
+EXCLUDE : E X C L U D E;
EXISTS : E X I S T S;
EXPLAIN : E X P L A I N;
EXTERNAL : E X T E R N A L;
@@ -225,6 +231,7 @@
FILTER : F I L T E R;
FIRST : F I R S T;
+FOLLOWING : F O L L O W I N G;
FORMAT : F O R M A T;
FUSION : F U S I O N;
@@ -256,20 +263,28 @@
NATIONAL : N A T I O N A L;
NULLIF : N U L L I F;
+NO : N O;
OVERWRITE : O V E R W R I T E;
+OTHERS: O T H E R S;
PARTITION : P A R T I T I O N;
PARTITIONS : P A R T I T I O N S;
+PERCENT_RANK : P E R C E N T UNDERLINE R A N K;
+PRECEDING : P R E C E D I N G;
PRECISION : P R E C I S I O N;
PURGE : P U R G E;
QUARTER : Q U A R T E R;
RANGE : R A N G E;
+RANK : R A N K;
REGEXP : R E G E X P;
RLIKE : R L I K E;
ROLLUP : R O L L U P;
+ROW : R O W;
+ROWS : R O W S;
+ROW_NUMBER : R O W UNDERLINE N U M B E R;
RENAME : R E N A M E;
SECOND : S E C O N D;
@@ -282,6 +297,7 @@
TABLESPACE : T A B L E S P A C E;
THAN : T H A N;
+TIES : T I E S;
TIMEZONE: T I M E Z O N E;
TIMEZONE_HOUR: T I M E Z O N E UNDERLINE H O U R;
TIMEZONE_MINUTE: T I M E Z O N E UNDERLINE M I N U T E;
@@ -289,6 +305,7 @@
TO : T O;
TRUNCATE : T R U N C A T E;
+UNBOUNDED : U N B O U N D E D;
UNKNOWN : U N K N O W N;
VALUES : V A L U E S;
diff --git a/tajo-core/src/main/antlr4/org/apache/tajo/engine/parser/SQLParser.g4 b/tajo-core/src/main/antlr4/org/apache/tajo/engine/parser/SQLParser.g4
index c601d37..beba248 100644
--- a/tajo-core/src/main/antlr4/org/apache/tajo/engine/parser/SQLParser.g4
+++ b/tajo-core/src/main/antlr4/org/apache/tajo/engine/parser/SQLParser.g4
@@ -228,20 +228,25 @@
| COLUMN
| COUNT
| CUBE
+ | CUME_DIST
+ | CURRENT
| DAY
| DEC
| DECADE
+ | DENSE_RANK
| DOW
| DOY
| DROP
| EPOCH
| EVERY
| EXISTS
+ | EXCLUDE
| EXPLAIN
| EXTERNAL
| EXTRACT
| FILTER
| FIRST
+ | FOLLOWING
| FORMAT
| FUSION
| GROUPING
@@ -264,18 +269,26 @@
| MINUTE
| MONTH
| NATIONAL
+ | NO
| NULLIF
| OVERWRITE
+ | OTHERS
| PARTITION
| PARTITIONS
+ | PERCENT_RANK
+ | PRECEDING
| PRECISION
| PURGE
| QUARTER
| RANGE
+ | RANK
| REGEXP
| RENAME
| RLIKE
| ROLLUP
+ | ROW
+ | ROWS
+ | ROW_NUMBER
| SECOND
| SET
| SIMILAR
@@ -285,11 +298,13 @@
| SUM
| TABLESPACE
| THAN
+ | TIES
| TIMEZONE
| TIMEZONE_HOUR
| TIMEZONE_MINUTE
| TRIM
| TO
+ | UNBOUNDED
| UNKNOWN
| VALUES
| VAR_POP
@@ -513,6 +528,7 @@
: unsigned_value_specification
| column_reference
| set_function_specification
+ | window_function
| scalar_subquery
| case_expression
| cast_specification
@@ -586,6 +602,32 @@
/*
===============================================================================
+ 6.10 window function
+===============================================================================
+*/
+
+window_function
+ : window_function_type OVER window_name_or_specification
+ ;
+
+window_function_type
+ : rank_function_type LEFT_PAREN RIGHT_PAREN
+ | ROW_NUMBER LEFT_PAREN RIGHT_PAREN
+ | aggregate_function
+ ;
+
+rank_function_type
+ : RANK | DENSE_RANK | PERCENT_RANK | CUME_DIST
+ ;
+
+
+window_name_or_specification
+ : window_name
+ | window_specification
+ ;
+
+/*
+===============================================================================
6.11 <case expression>
===============================================================================
*/
@@ -906,6 +948,7 @@
groupby_clause?
having_clause?
orderby_clause?
+ window_clause?
limit_clause?
;
@@ -1070,6 +1113,84 @@
: row_value_predicand (COMMA row_value_predicand)*
;
+
+ /*
+ ===============================================================================
+ 7.11 <window clause> (p331)
+ ===============================================================================
+ */
+
+window_clause
+ : WINDOW window_definition_list;
+
+window_definition_list
+ : window_definition (COMMA window_definition)*
+ ;
+
+window_definition
+ : window_name AS window_specification
+ ;
+
+window_name
+ : identifier
+ ;
+
+window_specification
+ : LEFT_PAREN window_specification_details RIGHT_PAREN
+ ;
+
+window_specification_details
+ : (existing_window_name)? (window_partition_clause)? (window_order_clause)? (window_frame_clause)?
+ ;
+
+existing_window_name
+ : window_name
+ ;
+
+window_partition_clause
+ : PARTITION BY row_value_predicand_list
+ ;
+
+window_order_clause
+ : orderby_clause
+ ;
+
+window_frame_clause
+ : window_frame_units window_frame_extent (window_frame_exclusion)?
+ ;
+
+window_frame_units
+ : ROWS | RANGE
+ ;
+
+window_frame_extent
+ : window_frame_start_bound
+ | window_frame_between
+ ;
+
+window_frame_start_bound
+ : UNBOUNDED PRECEDING
+ | unsigned_value_specification PRECEDING // window_frame_preceding
+ | CURRENT ROW
+ ;
+
+window_frame_between
+ : BETWEEN bound1=window_frame_start_bound AND bound2=window_frame_end_bound
+ ;
+
+window_frame_end_bound
+ : UNBOUNDED FOLLOWING
+ | unsigned_value_specification FOLLOWING // window_frame_following FOLLOWING
+ | CURRENT ROW
+ ;
+
+window_frame_exclusion
+ : EXCLUDE CURRENT ROW
+ | EXCLUDE GROUP
+ | EXCLUDE TIES
+ | EXCLUDE NO OTHERS
+ ;
+
/*
===============================================================================
7.13 <query expression>
diff --git a/tajo-core/src/main/java/org/apache/tajo/engine/parser/SQLAnalyzer.java b/tajo-core/src/main/java/org/apache/tajo/engine/parser/SQLAnalyzer.java
index 01568af..59a9b46 100644
--- a/tajo-core/src/main/java/org/apache/tajo/engine/parser/SQLAnalyzer.java
+++ b/tajo-core/src/main/java/org/apache/tajo/engine/parser/SQLAnalyzer.java
@@ -36,6 +36,8 @@
import static org.apache.tajo.algebra.Aggregation.GroupElement;
import static org.apache.tajo.algebra.CreateTable.*;
+import static org.apache.tajo.algebra.WindowSpecExpr.WindowFrameEndBoundType;
+import static org.apache.tajo.algebra.WindowSpecExpr.WindowFrameStartBoundType;
import static org.apache.tajo.common.TajoDataTypes.Type;
import static org.apache.tajo.engine.parser.SQLParser.*;
@@ -192,6 +194,12 @@
current = sort;
}
+ if (checkIfExist(ctx.table_expression().window_clause())) {
+ Window window = visitWindow_clause(ctx.table_expression().window_clause());
+ window.setChild(current);
+ current = window;
+ }
+
if (ctx.table_expression().limit_clause() != null) {
Limit limit = visitLimit_clause(ctx.table_expression().limit_clause());
limit.setChild(current);
@@ -312,14 +320,146 @@
return clause;
}
+ @Override public WindowFunctionExpr visitWindow_function(@NotNull SQLParser.Window_functionContext context) {
+ WindowFunctionExpr windowFunction = null;
+
+ Window_function_typeContext functionType = context.window_function_type();
+ GeneralSetFunctionExpr functionBody;
+ if (checkIfExist(functionType.rank_function_type())) {
+ Rank_function_typeContext rankFunction = functionType.rank_function_type();
+ if (checkIfExist(rankFunction.RANK())) {
+ functionBody = new GeneralSetFunctionExpr("rank", false, new Expr[] {});
+ } else if (checkIfExist(rankFunction.DENSE_RANK())) {
+ functionBody = new GeneralSetFunctionExpr("dense_rank", false, new Expr[] {});
+ } else if (checkIfExist(rankFunction.PERCENT_RANK())) {
+ functionBody = new GeneralSetFunctionExpr("percent_rank", false, new Expr[] {});
+ } else {
+ functionBody = new GeneralSetFunctionExpr("cume_dist", false, new Expr[] {});
+ }
+ } else if (checkIfExist(functionType.ROW_NUMBER())) {
+ functionBody = new GeneralSetFunctionExpr("row_number", false, new Expr[] {});
+ } else {
+ functionBody = visitAggregate_function(functionType.aggregate_function());
+ }
+ windowFunction = new WindowFunctionExpr(functionBody);
+
+ Window_name_or_specificationContext windowNameOrSpec = context.window_name_or_specification();
+ if (checkIfExist(windowNameOrSpec.window_name())) {
+ windowFunction.setWindowName(windowNameOrSpec.window_name().getText());
+ } else {
+ windowFunction.setWindowSpec(visitWindow_specification(windowNameOrSpec.window_specification()));
+ }
+
+ return windowFunction;
+ }
+
@Override
- public Sort visitOrderby_clause(SQLParser.Orderby_clauseContext ctx) {
- int size = ctx.sort_specifier_list().sort_specifier().size();
+ public Window visitWindow_clause(@NotNull SQLParser.Window_clauseContext ctx) {
+ Window.WindowDefinition [] definitions =
+ new Window.WindowDefinition[ctx.window_definition_list().window_definition().size()];
+ for (int i = 0; i < definitions.length; i++) {
+ Window_definitionContext windowDefinitionContext = ctx.window_definition_list().window_definition(i);
+ String windowName = windowDefinitionContext.window_name().identifier().getText();
+ WindowSpecExpr windowSpec = visitWindow_specification(windowDefinitionContext.window_specification());
+ definitions[i] = new Window.WindowDefinition(windowName, windowSpec);
+ }
+ return new Window(definitions);
+ }
+
+ @Override public WindowSpecExpr visitWindow_specification(@NotNull SQLParser.Window_specificationContext ctx) {
+ WindowSpecExpr windowSpec = new WindowSpecExpr();
+ if (checkIfExist(ctx.window_specification_details())) {
+ Window_specification_detailsContext windowSpecDetail = ctx.window_specification_details();
+
+ if (checkIfExist(windowSpecDetail.existing_window_name())) {
+ windowSpec.setWindowName(windowSpecDetail.existing_window_name().getText());
+ }
+
+ if (checkIfExist(windowSpecDetail.window_partition_clause())) {
+ windowSpec.setPartitionKeys(
+ buildRowValuePredicands(windowSpecDetail.window_partition_clause().row_value_predicand_list()));
+ }
+
+ if (checkIfExist(windowSpecDetail.window_order_clause())) {
+ windowSpec.setSortSpecs(
+ buildSortSpecs(windowSpecDetail.window_order_clause().orderby_clause().sort_specifier_list()));
+ }
+
+ if (checkIfExist(windowSpecDetail.window_frame_clause())) {
+ Window_frame_clauseContext frameContext = windowSpecDetail.window_frame_clause();
+
+ WindowSpecExpr.WindowFrameUnit unit;
+ // frame unit - there are only two cases: RANGE and ROW
+ if (checkIfExist(frameContext.window_frame_units().RANGE())) {
+ unit = WindowSpecExpr.WindowFrameUnit.RANGE;
+ } else {
+ unit = WindowSpecExpr.WindowFrameUnit.ROW;
+ }
+
+ WindowSpecExpr.WindowFrame windowFrame;
+
+ if (checkIfExist(frameContext.window_frame_extent().window_frame_between())) { // when 'between' is given
+ Window_frame_betweenContext between = frameContext.window_frame_extent().window_frame_between();
+ WindowSpecExpr.WindowStartBound startBound = buildWindowStartBound(between.window_frame_start_bound());
+ WindowSpecExpr.WindowEndBound endBound = buildWindowEndBound(between.window_frame_end_bound());
+
+ windowFrame = new WindowSpecExpr.WindowFrame(unit, startBound, endBound);
+ } else { // if there is only start bound
+ WindowSpecExpr.WindowStartBound startBound =
+ buildWindowStartBound(frameContext.window_frame_extent().window_frame_start_bound());
+ windowFrame = new WindowSpecExpr.WindowFrame(unit, startBound);
+ }
+
+ windowSpec.setWindowFrame(windowFrame);
+ }
+ }
+ return windowSpec;
+ }
+
+ public WindowSpecExpr.WindowStartBound buildWindowStartBound(Window_frame_start_boundContext context) {
+ WindowFrameStartBoundType boundType = null;
+ if (checkIfExist(context.UNBOUNDED())) {
+ boundType = WindowFrameStartBoundType.UNBOUNDED_PRECEDING;
+ } else if (checkIfExist(context.unsigned_value_specification())) {
+ boundType = WindowFrameStartBoundType.PRECEDING;
+ } else {
+ boundType = WindowFrameStartBoundType.CURRENT_ROW;
+ }
+
+ WindowSpecExpr.WindowStartBound bound = new WindowSpecExpr.WindowStartBound(boundType);
+ if (boundType == WindowFrameStartBoundType.PRECEDING) {
+ bound.setNumber(visitUnsigned_value_specification(context.unsigned_value_specification()));
+ }
+
+ return bound;
+ }
+
+ public WindowSpecExpr.WindowEndBound buildWindowEndBound(Window_frame_end_boundContext context) {
+ WindowFrameEndBoundType boundType;
+ if (checkIfExist(context.UNBOUNDED())) {
+ boundType = WindowFrameEndBoundType.UNBOUNDED_FOLLOWING;
+ } else if (checkIfExist(context.unsigned_value_specification())) {
+ boundType = WindowFrameEndBoundType.FOLLOWING;
+ } else {
+ boundType = WindowFrameEndBoundType.CURRENT_ROW;
+ }
+
+ WindowSpecExpr.WindowEndBound endBound = new WindowSpecExpr.WindowEndBound(boundType);
+ if (boundType == WindowFrameEndBoundType.FOLLOWING) {
+ endBound.setNumber(visitUnsigned_value_specification(context.unsigned_value_specification()));
+ }
+
+ return endBound;
+ }
+
+ public Sort.SortSpec[] buildSortSpecs(Sort_specifier_listContext context) {
+ int size = context.sort_specifier().size();
+
Sort.SortSpec specs[] = new Sort.SortSpec[size];
for (int i = 0; i < size; i++) {
- SQLParser.Sort_specifierContext specContext = ctx.sort_specifier_list().sort_specifier(i);
- Expr column = visitRow_value_predicand(specContext.key);
- specs[i] = new Sort.SortSpec(column);
+ SQLParser.Sort_specifierContext specContext = context.sort_specifier(i);
+ Expr sortKeyExpr = visitRow_value_predicand(specContext.key);
+ specs[i] = new Sort.SortSpec(sortKeyExpr);
if (specContext.order_specification() != null) {
if (specContext.order.DESC() != null) {
specs[i].setDescending();
@@ -333,7 +473,12 @@
}
}
- return new Sort(specs);
+ return specs;
+ }
+
+ @Override
+ public Sort visitOrderby_clause(SQLParser.Orderby_clauseContext ctx) {
+ return new Sort(buildSortSpecs(ctx.sort_specifier_list()));
}
@Override
@@ -388,7 +533,7 @@
join_condition().search_condition());
join.setQual(searchCondition);
} else if (ctx.join_specification().named_columns_join() != null) {
- ColumnReferenceExpr[] columns = getColumnReferences(ctx.join_specification().
+ ColumnReferenceExpr[] columns = buildColumnReferenceList(ctx.join_specification().
named_columns_join().column_reference_list());
join.setJoinColumns(columns);
}
@@ -413,12 +558,12 @@
rowValuePredicands.add(visitRow_value_predicand(ctx.row_value_predicand()));
}
if (ctx.row_value_predicand_list() != null) {
- Collections.addAll(rowValuePredicands, getRowValuePredicands(ctx.row_value_predicand_list()));
+ Collections.addAll(rowValuePredicands, buildRowValuePredicands(ctx.row_value_predicand_list()));
}
return rowValuePredicands.toArray(new Expr[rowValuePredicands.size()]);
}
- private Expr[] getRowValuePredicands(Row_value_predicand_listContext ctx) {
+ private Expr[] buildRowValuePredicands(Row_value_predicand_listContext ctx) {
Expr[] rowValuePredicands = new Expr[ctx.row_value_predicand().size()];
for (int i = 0; i < rowValuePredicands.length; i++) {
rowValuePredicands[i] = visitRow_value_predicand(ctx.row_value_predicand(i));
@@ -426,7 +571,7 @@
return rowValuePredicands;
}
- private ColumnReferenceExpr[] getColumnReferences(Column_reference_listContext ctx) {
+ private ColumnReferenceExpr[] buildColumnReferenceList(Column_reference_listContext ctx) {
ColumnReferenceExpr[] columnRefs = new ColumnReferenceExpr[ctx.column_reference().size()];
for (int i = 0; i < columnRefs.length; i++) {
columnRefs[i] = visitColumn_reference(ctx.column_reference(i));
@@ -853,7 +998,7 @@
}
@Override
- public FunctionExpr visitAggregate_function(SQLParser.Aggregate_functionContext ctx) {
+ public GeneralSetFunctionExpr visitAggregate_function(SQLParser.Aggregate_functionContext ctx) {
if (ctx.COUNT() != null && ctx.MULTIPLY() != null) {
return new CountRowsFunctionExpr();
} else {
@@ -862,12 +1007,12 @@
}
@Override
- public FunctionExpr visitGeneral_set_function(SQLParser.General_set_functionContext ctx) {
+ public GeneralSetFunctionExpr visitGeneral_set_function(SQLParser.General_set_functionContext ctx) {
String signature = ctx.set_function_type().getText();
boolean distinct = checkIfExist(ctx.set_qualifier()) && checkIfExist(ctx.set_qualifier().DISTINCT());
Expr param = visitValue_expression(ctx.value_expression());
- return new GeneralSetFunctionExpr(signature, distinct, param);
+ return new GeneralSetFunctionExpr(signature, distinct, new Expr [] {param});
}
@Override
@@ -1094,14 +1239,14 @@
visitValue_expression(rangeValue.value_expression())));
}
}
- return new CreateTable.RangePartition(getColumnReferences(ctx.range_partitions().column_reference_list()),
+ return new CreateTable.RangePartition(buildColumnReferenceList(ctx.range_partitions().column_reference_list()),
specifiers);
} else if (checkIfExist(ctx.hash_partitions())) { // For Hash Partition
Hash_partitionsContext hashPartitions = ctx.hash_partitions();
if (checkIfExist(hashPartitions.hash_partitions_by_quantity())) { // PARTITIONS (num)
- return new HashPartition(getColumnReferences(hashPartitions.column_reference_list()),
+ return new HashPartition(buildColumnReferenceList(hashPartitions.column_reference_list()),
visitNumeric_value_expression(hashPartitions.hash_partitions_by_quantity().quantity));
} else { // ( PARTITION part_name , ...)
@@ -1110,7 +1255,7 @@
hashPartitions.individual_hash_partitions().individual_hash_partition()) {
specifiers.add(new CreateTable.PartitionSpecifier(partition.partition_name().getText()));
}
- return new HashPartition(getColumnReferences(hashPartitions.column_reference_list()), specifiers);
+ return new HashPartition(buildColumnReferenceList(hashPartitions.column_reference_list()), specifiers);
}
} else if (checkIfExist(ctx.list_partitions())) { // For List Partition
@@ -1127,7 +1272,7 @@
specifiers.add(new ListPartitionSpecifier(listValuePartition.partition_name().getText(),
new ValueListExpr(exprs)));
}
- return new ListPartition(getColumnReferences(ctx.list_partitions().column_reference_list()), specifiers);
+ return new ListPartition(buildColumnReferenceList(ctx.list_partitions().column_reference_list()), specifiers);
} else if (checkIfExist(ctx.column_partitions())) { // For Column Partition (Hive Style)
return new CreateTable.ColumnPartition(getDefinitions(ctx.column_partitions().table_elements()), true);
diff --git a/tajo-core/src/test/java/org/apache/tajo/engine/parser/TestSQLAnalyzer.java b/tajo-core/src/test/java/org/apache/tajo/engine/parser/TestSQLAnalyzer.java
index 5423813..1dc54f6 100644
--- a/tajo-core/src/test/java/org/apache/tajo/engine/parser/TestSQLAnalyzer.java
+++ b/tajo-core/src/test/java/org/apache/tajo/engine/parser/TestSQLAnalyzer.java
@@ -52,6 +52,14 @@
return visitor.visitSql(context);
}
+ public void assertParseResult(String sqlFileName, String resultFileName) throws IOException {
+ String sql = FileUtil.readTextFileFromResource("queries/TestSQLAnalyzer/" + sqlFileName);
+ String result = FileUtil.readTextFileFromResource("results/TestSQLAnalyzer/" + resultFileName);
+
+ Expr expr = parseQuery(sql);
+ assertEquals(expr.toJson().trim(), result.trim());
+ }
+
@Test
public void testSelect1() throws IOException {
@@ -479,4 +487,49 @@
parseExpr(exprs[i]);
}
}
+
+ @Test
+ public void windowFunction1() throws IOException {
+ assertParseResult("window1.sql", "window1.result");
+ }
+
+ @Test
+ public void windowFunction2() throws IOException {
+ assertParseResult("window2.sql", "window2.result");
+ }
+
+ @Test
+ public void windowFunction3() throws IOException {
+ assertParseResult("window3.sql", "window3.result");
+ }
+
+ @Test
+ public void windowFunction4() throws IOException {
+ assertParseResult("window4.sql", "window4.result");
+ }
+
+ @Test
+ public void windowFunction5() throws IOException {
+ assertParseResult("window5.sql", "window5.result");
+ }
+
+ @Test
+ public void windowFunction6() throws IOException {
+ assertParseResult("window6.sql", "window6.result");
+ }
+
+ @Test
+ public void windowFunction7() throws IOException {
+ assertParseResult("window7.sql", "window7.result");
+ }
+
+ @Test
+ public void windowFunction8() throws IOException {
+ assertParseResult("window8.sql", "window8.result");
+ }
+
+ @Test
+ public void windowFunction9() throws IOException {
+ assertParseResult("window9.sql", "window9.result");
+ }
}
diff --git a/tajo-core/tajo-core-backend/src/test/resources/queries/TestSQLAnalyzer/window1.sql b/tajo-core/tajo-core-backend/src/test/resources/queries/TestSQLAnalyzer/window1.sql
new file mode 100644
index 0000000..52156b8
--- /dev/null
+++ b/tajo-core/tajo-core-backend/src/test/resources/queries/TestSQLAnalyzer/window1.sql
@@ -0,0 +1,5 @@
+ SELECT
+ dt,
+ sum(xy) over()
+FROM
+ sum_example;
\ No newline at end of file
diff --git a/tajo-core/tajo-core-backend/src/test/resources/queries/TestSQLAnalyzer/window2.sql b/tajo-core/tajo-core-backend/src/test/resources/queries/TestSQLAnalyzer/window2.sql
new file mode 100644
index 0000000..60f1fbf
--- /dev/null
+++ b/tajo-core/tajo-core-backend/src/test/resources/queries/TestSQLAnalyzer/window2.sql
@@ -0,0 +1,5 @@
+ SELECT
+ dt,
+ sum(xy) over(partition by dt)
+FROM
+ sum_example;
\ No newline at end of file
diff --git a/tajo-core/tajo-core-backend/src/test/resources/queries/TestSQLAnalyzer/window3.sql b/tajo-core/tajo-core-backend/src/test/resources/queries/TestSQLAnalyzer/window3.sql
new file mode 100644
index 0000000..01dd542
--- /dev/null
+++ b/tajo-core/tajo-core-backend/src/test/resources/queries/TestSQLAnalyzer/window3.sql
@@ -0,0 +1,5 @@
+ SELECT
+ dt,
+ sum(xy) over(partition by round(dt))
+FROM
+ sum_example;
\ No newline at end of file
diff --git a/tajo-core/tajo-core-backend/src/test/resources/queries/TestSQLAnalyzer/window4.sql b/tajo-core/tajo-core-backend/src/test/resources/queries/TestSQLAnalyzer/window4.sql
new file mode 100644
index 0000000..629d5e4
--- /dev/null
+++ b/tajo-core/tajo-core-backend/src/test/resources/queries/TestSQLAnalyzer/window4.sql
@@ -0,0 +1,5 @@
+ SELECT
+ dt,
+ sum(xy) over(order by dt)
+FROM
+ sum_example;
\ No newline at end of file
diff --git a/tajo-core/tajo-core-backend/src/test/resources/queries/TestSQLAnalyzer/window5.sql b/tajo-core/tajo-core-backend/src/test/resources/queries/TestSQLAnalyzer/window5.sql
new file mode 100644
index 0000000..6338817
--- /dev/null
+++ b/tajo-core/tajo-core-backend/src/test/resources/queries/TestSQLAnalyzer/window5.sql
@@ -0,0 +1,6 @@
+ SELECT
+ dt,
+ dt2,
+ sum(xy) over(partition by round(dt),dt2 order by ceil(dt) asc null last)
+FROM
+ sum_example;
\ No newline at end of file
diff --git a/tajo-core/tajo-core-backend/src/test/resources/queries/TestSQLAnalyzer/window6.sql b/tajo-core/tajo-core-backend/src/test/resources/queries/TestSQLAnalyzer/window6.sql
new file mode 100644
index 0000000..1f1870e
--- /dev/null
+++ b/tajo-core/tajo-core-backend/src/test/resources/queries/TestSQLAnalyzer/window6.sql
@@ -0,0 +1,6 @@
+ SELECT
+ dt,
+ dt2,
+ sum(xy) over(partition by round(dt),dt2 order by ceil(dt) asc null last ROWS UNBOUNDED PRECEDING)
+FROM
+ sum_example;
\ No newline at end of file
diff --git a/tajo-core/tajo-core-backend/src/test/resources/queries/TestSQLAnalyzer/window7.sql b/tajo-core/tajo-core-backend/src/test/resources/queries/TestSQLAnalyzer/window7.sql
new file mode 100644
index 0000000..6daa806
--- /dev/null
+++ b/tajo-core/tajo-core-backend/src/test/resources/queries/TestSQLAnalyzer/window7.sql
@@ -0,0 +1,6 @@
+ SELECT
+ dt,
+ dt2,
+ row_number() over(partition by round(dt),dt2 order by ceil(dt) asc null last ROWS BETWEEN UNBOUNDED PRECEDING AND UNBOUNDED FOLLOWING)
+FROM
+ sum_example;
\ No newline at end of file
diff --git a/tajo-core/tajo-core-backend/src/test/resources/queries/TestSQLAnalyzer/window8.sql b/tajo-core/tajo-core-backend/src/test/resources/queries/TestSQLAnalyzer/window8.sql
new file mode 100644
index 0000000..6f70690
--- /dev/null
+++ b/tajo-core/tajo-core-backend/src/test/resources/queries/TestSQLAnalyzer/window8.sql
@@ -0,0 +1,6 @@
+ SELECT
+ dt,
+ dt2,
+ row_number() over(partition by round(dt),dt2 order by ceil(dt) asc null last ROWS BETWEEN 1 PRECEDING AND CURRENT ROW)
+FROM
+ sum_example;
\ No newline at end of file
diff --git a/tajo-core/tajo-core-backend/src/test/resources/queries/TestSQLAnalyzer/window9.sql b/tajo-core/tajo-core-backend/src/test/resources/queries/TestSQLAnalyzer/window9.sql
new file mode 100644
index 0000000..b289ebf
--- /dev/null
+++ b/tajo-core/tajo-core-backend/src/test/resources/queries/TestSQLAnalyzer/window9.sql
@@ -0,0 +1,9 @@
+ SELECT
+ dt,
+ dt2,
+ row_number() over(window1),
+ rank() over(window1)
+FROM
+ sum_example
+WINDOW
+ window1 AS (partition by round(dt),dt2 order by ceil(dt) asc null last ROWS BETWEEN 1 PRECEDING AND CURRENT ROW);
\ No newline at end of file
diff --git a/tajo-core/tajo-core-backend/src/test/resources/results/TestSQLAnalyzer/window1.result b/tajo-core/tajo-core-backend/src/test/resources/results/TestSQLAnalyzer/window1.result
new file mode 100644
index 0000000..31ed149
--- /dev/null
+++ b/tajo-core/tajo-core-backend/src/test/resources/results/TestSQLAnalyzer/window1.result
@@ -0,0 +1,42 @@
+{
+ "distinct": false,
+ "targets": [
+ {
+ "child": {
+ "name": "dt",
+ "type": "Column"
+ },
+ "type": "Target"
+ },
+ {
+ "child": {
+ "function": {
+ "distinct": false,
+ "signature": "sum",
+ "params": [
+ {
+ "name": "xy",
+ "type": "Column"
+ }
+ ],
+ "type": "GeneralSetFunction"
+ },
+ "windowSpec": {
+ "type": "WindowSpec"
+ },
+ "type": "WindowFunction"
+ },
+ "type": "Target"
+ }
+ ],
+ "child": {
+ "relations": [
+ {
+ "tableName": "sum_example",
+ "type": "Relation"
+ }
+ ],
+ "type": "RelationList"
+ },
+ "type": "Projection"
+}
\ No newline at end of file
diff --git a/tajo-core/tajo-core-backend/src/test/resources/results/TestSQLAnalyzer/window2.result b/tajo-core/tajo-core-backend/src/test/resources/results/TestSQLAnalyzer/window2.result
new file mode 100644
index 0000000..378232c
--- /dev/null
+++ b/tajo-core/tajo-core-backend/src/test/resources/results/TestSQLAnalyzer/window2.result
@@ -0,0 +1,48 @@
+{
+ "distinct": false,
+ "targets": [
+ {
+ "child": {
+ "name": "dt",
+ "type": "Column"
+ },
+ "type": "Target"
+ },
+ {
+ "child": {
+ "function": {
+ "distinct": false,
+ "signature": "sum",
+ "params": [
+ {
+ "name": "xy",
+ "type": "Column"
+ }
+ ],
+ "type": "GeneralSetFunction"
+ },
+ "windowSpec": {
+ "partitionKeys": [
+ {
+ "name": "dt",
+ "type": "Column"
+ }
+ ],
+ "type": "WindowSpec"
+ },
+ "type": "WindowFunction"
+ },
+ "type": "Target"
+ }
+ ],
+ "child": {
+ "relations": [
+ {
+ "tableName": "sum_example",
+ "type": "Relation"
+ }
+ ],
+ "type": "RelationList"
+ },
+ "type": "Projection"
+}
\ No newline at end of file
diff --git a/tajo-core/tajo-core-backend/src/test/resources/results/TestSQLAnalyzer/window3.result b/tajo-core/tajo-core-backend/src/test/resources/results/TestSQLAnalyzer/window3.result
new file mode 100644
index 0000000..c5bc47d
--- /dev/null
+++ b/tajo-core/tajo-core-backend/src/test/resources/results/TestSQLAnalyzer/window3.result
@@ -0,0 +1,54 @@
+{
+ "distinct": false,
+ "targets": [
+ {
+ "child": {
+ "name": "dt",
+ "type": "Column"
+ },
+ "type": "Target"
+ },
+ {
+ "child": {
+ "function": {
+ "distinct": false,
+ "signature": "sum",
+ "params": [
+ {
+ "name": "xy",
+ "type": "Column"
+ }
+ ],
+ "type": "GeneralSetFunction"
+ },
+ "windowSpec": {
+ "partitionKeys": [
+ {
+ "signature": "round",
+ "params": [
+ {
+ "name": "dt",
+ "type": "Column"
+ }
+ ],
+ "type": "Function"
+ }
+ ],
+ "type": "WindowSpec"
+ },
+ "type": "WindowFunction"
+ },
+ "type": "Target"
+ }
+ ],
+ "child": {
+ "relations": [
+ {
+ "tableName": "sum_example",
+ "type": "Relation"
+ }
+ ],
+ "type": "RelationList"
+ },
+ "type": "Projection"
+}
\ No newline at end of file
diff --git a/tajo-core/tajo-core-backend/src/test/resources/results/TestSQLAnalyzer/window4.result b/tajo-core/tajo-core-backend/src/test/resources/results/TestSQLAnalyzer/window4.result
new file mode 100644
index 0000000..0edd7d4
--- /dev/null
+++ b/tajo-core/tajo-core-backend/src/test/resources/results/TestSQLAnalyzer/window4.result
@@ -0,0 +1,52 @@
+{
+ "distinct": false,
+ "targets": [
+ {
+ "child": {
+ "name": "dt",
+ "type": "Column"
+ },
+ "type": "Target"
+ },
+ {
+ "child": {
+ "function": {
+ "distinct": false,
+ "signature": "sum",
+ "params": [
+ {
+ "name": "xy",
+ "type": "Column"
+ }
+ ],
+ "type": "GeneralSetFunction"
+ },
+ "windowSpec": {
+ "sortSpecs": [
+ {
+ "key": {
+ "name": "dt",
+ "type": "Column"
+ },
+ "asc": true,
+ "nullFirst": false
+ }
+ ],
+ "type": "WindowSpec"
+ },
+ "type": "WindowFunction"
+ },
+ "type": "Target"
+ }
+ ],
+ "child": {
+ "relations": [
+ {
+ "tableName": "sum_example",
+ "type": "Relation"
+ }
+ ],
+ "type": "RelationList"
+ },
+ "type": "Projection"
+}
\ No newline at end of file
diff --git a/tajo-core/tajo-core-backend/src/test/resources/results/TestSQLAnalyzer/window5.result b/tajo-core/tajo-core-backend/src/test/resources/results/TestSQLAnalyzer/window5.result
new file mode 100644
index 0000000..06192ff
--- /dev/null
+++ b/tajo-core/tajo-core-backend/src/test/resources/results/TestSQLAnalyzer/window5.result
@@ -0,0 +1,81 @@
+{
+ "distinct": false,
+ "targets": [
+ {
+ "child": {
+ "name": "dt",
+ "type": "Column"
+ },
+ "type": "Target"
+ },
+ {
+ "child": {
+ "name": "dt2",
+ "type": "Column"
+ },
+ "type": "Target"
+ },
+ {
+ "child": {
+ "function": {
+ "distinct": false,
+ "signature": "sum",
+ "params": [
+ {
+ "name": "xy",
+ "type": "Column"
+ }
+ ],
+ "type": "GeneralSetFunction"
+ },
+ "windowSpec": {
+ "partitionKeys": [
+ {
+ "signature": "round",
+ "params": [
+ {
+ "name": "dt",
+ "type": "Column"
+ }
+ ],
+ "type": "Function"
+ },
+ {
+ "name": "dt2",
+ "type": "Column"
+ }
+ ],
+ "sortSpecs": [
+ {
+ "key": {
+ "signature": "ceil",
+ "params": [
+ {
+ "name": "dt",
+ "type": "Column"
+ }
+ ],
+ "type": "Function"
+ },
+ "asc": true,
+ "nullFirst": false
+ }
+ ],
+ "type": "WindowSpec"
+ },
+ "type": "WindowFunction"
+ },
+ "type": "Target"
+ }
+ ],
+ "child": {
+ "relations": [
+ {
+ "tableName": "sum_example",
+ "type": "Relation"
+ }
+ ],
+ "type": "RelationList"
+ },
+ "type": "Projection"
+}
\ No newline at end of file
diff --git a/tajo-core/tajo-core-backend/src/test/resources/results/TestSQLAnalyzer/window6.result b/tajo-core/tajo-core-backend/src/test/resources/results/TestSQLAnalyzer/window6.result
new file mode 100644
index 0000000..97bd236
--- /dev/null
+++ b/tajo-core/tajo-core-backend/src/test/resources/results/TestSQLAnalyzer/window6.result
@@ -0,0 +1,87 @@
+{
+ "distinct": false,
+ "targets": [
+ {
+ "child": {
+ "name": "dt",
+ "type": "Column"
+ },
+ "type": "Target"
+ },
+ {
+ "child": {
+ "name": "dt2",
+ "type": "Column"
+ },
+ "type": "Target"
+ },
+ {
+ "child": {
+ "function": {
+ "distinct": false,
+ "signature": "sum",
+ "params": [
+ {
+ "name": "xy",
+ "type": "Column"
+ }
+ ],
+ "type": "GeneralSetFunction"
+ },
+ "windowSpec": {
+ "partitionKeys": [
+ {
+ "signature": "round",
+ "params": [
+ {
+ "name": "dt",
+ "type": "Column"
+ }
+ ],
+ "type": "Function"
+ },
+ {
+ "name": "dt2",
+ "type": "Column"
+ }
+ ],
+ "sortSpecs": [
+ {
+ "key": {
+ "signature": "ceil",
+ "params": [
+ {
+ "name": "dt",
+ "type": "Column"
+ }
+ ],
+ "type": "Function"
+ },
+ "asc": true,
+ "nullFirst": false
+ }
+ ],
+ "windowFrame": {
+ "unit": "ROW",
+ "startBound": {
+ "boundType": "UNBOUNDED_PRECEDING"
+ }
+ },
+ "type": "WindowSpec"
+ },
+ "type": "WindowFunction"
+ },
+ "type": "Target"
+ }
+ ],
+ "child": {
+ "relations": [
+ {
+ "tableName": "sum_example",
+ "type": "Relation"
+ }
+ ],
+ "type": "RelationList"
+ },
+ "type": "Projection"
+}
\ No newline at end of file
diff --git a/tajo-core/tajo-core-backend/src/test/resources/results/TestSQLAnalyzer/window7.result b/tajo-core/tajo-core-backend/src/test/resources/results/TestSQLAnalyzer/window7.result
new file mode 100644
index 0000000..9ae01bd
--- /dev/null
+++ b/tajo-core/tajo-core-backend/src/test/resources/results/TestSQLAnalyzer/window7.result
@@ -0,0 +1,85 @@
+{
+ "distinct": false,
+ "targets": [
+ {
+ "child": {
+ "name": "dt",
+ "type": "Column"
+ },
+ "type": "Target"
+ },
+ {
+ "child": {
+ "name": "dt2",
+ "type": "Column"
+ },
+ "type": "Target"
+ },
+ {
+ "child": {
+ "function": {
+ "distinct": false,
+ "signature": "row_number",
+ "params": [],
+ "type": "GeneralSetFunction"
+ },
+ "windowSpec": {
+ "partitionKeys": [
+ {
+ "signature": "round",
+ "params": [
+ {
+ "name": "dt",
+ "type": "Column"
+ }
+ ],
+ "type": "Function"
+ },
+ {
+ "name": "dt2",
+ "type": "Column"
+ }
+ ],
+ "sortSpecs": [
+ {
+ "key": {
+ "signature": "ceil",
+ "params": [
+ {
+ "name": "dt",
+ "type": "Column"
+ }
+ ],
+ "type": "Function"
+ },
+ "asc": true,
+ "nullFirst": false
+ }
+ ],
+ "windowFrame": {
+ "unit": "ROW",
+ "startBound": {
+ "boundType": "UNBOUNDED_PRECEDING"
+ },
+ "endBound": {
+ "boundType": "UNBOUNDED_FOLLOWING"
+ }
+ },
+ "type": "WindowSpec"
+ },
+ "type": "WindowFunction"
+ },
+ "type": "Target"
+ }
+ ],
+ "child": {
+ "relations": [
+ {
+ "tableName": "sum_example",
+ "type": "Relation"
+ }
+ ],
+ "type": "RelationList"
+ },
+ "type": "Projection"
+}
\ No newline at end of file
diff --git a/tajo-core/tajo-core-backend/src/test/resources/results/TestSQLAnalyzer/window8.result b/tajo-core/tajo-core-backend/src/test/resources/results/TestSQLAnalyzer/window8.result
new file mode 100644
index 0000000..b9abace
--- /dev/null
+++ b/tajo-core/tajo-core-backend/src/test/resources/results/TestSQLAnalyzer/window8.result
@@ -0,0 +1,90 @@
+{
+ "distinct": false,
+ "targets": [
+ {
+ "child": {
+ "name": "dt",
+ "type": "Column"
+ },
+ "type": "Target"
+ },
+ {
+ "child": {
+ "name": "dt2",
+ "type": "Column"
+ },
+ "type": "Target"
+ },
+ {
+ "child": {
+ "function": {
+ "distinct": false,
+ "signature": "row_number",
+ "params": [],
+ "type": "GeneralSetFunction"
+ },
+ "windowSpec": {
+ "partitionKeys": [
+ {
+ "signature": "round",
+ "params": [
+ {
+ "name": "dt",
+ "type": "Column"
+ }
+ ],
+ "type": "Function"
+ },
+ {
+ "name": "dt2",
+ "type": "Column"
+ }
+ ],
+ "sortSpecs": [
+ {
+ "key": {
+ "signature": "ceil",
+ "params": [
+ {
+ "name": "dt",
+ "type": "Column"
+ }
+ ],
+ "type": "Function"
+ },
+ "asc": true,
+ "nullFirst": false
+ }
+ ],
+ "windowFrame": {
+ "unit": "ROW",
+ "startBound": {
+ "boundType": "PRECEDING",
+ "number": {
+ "valueType": "Unsigned_Integer",
+ "value": "1",
+ "type": "Literal"
+ }
+ },
+ "endBound": {
+ "boundType": "CURRENT_ROW"
+ }
+ },
+ "type": "WindowSpec"
+ },
+ "type": "WindowFunction"
+ },
+ "type": "Target"
+ }
+ ],
+ "child": {
+ "relations": [
+ {
+ "tableName": "sum_example",
+ "type": "Relation"
+ }
+ ],
+ "type": "RelationList"
+ },
+ "type": "Projection"
+}
\ No newline at end of file
diff --git a/tajo-core/tajo-core-backend/src/test/resources/results/TestSQLAnalyzer/window9.result b/tajo-core/tajo-core-backend/src/test/resources/results/TestSQLAnalyzer/window9.result
new file mode 100644
index 0000000..613fb9b
--- /dev/null
+++ b/tajo-core/tajo-core-backend/src/test/resources/results/TestSQLAnalyzer/window9.result
@@ -0,0 +1,118 @@
+{
+ "distinct": false,
+ "targets": [
+ {
+ "child": {
+ "name": "dt",
+ "type": "Column"
+ },
+ "type": "Target"
+ },
+ {
+ "child": {
+ "name": "dt2",
+ "type": "Column"
+ },
+ "type": "Target"
+ },
+ {
+ "child": {
+ "function": {
+ "distinct": false,
+ "signature": "row_number",
+ "params": [],
+ "type": "GeneralSetFunction"
+ },
+ "windowSpec": {
+ "windowName": "window1",
+ "type": "WindowSpec"
+ },
+ "type": "WindowFunction"
+ },
+ "type": "Target"
+ },
+ {
+ "child": {
+ "function": {
+ "distinct": false,
+ "signature": "rank",
+ "params": [],
+ "type": "GeneralSetFunction"
+ },
+ "windowSpec": {
+ "windowName": "window1",
+ "type": "WindowSpec"
+ },
+ "type": "WindowFunction"
+ },
+ "type": "Target"
+ }
+ ],
+ "child": {
+ "definitions": [
+ {
+ "windowName": "window1",
+ "windowSpec": {
+ "partitionKeys": [
+ {
+ "signature": "round",
+ "params": [
+ {
+ "name": "dt",
+ "type": "Column"
+ }
+ ],
+ "type": "Function"
+ },
+ {
+ "name": "dt2",
+ "type": "Column"
+ }
+ ],
+ "sortSpecs": [
+ {
+ "key": {
+ "signature": "ceil",
+ "params": [
+ {
+ "name": "dt",
+ "type": "Column"
+ }
+ ],
+ "type": "Function"
+ },
+ "asc": true,
+ "nullFirst": false
+ }
+ ],
+ "windowFrame": {
+ "unit": "ROW",
+ "startBound": {
+ "boundType": "PRECEDING",
+ "number": {
+ "valueType": "Unsigned_Integer",
+ "value": "1",
+ "type": "Literal"
+ }
+ },
+ "endBound": {
+ "boundType": "CURRENT_ROW"
+ }
+ },
+ "type": "WindowSpec"
+ }
+ }
+ ],
+ "child": {
+ "relations": [
+ {
+ "tableName": "sum_example",
+ "type": "Relation"
+ }
+ ],
+ "type": "RelationList"
+ },
+ "type": "Window"
+ },
+ "type": "Projection"
+}
\ No newline at end of file