From 04a22c20ab76759fe72b6dea97775d94b3e2c026 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=EA=B9=80=ED=98=95=EC=A4=80?= Date: Thu, 29 May 2014 15:47:50 +0900 Subject: [PATCH] TAJO-843: implements COALESCE for BOOLEAN, DATE, TIME, TIMESTAMP --- .../org/apache/tajo/catalog/CatalogUtil.java | 8 ++++ .../function/builtin/CoalesceBoolean.java | 44 +++++++++++++++++++ .../engine/function/builtin/CoalesceDate.java | 44 +++++++++++++++++++ .../engine/function/builtin/CoalesceTime.java | 44 +++++++++++++++++++ .../function/builtin/CoalesceTimestamp.java | 44 +++++++++++++++++++ .../function/TestConditionalExpressions.java | 40 +++++++++++++++++ 6 files changed, 224 insertions(+) create mode 100644 tajo-core/src/main/java/org/apache/tajo/engine/function/builtin/CoalesceBoolean.java create mode 100644 tajo-core/src/main/java/org/apache/tajo/engine/function/builtin/CoalesceDate.java create mode 100644 tajo-core/src/main/java/org/apache/tajo/engine/function/builtin/CoalesceTime.java create mode 100644 tajo-core/src/main/java/org/apache/tajo/engine/function/builtin/CoalesceTimestamp.java 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 85ea516f67..2ee0a67718 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 @@ -658,6 +658,14 @@ public static boolean isCompatibleType(final Type definedType, final Type givenT if (Type.TEXT_ARRAY.getNumber() <= argTypeNumber && argTypeNumber <= exitingTypeNumber) { flag = true; } + } else if (givenType == Type.BOOLEAN && (definedType == Type.BOOLEAN || definedType == Type.BOOLEAN_ARRAY)) { + flag = true; + } else if (givenType == Type.DATE && (definedType == Type.DATE || definedType == Type.DATE_ARRAY)) { + flag = true; + } else if (givenType == Type.TIME && (definedType == Type.TIME || definedType == Type.TIME_ARRAY)) { + flag = true; + } else if (givenType == Type.TIMESTAMP && (definedType == Type.TIMESTAMP || definedType == Type.TIMESTAMP_ARRAY)) { + flag = true; } } return flag; diff --git a/tajo-core/src/main/java/org/apache/tajo/engine/function/builtin/CoalesceBoolean.java b/tajo-core/src/main/java/org/apache/tajo/engine/function/builtin/CoalesceBoolean.java new file mode 100644 index 0000000000..8c714c5eff --- /dev/null +++ b/tajo-core/src/main/java/org/apache/tajo/engine/function/builtin/CoalesceBoolean.java @@ -0,0 +1,44 @@ +/** + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.apache.tajo.engine.function.builtin; + +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 = "coalesce", + description = "Returns the first of its arguments that is not null.", + detail = "Like a CASE expression, COALESCE only evaluates the arguments that are needed to determine the result; " + + "that is, arguments to the right of the first non-null argument are not evaluated", + example = "> SELECT coalesce(null, null, true);\n" + + "true", + returnType = Type.BOOLEAN, + paramTypes = {@ParamTypes(paramTypes = {Type.BOOLEAN, TajoDataTypes.Type.BOOLEAN_ARRAY})} +) +public class CoalesceBoolean extends Coalesce { + public CoalesceBoolean() { + super(new Column[] { + new Column("column", TajoDataTypes.Type.BOOLEAN), + new Column("params", TajoDataTypes.Type.BOOLEAN_ARRAY), + }); + } +} diff --git a/tajo-core/src/main/java/org/apache/tajo/engine/function/builtin/CoalesceDate.java b/tajo-core/src/main/java/org/apache/tajo/engine/function/builtin/CoalesceDate.java new file mode 100644 index 0000000000..23f8f0c545 --- /dev/null +++ b/tajo-core/src/main/java/org/apache/tajo/engine/function/builtin/CoalesceDate.java @@ -0,0 +1,44 @@ +/** + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.apache.tajo.engine.function.builtin; + +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 = "coalesce", + description = "Returns the first of its arguments that is not null.", + detail = "Like a CASE expression, COALESCE only evaluates the arguments that are needed to determine the result; " + + "that is, arguments to the right of the first non-null argument are not evaluated", + example = "> SELECT coalesce(null, null, date '2014-01-01');\n" + + "2014-01-01", + returnType = Type.DATE, + paramTypes = {@ParamTypes(paramTypes = {Type.DATE, Type.DATE_ARRAY})} +) +public class CoalesceDate extends Coalesce { + public CoalesceDate() { + super(new Column[] { + new Column("column", TajoDataTypes.Type.DATE), + new Column("params", TajoDataTypes.Type.DATE_ARRAY), + }); + } +} diff --git a/tajo-core/src/main/java/org/apache/tajo/engine/function/builtin/CoalesceTime.java b/tajo-core/src/main/java/org/apache/tajo/engine/function/builtin/CoalesceTime.java new file mode 100644 index 0000000000..01bb6ded5f --- /dev/null +++ b/tajo-core/src/main/java/org/apache/tajo/engine/function/builtin/CoalesceTime.java @@ -0,0 +1,44 @@ +/** + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.apache.tajo.engine.function.builtin; + +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 = "coalesce", + description = "Returns the first of its arguments that is not null.", + detail = "Like a CASE expression, COALESCE only evaluates the arguments that are needed to determine the result; " + + "that is, arguments to the right of the first non-null argument are not evaluated", + example = "> SELECT coalesce(null, null, time '12:10:00');\n" + + "12:10:00", + returnType = Type.TIME, + paramTypes = {@ParamTypes(paramTypes = {Type.TIME, Type.TIME_ARRAY})} +) +public class CoalesceTime extends Coalesce { + public CoalesceTime() { + super(new Column[] { + new Column("column", TajoDataTypes.Type.TIME), + new Column("params", TajoDataTypes.Type.TIME_ARRAY), + }); + } +} diff --git a/tajo-core/src/main/java/org/apache/tajo/engine/function/builtin/CoalesceTimestamp.java b/tajo-core/src/main/java/org/apache/tajo/engine/function/builtin/CoalesceTimestamp.java new file mode 100644 index 0000000000..2609717ec9 --- /dev/null +++ b/tajo-core/src/main/java/org/apache/tajo/engine/function/builtin/CoalesceTimestamp.java @@ -0,0 +1,44 @@ +/** + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.apache.tajo.engine.function.builtin; + +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 = "coalesce", + description = "Returns the first of its arguments that is not null.", + detail = "Like a CASE expression, COALESCE only evaluates the arguments that are needed to determine the result; " + + "that is, arguments to the right of the first non-null argument are not evaluated", + example = "> SELECT coalesce(null, null, timestamp '2014-01-01');\n" + + "2014-01-01 00:00:00", + returnType = Type.TIMESTAMP, + paramTypes = {@ParamTypes(paramTypes = {Type.TIMESTAMP, Type.TIMESTAMP_ARRAY})} +) +public class CoalesceTimestamp extends Coalesce { + public CoalesceTimestamp() { + super(new Column[] { + new Column("column", TajoDataTypes.Type.TIMESTAMP), + new Column("params", TajoDataTypes.Type.TIMESTAMP_ARRAY), + }); + } +} diff --git a/tajo-core/src/test/java/org/apache/tajo/engine/function/TestConditionalExpressions.java b/tajo-core/src/test/java/org/apache/tajo/engine/function/TestConditionalExpressions.java index af8638731f..ece34e7155 100644 --- a/tajo-core/src/test/java/org/apache/tajo/engine/function/TestConditionalExpressions.java +++ b/tajo-core/src/test/java/org/apache/tajo/engine/function/TestConditionalExpressions.java @@ -79,4 +79,44 @@ public void testCoalesceDouble() throws Exception { //success } } + + @Test + public void testCoalesceBoolean() throws Exception { + testSimpleEval("select coalesce(null, false);", new String[]{"f"}); + testSimpleEval("select coalesce(null, null, true);", new String[]{"t"}); + testSimpleEval("select coalesce(true, null, false);", new String[]{"t"}); + testSimpleEval("select coalesce(null, true, false);", new String[]{"t"}); + } + + @Test + public void testCoalesceTimestamp() throws Exception { + testSimpleEval("select coalesce(null, timestamp '2014-01-01 00:00:00');", + new String[]{"2014-01-01 00:00:00" + getUserTimeZoneDisplay()}); + testSimpleEval("select coalesce(null, null, timestamp '2014-01-01 00:00:00');", + new String[]{"2014-01-01 00:00:00" + getUserTimeZoneDisplay()}); + testSimpleEval("select coalesce(timestamp '2014-01-01 00:00:00', null, timestamp '2014-01-02 00:00:00');", + new String[]{"2014-01-01 00:00:00" + getUserTimeZoneDisplay()}); + testSimpleEval("select coalesce(null, timestamp '2014-01-01 00:00:00', timestamp '2014-02-01 00:00:00');", + new String[]{"2014-01-01 00:00:00" + getUserTimeZoneDisplay()}); + } + + @Test + public void testCoalesceTime() throws Exception { + testSimpleEval("select coalesce(null, time '12:00:00');", + new String[]{"12:00:00" + getUserTimeZoneDisplay()}); + testSimpleEval("select coalesce(null, null, time '12:00:00');", + new String[]{"12:00:00" + getUserTimeZoneDisplay()}); + testSimpleEval("select coalesce(time '12:00:00', null, time '13:00:00');", + new String[]{"12:00:00" + getUserTimeZoneDisplay()}); + testSimpleEval("select coalesce(null, time '12:00:00', time '13:00:00');", + new String[]{"12:00:00" + getUserTimeZoneDisplay()}); + } + + @Test + public void testCoalesceDate() throws Exception { + testSimpleEval("select coalesce(null, date '2014-01-01');", new String[]{"2014-01-01"}); + testSimpleEval("select coalesce(null, null, date '2014-01-01');", new String[]{"2014-01-01"}); + testSimpleEval("select coalesce(date '2014-01-01', null, date '2014-02-01');", new String[]{"2014-01-01"}); + testSimpleEval("select coalesce(null, date '2014-01-01', date '2014-02-01');", new String[]{"2014-01-01"}); + } }