From d07fdb3ccdf4b929d8562a4fc3535f7a3df68280 Mon Sep 17 00:00:00 2001 From: sirpkt Date: Thu, 18 Dec 2014 17:03:51 +0900 Subject: [PATCH 1/3] TAJO-920: Add FIRST_VALUE and LAST_VALUE window functions --- .../org/apache/tajo/engine/parser/SQLLexer.g4 | 2 + .../apache/tajo/engine/parser/SQLParser.g4 | 4 + .../function/builtin/LastValueString.java | 90 +++++++++++++++++++ .../function/window/FirstValueString.java | 76 ++++++++++++++++ .../tajo/engine/parser/SQLAnalyzer.java | 4 + .../tajo/engine/query/TestWindowQuery.java | 15 ++++ .../queries/TestWindowQuery/firstValue1.sql | 5 ++ .../queries/TestWindowQuery/lastValue1.sql | 5 ++ .../TestWindowQuery/firstValue1.result | 7 ++ .../results/TestWindowQuery/lastValue1.result | 7 ++ .../org/apache/tajo/plan/ExprAnnotator.java | 2 +- 11 files changed, 216 insertions(+), 1 deletion(-) create mode 100644 tajo-core/src/main/java/org/apache/tajo/engine/function/builtin/LastValueString.java create mode 100644 tajo-core/src/main/java/org/apache/tajo/engine/function/window/FirstValueString.java create mode 100644 tajo-core/src/test/resources/queries/TestWindowQuery/firstValue1.sql create mode 100644 tajo-core/src/test/resources/queries/TestWindowQuery/lastValue1.sql create mode 100644 tajo-core/src/test/resources/results/TestWindowQuery/firstValue1.result create mode 100644 tajo-core/src/test/resources/results/TestWindowQuery/lastValue1.result 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 3ba008fcf8..48a6fbe6ab 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 @@ -232,6 +232,7 @@ EXTRACT : E X T R A C T; FILTER : F I L T E R; FIRST : F I R S T; +FIRST_VALUE : F I R S T UNDERLINE V A L U E; FOLLOWING : F O L L O W I N G; FORMAT : F O R M A T; FUSION : F U S I O N; @@ -249,6 +250,7 @@ ISODOW : I S O D O W; ISOYEAR : I S O Y E A R; LAST : L A S T; +LAST_VALUE : L A S T UNDERLINE V A L U E; LESS : L E S S; LIST : L I S T; LOCATION : L O C A T I O N; 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 f3cd298932..0bc89db69f 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 @@ -257,6 +257,7 @@ nonreserved_keywords | EXTRACT | FILTER | FIRST + | FIRST_VALUE | FOLLOWING | FORMAT | FUSION @@ -268,6 +269,7 @@ nonreserved_keywords | ISODOW | ISOYEAR | LAST + | LAST_VALUE | LESS | LIST | LOCATION @@ -627,6 +629,8 @@ window_function_type : rank_function_type LEFT_PAREN RIGHT_PAREN | ROW_NUMBER LEFT_PAREN RIGHT_PAREN | aggregate_function + | FIRST_VALUE LEFT_PAREN column_reference RIGHT_PAREN + | LAST_VALUE LEFT_PAREN column_reference RIGHT_PAREN ; rank_function_type diff --git a/tajo-core/src/main/java/org/apache/tajo/engine/function/builtin/LastValueString.java b/tajo-core/src/main/java/org/apache/tajo/engine/function/builtin/LastValueString.java new file mode 100644 index 0000000000..e874600400 --- /dev/null +++ b/tajo-core/src/main/java/org/apache/tajo/engine/function/builtin/LastValueString.java @@ -0,0 +1,90 @@ +/** + * 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.builtin; + +import org.apache.tajo.catalog.CatalogUtil; +import org.apache.tajo.catalog.Column; +import org.apache.tajo.common.TajoDataTypes; +import org.apache.tajo.datum.Datum; +import org.apache.tajo.datum.DatumFactory; +import org.apache.tajo.datum.NullDatum; +import org.apache.tajo.plan.function.AggFunction; +import org.apache.tajo.plan.function.FunctionContext; +import org.apache.tajo.engine.function.annotation.Description; +import org.apache.tajo.engine.function.annotation.ParamTypes; +import org.apache.tajo.storage.Tuple; + +@Description( + functionName = "last_value", + description = "the last value of expr", + example = "> SELECT last_value(expr);", + returnType = TajoDataTypes.Type.TEXT, + paramTypes = {@ParamTypes(paramTypes = {TajoDataTypes.Type.TEXT})} +) +public class LastValueString extends AggFunction { + + public LastValueString() { + super(new Column[] { + new Column("expr", TajoDataTypes.Type.TEXT) + }); + } + + @Override + public FunctionContext newContext() { + return new LastValueContext(); + } + + @Override + public void eval(FunctionContext ctx, Tuple params) { + LastValueContext lastValueCtx = (LastValueContext) ctx; + Datum datum = params.get(0); + if ( datum instanceof NullDatum ) { + lastValueCtx.isNull = true; + } else + { + lastValueCtx.isNull = false; + } + lastValueCtx.lastString = params.get(0).asChars(); + } + + @Override + public Datum getPartialResult(FunctionContext ctx) { + return DatumFactory.createText(((LastValueContext) ctx).lastString); + } + + @Override + public TajoDataTypes.DataType getPartialResultType() { + return CatalogUtil.newSimpleDataType(TajoDataTypes.Type.TEXT); + } + + @Override + public Datum terminate(FunctionContext ctx) { + if (((LastValueContext) ctx).isNull) { + return NullDatum.get(); + } + else { + return DatumFactory.createText(((LastValueContext) ctx).lastString); + } + } + + private class LastValueContext implements FunctionContext { + String lastString = null; + boolean isNull = true; + } +} \ No newline at end of file diff --git a/tajo-core/src/main/java/org/apache/tajo/engine/function/window/FirstValueString.java b/tajo-core/src/main/java/org/apache/tajo/engine/function/window/FirstValueString.java new file mode 100644 index 0000000000..ab0b3baad2 --- /dev/null +++ b/tajo-core/src/main/java/org/apache/tajo/engine/function/window/FirstValueString.java @@ -0,0 +1,76 @@ +/** + * 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.window; + +import org.apache.tajo.catalog.Column; +import org.apache.tajo.catalog.proto.CatalogProtos; +import org.apache.tajo.common.TajoDataTypes; +import org.apache.tajo.common.TajoDataTypes.Type; +import org.apache.tajo.datum.*; +import org.apache.tajo.plan.function.FunctionContext; +import org.apache.tajo.plan.function.WindowAggFunc; +import org.apache.tajo.engine.function.annotation.Description; +import org.apache.tajo.engine.function.annotation.ParamTypes; +import org.apache.tajo.storage.Tuple; + +@Description( + functionName = "first_value", + description = "the first value of retrieved rows", + example = "> SELECT first_value(column) OVER ();", + returnType = Type.TEXT, + paramTypes = {@ParamTypes(paramTypes = {Type.TEXT})} +) +public class FirstValueString extends WindowAggFunc { + + public FirstValueString() { + super(NoArgs); + } + + public FirstValueString(Column[] columns) { + super(columns); + } + + @Override + public FunctionContext newContext() { + return new FirstValueStringContext(); + } + + @Override + public void eval(FunctionContext ctx, Tuple params) { + FirstValueStringContext firstValueCtx = (FirstValueStringContext)ctx; + if(firstValueCtx.firstString == null && !(params.get(0) instanceof NullDatum)) { + firstValueCtx.firstString = params.get(0).asChars(); + } + } + + @Override + public Datum terminate(FunctionContext ctx) { + if (((FirstValueStringContext) ctx).firstString == null) { + return NullDatum.get(); + } + else { + return DatumFactory.createText(((FirstValueStringContext) ctx).firstString); + } + } + + protected class FirstValueStringContext implements FunctionContext { + String firstString = null; + } + +} 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 90230c9bcd..3669625117 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 @@ -379,6 +379,10 @@ public Aggregation visitGroupby_clause(SQLParser.Groupby_clauseContext ctx) { } } else if (checkIfExist(functionType.ROW_NUMBER())) { functionBody = new GeneralSetFunctionExpr("row_number", false, new Expr[] {}); + } else if (checkIfExist(functionType.FIRST_VALUE())) { + functionBody = new GeneralSetFunctionExpr("first_value", false, new Expr[]{ visitColumn_reference(functionType.column_reference())}); + } else if (checkIfExist(functionType.LAST_VALUE())) { + functionBody = new GeneralSetFunctionExpr("last_value", false, new Expr[]{visitColumn_reference(functionType.column_reference())}); } else { functionBody = visitAggregate_function(functionType.aggregate_function()); } diff --git a/tajo-core/src/test/java/org/apache/tajo/engine/query/TestWindowQuery.java b/tajo-core/src/test/java/org/apache/tajo/engine/query/TestWindowQuery.java index d64dd20180..0b203792aa 100644 --- a/tajo-core/src/test/java/org/apache/tajo/engine/query/TestWindowQuery.java +++ b/tajo-core/src/test/java/org/apache/tajo/engine/query/TestWindowQuery.java @@ -244,4 +244,19 @@ public final void rowNumber3() throws Exception { assertResultSet(res); cleanupQuery(res); } + + @Test + public final void firstValue1() throws Exception { + ResultSet res = executeQuery(); + assertResultSet(res); + cleanupQuery(res); + } + + @Test + public final void lastValue1() throws Exception { + ResultSet res = executeQuery(); + assertResultSet(res); + cleanupQuery(res); + } + } \ No newline at end of file diff --git a/tajo-core/src/test/resources/queries/TestWindowQuery/firstValue1.sql b/tajo-core/src/test/resources/queries/TestWindowQuery/firstValue1.sql new file mode 100644 index 0000000000..e11e0e6c6d --- /dev/null +++ b/tajo-core/src/test/resources/queries/TestWindowQuery/firstValue1.sql @@ -0,0 +1,5 @@ +SELECT + l_orderkey, + first_value(l_shipmode) over (PARTITION BY L_ORDERKEY order by l_shipmode ) as shipmode_first +FROM + LINEITEM \ No newline at end of file diff --git a/tajo-core/src/test/resources/queries/TestWindowQuery/lastValue1.sql b/tajo-core/src/test/resources/queries/TestWindowQuery/lastValue1.sql new file mode 100644 index 0000000000..627adefcaa --- /dev/null +++ b/tajo-core/src/test/resources/queries/TestWindowQuery/lastValue1.sql @@ -0,0 +1,5 @@ +SELECT + l_orderkey, + last_value(l_shipmode) over (PARTITION BY L_ORDERKEY order by l_shipmode ) as shipmode_first +FROM + LINEITEM \ No newline at end of file diff --git a/tajo-core/src/test/resources/results/TestWindowQuery/firstValue1.result b/tajo-core/src/test/resources/results/TestWindowQuery/firstValue1.result new file mode 100644 index 0000000000..43e6b42462 --- /dev/null +++ b/tajo-core/src/test/resources/results/TestWindowQuery/firstValue1.result @@ -0,0 +1,7 @@ +l_orderkey,shipmode_first +------------------------------- +1,MAIL +1,MAIL +2,RAIL +3,AIR +3,AIR \ No newline at end of file diff --git a/tajo-core/src/test/resources/results/TestWindowQuery/lastValue1.result b/tajo-core/src/test/resources/results/TestWindowQuery/lastValue1.result new file mode 100644 index 0000000000..d68d2bd9ac --- /dev/null +++ b/tajo-core/src/test/resources/results/TestWindowQuery/lastValue1.result @@ -0,0 +1,7 @@ +l_orderkey,shipmode_first +------------------------------- +1,TRUCK +1,TRUCK +2,RAIL +3,RAIL +3,RAIL \ No newline at end of file diff --git a/tajo-plan/src/main/java/org/apache/tajo/plan/ExprAnnotator.java b/tajo-plan/src/main/java/org/apache/tajo/plan/ExprAnnotator.java index fcbbb212ca..c8eaffcda6 100644 --- a/tajo-plan/src/main/java/org/apache/tajo/plan/ExprAnnotator.java +++ b/tajo-plan/src/main/java/org/apache/tajo/plan/ExprAnnotator.java @@ -679,7 +679,7 @@ public EvalNode visitGeneralSetFunction(Context ctx, Stack stack, GeneralS } public static final Set WINDOW_FUNCTIONS = - Sets.newHashSet("row_number", "rank", "dense_rank", "percent_rank", "cume_dist"); + Sets.newHashSet("row_number", "rank", "dense_rank", "percent_rank", "cume_dist", "first_value"); public EvalNode visitWindowFunction(Context ctx, Stack stack, WindowFunctionExpr windowFunc) throws PlanningException { From 7464d62460bc7af2b268541c0be57d57d7e899ce Mon Sep 17 00:00:00 2001 From: sirpkt Date: Thu, 18 Dec 2014 18:16:26 +0900 Subject: [PATCH 2/3] TAJO-920: Add FIRST_VALUE and LAST_VALUE window functions --- .../engine/function/builtin/LastValue.java | 67 +++++++++++++++++++ .../function/builtin/LastValueString.java | 46 +------------ .../engine/function/window/FirstValue.java | 64 ++++++++++++++++++ .../function/window/FirstValueString.java | 43 ++---------- .../tajo/engine/query/TestWindowQuery.java | 2 +- 5 files changed, 137 insertions(+), 85 deletions(-) create mode 100644 tajo-core/src/main/java/org/apache/tajo/engine/function/builtin/LastValue.java create mode 100644 tajo-core/src/main/java/org/apache/tajo/engine/function/window/FirstValue.java diff --git a/tajo-core/src/main/java/org/apache/tajo/engine/function/builtin/LastValue.java b/tajo-core/src/main/java/org/apache/tajo/engine/function/builtin/LastValue.java new file mode 100644 index 0000000000..db4f79f380 --- /dev/null +++ b/tajo-core/src/main/java/org/apache/tajo/engine/function/builtin/LastValue.java @@ -0,0 +1,67 @@ +/** + * 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.builtin; + +import org.apache.tajo.catalog.Column; +import org.apache.tajo.datum.Datum; +import org.apache.tajo.datum.NullDatum; +import org.apache.tajo.plan.function.AggFunction; +import org.apache.tajo.plan.function.FunctionContext; +import org.apache.tajo.storage.Tuple; + + +public abstract class LastValue extends AggFunction { + + public LastValue(Column[] columns) { + super(columns); + } + + @Override + public FunctionContext newContext() { + return new LastValueContext(); + } + + @Override + public void eval(FunctionContext ctx, Tuple params) { + LastValueContext lastValueCtx = (LastValueContext) ctx; + Datum datum = params.get(0); + if ( datum.isNotNull() ) { + lastValueCtx.last = datum; + } + } + + @Override + public Datum getPartialResult(FunctionContext ctx) { + return ((LastValueContext) ctx).last; + } + + @Override + public Datum terminate(FunctionContext ctx) { + if (((LastValueContext) ctx).last == null) { + return NullDatum.get(); + } + else { + return ((LastValueContext) ctx).last; + } + } + + private class LastValueContext implements FunctionContext { + Datum last = null; + } +} \ No newline at end of file diff --git a/tajo-core/src/main/java/org/apache/tajo/engine/function/builtin/LastValueString.java b/tajo-core/src/main/java/org/apache/tajo/engine/function/builtin/LastValueString.java index e874600400..8ab8d2ea48 100644 --- a/tajo-core/src/main/java/org/apache/tajo/engine/function/builtin/LastValueString.java +++ b/tajo-core/src/main/java/org/apache/tajo/engine/function/builtin/LastValueString.java @@ -21,14 +21,8 @@ import org.apache.tajo.catalog.CatalogUtil; import org.apache.tajo.catalog.Column; import org.apache.tajo.common.TajoDataTypes; -import org.apache.tajo.datum.Datum; -import org.apache.tajo.datum.DatumFactory; -import org.apache.tajo.datum.NullDatum; -import org.apache.tajo.plan.function.AggFunction; -import org.apache.tajo.plan.function.FunctionContext; import org.apache.tajo.engine.function.annotation.Description; import org.apache.tajo.engine.function.annotation.ParamTypes; -import org.apache.tajo.storage.Tuple; @Description( functionName = "last_value", @@ -37,7 +31,7 @@ returnType = TajoDataTypes.Type.TEXT, paramTypes = {@ParamTypes(paramTypes = {TajoDataTypes.Type.TEXT})} ) -public class LastValueString extends AggFunction { +public class LastValueString extends LastValue { public LastValueString() { super(new Column[] { @@ -45,46 +39,8 @@ public LastValueString() { }); } - @Override - public FunctionContext newContext() { - return new LastValueContext(); - } - - @Override - public void eval(FunctionContext ctx, Tuple params) { - LastValueContext lastValueCtx = (LastValueContext) ctx; - Datum datum = params.get(0); - if ( datum instanceof NullDatum ) { - lastValueCtx.isNull = true; - } else - { - lastValueCtx.isNull = false; - } - lastValueCtx.lastString = params.get(0).asChars(); - } - - @Override - public Datum getPartialResult(FunctionContext ctx) { - return DatumFactory.createText(((LastValueContext) ctx).lastString); - } - @Override public TajoDataTypes.DataType getPartialResultType() { return CatalogUtil.newSimpleDataType(TajoDataTypes.Type.TEXT); } - - @Override - public Datum terminate(FunctionContext ctx) { - if (((LastValueContext) ctx).isNull) { - return NullDatum.get(); - } - else { - return DatumFactory.createText(((LastValueContext) ctx).lastString); - } - } - - private class LastValueContext implements FunctionContext { - String lastString = null; - boolean isNull = true; - } } \ No newline at end of file diff --git a/tajo-core/src/main/java/org/apache/tajo/engine/function/window/FirstValue.java b/tajo-core/src/main/java/org/apache/tajo/engine/function/window/FirstValue.java new file mode 100644 index 0000000000..93cdffb5f6 --- /dev/null +++ b/tajo-core/src/main/java/org/apache/tajo/engine/function/window/FirstValue.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.engine.function.window; + +import org.apache.tajo.catalog.Column; +import org.apache.tajo.datum.*; +import org.apache.tajo.plan.function.FunctionContext; +import org.apache.tajo.plan.function.WindowAggFunc; +import org.apache.tajo.storage.Tuple; + +public abstract class FirstValue extends WindowAggFunc { + + public FirstValue(Column[] columns) { + super(columns); + } + + @Override + public FunctionContext newContext() { + return new FirstValueContext(); + } + + @Override + public void eval(FunctionContext ctx, Tuple params) { + FirstValueContext firstValueCtx = (FirstValueContext)ctx; + if(firstValueCtx.isSet == false) { + firstValueCtx.isSet = true; + if (params.get(0).isNotNull()) { + firstValueCtx.first = params.get(0); + } + } + } + + @Override + public Datum terminate(FunctionContext ctx) { + if (((FirstValueContext) ctx).first == null) { + return NullDatum.get(); + } + else { + return ((FirstValueContext) ctx).first; + } + } + + protected class FirstValueContext implements FunctionContext { + boolean isSet = false; + Datum first = null; + } + +} diff --git a/tajo-core/src/main/java/org/apache/tajo/engine/function/window/FirstValueString.java b/tajo-core/src/main/java/org/apache/tajo/engine/function/window/FirstValueString.java index ab0b3baad2..6203413d12 100644 --- a/tajo-core/src/main/java/org/apache/tajo/engine/function/window/FirstValueString.java +++ b/tajo-core/src/main/java/org/apache/tajo/engine/function/window/FirstValueString.java @@ -19,15 +19,10 @@ package org.apache.tajo.engine.function.window; import org.apache.tajo.catalog.Column; -import org.apache.tajo.catalog.proto.CatalogProtos; import org.apache.tajo.common.TajoDataTypes; import org.apache.tajo.common.TajoDataTypes.Type; -import org.apache.tajo.datum.*; -import org.apache.tajo.plan.function.FunctionContext; -import org.apache.tajo.plan.function.WindowAggFunc; import org.apache.tajo.engine.function.annotation.Description; import org.apache.tajo.engine.function.annotation.ParamTypes; -import org.apache.tajo.storage.Tuple; @Description( functionName = "first_value", @@ -36,41 +31,11 @@ returnType = Type.TEXT, paramTypes = {@ParamTypes(paramTypes = {Type.TEXT})} ) -public class FirstValueString extends WindowAggFunc { +public class FirstValueString extends FirstValue { public FirstValueString() { - super(NoArgs); + super(new Column[] { + new Column("expr", TajoDataTypes.Type.TEXT) + }); } - - public FirstValueString(Column[] columns) { - super(columns); - } - - @Override - public FunctionContext newContext() { - return new FirstValueStringContext(); - } - - @Override - public void eval(FunctionContext ctx, Tuple params) { - FirstValueStringContext firstValueCtx = (FirstValueStringContext)ctx; - if(firstValueCtx.firstString == null && !(params.get(0) instanceof NullDatum)) { - firstValueCtx.firstString = params.get(0).asChars(); - } - } - - @Override - public Datum terminate(FunctionContext ctx) { - if (((FirstValueStringContext) ctx).firstString == null) { - return NullDatum.get(); - } - else { - return DatumFactory.createText(((FirstValueStringContext) ctx).firstString); - } - } - - protected class FirstValueStringContext implements FunctionContext { - String firstString = null; - } - } diff --git a/tajo-core/src/test/java/org/apache/tajo/engine/query/TestWindowQuery.java b/tajo-core/src/test/java/org/apache/tajo/engine/query/TestWindowQuery.java index 0b203792aa..06eebe9eb0 100644 --- a/tajo-core/src/test/java/org/apache/tajo/engine/query/TestWindowQuery.java +++ b/tajo-core/src/test/java/org/apache/tajo/engine/query/TestWindowQuery.java @@ -258,5 +258,5 @@ public final void lastValue1() throws Exception { assertResultSet(res); cleanupQuery(res); } - + } \ No newline at end of file From 5f7c2dc74f07da68b176d80bd55d67cc238fd884 Mon Sep 17 00:00:00 2001 From: sirpkt Date: Sat, 20 Dec 2014 18:45:11 +0900 Subject: [PATCH 3/3] TAJO-920: Add FIRST_VALUE and LAST_VALUE window functions --- .../function/builtin/LastValueDate.java | 46 ++++++++++++++ .../function/builtin/LastValueDouble.java | 46 ++++++++++++++ .../function/builtin/LastValueFloat.java | 46 ++++++++++++++ .../engine/function/builtin/LastValueInt.java | 46 ++++++++++++++ .../function/builtin/LastValueLong.java | 46 ++++++++++++++ .../function/builtin/LastValueTime.java | 46 ++++++++++++++ .../function/builtin/LastValueTimestamp.java | 46 ++++++++++++++ .../function/window/FirstValueDate.java | 41 +++++++++++++ .../function/window/FirstValueDouble.java | 41 +++++++++++++ .../function/window/FirstValueFloat.java | 41 +++++++++++++ .../engine/function/window/FirstValueInt.java | 41 +++++++++++++ .../function/window/FirstValueLong.java | 41 +++++++++++++ .../function/window/FirstValueString.java | 2 +- .../function/window/FirstValueTime.java | 41 +++++++++++++ .../function/window/FirstValueTimestamp.java | 41 +++++++++++++ .../tajo/engine/query/TestWindowQuery.java | 60 +++++++++++++++++++ .../queries/TestWindowQuery/firstValue1.sql | 17 +++++- .../queries/TestWindowQuery/lastValue1.sql | 17 +++++- .../TestWindowQuery/firstValue1.result | 12 ++-- .../results/TestWindowQuery/lastValue1.result | 12 ++-- 20 files changed, 712 insertions(+), 17 deletions(-) create mode 100644 tajo-core/src/main/java/org/apache/tajo/engine/function/builtin/LastValueDate.java create mode 100644 tajo-core/src/main/java/org/apache/tajo/engine/function/builtin/LastValueDouble.java create mode 100644 tajo-core/src/main/java/org/apache/tajo/engine/function/builtin/LastValueFloat.java create mode 100644 tajo-core/src/main/java/org/apache/tajo/engine/function/builtin/LastValueInt.java create mode 100644 tajo-core/src/main/java/org/apache/tajo/engine/function/builtin/LastValueLong.java create mode 100644 tajo-core/src/main/java/org/apache/tajo/engine/function/builtin/LastValueTime.java create mode 100644 tajo-core/src/main/java/org/apache/tajo/engine/function/builtin/LastValueTimestamp.java create mode 100644 tajo-core/src/main/java/org/apache/tajo/engine/function/window/FirstValueDate.java create mode 100644 tajo-core/src/main/java/org/apache/tajo/engine/function/window/FirstValueDouble.java create mode 100644 tajo-core/src/main/java/org/apache/tajo/engine/function/window/FirstValueFloat.java create mode 100644 tajo-core/src/main/java/org/apache/tajo/engine/function/window/FirstValueInt.java create mode 100644 tajo-core/src/main/java/org/apache/tajo/engine/function/window/FirstValueLong.java create mode 100644 tajo-core/src/main/java/org/apache/tajo/engine/function/window/FirstValueTime.java create mode 100644 tajo-core/src/main/java/org/apache/tajo/engine/function/window/FirstValueTimestamp.java diff --git a/tajo-core/src/main/java/org/apache/tajo/engine/function/builtin/LastValueDate.java b/tajo-core/src/main/java/org/apache/tajo/engine/function/builtin/LastValueDate.java new file mode 100644 index 0000000000..950e6c40ec --- /dev/null +++ b/tajo-core/src/main/java/org/apache/tajo/engine/function/builtin/LastValueDate.java @@ -0,0 +1,46 @@ +/** + * 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.builtin; + +import org.apache.tajo.catalog.CatalogUtil; +import org.apache.tajo.catalog.Column; +import org.apache.tajo.common.TajoDataTypes; +import org.apache.tajo.engine.function.annotation.Description; +import org.apache.tajo.engine.function.annotation.ParamTypes; + +@Description( + functionName = "last_value", + description = "the last value of expr", + example = "> SELECT last_value(expr);", + returnType = TajoDataTypes.Type.DATE, + paramTypes = {@ParamTypes(paramTypes = {TajoDataTypes.Type.DATE})} +) +public class LastValueDate extends LastValue { + + public LastValueDate() { + super(new Column[] { + new Column("expr", TajoDataTypes.Type.DATE) + }); + } + + @Override + public TajoDataTypes.DataType getPartialResultType() { + return CatalogUtil.newSimpleDataType(TajoDataTypes.Type.DATE); + } +} \ No newline at end of file diff --git a/tajo-core/src/main/java/org/apache/tajo/engine/function/builtin/LastValueDouble.java b/tajo-core/src/main/java/org/apache/tajo/engine/function/builtin/LastValueDouble.java new file mode 100644 index 0000000000..3bd71f71a9 --- /dev/null +++ b/tajo-core/src/main/java/org/apache/tajo/engine/function/builtin/LastValueDouble.java @@ -0,0 +1,46 @@ +/** + * 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.builtin; + +import org.apache.tajo.catalog.CatalogUtil; +import org.apache.tajo.catalog.Column; +import org.apache.tajo.common.TajoDataTypes; +import org.apache.tajo.engine.function.annotation.Description; +import org.apache.tajo.engine.function.annotation.ParamTypes; + +@Description( + functionName = "last_value", + description = "the last value of expr", + example = "> SELECT last_value(expr);", + returnType = TajoDataTypes.Type.FLOAT8, + paramTypes = {@ParamTypes(paramTypes = {TajoDataTypes.Type.FLOAT8})} +) +public class LastValueDouble extends LastValue { + + public LastValueDouble() { + super(new Column[] { + new Column("expr", TajoDataTypes.Type.FLOAT8) + }); + } + + @Override + public TajoDataTypes.DataType getPartialResultType() { + return CatalogUtil.newSimpleDataType(TajoDataTypes.Type.FLOAT8); + } +} \ No newline at end of file diff --git a/tajo-core/src/main/java/org/apache/tajo/engine/function/builtin/LastValueFloat.java b/tajo-core/src/main/java/org/apache/tajo/engine/function/builtin/LastValueFloat.java new file mode 100644 index 0000000000..d705cd755a --- /dev/null +++ b/tajo-core/src/main/java/org/apache/tajo/engine/function/builtin/LastValueFloat.java @@ -0,0 +1,46 @@ +/** + * 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.builtin; + +import org.apache.tajo.catalog.CatalogUtil; +import org.apache.tajo.catalog.Column; +import org.apache.tajo.common.TajoDataTypes; +import org.apache.tajo.engine.function.annotation.Description; +import org.apache.tajo.engine.function.annotation.ParamTypes; + +@Description( + functionName = "last_value", + description = "the last value of expr", + example = "> SELECT last_value(expr);", + returnType = TajoDataTypes.Type.FLOAT4, + paramTypes = {@ParamTypes(paramTypes = {TajoDataTypes.Type.FLOAT4})} +) +public class LastValueFloat extends LastValue { + + public LastValueFloat() { + super(new Column[] { + new Column("expr", TajoDataTypes.Type.FLOAT4) + }); + } + + @Override + public TajoDataTypes.DataType getPartialResultType() { + return CatalogUtil.newSimpleDataType(TajoDataTypes.Type.FLOAT4); + } +} \ No newline at end of file diff --git a/tajo-core/src/main/java/org/apache/tajo/engine/function/builtin/LastValueInt.java b/tajo-core/src/main/java/org/apache/tajo/engine/function/builtin/LastValueInt.java new file mode 100644 index 0000000000..5b44649b31 --- /dev/null +++ b/tajo-core/src/main/java/org/apache/tajo/engine/function/builtin/LastValueInt.java @@ -0,0 +1,46 @@ +/** + * 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.builtin; + +import org.apache.tajo.catalog.CatalogUtil; +import org.apache.tajo.catalog.Column; +import org.apache.tajo.common.TajoDataTypes; +import org.apache.tajo.engine.function.annotation.Description; +import org.apache.tajo.engine.function.annotation.ParamTypes; + +@Description( + functionName = "last_value", + description = "the last value of expr", + example = "> SELECT last_value(expr);", + returnType = TajoDataTypes.Type.INT4, + paramTypes = {@ParamTypes(paramTypes = {TajoDataTypes.Type.INT4})} +) +public class LastValueInt extends LastValue { + + public LastValueInt() { + super(new Column[] { + new Column("expr", TajoDataTypes.Type.INT4) + }); + } + + @Override + public TajoDataTypes.DataType getPartialResultType() { + return CatalogUtil.newSimpleDataType(TajoDataTypes.Type.INT4); + } +} \ No newline at end of file diff --git a/tajo-core/src/main/java/org/apache/tajo/engine/function/builtin/LastValueLong.java b/tajo-core/src/main/java/org/apache/tajo/engine/function/builtin/LastValueLong.java new file mode 100644 index 0000000000..210b936857 --- /dev/null +++ b/tajo-core/src/main/java/org/apache/tajo/engine/function/builtin/LastValueLong.java @@ -0,0 +1,46 @@ +/** + * 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.builtin; + +import org.apache.tajo.catalog.CatalogUtil; +import org.apache.tajo.catalog.Column; +import org.apache.tajo.common.TajoDataTypes; +import org.apache.tajo.engine.function.annotation.Description; +import org.apache.tajo.engine.function.annotation.ParamTypes; + +@Description( + functionName = "last_value", + description = "the last value of expr", + example = "> SELECT last_value(expr);", + returnType = TajoDataTypes.Type.INT8, + paramTypes = {@ParamTypes(paramTypes = {TajoDataTypes.Type.INT8})} +) +public class LastValueLong extends LastValue { + + public LastValueLong() { + super(new Column[] { + new Column("expr", TajoDataTypes.Type.INT8) + }); + } + + @Override + public TajoDataTypes.DataType getPartialResultType() { + return CatalogUtil.newSimpleDataType(TajoDataTypes.Type.INT8); + } +} \ No newline at end of file diff --git a/tajo-core/src/main/java/org/apache/tajo/engine/function/builtin/LastValueTime.java b/tajo-core/src/main/java/org/apache/tajo/engine/function/builtin/LastValueTime.java new file mode 100644 index 0000000000..146c1e55a2 --- /dev/null +++ b/tajo-core/src/main/java/org/apache/tajo/engine/function/builtin/LastValueTime.java @@ -0,0 +1,46 @@ +/** + * 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.builtin; + +import org.apache.tajo.catalog.CatalogUtil; +import org.apache.tajo.catalog.Column; +import org.apache.tajo.common.TajoDataTypes; +import org.apache.tajo.engine.function.annotation.Description; +import org.apache.tajo.engine.function.annotation.ParamTypes; + +@Description( + functionName = "last_value", + description = "the last value of expr", + example = "> SELECT last_value(expr);", + returnType = TajoDataTypes.Type.TIME, + paramTypes = {@ParamTypes(paramTypes = {TajoDataTypes.Type.TIME})} +) +public class LastValueTime extends LastValue { + + public LastValueTime() { + super(new Column[] { + new Column("expr", TajoDataTypes.Type.TIME) + }); + } + + @Override + public TajoDataTypes.DataType getPartialResultType() { + return CatalogUtil.newSimpleDataType(TajoDataTypes.Type.TIME); + } +} \ No newline at end of file diff --git a/tajo-core/src/main/java/org/apache/tajo/engine/function/builtin/LastValueTimestamp.java b/tajo-core/src/main/java/org/apache/tajo/engine/function/builtin/LastValueTimestamp.java new file mode 100644 index 0000000000..cabe43bf82 --- /dev/null +++ b/tajo-core/src/main/java/org/apache/tajo/engine/function/builtin/LastValueTimestamp.java @@ -0,0 +1,46 @@ +/** + * 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.builtin; + +import org.apache.tajo.catalog.CatalogUtil; +import org.apache.tajo.catalog.Column; +import org.apache.tajo.common.TajoDataTypes; +import org.apache.tajo.engine.function.annotation.Description; +import org.apache.tajo.engine.function.annotation.ParamTypes; + +@Description( + functionName = "last_value", + description = "the last value of expr", + example = "> SELECT last_value(expr);", + returnType = TajoDataTypes.Type.TIMESTAMP, + paramTypes = {@ParamTypes(paramTypes = {TajoDataTypes.Type.TIMESTAMP})} +) +public class LastValueTimestamp extends LastValue { + + public LastValueTimestamp() { + super(new Column[] { + new Column("expr", TajoDataTypes.Type.TIMESTAMP) + }); + } + + @Override + public TajoDataTypes.DataType getPartialResultType() { + return CatalogUtil.newSimpleDataType(TajoDataTypes.Type.TIMESTAMP); + } +} \ No newline at end of file diff --git a/tajo-core/src/main/java/org/apache/tajo/engine/function/window/FirstValueDate.java b/tajo-core/src/main/java/org/apache/tajo/engine/function/window/FirstValueDate.java new file mode 100644 index 0000000000..44364ee123 --- /dev/null +++ b/tajo-core/src/main/java/org/apache/tajo/engine/function/window/FirstValueDate.java @@ -0,0 +1,41 @@ +/** + * 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.window; + +import org.apache.tajo.catalog.Column; +import org.apache.tajo.common.TajoDataTypes; +import org.apache.tajo.common.TajoDataTypes.Type; +import org.apache.tajo.engine.function.annotation.Description; +import org.apache.tajo.engine.function.annotation.ParamTypes; + +@Description( + functionName = "first_value", + description = "the first value of retrieved rows", + example = "> SELECT first_value(column) OVER ();", + returnType = Type.DATE, + paramTypes = {@ParamTypes(paramTypes = {Type.DATE})} +) +public class FirstValueDate extends FirstValue { + + public FirstValueDate() { + super(new Column[] { + new Column("expr", Type.DATE) + }); + } +} diff --git a/tajo-core/src/main/java/org/apache/tajo/engine/function/window/FirstValueDouble.java b/tajo-core/src/main/java/org/apache/tajo/engine/function/window/FirstValueDouble.java new file mode 100644 index 0000000000..01bbc7f767 --- /dev/null +++ b/tajo-core/src/main/java/org/apache/tajo/engine/function/window/FirstValueDouble.java @@ -0,0 +1,41 @@ +/** + * 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.window; + +import org.apache.tajo.catalog.Column; +import org.apache.tajo.common.TajoDataTypes; +import org.apache.tajo.common.TajoDataTypes.Type; +import org.apache.tajo.engine.function.annotation.Description; +import org.apache.tajo.engine.function.annotation.ParamTypes; + +@Description( + functionName = "first_value", + description = "the first value of retrieved rows", + example = "> SELECT first_value(column) OVER ();", + returnType = Type.FLOAT8, + paramTypes = {@ParamTypes(paramTypes = {Type.FLOAT8})} +) +public class FirstValueDouble extends FirstValue { + + public FirstValueDouble() { + super(new Column[] { + new Column("expr", Type.FLOAT8) + }); + } +} diff --git a/tajo-core/src/main/java/org/apache/tajo/engine/function/window/FirstValueFloat.java b/tajo-core/src/main/java/org/apache/tajo/engine/function/window/FirstValueFloat.java new file mode 100644 index 0000000000..317c7ef9a2 --- /dev/null +++ b/tajo-core/src/main/java/org/apache/tajo/engine/function/window/FirstValueFloat.java @@ -0,0 +1,41 @@ +/** + * 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.window; + +import org.apache.tajo.catalog.Column; +import org.apache.tajo.common.TajoDataTypes; +import org.apache.tajo.common.TajoDataTypes.Type; +import org.apache.tajo.engine.function.annotation.Description; +import org.apache.tajo.engine.function.annotation.ParamTypes; + +@Description( + functionName = "first_value", + description = "the first value of retrieved rows", + example = "> SELECT first_value(column) OVER ();", + returnType = Type.FLOAT4, + paramTypes = {@ParamTypes(paramTypes = {Type.FLOAT4})} +) +public class FirstValueFloat extends FirstValue { + + public FirstValueFloat() { + super(new Column[] { + new Column("expr", Type.FLOAT4) + }); + } +} diff --git a/tajo-core/src/main/java/org/apache/tajo/engine/function/window/FirstValueInt.java b/tajo-core/src/main/java/org/apache/tajo/engine/function/window/FirstValueInt.java new file mode 100644 index 0000000000..8cb8e4e7e8 --- /dev/null +++ b/tajo-core/src/main/java/org/apache/tajo/engine/function/window/FirstValueInt.java @@ -0,0 +1,41 @@ +/** + * 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.window; + +import org.apache.tajo.catalog.Column; +import org.apache.tajo.common.TajoDataTypes; +import org.apache.tajo.common.TajoDataTypes.Type; +import org.apache.tajo.engine.function.annotation.Description; +import org.apache.tajo.engine.function.annotation.ParamTypes; + +@Description( + functionName = "first_value", + description = "the first value of retrieved rows", + example = "> SELECT first_value(column) OVER ();", + returnType = Type.INT4, + paramTypes = {@ParamTypes(paramTypes = {Type.INT4})} +) +public class FirstValueInt extends FirstValue { + + public FirstValueInt() { + super(new Column[] { + new Column("expr", Type.INT4) + }); + } +} diff --git a/tajo-core/src/main/java/org/apache/tajo/engine/function/window/FirstValueLong.java b/tajo-core/src/main/java/org/apache/tajo/engine/function/window/FirstValueLong.java new file mode 100644 index 0000000000..3c07c0c5be --- /dev/null +++ b/tajo-core/src/main/java/org/apache/tajo/engine/function/window/FirstValueLong.java @@ -0,0 +1,41 @@ +/** + * 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.window; + +import org.apache.tajo.catalog.Column; +import org.apache.tajo.common.TajoDataTypes; +import org.apache.tajo.common.TajoDataTypes.Type; +import org.apache.tajo.engine.function.annotation.Description; +import org.apache.tajo.engine.function.annotation.ParamTypes; + +@Description( + functionName = "first_value", + description = "the first value of retrieved rows", + example = "> SELECT first_value(column) OVER ();", + returnType = Type.INT8, + paramTypes = {@ParamTypes(paramTypes = {Type.INT8})} +) +public class FirstValueLong extends FirstValue { + + public FirstValueLong() { + super(new Column[] { + new Column("expr", Type.INT8) + }); + } +} diff --git a/tajo-core/src/main/java/org/apache/tajo/engine/function/window/FirstValueString.java b/tajo-core/src/main/java/org/apache/tajo/engine/function/window/FirstValueString.java index 6203413d12..253417452d 100644 --- a/tajo-core/src/main/java/org/apache/tajo/engine/function/window/FirstValueString.java +++ b/tajo-core/src/main/java/org/apache/tajo/engine/function/window/FirstValueString.java @@ -35,7 +35,7 @@ public class FirstValueString extends FirstValue { public FirstValueString() { super(new Column[] { - new Column("expr", TajoDataTypes.Type.TEXT) + new Column("expr", Type.TEXT) }); } } diff --git a/tajo-core/src/main/java/org/apache/tajo/engine/function/window/FirstValueTime.java b/tajo-core/src/main/java/org/apache/tajo/engine/function/window/FirstValueTime.java new file mode 100644 index 0000000000..fc5adc46e9 --- /dev/null +++ b/tajo-core/src/main/java/org/apache/tajo/engine/function/window/FirstValueTime.java @@ -0,0 +1,41 @@ +/** + * 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.window; + +import org.apache.tajo.catalog.Column; +import org.apache.tajo.common.TajoDataTypes; +import org.apache.tajo.common.TajoDataTypes.Type; +import org.apache.tajo.engine.function.annotation.Description; +import org.apache.tajo.engine.function.annotation.ParamTypes; + +@Description( + functionName = "first_value", + description = "the first value of retrieved rows", + example = "> SELECT first_value(column) OVER ();", + returnType = Type.TIME, + paramTypes = {@ParamTypes(paramTypes = {Type.TIME})} +) +public class FirstValueTime extends FirstValue { + + public FirstValueTime() { + super(new Column[] { + new Column("expr", Type.TIME) + }); + } +} diff --git a/tajo-core/src/main/java/org/apache/tajo/engine/function/window/FirstValueTimestamp.java b/tajo-core/src/main/java/org/apache/tajo/engine/function/window/FirstValueTimestamp.java new file mode 100644 index 0000000000..1e7bd26a18 --- /dev/null +++ b/tajo-core/src/main/java/org/apache/tajo/engine/function/window/FirstValueTimestamp.java @@ -0,0 +1,41 @@ +/** + * 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.window; + +import org.apache.tajo.catalog.Column; +import org.apache.tajo.common.TajoDataTypes; +import org.apache.tajo.common.TajoDataTypes.Type; +import org.apache.tajo.engine.function.annotation.Description; +import org.apache.tajo.engine.function.annotation.ParamTypes; + +@Description( + functionName = "first_value", + description = "the first value of retrieved rows", + example = "> SELECT first_value(column) OVER ();", + returnType = Type.TIMESTAMP, + paramTypes = {@ParamTypes(paramTypes = {Type.TIMESTAMP})} +) +public class FirstValueTimestamp extends FirstValue { + + public FirstValueTimestamp() { + super(new Column[] { + new Column("expr", Type.TIMESTAMP) + }); + } +} diff --git a/tajo-core/src/test/java/org/apache/tajo/engine/query/TestWindowQuery.java b/tajo-core/src/test/java/org/apache/tajo/engine/query/TestWindowQuery.java index 06eebe9eb0..2af5ce9d68 100644 --- a/tajo-core/src/test/java/org/apache/tajo/engine/query/TestWindowQuery.java +++ b/tajo-core/src/test/java/org/apache/tajo/engine/query/TestWindowQuery.java @@ -21,11 +21,18 @@ import org.apache.tajo.IntegrationTest; import org.apache.tajo.QueryTestCaseBase; import org.apache.tajo.TajoConstants; +import org.apache.tajo.TajoTestingCluster; +import org.apache.tajo.catalog.Schema; +import org.apache.tajo.common.TajoDataTypes; +import org.apache.tajo.storage.StorageConstants; +import org.apache.tajo.util.KeyValueSet; import org.junit.Test; import org.junit.experimental.categories.Category; import java.sql.ResultSet; +import static org.junit.Assert.assertEquals; + @Category(IntegrationTest.class) public class TestWindowQuery extends QueryTestCaseBase { @@ -252,6 +259,33 @@ public final void firstValue1() throws Exception { cleanupQuery(res); } + @Test + public final void firstValueTime() throws Exception { + KeyValueSet tableOptions = new KeyValueSet(); + tableOptions.set(StorageConstants.TEXT_DELIMITER, StorageConstants.DEFAULT_FIELD_DELIMITER); + tableOptions.set(StorageConstants.TEXT_NULL, "\\\\N"); + + Schema schema = new Schema(); + schema.addColumn("id", TajoDataTypes.Type.INT4); + schema.addColumn("time", TajoDataTypes.Type.TIME); + String[] data = new String[]{ "1|12:11:12", "2|10:11:13", "2|05:42:41" }; + TajoTestingCluster.createTable("firstvaluetime", schema, tableOptions, data, 1); + + try { + ResultSet res = executeString("select id, first_value(time) over ( partition by id order by time ) as time_first from firstvaluetime"); + String ascExpected = "id,time_first\n" + + "-------------------------------\n" + + "1,12:11:12\n" + + "2,05:42:41\n" + + "2,05:42:41\n"; + + assertEquals(ascExpected, resultSetToString(res)); + res.close(); + } finally { + executeString("DROP TABLE firstvaluetime PURGE"); + } + } + @Test public final void lastValue1() throws Exception { ResultSet res = executeQuery(); @@ -259,4 +293,30 @@ public final void lastValue1() throws Exception { cleanupQuery(res); } + @Test + public final void lastValueTime() throws Exception { + KeyValueSet tableOptions = new KeyValueSet(); + tableOptions.set(StorageConstants.TEXT_DELIMITER, StorageConstants.DEFAULT_FIELD_DELIMITER); + tableOptions.set(StorageConstants.TEXT_NULL, "\\\\N"); + + Schema schema = new Schema(); + schema.addColumn("id", TajoDataTypes.Type.INT4); + schema.addColumn("time", TajoDataTypes.Type.TIME); + String[] data = new String[]{ "1|12:11:12", "2|10:11:13", "2|05:42:41" }; + TajoTestingCluster.createTable("lastvaluetime", schema, tableOptions, data, 1); + + try { + ResultSet res = executeString("select id, last_value(time) over ( partition by id order by time ) as time_last from lastvaluetime"); + String ascExpected = "id,time_last\n" + + "-------------------------------\n" + + "1,12:11:12\n" + + "2,10:11:13\n" + + "2,10:11:13\n"; + + assertEquals(ascExpected, resultSetToString(res)); + res.close(); + } finally { + executeString("DROP TABLE lastvaluetime PURGE"); + } + } } \ No newline at end of file diff --git a/tajo-core/src/test/resources/queries/TestWindowQuery/firstValue1.sql b/tajo-core/src/test/resources/queries/TestWindowQuery/firstValue1.sql index e11e0e6c6d..e9c9c73c34 100644 --- a/tajo-core/src/test/resources/queries/TestWindowQuery/firstValue1.sql +++ b/tajo-core/src/test/resources/queries/TestWindowQuery/firstValue1.sql @@ -1,5 +1,18 @@ SELECT l_orderkey, - first_value(l_shipmode) over (PARTITION BY L_ORDERKEY order by l_shipmode ) as shipmode_first + first_value(l_shipmode) over (PARTITION BY L_ORDERKEY order by l_shipmode ) as shipmode_first, + first_value(l_linenumber) over (PARTITION BY L_ORDERKEY order by l_linenumber ) as linenumber_first, + first_value(l_suppkey_t) over (PARTITION BY L_ORDERKEY order by l_suppkey_t ) as suppkey_first, + first_value(l_shipdate_t) over (PARTITION BY L_ORDERKEY order by l_shipdate_t ) as shipdate_first, + first_value(l_commitdate_t) over (PARTITION BY L_ORDERKEY order by l_commitdate_t ) as commitdate_first, + first_value(l_extendedprice) over (PARTITION BY L_ORDERKEY order by l_extendedprice ) as extendedprice_first, + first_value(l_discount_t) over (PARTITION BY L_ORDERKEY order by l_discount_t ) as discount_first FROM - LINEITEM \ No newline at end of file +( + SELECT + l_orderkey,l_partkey,l_suppkey::INT8 as l_suppkey_t,l_linenumber,l_quantity, + l_extendedprice,l_discount::FLOAT4 as l_discount_t,l_tax,l_returnflag,l_linestatus, + l_shipdate::DATE as l_shipdate_t,l_commitdate::TIMESTAMP as l_commitdate_t,l_receiptdate,l_shipinstruct,l_shipmode,l_comment + FROM + LINEITEM +) xx \ No newline at end of file diff --git a/tajo-core/src/test/resources/queries/TestWindowQuery/lastValue1.sql b/tajo-core/src/test/resources/queries/TestWindowQuery/lastValue1.sql index 627adefcaa..150b91256d 100644 --- a/tajo-core/src/test/resources/queries/TestWindowQuery/lastValue1.sql +++ b/tajo-core/src/test/resources/queries/TestWindowQuery/lastValue1.sql @@ -1,5 +1,18 @@ SELECT l_orderkey, - last_value(l_shipmode) over (PARTITION BY L_ORDERKEY order by l_shipmode ) as shipmode_first + last_value(l_shipmode) over (PARTITION BY L_ORDERKEY order by l_shipmode ) as shipmode_last, + last_value(l_linenumber) over (PARTITION BY L_ORDERKEY order by l_linenumber ) as linenumber_last, + last_value(l_suppkey_t) over (PARTITION BY L_ORDERKEY order by l_suppkey_t ) as suppkey_last, + last_value(l_shipdate_t) over (PARTITION BY L_ORDERKEY order by l_shipdate_t ) as shipdate_last, + last_value(l_commitdate_t) over (PARTITION BY L_ORDERKEY order by l_commitdate_t ) as commitdate_last, + last_value(l_extendedprice) over (PARTITION BY L_ORDERKEY order by l_extendedprice ) as extendedprice_last, + last_value(l_discount_t) over (PARTITION BY L_ORDERKEY order by l_discount_t ) as discount_last FROM - LINEITEM \ No newline at end of file +( + SELECT + l_orderkey,l_partkey,l_suppkey::INT8 as l_suppkey_t,l_linenumber,l_quantity, + l_extendedprice,l_discount::FLOAT4 as l_discount_t,l_tax,l_returnflag,l_linestatus, + l_shipdate::DATE as l_shipdate_t,l_commitdate::TIMESTAMP as l_commitdate_t,l_receiptdate,l_shipinstruct,l_shipmode,l_comment + FROM + LINEITEM +) xx \ No newline at end of file diff --git a/tajo-core/src/test/resources/results/TestWindowQuery/firstValue1.result b/tajo-core/src/test/resources/results/TestWindowQuery/firstValue1.result index 43e6b42462..8ca4ea9897 100644 --- a/tajo-core/src/test/resources/results/TestWindowQuery/firstValue1.result +++ b/tajo-core/src/test/resources/results/TestWindowQuery/firstValue1.result @@ -1,7 +1,7 @@ -l_orderkey,shipmode_first +l_orderkey,shipmode_first,linenumber_first,suppkey_first,shipdate_first,commitdate_first,extendedprice_first,discount_first ------------------------------- -1,MAIL -1,MAIL -2,RAIL -3,AIR -3,AIR \ No newline at end of file +1,MAIL,1,7311,1996-03-13,1996-02-12 00:00:00,21168.23,0.04 +1,MAIL,1,7311,1996-03-13,1996-02-12 00:00:00,21168.23,0.04 +2,RAIL,1,1191,1997-01-28,1997-01-14 00:00:00,44694.46,0.0 +3,AIR,1,1798,1993-11-09,1993-12-20 00:00:00,46796.47,0.06 +3,AIR,1,1798,1993-11-09,1993-12-20 00:00:00,46796.47,0.06 \ No newline at end of file diff --git a/tajo-core/src/test/resources/results/TestWindowQuery/lastValue1.result b/tajo-core/src/test/resources/results/TestWindowQuery/lastValue1.result index d68d2bd9ac..825f9828a4 100644 --- a/tajo-core/src/test/resources/results/TestWindowQuery/lastValue1.result +++ b/tajo-core/src/test/resources/results/TestWindowQuery/lastValue1.result @@ -1,7 +1,7 @@ -l_orderkey,shipmode_first +l_orderkey,shipmode_last,linenumber_last,suppkey_last,shipdate_last,commitdate_last,extendedprice_last,discount_last ------------------------------- -1,TRUCK -1,TRUCK -2,RAIL -3,RAIL -3,RAIL \ No newline at end of file +1,TRUCK,2,7706,1996-04-12,1996-02-28 00:00:00,45983.16,0.09 +1,TRUCK,2,7706,1996-04-12,1996-02-28 00:00:00,45983.16,0.09 +2,RAIL,1,1191,1997-01-28,1997-01-14 00:00:00,44694.46,0.0 +3,RAIL,2,6540,1994-02-02,1994-01-04 00:00:00,54058.05,0.1 +3,RAIL,2,6540,1994-02-02,1994-01-04 00:00:00,54058.05,0.1 \ No newline at end of file