You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@calcite.apache.org by se...@apache.org on 2019/03/11 02:48:39 UTC

[calcite] branch master updated: [CALCITE-2599] Implement SQL ASCII function (Chunwei Lei)

This is an automated email from the ASF dual-hosted git repository.

sereda pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/calcite.git


The following commit(s) were added to refs/heads/master by this push:
     new a481357  [CALCITE-2599] Implement SQL ASCII function (Chunwei Lei)
a481357 is described below

commit a4813575ea8bfdb7dd65ddbf37d150835dad1d5d
Author: Chunwei Lei <ch...@alibaba-inc.com>
AuthorDate: Sun Mar 10 00:56:15 2019 +0800

    [CALCITE-2599] Implement SQL ASCII function (Chunwei Lei)
    
    It follows PostgreSQL standard which returns unicode code point for non-ASCII chars
---
 .../org/apache/calcite/adapter/enumerable/RexImpTable.java  |  2 ++
 .../main/java/org/apache/calcite/runtime/SqlFunctions.java  |  6 ++++++
 .../org/apache/calcite/sql/fun/SqlStdOperatorTable.java     |  9 +++++++++
 .../main/java/org/apache/calcite/util/BuiltInMethod.java    |  1 +
 .../org/apache/calcite/sql/test/SqlOperatorBaseTest.java    | 13 +++++++++++++
 site/_docs/reference.md                                     |  2 +-
 6 files changed, 32 insertions(+), 1 deletion(-)

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 1237ad2..9554f80 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
@@ -97,6 +97,7 @@ import static org.apache.calcite.sql.fun.SqlStdOperatorTable.ACOS;
 import static org.apache.calcite.sql.fun.SqlStdOperatorTable.AND;
 import static org.apache.calcite.sql.fun.SqlStdOperatorTable.ANY_VALUE;
 import static org.apache.calcite.sql.fun.SqlStdOperatorTable.ARRAY_VALUE_CONSTRUCTOR;
+import static org.apache.calcite.sql.fun.SqlStdOperatorTable.ASCII;
 import static org.apache.calcite.sql.fun.SqlStdOperatorTable.ASIN;
 import static org.apache.calcite.sql.fun.SqlStdOperatorTable.ATAN;
 import static org.apache.calcite.sql.fun.SqlStdOperatorTable.ATAN2;
@@ -279,6 +280,7 @@ public class RexImpTable {
         NullPolicy.STRICT);
     defineMethod(OVERLAY, BuiltInMethod.OVERLAY.method, NullPolicy.STRICT);
     defineMethod(POSITION, BuiltInMethod.POSITION.method, NullPolicy.STRICT);
+    defineMethod(ASCII, BuiltInMethod.ASCII.method, NullPolicy.STRICT);
 
     final TrimImplementor trimImplementor = new TrimImplementor();
     defineImplementor(TRIM, NullPolicy.STRICT, trimImplementor, false);
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 b475000..5e9d6df 100644
--- a/core/src/main/java/org/apache/calcite/runtime/SqlFunctions.java
+++ b/core/src/main/java/org/apache/calcite/runtime/SqlFunctions.java
@@ -237,6 +237,12 @@ public class SqlFunctions {
     return newS.toString();
   }
 
+  /** SQL ASCII(string) function. */
+  public static int ascii(String s) {
+    return s.isEmpty()
+        ? 0 : s.codePointAt(0);
+  }
+
   /** SQL CHARACTER_LENGTH(string) function. */
   public static int charLength(String s) {
     return s.length();
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 3e66b9c..f514ccd 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
@@ -1483,6 +1483,15 @@ public class SqlStdOperatorTable extends ReflectiveSqlOperatorTable {
           OperandTypes.CHARACTER,
           SqlFunctionCategory.STRING);
 
+  public static final SqlFunction ASCII =
+      new SqlFunction(
+          "ASCII",
+          SqlKind.OTHER_FUNCTION,
+          ReturnTypes.INTEGER_NULLABLE,
+          null,
+          OperandTypes.CHARACTER,
+          SqlFunctionCategory.STRING);
+
   /**
    * Uses SqlOperatorTable.useDouble for its return type since we don't know
    * what the result type will be by just looking at the operand types. For
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 3169b55..9a67e16 100644
--- a/core/src/main/java/org/apache/calcite/util/BuiltInMethod.java
+++ b/core/src/main/java/org/apache/calcite/util/BuiltInMethod.java
@@ -266,6 +266,7 @@ public enum BuiltInMethod {
   ANY_ITEM(SqlFunctions.class, "itemOptional", Object.class, Object.class),
   UPPER(SqlFunctions.class, "upper", String.class),
   LOWER(SqlFunctions.class, "lower", String.class),
+  ASCII(SqlFunctions.class, "ascii", String.class),
   JSONIZE(SqlFunctions.class, "jsonize", Object.class),
   DEJSONIZE(SqlFunctions.class, "dejsonize", String.class),
   JSON_VALUE_EXPRESSION(SqlFunctions.class, "jsonValueExpression",
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 0e876bc..fcf7fe9 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
@@ -4247,6 +4247,19 @@ public abstract class SqlOperatorBaseTest {
     tester.checkNull("CHARACTER_LENGTH(cast(null as varchar(1)))");
   }
 
+  @Test public void testAsciiFunc() {
+    tester.setFor(SqlStdOperatorTable.ASCII);
+    tester.checkScalarExact("ASCII('')", "0");
+    tester.checkScalarExact("ASCII('a')", "97");
+    tester.checkScalarExact("ASCII('1')", "49");
+    tester.checkScalarExact("ASCII('abc')", "97");
+    tester.checkScalarExact("ASCII('ABC')", "65");
+    tester.checkScalarExact("ASCII(_UTF8'\u0082')", "130");
+    tester.checkScalarExact("ASCII(_UTF8'\u5B57')", "23383");
+    tester.checkScalarExact("ASCII(_UTF8'Ω')", "937");
+    tester.checkNull("ASCII(cast(null as varchar(1)))");
+  }
+
   @Test public void testUpperFunc() {
     tester.setFor(SqlStdOperatorTable.UPPER);
     tester.checkString("upper('a')", "A", "CHAR(1) NOT NULL");
diff --git a/site/_docs/reference.md b/site/_docs/reference.md
index 31508dd..e7e9282 100644
--- a/site/_docs/reference.md
+++ b/site/_docs/reference.md
@@ -1448,10 +1448,10 @@ period:
 | {fn SUBSTRING(string, offset, length)} | Returns a character string that consists of *length* characters from *string* starting at the *offset* position
 | {fn UCASE(string)} | Returns a string in which all alphabetic characters in *string* have been converted to upper case
 | {fn REPLACE(string, search, replacement)} | Returns a string in which all the occurrences of *search* in *string* are replaced with *replacement*; if *replacement* is the empty string, the occurrences of *search* are removed
+| {fn ASCII(string)} | Returns the corresponding ASCII code of the first character of *string*; Returns 0 if *string* is empty; Returns NULL if *string* is NULL; Returns the Unicode code point for non-ASCII character
 
 Not implemented:
 
-* {fn ASCII(string)} - Convert a single-character string to the corresponding ASCII code, an integer between 0 and 255
 * {fn CHAR(string)}
 * {fn DIFFERENCE(string, string)}
 * {fn LEFT(string, integer)}