You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@tajo.apache.org by hy...@apache.org on 2013/12/07 20:33:15 UTC
git commit: TAJO-343: Implement locate function. (KyoungBok Lee via
hyunsik)
Updated Branches:
refs/heads/master b444061e2 -> 3c2a6343f
TAJO-343: Implement locate function. (KyoungBok Lee via hyunsik)
Project: http://git-wip-us.apache.org/repos/asf/incubator-tajo/repo
Commit: http://git-wip-us.apache.org/repos/asf/incubator-tajo/commit/3c2a6343
Tree: http://git-wip-us.apache.org/repos/asf/incubator-tajo/tree/3c2a6343
Diff: http://git-wip-us.apache.org/repos/asf/incubator-tajo/diff/3c2a6343
Branch: refs/heads/master
Commit: 3c2a6343fe9056c9e520442b744ba924704fc3dd
Parents: b444061
Author: Hyunsik Choi <hy...@apache.org>
Authored: Sun Dec 8 04:32:56 2013 +0900
Committer: Hyunsik Choi <hy...@apache.org>
Committed: Sun Dec 8 04:32:56 2013 +0900
----------------------------------------------------------------------
CHANGES.txt | 2 +
.../tajo/engine/function/string/Locate.java | 94 ++++++++++++++++++++
.../java/org/apache/tajo/master/TajoMaster.java | 9 ++
.../TestStringOperatorsAndFunctions.java | 51 +++++++++++
4 files changed, 156 insertions(+)
----------------------------------------------------------------------
http://git-wip-us.apache.org/repos/asf/incubator-tajo/blob/3c2a6343/CHANGES.txt
----------------------------------------------------------------------
diff --git a/CHANGES.txt b/CHANGES.txt
index 728858e..41ae245 100644
--- a/CHANGES.txt
+++ b/CHANGES.txt
@@ -4,6 +4,8 @@ Release 0.8.0 - unreleased
NEW FEATURES
+ TAJO-343: Implement locate function. (KyoungBok Lee via hyunsik)
+
TAJO-364: Implement mod/div function. (DaeMyung Kang via jaehwa)
TAJO-361: Implement rpad function. (Seungun Choe via jaehwa)
http://git-wip-us.apache.org/repos/asf/incubator-tajo/blob/3c2a6343/tajo-core/tajo-core-backend/src/main/java/org/apache/tajo/engine/function/string/Locate.java
----------------------------------------------------------------------
diff --git a/tajo-core/tajo-core-backend/src/main/java/org/apache/tajo/engine/function/string/Locate.java b/tajo-core/tajo-core-backend/src/main/java/org/apache/tajo/engine/function/string/Locate.java
new file mode 100644
index 0000000..704d944
--- /dev/null
+++ b/tajo-core/tajo-core-backend/src/main/java/org/apache/tajo/engine/function/string/Locate.java
@@ -0,0 +1,94 @@
+/**
+ * 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.string;
+
+import org.apache.commons.lang.StringUtils;
+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.engine.function.GeneralFunction;
+import org.apache.tajo.storage.Tuple;
+
+/**
+ * Function definition.
+ *
+ * INT4 locate(string TEXT, substr TEXT, [, pos INT4])
+ */
+public class Locate extends GeneralFunction {
+ public Locate() {
+ super(new Column[] {
+ new Column("string", TajoDataTypes.Type.TEXT),
+ new Column("substr", TajoDataTypes.Type.TEXT),
+ new Column("pos", TajoDataTypes.Type.INT4)
+ });
+ }
+
+ /**
+ * Returns the position of the first occurance of substr in string after position pos (using one-based index).
+ *
+ * if substr is empty string, it always matches except
+ * pos is greater than string length + 1.(mysql locate() function spec.)
+ * At any not matched case, it returns 0.
+ */
+ private int locate(String str, String substr, int pos) {
+ if (substr.length() == 0) {
+ if (pos <= (str.length() + 1)) {
+ return pos;
+ }
+ else {
+ return 0;
+ }
+ }
+ int idx = StringUtils.indexOf(str, substr, pos - 1);
+ if (idx == -1) {
+ return 0;
+ }
+ return idx + 1;
+ }
+
+ @Override
+ public Datum eval(Tuple params) {
+ Datum strDatum = params.get(0);
+ if(strDatum instanceof NullDatum) {
+ return NullDatum.get();
+ }
+ Datum substrDatum = params.get(1);
+ if (substrDatum instanceof NullDatum) {
+ return NullDatum.get();
+ }
+
+ int pos = 1; // one-based index
+ if (params.size() > 2) {
+ pos = params.get(2).asInt4();
+ if (pos < 0) {
+ return DatumFactory.createInt4(0); // negative value is not acceptable.
+ }
+ if (pos == 0) {
+ pos = 1; // one-based index
+ }
+ }
+
+ String str = strDatum.asChars();
+ String substr = substrDatum.asChars();
+
+ return DatumFactory.createInt4(locate(str, substr, pos));
+ }
+}
http://git-wip-us.apache.org/repos/asf/incubator-tajo/blob/3c2a6343/tajo-core/tajo-core-backend/src/main/java/org/apache/tajo/master/TajoMaster.java
----------------------------------------------------------------------
diff --git a/tajo-core/tajo-core-backend/src/main/java/org/apache/tajo/master/TajoMaster.java b/tajo-core/tajo-core-backend/src/main/java/org/apache/tajo/master/TajoMaster.java
index fa3732d..9243aa4 100644
--- a/tajo-core/tajo-core-backend/src/main/java/org/apache/tajo/master/TajoMaster.java
+++ b/tajo-core/tajo-core-backend/src/main/java/org/apache/tajo/master/TajoMaster.java
@@ -448,6 +448,15 @@ public class TajoMaster extends CompositeService {
new FunctionDesc("substr", Substr.class, FunctionType.GENERAL,
CatalogUtil.newSimpleDataType(Type.TEXT),
CatalogUtil.newSimpleDataTypeArray(Type.TEXT, Type.INT4, Type.INT4)));
+
+ sqlFuncs.add(
+ new FunctionDesc("locate", Locate.class, FunctionType.GENERAL,
+ CatalogUtil.newSimpleDataType(Type.INT4),
+ CatalogUtil.newSimpleDataTypeArray(Type.TEXT, Type.TEXT)));
+ sqlFuncs.add(
+ new FunctionDesc("locate", Locate.class, FunctionType.GENERAL,
+ CatalogUtil.newSimpleDataType(Type.INT4),
+ CatalogUtil.newSimpleDataTypeArray(Type.TEXT, Type.TEXT, Type.INT4)));
sqlFuncs.add(
new FunctionDesc("round", Round.class, FunctionType.GENERAL,
http://git-wip-us.apache.org/repos/asf/incubator-tajo/blob/3c2a6343/tajo-core/tajo-core-backend/src/test/java/org/apache/tajo/engine/function/TestStringOperatorsAndFunctions.java
----------------------------------------------------------------------
diff --git a/tajo-core/tajo-core-backend/src/test/java/org/apache/tajo/engine/function/TestStringOperatorsAndFunctions.java b/tajo-core/tajo-core-backend/src/test/java/org/apache/tajo/engine/function/TestStringOperatorsAndFunctions.java
index 92507ad..bbe965f 100644
--- a/tajo-core/tajo-core-backend/src/test/java/org/apache/tajo/engine/function/TestStringOperatorsAndFunctions.java
+++ b/tajo-core/tajo-core-backend/src/test/java/org/apache/tajo/engine/function/TestStringOperatorsAndFunctions.java
@@ -353,6 +353,57 @@ public class TestStringOperatorsAndFunctions extends ExprTestBase {
testEval(schema, "table1", ",abcdef,3.14", "select substr(lower(col2), 2, 3) from table1",
new String[]{"bcd"});
}
+
+ @Test
+ public void testLocate() throws IOException {
+ // normal case
+ testSimpleEval("select locate('abcdef', 'a') as col1 ", new String[]{"1"});
+ testSimpleEval("select locate('abcdef', 'a', 0) as col1 ", new String[]{"1"});
+ testSimpleEval("select locate('abcdef', 'a', 1) as col1 ", new String[]{"1"});
+ testSimpleEval("select locate('abcdef', 'z') as col1 ", new String[]{"0"});
+ testSimpleEval("select locate('abcdef', 'z', 1) as col1 ", new String[]{"0"});
+ testSimpleEval("select locate('foobarbar', 'bar') as col1 ", new String[]{"4"});
+ testSimpleEval("select locate('foobarbar', 'bar', 0) as col1 ", new String[]{"4"});
+ testSimpleEval("select locate('foobarbar', 'bar', 1) as col1 ", new String[]{"4"});
+ testSimpleEval("select locate('foobarbar', 'bar', 5) as col1 ", new String[]{"7"});
+ testSimpleEval("select locate('foobarbar', 'bar', 9) as col1 ", new String[]{"0"});
+ testSimpleEval("select locate('가나다라마라마', '라마') as col1 ", new String[]{"4"});
+ testSimpleEval("select locate('가나다라마라마', '라마', 5) as col1 ", new String[]{"6"});
+ // empty string
+ testSimpleEval("select locate('abcdef', '') as col1 ", new String[]{"1"});
+ testSimpleEval("select locate('abcdef', '', 2) as col1 ", new String[]{"2"});
+ testSimpleEval("select locate('abcdef', '', 6) as col1 ", new String[]{"6"}); // pos = last index of string (expected value(6) is tested on mysql)
+ testSimpleEval("select locate('abcdef', '', 7) as col1 ", new String[]{"7"}); // pos = last index + 1 (expected value(7) is tested on mysql)
+ testSimpleEval("select locate('abcdef', '', 8) as col1 ", new String[]{"0"}); // pos = greater then last index + 1 (expected value(0) is tested on mysql)
+ testSimpleEval("select locate('abcdef', '', 9) as col1 ", new String[]{"0"}); // pos = greater then last index + 1 (expected value(0) is tested on mysql)
+ testSimpleEval("select locate('가나다라', '', 2) as col1 ", new String[]{"2"});
+ testSimpleEval("select locate('가나다라', '', 4) as col1 ", new String[]{"4"});
+ testSimpleEval("select locate('가나다라', '', 5) as col1 ", new String[]{"5"});
+ testSimpleEval("select locate('가나다라', '', 6) as col1 ", new String[]{"0"});
+
+ //TODO If there is a minus value in function argument, next error occurred.
+ //org.apache.tajo.engine.parser.SQLSyntaxError: ERROR: syntax error at or near 'locate'
+ //LINE 1:7 select locate('abcdef', 'a', -1) as col1
+ // ^^^^^^
+ //at org.apache.tajo.engine.parser.SQLAnalyzer.parse(SQLAnalyzer.java:64)
+
+ // negative pos
+ //testSimpleEval("select locate('abcdef', 'a', -1) as col1 ", new String[]{"0"});
+ //testSimpleEval("select locate('abcdef', 'a', -5) as col1 ", new String[]{"0"});
+
+ Schema schema = new Schema();
+ schema.addColumn("col1", TEXT);
+ schema.addColumn("col2", TEXT);
+ schema.addColumn("col3", TEXT);
+ testEval(schema, "table1", ",abcdef,3.14", "select locate(col2, 'cd') from table1", new String[]{"3"});
+ testEval(schema, "table1", ",abcdef,3.14", "select locate(col2, 'cd', 1) from table1", new String[]{"3"});
+ testEval(schema, "table1", ",abcdef,3.14", "select locate(col2, 'cd', 4) from table1", new String[]{"0"});
+ testEval(schema, "table1", ",abcdef,3.14", "select locate(col2, 'xy') from table1", new String[]{"0"});
+ // null string
+ testEval(schema, "table1", ",abcdef,3.14", "select locate(col1, 'cd') is null from table1", new String[]{"t"});
+ // nul substring
+ testEval(schema, "table1", ",abcdef,3.14", "select locate('cd', col1) is null from table1", new String[]{"t"});
+ }
@Test
public void testBitLength() throws IOException {