From 8ff0b08504b1fd0ae5f471aab053204ac2f5739e Mon Sep 17 00:00:00 2001 From: hongyu guo Date: Mon, 30 Mar 2026 22:59:33 +0800 Subject: [PATCH 1/2] [CALCITE-7407] Illegal use of dynamic parameter with || --- .../apache/calcite/sql/fun/SqlStdOperatorTable.java | 2 +- .../test/java/org/apache/calcite/test/JdbcTest.java | 11 +++++++++++ .../org/apache/calcite/test/SqlValidatorTest.java | 8 ++++++++ 3 files changed, 20 insertions(+), 1 deletion(-) 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 2a26a78929cf..272721ab9ff9 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 @@ -284,7 +284,7 @@ public class SqlStdOperatorTable extends ReflectiveSqlOperatorTable { } return type; }), - null, + InferTypes.RETURN_TYPE, OperandTypes.STRING_SAME_SAME_OR_ARRAY_SAME_SAME); 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 e25c6f31ccf2..45b980b1ebae 100644 --- a/core/src/test/java/org/apache/calcite/test/JdbcTest.java +++ b/core/src/test/java/org/apache/calcite/test/JdbcTest.java @@ -5967,6 +5967,17 @@ private CalciteAssert.AssertQuery withEmpDept(String sql) { }); } + /** Test case for + * [CALCITE-7407] + * Illegal use of dynamic parameter with ||. */ + @Test void testPreparedStatementConcatDynamicParameter() { + CalciteAssert.hr() + .query("select \"name\" from \"hr\".\"emps\"\n" + + "where \"name\" = (? || 'odore')") + .consumesPreparedStatement(p -> p.setString(1, "The")) + .returns("name=Theodore\n"); + } + /** Test case for * [CALCITE-2061] * Dynamic parameters in offset/fetch. */ 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 dd66362819a7..7055e8586ad2 100644 --- a/core/src/test/java/org/apache/calcite/test/SqlValidatorTest.java +++ b/core/src/test/java/org/apache/calcite/test/SqlValidatorTest.java @@ -8287,6 +8287,14 @@ void testGroupExpressionEquivalenceParams() { sql("select 1 from emp having sum(sal) < ?").ok(); } + /** Test case for + * [CALCITE-7407] + * Illegal use of dynamic parameter with ||. */ + @Test void testBindConcat() { + sql("select * from emp where ename = (? || 'KI')").ok(); + sql("select * from emp where ename = ('SM' || ?)").ok(); + } + /** Test case for * [CALCITE-1310] * Infer type of arguments to BETWEEN operator. */ From ae7fba4775831732b31a2004b1f7f0dc6332bd30 Mon Sep 17 00:00:00 2001 From: hongyu guo Date: Sat, 4 Apr 2026 18:02:51 +0800 Subject: [PATCH 2/2] [CALCITE-7407] Illegal use of dynamic parameter with || --- .../org/apache/calcite/test/SqlValidatorTest.java | 14 ++++++++++++++ 1 file changed, 14 insertions(+) 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 7055e8586ad2..f6d26c6af7ed 100644 --- a/core/src/test/java/org/apache/calcite/test/SqlValidatorTest.java +++ b/core/src/test/java/org/apache/calcite/test/SqlValidatorTest.java @@ -822,6 +822,10 @@ static SqlOperatorTable operatorTableFor(SqlLibrary library) { .columnType("CHAR(6) NOT NULL"); expr("'a'||'b'||cast('cde' as VARCHAR(3))|| 'f'") .columnType("VARCHAR(6) NOT NULL"); + expr("null||'b'") + .columnType("VARCHAR"); + expr("cast(null as ANY)||cast(null as ANY)") + .columnType("ANY"); expr("_UTF16'a'||_UTF16'b'||_UTF16'c'").ok(); } @@ -8295,6 +8299,16 @@ void testGroupExpressionEquivalenceParams() { sql("select * from emp where ename = ('SM' || ?)").ok(); } + /** Test case for + * [CALCITE-7407] + * Illegal use of dynamic parameter with ||. */ + @Test void testConcatNullAndAnyWithContext() { + sql("select * from emp where ename = (null || 'KI')").ok(); + sql("select * from emp where ename = ('SM' || null)").ok(); + sql("select * from emp where ename = (cast(null as any) || 'KI')").ok(); + sql("select * from emp where ename = ('SM' || cast(null as any))").ok(); + } + /** Test case for * [CALCITE-1310] * Infer type of arguments to BETWEEN operator. */