You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@calcite.apache.org by jh...@apache.org on 2016/05/04 00:03:09 UTC

[1/2] calcite git commit: [CALCITE-1115] Add TRANSLATE function with 3 parameters, like the one in Oracle (Javanshir Yelchiyev)

Repository: calcite
Updated Branches:
  refs/heads/master af315fbea -> 1be4056b4


[CALCITE-1115] Add TRANSLATE function with 3 parameters, like the one in Oracle (Javanshir Yelchiyev)

Close apache/calcite#225


Project: http://git-wip-us.apache.org/repos/asf/calcite/repo
Commit: http://git-wip-us.apache.org/repos/asf/calcite/commit/4e33eedc
Tree: http://git-wip-us.apache.org/repos/asf/calcite/tree/4e33eedc
Diff: http://git-wip-us.apache.org/repos/asf/calcite/diff/4e33eedc

Branch: refs/heads/master
Commit: 4e33eedc2412085a475110101d92c9910930f897
Parents: af315fb
Author: Javanshir Yelchiyev <ja...@gmail.com>
Authored: Thu Apr 28 13:41:58 2016 +0300
Committer: Julian Hyde <jh...@apache.org>
Committed: Tue May 3 10:27:47 2016 -0700

----------------------------------------------------------------------
 core/pom.xml                                    |  1 -
 core/src/main/codegen/templates/Parser.jj       | 32 ++++++---
 .../calcite/adapter/enumerable/RexImpTable.java |  2 +
 .../adapter/enumerable/RexToLixTranslator.java  |  5 +-
 .../rex/RexSqlStandardConvertletTable.java      |  1 +
 .../apache/calcite/runtime/SqlFunctions.java    |  5 ++
 .../calcite/sql/fun/SqlStdOperatorTable.java    | 11 +++
 .../calcite/sql/fun/SqlTranslate3Function.java  | 72 ++++++++++++++++++++
 .../org/apache/calcite/util/BuiltInMethod.java  |  1 +
 .../calcite/sql/parser/SqlParserTest.java       |  6 ++
 .../calcite/sql/test/SqlOperatorBaseTest.java   | 26 +++++++
 .../apache/calcite/test/SqlValidatorTest.java   |  4 ++
 12 files changed, 154 insertions(+), 12 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/calcite/blob/4e33eedc/core/pom.xml
----------------------------------------------------------------------
diff --git a/core/pom.xml b/core/pom.xml
index 9e6cdb2..4d46afd 100644
--- a/core/pom.xml
+++ b/core/pom.xml
@@ -58,7 +58,6 @@ limitations under the License.
     <dependency>
       <groupId>org.apache.commons</groupId>
       <artifactId>commons-lang3</artifactId>
-      <scope>test</scope>
     </dependency>
     <dependency>
       <groupId>com.google.code.findbugs</groupId>

http://git-wip-us.apache.org/repos/asf/calcite/blob/4e33eedc/core/src/main/codegen/templates/Parser.jj
----------------------------------------------------------------------
diff --git a/core/src/main/codegen/templates/Parser.jj b/core/src/main/codegen/templates/Parser.jj
index 05de289..51133e6 100644
--- a/core/src/main/codegen/templates/Parser.jj
+++ b/core/src/main/codegen/templates/Parser.jj
@@ -4090,16 +4090,28 @@ SqlNode BuiltinFunctionCall() :
         {
             args = startList(e);
         }
-        <USING> name = Identifier()
-        {
-            namePos = getPos();
-            args.add(new SqlIdentifier(name, namePos));
-        }
-        <RPAREN>
-        {
-            return SqlStdOperatorTable.TRANSLATE.createCall(
-                pos, SqlParserUtil.toNodeArray(args));
-        }
+        (
+            <USING> name = Identifier()
+            {
+                namePos = getPos();
+                args.add(new SqlIdentifier(name, namePos));
+            }
+            <RPAREN>
+            {
+                return SqlStdOperatorTable.TRANSLATE.createCall(
+                    pos, SqlParserUtil.toNodeArray(args));
+            }
+            |
+            <COMMA>
+            e = Expression(ExprContext.ACCEPT_SUBQUERY) { args.add(e); }
+            <COMMA>
+            e = Expression(ExprContext.ACCEPT_SUBQUERY) { args.add(e); }
+            <RPAREN>
+            {
+                return SqlStdOperatorTable.TRANSLATE3.createCall(
+                    pos.plus(getPos()), SqlParserUtil.toNodeArray(args));
+            }
+        )
     )
     |
     (

http://git-wip-us.apache.org/repos/asf/calcite/blob/4e33eedc/core/src/main/java/org/apache/calcite/adapter/enumerable/RexImpTable.java
----------------------------------------------------------------------
diff --git a/core/src/main/java/org/apache/calcite/adapter/enumerable/RexImpTable.java b/core/src/main/java/org/apache/calcite/adapter/enumerable/RexImpTable.java
index e03f6b8..567f88c 100644
--- a/core/src/main/java/org/apache/calcite/adapter/enumerable/RexImpTable.java
+++ b/core/src/main/java/org/apache/calcite/adapter/enumerable/RexImpTable.java
@@ -168,6 +168,7 @@ import static org.apache.calcite.sql.fun.SqlStdOperatorTable.SUBSTRING;
 import static org.apache.calcite.sql.fun.SqlStdOperatorTable.SUM;
 import static org.apache.calcite.sql.fun.SqlStdOperatorTable.SUM0;
 import static org.apache.calcite.sql.fun.SqlStdOperatorTable.SYSTEM_USER;
+import static org.apache.calcite.sql.fun.SqlStdOperatorTable.TRANSLATE3;
 import static org.apache.calcite.sql.fun.SqlStdOperatorTable.TRIM;
 import static org.apache.calcite.sql.fun.SqlStdOperatorTable.UNARY_MINUS;
 import static org.apache.calcite.sql.fun.SqlStdOperatorTable.UNARY_PLUS;
@@ -201,6 +202,7 @@ public class RexImpTable {
     defineMethod(LOWER, BuiltInMethod.LOWER.method, NullPolicy.STRICT);
     defineMethod(INITCAP,  BuiltInMethod.INITCAP.method, NullPolicy.STRICT);
     defineMethod(SUBSTRING, BuiltInMethod.SUBSTRING.method, NullPolicy.STRICT);
+    defineMethod(TRANSLATE3, BuiltInMethod.TRANSLATE3.method, NullPolicy.STRICT);
     defineMethod(CHARACTER_LENGTH, BuiltInMethod.CHAR_LENGTH.method,
         NullPolicy.STRICT);
     defineMethod(CHAR_LENGTH, BuiltInMethod.CHAR_LENGTH.method,

http://git-wip-us.apache.org/repos/asf/calcite/blob/4e33eedc/core/src/main/java/org/apache/calcite/adapter/enumerable/RexToLixTranslator.java
----------------------------------------------------------------------
diff --git a/core/src/main/java/org/apache/calcite/adapter/enumerable/RexToLixTranslator.java b/core/src/main/java/org/apache/calcite/adapter/enumerable/RexToLixTranslator.java
index 2af6b46..4732d26 100644
--- a/core/src/main/java/org/apache/calcite/adapter/enumerable/RexToLixTranslator.java
+++ b/core/src/main/java/org/apache/calcite/adapter/enumerable/RexToLixTranslator.java
@@ -67,6 +67,7 @@ import java.util.Map;
 import static org.apache.calcite.sql.fun.SqlStdOperatorTable.CHARACTER_LENGTH;
 import static org.apache.calcite.sql.fun.SqlStdOperatorTable.CHAR_LENGTH;
 import static org.apache.calcite.sql.fun.SqlStdOperatorTable.SUBSTRING;
+import static org.apache.calcite.sql.fun.SqlStdOperatorTable.TRANSLATE3;
 import static org.apache.calcite.sql.fun.SqlStdOperatorTable.UPPER;
 
 /**
@@ -83,7 +84,9 @@ public class RexToLixTranslator {
           findMethod(SqlFunctions.class, "charLength", String.class),
           CHARACTER_LENGTH,
           findMethod(SqlFunctions.class, "charLength", String.class),
-          CHAR_LENGTH);
+          CHAR_LENGTH,
+          findMethod(SqlFunctions.class, "translate3", String.class, String.class,
+              String.class), TRANSLATE3);
 
   final JavaTypeFactory typeFactory;
   final RexBuilder builder;

http://git-wip-us.apache.org/repos/asf/calcite/blob/4e33eedc/core/src/main/java/org/apache/calcite/rex/RexSqlStandardConvertletTable.java
----------------------------------------------------------------------
diff --git a/core/src/main/java/org/apache/calcite/rex/RexSqlStandardConvertletTable.java b/core/src/main/java/org/apache/calcite/rex/RexSqlStandardConvertletTable.java
index 0745995..034c0ac 100644
--- a/core/src/main/java/org/apache/calcite/rex/RexSqlStandardConvertletTable.java
+++ b/core/src/main/java/org/apache/calcite/rex/RexSqlStandardConvertletTable.java
@@ -99,6 +99,7 @@ public class RexSqlStandardConvertletTable
     registerEquivOp(SqlStdOperatorTable.TRANSLATE);
     registerEquivOp(SqlStdOperatorTable.OVERLAY);
     registerEquivOp(SqlStdOperatorTable.TRIM);
+    registerEquivOp(SqlStdOperatorTable.TRANSLATE3);
     registerEquivOp(SqlStdOperatorTable.POSITION);
     registerEquivOp(SqlStdOperatorTable.CHAR_LENGTH);
     registerEquivOp(SqlStdOperatorTable.CHARACTER_LENGTH);

http://git-wip-us.apache.org/repos/asf/calcite/blob/4e33eedc/core/src/main/java/org/apache/calcite/runtime/SqlFunctions.java
----------------------------------------------------------------------
diff --git a/core/src/main/java/org/apache/calcite/runtime/SqlFunctions.java b/core/src/main/java/org/apache/calcite/runtime/SqlFunctions.java
index 8abdb97..d9657b2 100644
--- a/core/src/main/java/org/apache/calcite/runtime/SqlFunctions.java
+++ b/core/src/main/java/org/apache/calcite/runtime/SqlFunctions.java
@@ -1313,6 +1313,11 @@ public class SqlFunctions {
     return (int) (localTimestamp(root) % DateTimeUtils.MILLIS_PER_DAY);
   }
 
+  /** SQL TRANSLATE(string, search_chars, replacement_chars) function. */
+  public static String translate3(String s, String search, String replacement) {
+    return org.apache.commons.lang3.StringUtils.replaceChars(s, search, replacement);
+  }
+
   /** Helper for "array element reference". Caller has already ensured that
    * array and index are not null. Index is 1-based, per SQL. */
   public static Object arrayItem(List list, int item) {

http://git-wip-us.apache.org/repos/asf/calcite/blob/4e33eedc/core/src/main/java/org/apache/calcite/sql/fun/SqlStdOperatorTable.java
----------------------------------------------------------------------
diff --git a/core/src/main/java/org/apache/calcite/sql/fun/SqlStdOperatorTable.java b/core/src/main/java/org/apache/calcite/sql/fun/SqlStdOperatorTable.java
index c075363..6c0a0a3 100644
--- a/core/src/main/java/org/apache/calcite/sql/fun/SqlStdOperatorTable.java
+++ b/core/src/main/java/org/apache/calcite/sql/fun/SqlStdOperatorTable.java
@@ -1093,9 +1093,20 @@ public class SqlStdOperatorTable extends ReflectiveSqlOperatorTable {
   public static final SqlFunction CONVERT =
       new SqlConvertFunction("CONVERT");
 
+  /**
+   * The <code>TRANSLATE(<i>char_value</i> USING <i>translation_name</i>)</code> function
+   * alters the character set of a string value from one base character set to another.
+   */
   public static final SqlFunction TRANSLATE =
       new SqlConvertFunction("TRANSLATE");
 
+  /**
+   * The <code>TRANSLATE(<i>string_expr</i>, <i>search_chars</i>, <i>replacement_chars</i>)</code>
+   * function returns <i>string_expr</i> with all occurrences of each character in
+   * <i>search_chars</i> replaced by its corresponding character in <i>replacement_chars</i>.
+   */
+  public static final SqlFunction TRANSLATE3 = new SqlTranslate3Function();
+
   public static final SqlFunction OVERLAY = new SqlOverlayFunction();
 
   /** The "TRIM" function. */

http://git-wip-us.apache.org/repos/asf/calcite/blob/4e33eedc/core/src/main/java/org/apache/calcite/sql/fun/SqlTranslate3Function.java
----------------------------------------------------------------------
diff --git a/core/src/main/java/org/apache/calcite/sql/fun/SqlTranslate3Function.java b/core/src/main/java/org/apache/calcite/sql/fun/SqlTranslate3Function.java
new file mode 100644
index 0000000..7173207
--- /dev/null
+++ b/core/src/main/java/org/apache/calcite/sql/fun/SqlTranslate3Function.java
@@ -0,0 +1,72 @@
+/*
+ * 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.calcite.sql.fun;
+
+import org.apache.calcite.sql.SqlCall;
+import org.apache.calcite.sql.SqlFunction;
+import org.apache.calcite.sql.SqlFunctionCategory;
+import org.apache.calcite.sql.SqlKind;
+import org.apache.calcite.sql.SqlNode;
+import org.apache.calcite.sql.SqlWriter;
+import org.apache.calcite.sql.type.OperandTypes;
+import org.apache.calcite.sql.type.ReturnTypes;
+
+/**
+ * Definition of the "TRANSLATE" builtin SQL function.
+ */
+public class SqlTranslate3Function extends SqlFunction {
+  //~ Constructors -----------------------------------------------------------
+
+  /**
+   * Creates the SqlTranslate3Function.
+   */
+  SqlTranslate3Function() {
+    super(
+        "TRANSLATE3",
+        SqlKind.OTHER_FUNCTION,
+        ReturnTypes.ARG0_NULLABLE_VARYING,
+        null,
+        OperandTypes.STRING_STRING_STRING,
+        SqlFunctionCategory.STRING);
+  }
+
+  //~ Methods ----------------------------------------------------------------
+
+  //Check logic
+  public void unparse(
+      SqlWriter writer,
+      SqlCall call,
+      int leftPrec,
+      int rightPrec) {
+    final SqlWriter.Frame frame = writer.startFunCall("TRANSLATE");
+    for (SqlNode sqlNode : call.getOperandList()) {
+      writer.sep(",");
+      sqlNode.unparse(writer, leftPrec, rightPrec);
+    }
+    writer.endFunCall(frame);
+  }
+
+  public String getSignatureTemplate(final int operandsCount) {
+    if (3 == operandsCount) {
+      return "{0}({1}, {2}, {3})";
+    }
+    throw new AssertionError();
+  }
+
+}
+
+// End SqlTranslate3Function.java

http://git-wip-us.apache.org/repos/asf/calcite/blob/4e33eedc/core/src/main/java/org/apache/calcite/util/BuiltInMethod.java
----------------------------------------------------------------------
diff --git a/core/src/main/java/org/apache/calcite/util/BuiltInMethod.java b/core/src/main/java/org/apache/calcite/util/BuiltInMethod.java
index b9924f1..fd5f78f 100644
--- a/core/src/main/java/org/apache/calcite/util/BuiltInMethod.java
+++ b/core/src/main/java/org/apache/calcite/util/BuiltInMethod.java
@@ -255,6 +255,7 @@ public enum BuiltInMethod {
   TRUNCATE(SqlFunctions.class, "truncate", String.class, int.class),
   TRIM(SqlFunctions.class, "trim", boolean.class, boolean.class, String.class,
       String.class),
+  TRANSLATE3(SqlFunctions.class, "translate3", String.class, String.class, String.class),
   LTRIM(SqlFunctions.class, "ltrim", String.class),
   RTRIM(SqlFunctions.class, "rtrim", String.class),
   LIKE(SqlFunctions.class, "like", String.class, String.class),

http://git-wip-us.apache.org/repos/asf/calcite/blob/4e33eedc/core/src/test/java/org/apache/calcite/sql/parser/SqlParserTest.java
----------------------------------------------------------------------
diff --git a/core/src/test/java/org/apache/calcite/sql/parser/SqlParserTest.java b/core/src/test/java/org/apache/calcite/sql/parser/SqlParserTest.java
index 58cad3a..2ca511e 100644
--- a/core/src/test/java/org/apache/calcite/sql/parser/SqlParserTest.java
+++ b/core/src/test/java/org/apache/calcite/sql/parser/SqlParserTest.java
@@ -2740,6 +2740,12 @@ public class SqlParserTest {
         "TRANSLATE('abc' USING `LAZY_TRANSLATION`)");
   }
 
+  @Test public void testTranslate3() {
+    checkExp(
+        "translate('aaabbbccc', 'ab', '+-')",
+        "TRANSLATE('aaabbbccc', 'ab', '+-')");
+  }
+
   @Test public void testOverlay() {
     checkExp(
         "overlay('ABCdef' placing 'abc' from 1)",

http://git-wip-us.apache.org/repos/asf/calcite/blob/4e33eedc/core/src/test/java/org/apache/calcite/sql/test/SqlOperatorBaseTest.java
----------------------------------------------------------------------
diff --git a/core/src/test/java/org/apache/calcite/sql/test/SqlOperatorBaseTest.java b/core/src/test/java/org/apache/calcite/sql/test/SqlOperatorBaseTest.java
index 16abb8c..eefceee 100644
--- a/core/src/test/java/org/apache/calcite/sql/test/SqlOperatorBaseTest.java
+++ b/core/src/test/java/org/apache/calcite/sql/test/SqlOperatorBaseTest.java
@@ -3385,6 +3385,32 @@ public abstract class SqlOperatorBaseTest {
         VM_JAVA);
   }
 
+  @Test public void testTranslate3Func() {
+    tester.setFor(SqlStdOperatorTable.TRANSLATE3);
+    tester.checkString(
+       "translate('aabbcc', 'ab', '+-')",
+       "++--cc",
+       "VARCHAR(6) NOT NULL");
+    tester.checkString(
+        "translate('aabbcc', 'ab', '')",
+        "cc",
+        "VARCHAR(6) NOT NULL");
+    tester.checkString(
+        "translate('aabbcc', '', '+-')",
+        "aabbcc",
+        "VARCHAR(6) NOT NULL");
+    tester.checkString(
+       "translate(cast('aabbcc' as varchar(10)), 'ab', '+-')",
+       "++--cc",
+       "VARCHAR(10) NOT NULL");
+    tester.checkNull(
+       "translate(cast(null as varchar(7)), 'ab', '+-')");
+    tester.checkNull(
+       "translate('aabbcc', cast(null as varchar(2)), '+-')");
+    tester.checkNull(
+       "translate('aabbcc', 'ab', cast(null as varchar(2)))");
+  }
+
   @Test public void testOverlayFunc() {
     tester.setFor(SqlStdOperatorTable.OVERLAY);
     tester.checkString(

http://git-wip-us.apache.org/repos/asf/calcite/blob/4e33eedc/core/src/test/java/org/apache/calcite/test/SqlValidatorTest.java
----------------------------------------------------------------------
diff --git a/core/src/test/java/org/apache/calcite/test/SqlValidatorTest.java b/core/src/test/java/org/apache/calcite/test/SqlValidatorTest.java
index a56237c..cba6360 100644
--- a/core/src/test/java/org/apache/calcite/test/SqlValidatorTest.java
+++ b/core/src/test/java/org/apache/calcite/test/SqlValidatorTest.java
@@ -767,6 +767,10 @@ public class SqlValidatorTest extends SqlValidatorTestCase {
     checkExp("translate('abc' using translation)");
   }
 
+  @Test public void testTranslate3() {
+    checkExpType("translate('aabbcc', 'ab', '+-')", "VARCHAR(6) NOT NULL");
+  }
+
   @Test public void testOverlay() {
     checkExp("overlay('ABCdef' placing 'abc' from 1)");
     checkExp("overlay('ABCdef' placing 'abc' from 1 for 3)");


[2/2] calcite git commit: Fix up [CALCITE-1115], moving TRANSLATE3 to OracleSqlOperatorTable

Posted by jh...@apache.org.
Fix up [CALCITE-1115], moving TRANSLATE3 to OracleSqlOperatorTable

Also add some more validator tests.


Project: http://git-wip-us.apache.org/repos/asf/calcite/repo
Commit: http://git-wip-us.apache.org/repos/asf/calcite/commit/1be4056b
Tree: http://git-wip-us.apache.org/repos/asf/calcite/tree/1be4056b
Diff: http://git-wip-us.apache.org/repos/asf/calcite/diff/1be4056b

Branch: refs/heads/master
Commit: 1be4056b4b5ff4c75bf8f05bd2bc45e5cf01fa10
Parents: 4e33eed
Author: Julian Hyde <jh...@apache.org>
Authored: Tue May 3 11:35:06 2016 -0700
Committer: Julian Hyde <jh...@apache.org>
Committed: Tue May 3 11:35:06 2016 -0700

----------------------------------------------------------------------
 core/src/main/codegen/templates/Parser.jj       | 23 ++++++++++----------
 .../calcite/adapter/enumerable/RexImpTable.java |  2 +-
 .../adapter/enumerable/RexToLixTranslator.java  |  2 +-
 .../rex/RexSqlStandardConvertletTable.java      |  3 ++-
 .../calcite/sql/fun/OracleSqlOperatorTable.java |  9 ++++++++
 .../calcite/sql/fun/SqlStdOperatorTable.java    | 11 +++-------
 .../calcite/sql/fun/SqlTranslate3Function.java  | 18 +++++++--------
 .../calcite/sql/test/SqlOperatorBaseTest.java   | 21 +++++++++++-------
 .../apache/calcite/test/SqlValidatorTest.java   | 17 ++++++++++++++-
 .../calcite/test/SqlValidatorTestCase.java      |  2 +-
 10 files changed, 66 insertions(+), 42 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/calcite/blob/1be4056b/core/src/main/codegen/templates/Parser.jj
----------------------------------------------------------------------
diff --git a/core/src/main/codegen/templates/Parser.jj b/core/src/main/codegen/templates/Parser.jj
index 51133e6..088e741 100644
--- a/core/src/main/codegen/templates/Parser.jj
+++ b/core/src/main/codegen/templates/Parser.jj
@@ -85,6 +85,7 @@ import org.apache.calcite.sql.SqlWindow;
 import org.apache.calcite.sql.SqlWith;
 import org.apache.calcite.sql.SqlWithItem;
 import org.apache.calcite.sql.fun.SqlCase;
+import org.apache.calcite.sql.fun.OracleSqlOperatorTable;
 import org.apache.calcite.sql.fun.SqlStdOperatorTable;
 import org.apache.calcite.sql.fun.SqlTrimFunction;
 import org.apache.calcite.sql.parser.SqlAbstractParserImpl;
@@ -4091,24 +4092,22 @@ SqlNode BuiltinFunctionCall() :
             args = startList(e);
         }
         (
-            <USING> name = Identifier()
-            {
+            <USING> name = Identifier() {
                 namePos = getPos();
                 args.add(new SqlIdentifier(name, namePos));
             }
-            <RPAREN>
-            {
+            <RPAREN> {
                 return SqlStdOperatorTable.TRANSLATE.createCall(
                     pos, SqlParserUtil.toNodeArray(args));
             }
-            |
-            <COMMA>
-            e = Expression(ExprContext.ACCEPT_SUBQUERY) { args.add(e); }
-            <COMMA>
-            e = Expression(ExprContext.ACCEPT_SUBQUERY) { args.add(e); }
-            <RPAREN>
-            {
-                return SqlStdOperatorTable.TRANSLATE3.createCall(
+        |
+            (
+                <COMMA> e = Expression(ExprContext.ACCEPT_SUBQUERY) {
+                    args.add(e);
+                }
+            )*
+            <RPAREN> {
+                return OracleSqlOperatorTable.TRANSLATE3.createCall(
                     pos.plus(getPos()), SqlParserUtil.toNodeArray(args));
             }
         )

http://git-wip-us.apache.org/repos/asf/calcite/blob/1be4056b/core/src/main/java/org/apache/calcite/adapter/enumerable/RexImpTable.java
----------------------------------------------------------------------
diff --git a/core/src/main/java/org/apache/calcite/adapter/enumerable/RexImpTable.java b/core/src/main/java/org/apache/calcite/adapter/enumerable/RexImpTable.java
index 567f88c..a582a86 100644
--- a/core/src/main/java/org/apache/calcite/adapter/enumerable/RexImpTable.java
+++ b/core/src/main/java/org/apache/calcite/adapter/enumerable/RexImpTable.java
@@ -87,6 +87,7 @@ import static org.apache.calcite.linq4j.tree.ExpressionType.NotEqual;
 import static org.apache.calcite.linq4j.tree.ExpressionType.OrElse;
 import static org.apache.calcite.linq4j.tree.ExpressionType.Subtract;
 import static org.apache.calcite.linq4j.tree.ExpressionType.UnaryPlus;
+import static org.apache.calcite.sql.fun.OracleSqlOperatorTable.TRANSLATE3;
 import static org.apache.calcite.sql.fun.SqlStdOperatorTable.ABS;
 import static org.apache.calcite.sql.fun.SqlStdOperatorTable.AND;
 import static org.apache.calcite.sql.fun.SqlStdOperatorTable.ARRAY_VALUE_CONSTRUCTOR;
@@ -168,7 +169,6 @@ import static org.apache.calcite.sql.fun.SqlStdOperatorTable.SUBSTRING;
 import static org.apache.calcite.sql.fun.SqlStdOperatorTable.SUM;
 import static org.apache.calcite.sql.fun.SqlStdOperatorTable.SUM0;
 import static org.apache.calcite.sql.fun.SqlStdOperatorTable.SYSTEM_USER;
-import static org.apache.calcite.sql.fun.SqlStdOperatorTable.TRANSLATE3;
 import static org.apache.calcite.sql.fun.SqlStdOperatorTable.TRIM;
 import static org.apache.calcite.sql.fun.SqlStdOperatorTable.UNARY_MINUS;
 import static org.apache.calcite.sql.fun.SqlStdOperatorTable.UNARY_PLUS;

http://git-wip-us.apache.org/repos/asf/calcite/blob/1be4056b/core/src/main/java/org/apache/calcite/adapter/enumerable/RexToLixTranslator.java
----------------------------------------------------------------------
diff --git a/core/src/main/java/org/apache/calcite/adapter/enumerable/RexToLixTranslator.java b/core/src/main/java/org/apache/calcite/adapter/enumerable/RexToLixTranslator.java
index 4732d26..da3a62d 100644
--- a/core/src/main/java/org/apache/calcite/adapter/enumerable/RexToLixTranslator.java
+++ b/core/src/main/java/org/apache/calcite/adapter/enumerable/RexToLixTranslator.java
@@ -64,10 +64,10 @@ import java.util.LinkedHashMap;
 import java.util.List;
 import java.util.Map;
 
+import static org.apache.calcite.sql.fun.OracleSqlOperatorTable.TRANSLATE3;
 import static org.apache.calcite.sql.fun.SqlStdOperatorTable.CHARACTER_LENGTH;
 import static org.apache.calcite.sql.fun.SqlStdOperatorTable.CHAR_LENGTH;
 import static org.apache.calcite.sql.fun.SqlStdOperatorTable.SUBSTRING;
-import static org.apache.calcite.sql.fun.SqlStdOperatorTable.TRANSLATE3;
 import static org.apache.calcite.sql.fun.SqlStdOperatorTable.UPPER;
 
 /**

http://git-wip-us.apache.org/repos/asf/calcite/blob/1be4056b/core/src/main/java/org/apache/calcite/rex/RexSqlStandardConvertletTable.java
----------------------------------------------------------------------
diff --git a/core/src/main/java/org/apache/calcite/rex/RexSqlStandardConvertletTable.java b/core/src/main/java/org/apache/calcite/rex/RexSqlStandardConvertletTable.java
index 034c0ac..fae09a5 100644
--- a/core/src/main/java/org/apache/calcite/rex/RexSqlStandardConvertletTable.java
+++ b/core/src/main/java/org/apache/calcite/rex/RexSqlStandardConvertletTable.java
@@ -22,6 +22,7 @@ import org.apache.calcite.sql.SqlDataTypeSpec;
 import org.apache.calcite.sql.SqlNode;
 import org.apache.calcite.sql.SqlNodeList;
 import org.apache.calcite.sql.SqlOperator;
+import org.apache.calcite.sql.fun.OracleSqlOperatorTable;
 import org.apache.calcite.sql.fun.SqlCaseOperator;
 import org.apache.calcite.sql.fun.SqlStdOperatorTable;
 import org.apache.calcite.sql.parser.SqlParserPos;
@@ -99,7 +100,7 @@ public class RexSqlStandardConvertletTable
     registerEquivOp(SqlStdOperatorTable.TRANSLATE);
     registerEquivOp(SqlStdOperatorTable.OVERLAY);
     registerEquivOp(SqlStdOperatorTable.TRIM);
-    registerEquivOp(SqlStdOperatorTable.TRANSLATE3);
+    registerEquivOp(OracleSqlOperatorTable.TRANSLATE3);
     registerEquivOp(SqlStdOperatorTable.POSITION);
     registerEquivOp(SqlStdOperatorTable.CHAR_LENGTH);
     registerEquivOp(SqlStdOperatorTable.CHARACTER_LENGTH);

http://git-wip-us.apache.org/repos/asf/calcite/blob/1be4056b/core/src/main/java/org/apache/calcite/sql/fun/OracleSqlOperatorTable.java
----------------------------------------------------------------------
diff --git a/core/src/main/java/org/apache/calcite/sql/fun/OracleSqlOperatorTable.java b/core/src/main/java/org/apache/calcite/sql/fun/OracleSqlOperatorTable.java
index 1fc1fd5..e45a43c 100644
--- a/core/src/main/java/org/apache/calcite/sql/fun/OracleSqlOperatorTable.java
+++ b/core/src/main/java/org/apache/calcite/sql/fun/OracleSqlOperatorTable.java
@@ -103,6 +103,15 @@ public class OracleSqlOperatorTable extends ReflectiveSqlOperatorTable {
           OperandTypes.SAME_VARIADIC, SqlFunctionCategory.SYSTEM);
 
   /**
+   * The <code>TRANSLATE(<i>string_expr</i>, <i>search_chars</i>, <i>replacement_chars</i>)</code>
+   * function returns <i>string_expr</i> with all occurrences of each character in
+   * <i>search_chars</i> replaced by its corresponding character in <i>replacement_chars</i>.
+   *
+   * <p>It is not defined in the SQL standard, but occurs in Oracle and PostgreSQL.
+   */
+  public static final SqlFunction TRANSLATE3 = new SqlTranslate3Function();
+
+  /**
    * Returns the Oracle operator table, creating it if necessary.
    */
   public static synchronized OracleSqlOperatorTable instance() {

http://git-wip-us.apache.org/repos/asf/calcite/blob/1be4056b/core/src/main/java/org/apache/calcite/sql/fun/SqlStdOperatorTable.java
----------------------------------------------------------------------
diff --git a/core/src/main/java/org/apache/calcite/sql/fun/SqlStdOperatorTable.java b/core/src/main/java/org/apache/calcite/sql/fun/SqlStdOperatorTable.java
index 6c0a0a3..1a8aea5 100644
--- a/core/src/main/java/org/apache/calcite/sql/fun/SqlStdOperatorTable.java
+++ b/core/src/main/java/org/apache/calcite/sql/fun/SqlStdOperatorTable.java
@@ -1096,17 +1096,13 @@ public class SqlStdOperatorTable extends ReflectiveSqlOperatorTable {
   /**
    * The <code>TRANSLATE(<i>char_value</i> USING <i>translation_name</i>)</code> function
    * alters the character set of a string value from one base character set to another.
+   *
+   * <p>It is defined in the SQL standard. See also non-standard
+   * {@link OracleSqlOperatorTable#TRANSLATE3}.
    */
   public static final SqlFunction TRANSLATE =
       new SqlConvertFunction("TRANSLATE");
 
-  /**
-   * The <code>TRANSLATE(<i>string_expr</i>, <i>search_chars</i>, <i>replacement_chars</i>)</code>
-   * function returns <i>string_expr</i> with all occurrences of each character in
-   * <i>search_chars</i> replaced by its corresponding character in <i>replacement_chars</i>.
-   */
-  public static final SqlFunction TRANSLATE3 = new SqlTranslate3Function();
-
   public static final SqlFunction OVERLAY = new SqlOverlayFunction();
 
   /** The "TRIM" function. */
@@ -1184,7 +1180,6 @@ public class SqlStdOperatorTable extends ReflectiveSqlOperatorTable {
           SqlFunctionCategory.NUMERIC);
 
   public static final SqlFunction MOD =
-
       // Return type is same as divisor (2nd operand)
       // SQL2003 Part2 Section 6.27, Syntax Rules 9
       new SqlFunction(

http://git-wip-us.apache.org/repos/asf/calcite/blob/1be4056b/core/src/main/java/org/apache/calcite/sql/fun/SqlTranslate3Function.java
----------------------------------------------------------------------
diff --git a/core/src/main/java/org/apache/calcite/sql/fun/SqlTranslate3Function.java b/core/src/main/java/org/apache/calcite/sql/fun/SqlTranslate3Function.java
index 7173207..75ddf87 100644
--- a/core/src/main/java/org/apache/calcite/sql/fun/SqlTranslate3Function.java
+++ b/core/src/main/java/org/apache/calcite/sql/fun/SqlTranslate3Function.java
@@ -26,7 +26,12 @@ import org.apache.calcite.sql.type.OperandTypes;
 import org.apache.calcite.sql.type.ReturnTypes;
 
 /**
- * Definition of the "TRANSLATE" builtin SQL function.
+ * Definition of the "TRANSLATE" built-in SQL function that takes 3 arguments.
+ *
+ * <p>Based on Oracle's {@code TRANSLATE} function, it is commonly called
+ * "TRANSLATE3" to distinguish it from the standard SQL function
+ * {@link SqlStdOperatorTable#TRANSLATE} that takes 2 arguments and has an
+ * entirely different purpose.
  */
 public class SqlTranslate3Function extends SqlFunction {
   //~ Constructors -----------------------------------------------------------
@@ -35,8 +40,7 @@ public class SqlTranslate3Function extends SqlFunction {
    * Creates the SqlTranslate3Function.
    */
   SqlTranslate3Function() {
-    super(
-        "TRANSLATE3",
+    super("TRANSLATE3",
         SqlKind.OTHER_FUNCTION,
         ReturnTypes.ARG0_NULLABLE_VARYING,
         null,
@@ -46,11 +50,7 @@ public class SqlTranslate3Function extends SqlFunction {
 
   //~ Methods ----------------------------------------------------------------
 
-  //Check logic
-  public void unparse(
-      SqlWriter writer,
-      SqlCall call,
-      int leftPrec,
+  @Override public void unparse(SqlWriter writer, SqlCall call, int leftPrec,
       int rightPrec) {
     final SqlWriter.Frame frame = writer.startFunCall("TRANSLATE");
     for (SqlNode sqlNode : call.getOperandList()) {
@@ -60,7 +60,7 @@ public class SqlTranslate3Function extends SqlFunction {
     writer.endFunCall(frame);
   }
 
-  public String getSignatureTemplate(final int operandsCount) {
+  @Override public String getSignatureTemplate(final int operandsCount) {
     if (3 == operandsCount) {
       return "{0}({1}, {2}, {3})";
     }

http://git-wip-us.apache.org/repos/asf/calcite/blob/1be4056b/core/src/test/java/org/apache/calcite/sql/test/SqlOperatorBaseTest.java
----------------------------------------------------------------------
diff --git a/core/src/test/java/org/apache/calcite/sql/test/SqlOperatorBaseTest.java b/core/src/test/java/org/apache/calcite/sql/test/SqlOperatorBaseTest.java
index eefceee..6741b00 100644
--- a/core/src/test/java/org/apache/calcite/sql/test/SqlOperatorBaseTest.java
+++ b/core/src/test/java/org/apache/calcite/sql/test/SqlOperatorBaseTest.java
@@ -3386,28 +3386,33 @@ public abstract class SqlOperatorBaseTest {
   }
 
   @Test public void testTranslate3Func() {
-    tester.setFor(SqlStdOperatorTable.TRANSLATE3);
-    tester.checkString(
+    final SqlTester tester1 = oracleTester();
+    tester1.setFor(OracleSqlOperatorTable.TRANSLATE3);
+    tester1.checkString(
        "translate('aabbcc', 'ab', '+-')",
        "++--cc",
        "VARCHAR(6) NOT NULL");
-    tester.checkString(
+    tester1.checkString(
+        "translate('aabbcc', 'ab', 'ba')",
+       "bbaacc",
+       "VARCHAR(6) NOT NULL");
+    tester1.checkString(
         "translate('aabbcc', 'ab', '')",
         "cc",
         "VARCHAR(6) NOT NULL");
-    tester.checkString(
+    tester1.checkString(
         "translate('aabbcc', '', '+-')",
         "aabbcc",
         "VARCHAR(6) NOT NULL");
-    tester.checkString(
+    tester1.checkString(
        "translate(cast('aabbcc' as varchar(10)), 'ab', '+-')",
        "++--cc",
        "VARCHAR(10) NOT NULL");
-    tester.checkNull(
+    tester1.checkNull(
        "translate(cast(null as varchar(7)), 'ab', '+-')");
-    tester.checkNull(
+    tester1.checkNull(
        "translate('aabbcc', cast(null as varchar(2)), '+-')");
-    tester.checkNull(
+    tester1.checkNull(
        "translate('aabbcc', 'ab', cast(null as varchar(2)))");
   }
 

http://git-wip-us.apache.org/repos/asf/calcite/blob/1be4056b/core/src/test/java/org/apache/calcite/test/SqlValidatorTest.java
----------------------------------------------------------------------
diff --git a/core/src/test/java/org/apache/calcite/test/SqlValidatorTest.java b/core/src/test/java/org/apache/calcite/test/SqlValidatorTest.java
index cba6360..623517b 100644
--- a/core/src/test/java/org/apache/calcite/test/SqlValidatorTest.java
+++ b/core/src/test/java/org/apache/calcite/test/SqlValidatorTest.java
@@ -23,9 +23,11 @@ import org.apache.calcite.config.Lex;
 import org.apache.calcite.rel.type.RelDataTypeSystem;
 import org.apache.calcite.sql.SqlCollation;
 import org.apache.calcite.sql.SqlOperator;
+import org.apache.calcite.sql.fun.OracleSqlOperatorTable;
 import org.apache.calcite.sql.fun.SqlStdOperatorTable;
 import org.apache.calcite.sql.test.SqlTester;
 import org.apache.calcite.sql.type.SqlTypeName;
+import org.apache.calcite.sql.util.ChainedSqlOperatorTable;
 import org.apache.calcite.sql.validate.SqlConformance;
 import org.apache.calcite.sql.validate.SqlMonotonicity;
 import org.apache.calcite.sql.validate.SqlValidator;
@@ -768,7 +770,20 @@ public class SqlValidatorTest extends SqlValidatorTestCase {
   }
 
   @Test public void testTranslate3() {
-    checkExpType("translate('aabbcc', 'ab', '+-')", "VARCHAR(6) NOT NULL");
+    // TRANSLATE3 is not in the standard operator table
+    checkWholeExpFails("translate('aabbcc', 'ab', '+-')",
+        "No match found for function signature TRANSLATE3\\(<CHARACTER>, <CHARACTER>, <CHARACTER>\\)");
+    tester = tester.withOperatorTable(
+        ChainedSqlOperatorTable.of(OracleSqlOperatorTable.instance(),
+            SqlStdOperatorTable.instance()));
+    checkExpType("translate('aabbcc', 'ab', '+-')",
+        "VARCHAR(6) NOT NULL");
+    checkWholeExpFails("translate('abc', 'ab')",
+        "Invalid number of arguments to function 'TRANSLATE3'. Was expecting 3 arguments");
+    checkWholeExpFails("translate('abc', 'ab', 123)",
+        "(?s)Cannot apply 'TRANSLATE3' to arguments of type 'TRANSLATE3\\(<CHAR\\(3\\)>, <CHAR\\(2\\)>, <INTEGER>\\)'\\. .*");
+    checkWholeExpFails("translate('abc', 'ab', '+-', 'four')",
+        "Invalid number of arguments to function 'TRANSLATE3'. Was expecting 3 arguments");
   }
 
   @Test public void testOverlay() {

http://git-wip-us.apache.org/repos/asf/calcite/blob/1be4056b/core/src/test/java/org/apache/calcite/test/SqlValidatorTestCase.java
----------------------------------------------------------------------
diff --git a/core/src/test/java/org/apache/calcite/test/SqlValidatorTestCase.java b/core/src/test/java/org/apache/calcite/test/SqlValidatorTestCase.java
index ff87245..358bb2a 100644
--- a/core/src/test/java/org/apache/calcite/test/SqlValidatorTestCase.java
+++ b/core/src/test/java/org/apache/calcite/test/SqlValidatorTestCase.java
@@ -60,7 +60,7 @@ public class SqlValidatorTestCase {
 
   //~ Instance fields --------------------------------------------------------
 
-  protected final SqlTester tester;
+  protected SqlTester tester;
 
   //~ Constructors -----------------------------------------------------------