You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@calcite.apache.org by da...@apache.org on 2019/11/07 03:58:34 UTC
[calcite] branch master updated: [CALCITE-3423] Support using CAST
operation and BOOLEAN type value in table macro (Wang Yanlin)
This is an automated email from the ASF dual-hosted git repository.
danny0405 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 4299007 [CALCITE-3423] Support using CAST operation and BOOLEAN type value in table macro (Wang Yanlin)
4299007 is described below
commit 4299007f7baff9dbff3c959535f6476c48f924a0
Author: yanlin-Lynn <19...@163.com>
AuthorDate: Thu Oct 17 21:19:27 2019 +0800
[CALCITE-3423] Support using CAST operation and BOOLEAN type value in table macro (Wang Yanlin)
* Support cast with boolean and varchar type for user defined table function and table macro
* Open the coercion logic for user defined table macro in TypeCoercionImpl#userDefinedFunctionCoercion
close apache/calcite#1516
---
.../java/org/apache/calcite/rex/RexLiteral.java | 3 +-
.../sql/validate/SqlUserDefinedTableMacro.java | 6 +-
.../sql/validate/implicit/TypeCoercionImpl.java | 6 --
.../java/org/apache/calcite/test/JdbcTest.java | 84 +++++++++++++++++-----
.../org/apache/calcite/test/TableFunctionTest.java | 12 +---
5 files changed, 76 insertions(+), 35 deletions(-)
diff --git a/core/src/main/java/org/apache/calcite/rex/RexLiteral.java b/core/src/main/java/org/apache/calcite/rex/RexLiteral.java
index 192a962..cb4719a 100644
--- a/core/src/main/java/org/apache/calcite/rex/RexLiteral.java
+++ b/core/src/main/java/org/apache/calcite/rex/RexLiteral.java
@@ -458,7 +458,8 @@ public class RexLiteral extends RexNode {
if (o == null
|| o instanceof BigDecimal
|| o instanceof NlsString
- || o instanceof ByteString) {
+ || o instanceof ByteString
+ || o instanceof Boolean) {
return litmus.succeed();
} else if (o instanceof List) {
List list = (List) o;
diff --git a/core/src/main/java/org/apache/calcite/sql/validate/SqlUserDefinedTableMacro.java b/core/src/main/java/org/apache/calcite/sql/validate/SqlUserDefinedTableMacro.java
index 153ad2c..1bb9529 100644
--- a/core/src/main/java/org/apache/calcite/sql/validate/SqlUserDefinedTableMacro.java
+++ b/core/src/main/java/org/apache/calcite/sql/validate/SqlUserDefinedTableMacro.java
@@ -147,6 +147,8 @@ public class SqlUserDefinedTableMacro extends SqlFunction {
builder2.put(getValue(key), getValue(value));
}
return builder2.build();
+ case CAST:
+ return getValue(((SqlCall) right).operand(0));
default:
if (SqlUtil.isNullLiteral(right, true)) {
return null;
@@ -175,8 +177,8 @@ public class SqlUserDefinedTableMacro extends SqlFunction {
if (clazz.isAssignableFrom(o.getClass())) {
return o;
}
- if (clazz == String.class && o instanceof NlsString) {
- return ((NlsString) o).getValue();
+ if (o instanceof NlsString) {
+ return coerce(((NlsString) o).getValue(), type);
}
// We need optimization here for constant folding.
// Not all the expressions can be interpreted (e.g. ternary), so
diff --git a/core/src/main/java/org/apache/calcite/sql/validate/implicit/TypeCoercionImpl.java b/core/src/main/java/org/apache/calcite/sql/validate/implicit/TypeCoercionImpl.java
index 1800fee..354cc91 100644
--- a/core/src/main/java/org/apache/calcite/sql/validate/implicit/TypeCoercionImpl.java
+++ b/core/src/main/java/org/apache/calcite/sql/validate/implicit/TypeCoercionImpl.java
@@ -32,7 +32,6 @@ import org.apache.calcite.sql.fun.SqlCase;
import org.apache.calcite.sql.parser.SqlParserPos;
import org.apache.calcite.sql.type.SqlTypeFamily;
import org.apache.calcite.sql.type.SqlTypeUtil;
-import org.apache.calcite.sql.validate.SqlUserDefinedTableMacro;
import org.apache.calcite.sql.validate.SqlValidator;
import org.apache.calcite.sql.validate.SqlValidatorScope;
import org.apache.calcite.util.Util;
@@ -563,11 +562,6 @@ public class TypeCoercionImpl extends AbstractTypeCoercion {
final List<RelDataType> paramTypes = function.getParamTypes();
assert paramTypes != null;
boolean coerced = false;
- // User defined table macro only allows literals.
- // we should support this in the future.
- if (function instanceof SqlUserDefinedTableMacro) {
- return false;
- }
for (int i = 0; i < call.operandCount(); i++) {
SqlNode operand = call.operand(i);
if (operand.getKind() == SqlKind.ARGUMENT_ASSIGNMENT) {
diff --git a/core/src/test/java/org/apache/calcite/test/JdbcTest.java b/core/src/test/java/org/apache/calcite/test/JdbcTest.java
index e34effb..0635dba 100644
--- a/core/src/test/java/org/apache/calcite/test/JdbcTest.java
+++ b/core/src/test/java/org/apache/calcite/test/JdbcTest.java
@@ -107,6 +107,7 @@ import org.junit.Test;
import java.io.File;
import java.io.IOException;
import java.io.PrintWriter;
+import java.lang.reflect.Method;
import java.math.BigDecimal;
import java.sql.Array;
import java.sql.Connection;
@@ -409,6 +410,19 @@ public class JdbcTest {
}
/**
+ * Adds table macro for connection, with catalog named "s"
+ * and the method reflection name as the name of the macro.
+ */
+ private void addTableMacro(Connection connection, Method method) throws SQLException {
+ CalciteConnection calciteConnection =
+ connection.unwrap(CalciteConnection.class);
+ SchemaPlus rootSchema = calciteConnection.getRootSchema();
+ SchemaPlus schema = rootSchema.add("s", new AbstractSchema());
+ final TableMacro tableMacro = TableMacroImpl.create(method);
+ schema.add(method.getName(), tableMacro);
+ }
+
+ /**
* Tests a relation that is accessed via method syntax.
*
* <p>The function ({@link Smalls#view(String)} has a return type
@@ -419,14 +433,9 @@ public class JdbcTest {
throws SQLException, ClassNotFoundException {
Connection connection =
DriverManager.getConnection("jdbc:calcite:");
- CalciteConnection calciteConnection =
- connection.unwrap(CalciteConnection.class);
- SchemaPlus rootSchema = calciteConnection.getRootSchema();
- SchemaPlus schema = rootSchema.add("s", new AbstractSchema());
- final TableMacro tableMacro = TableMacroImpl.create(Smalls.VIEW_METHOD);
- schema.add("View", tableMacro);
+ addTableMacro(connection, Smalls.VIEW_METHOD);
ResultSet resultSet = connection.createStatement().executeQuery("select *\n"
- + "from table(\"s\".\"View\"('(10), (20)')) as t(n)\n"
+ + "from table(\"s\".\"view\"('(10), (20)')) as t(n)\n"
+ "where n < 15");
// The call to "View('(10), (2)')" expands to 'values (1), (3), (10), (20)'.
assertThat(CalciteAssert.toString(resultSet),
@@ -445,14 +454,9 @@ public class JdbcTest {
throws SQLException, ClassNotFoundException {
Connection connection =
DriverManager.getConnection("jdbc:calcite:");
- CalciteConnection calciteConnection =
- connection.unwrap(CalciteConnection.class);
- SchemaPlus rootSchema = calciteConnection.getRootSchema();
- SchemaPlus schema = rootSchema.add("s", new AbstractSchema());
- final TableMacro tableMacro = TableMacroImpl.create(Smalls.STR_METHOD);
- schema.add("Str", tableMacro);
+ addTableMacro(connection, Smalls.STR_METHOD);
ResultSet resultSet = connection.createStatement().executeQuery("select *\n"
- + "from table(\"s\".\"Str\"(MAP['a', 1, 'baz', 2],\n"
+ + "from table(\"s\".\"str\"(MAP['a', 1, 'baz', 2],\n"
+ " ARRAY[3, 4, CAST(null AS INTEGER)])) as t(n)");
// The call to "View('(10), (2)')" expands to 'values (1), (3), (10), (20)'.
assertThat(CalciteAssert.toString(resultSet),
@@ -461,6 +465,52 @@ public class JdbcTest {
connection.close();
}
+ /**
+ * <p>Test case for
+ * <a href="https://issues.apache.org/jira/browse/CALCITE-3423">[CALCITE-3423]
+ * Support using CAST operation and BOOLEAN type value in table macro</a>. */
+ @Test public void testTableMacroWithCastOrBoolean() throws SQLException {
+ Connection connection =
+ DriverManager.getConnection("jdbc:calcite:");
+ addTableMacro(connection, Smalls.STR_METHOD);
+ // check for cast
+ ResultSet resultSet = connection.createStatement().executeQuery(
+ "select * from table(\"s\".\"str\"(MAP['a', 1, 'baz', 2], cast(1 as bigint))) as t(n)");
+ assertThat(CalciteAssert.toString(resultSet),
+ equalTo("N={'a'=1, 'baz'=2}\n"
+ + "N=1 \n"));
+ // check for Boolean type
+ resultSet = connection.createStatement().executeQuery(
+ "select * from table(\"s\".\"str\"(MAP['a', 1, 'baz', 2], true)) as t(n)");
+ assertThat(CalciteAssert.toString(resultSet),
+ equalTo("N={'a'=1, 'baz'=2}\n"
+ + "N=true \n"));
+ // check for nested cast
+ resultSet = connection.createStatement().executeQuery(
+ "select * from table(\"s\".\"str\"(MAP['a', 1, 'baz', 2],"
+ + "cast(cast(1 as int) as varchar(1)))) as t(n)");
+ assertThat(CalciteAssert.toString(resultSet),
+ equalTo("N={'a'=1, 'baz'=2}\n"
+ + "N=1 \n"));
+
+ resultSet = connection.createStatement().executeQuery(
+ "select * from table(\"s\".\"str\"(MAP['a', 1, 'baz', 2],"
+ + "cast(cast(cast('2019-10-18 10:35:23' as TIMESTAMP) as BIGINT) as VARCHAR))) as t(n)");
+ assertThat(CalciteAssert.toString(resultSet),
+ equalTo("N={'a'=1, 'baz'=2} \n"
+ + "N='2019-10-18 10:35:23'\n"));
+
+ // check for implicit type coercion
+ addTableMacro(connection, Smalls.VIEW_METHOD);
+ resultSet = connection.createStatement().executeQuery(
+ "select * from table(\"s\".\"view\"(5)) as t(n)");
+ assertThat(CalciteAssert.toString(resultSet),
+ equalTo("N=1\n"
+ + "N=3\n"
+ + "N=5\n"));
+ connection.close();
+ }
+
/** Tests a table macro with named and optional parameters. */
@Test public void testTableMacroWithNamedParameters() throws Exception {
// View(String r optional, String s, int t optional)
@@ -482,13 +532,13 @@ public class JdbcTest {
.returns(expected2);
with.query("select * from table(\"adhoc\".\"View\"(t=>'5', t=>'6'))")
.throws_("Duplicate argument name 'T'");
- with.query("select * from table(\"adhoc\".\"View\"(t=>'5', s=>'6'))")
- .throws_(
- "No match found for function signature View(T => <CHARACTER>, S => <CHARACTER>)");
final String expected3 = "c=1\n"
+ "c=3\n"
+ "c=6\n"
+ "c=5\n";
+ // implicit type coercion
+ with.query("select * from table(\"adhoc\".\"View\"(t=>'5', s=>'6'))")
+ .returns(expected3);
with.query("select * from table(\"adhoc\".\"View\"(t=>5, s=>'6'))")
.returns(expected3);
}
diff --git a/core/src/test/java/org/apache/calcite/test/TableFunctionTest.java b/core/src/test/java/org/apache/calcite/test/TableFunctionTest.java
index fff7486..0320d66 100644
--- a/core/src/test/java/org/apache/calcite/test/TableFunctionTest.java
+++ b/core/src/test/java/org/apache/calcite/test/TableFunctionTest.java
@@ -377,16 +377,10 @@ public class TableFunctionTest {
}
@Test public void testUserDefinedTableFunction4() {
- final String q = "select *\n"
+ final String q = "select \"c1\"\n"
+ "from table(\"s\".\"multiplication\"('2', 3, 100))\n"
- + "where c1 + 2 < c2";
- // With type coercion, a cast node with null as argument would be
- // passed to the function to infer the table row type, we use
- // SqlUserDefinedTableMacro#convertArguments to decide the type.
- // For this table function: multiplication,
- // it will just throw IllegalArgumentException.
- final String e = "java.lang.IllegalArgumentException";
- with().query(q).throws_(e);
+ + "where \"c1\" + 2 < \"c2\"";
+ with().query(q).returnsUnordered("c1=103");
}
@Test public void testUserDefinedTableFunction5() {