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

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


The following commit(s) were added to refs/heads/master by this push:
     new 82cbc4c4913 IGNITE-16836 SQL Calcite: Fix SQL functions operand type 
inference - Fixes #9969.
82cbc4c4913 is described below

commit 82cbc4c4913e0ca7c0dcba01b11e50f199c65de8
Author: Aleksey Plekhanov <plehanov.a...@gmail.com>
AuthorDate: Thu Apr 14 16:03:49 2022 +0300

    IGNITE-16836 SQL Calcite: Fix SQL functions operand type inference - Fixes 
#9969.
    
    Signed-off-by: Aleksey Plekhanov <plehanov.a...@gmail.com>
---
 .../query/calcite/CalciteQueryProcessor.java       |   2 +-
 .../query/calcite/prepare/IgniteSqlValidator.java  |  62 +++++++
 .../query/calcite/type/IgniteTypeFactory.java      |  10 ++
 .../calcite/{ => integration}/FunctionsTest.java   | 181 +++++++++------------
 .../UserDefinedFunctionsIntegrationTest.java       |   1 +
 .../ignite/testsuites/IntegrationTestSuite.java    |   2 +-
 6 files changed, 153 insertions(+), 105 deletions(-)

diff --git 
a/modules/calcite/src/main/java/org/apache/ignite/internal/processors/query/calcite/CalciteQueryProcessor.java
 
b/modules/calcite/src/main/java/org/apache/ignite/internal/processors/query/calcite/CalciteQueryProcessor.java
index 5450a62b842..538fdb4ff60 100644
--- 
a/modules/calcite/src/main/java/org/apache/ignite/internal/processors/query/calcite/CalciteQueryProcessor.java
+++ 
b/modules/calcite/src/main/java/org/apache/ignite/internal/processors/query/calcite/CalciteQueryProcessor.java
@@ -430,7 +430,7 @@ public class CalciteQueryProcessor extends 
GridProcessorAdapter implements Query
         try {
             return executionSvc.executePlan(qry, plan.apply(qry));
         }
-        catch (Exception e) {
+        catch (Throwable e) {
             boolean isCanceled = qry.isCancelled();
 
             if (qrys != null)
diff --git 
a/modules/calcite/src/main/java/org/apache/ignite/internal/processors/query/calcite/prepare/IgniteSqlValidator.java
 
b/modules/calcite/src/main/java/org/apache/ignite/internal/processors/query/calcite/prepare/IgniteSqlValidator.java
index c77d463c56e..5c3ccb294c1 100644
--- 
a/modules/calcite/src/main/java/org/apache/ignite/internal/processors/query/calcite/prepare/IgniteSqlValidator.java
+++ 
b/modules/calcite/src/main/java/org/apache/ignite/internal/processors/query/calcite/prepare/IgniteSqlValidator.java
@@ -18,6 +18,7 @@
 package org.apache.ignite.internal.processors.query.calcite.prepare;
 
 import java.math.BigDecimal;
+import java.util.Arrays;
 import java.util.Collections;
 import java.util.EnumSet;
 import java.util.List;
@@ -31,6 +32,7 @@ import org.apache.calcite.rel.type.RelDataTypeField;
 import org.apache.calcite.sql.JoinConditionType;
 import org.apache.calcite.sql.SqlAggFunction;
 import org.apache.calcite.sql.SqlCall;
+import org.apache.calcite.sql.SqlCallBinding;
 import org.apache.calcite.sql.SqlDelete;
 import org.apache.calcite.sql.SqlDynamicParam;
 import org.apache.calcite.sql.SqlIdentifier;
@@ -47,6 +49,10 @@ import org.apache.calcite.sql.SqlUpdate;
 import org.apache.calcite.sql.SqlUtil;
 import org.apache.calcite.sql.dialect.CalciteSqlDialect;
 import org.apache.calcite.sql.parser.SqlParserPos;
+import org.apache.calcite.sql.type.FamilyOperandTypeChecker;
+import org.apache.calcite.sql.type.SqlOperandTypeChecker;
+import org.apache.calcite.sql.type.SqlOperandTypeInference;
+import org.apache.calcite.sql.type.SqlTypeFamily;
 import org.apache.calcite.sql.type.SqlTypeName;
 import org.apache.calcite.sql.validate.SelectScope;
 import org.apache.calcite.sql.validate.SqlValidator;
@@ -480,4 +486,60 @@ public class IgniteSqlValidator extends SqlValidatorImpl {
         return QueryUtils.KEY_FIELD_NAME.equalsIgnoreCase(alias)
             || QueryUtils.VAL_FIELD_NAME.equalsIgnoreCase(alias);
     }
+
+    /** {@inheritDoc} */
+    @Override protected void inferUnknownTypes(RelDataType inferredType, 
SqlValidatorScope scope, SqlNode node) {
+        if (node instanceof SqlDynamicParam && 
inferredType.equals(unknownType)) {
+            // Infer type of dynamic parameters of unknown type as OTHER.
+            // Parameter will be converted from Object class to required class 
in runtime.
+            // Such an approach helps to bypass some cases where parameter 
types can never be inferred (for example,
+            // in expression "CASE WHEN ... THEN ? ELSE ? END"), but also has 
new issues: if SQL function's method
+            // has overloads, it's not possible to find correct unique method 
to call, so random method will be choosen.
+            // For such functions operand type inference should be implemented 
to find the correct method
+            // (see https://issues.apache.org/jira/browse/CALCITE-4347).
+            setValidatedNodeType(node, 
typeFactory().createCustomType(Object.class));
+        }
+        else if (node instanceof SqlCall) {
+            final SqlValidatorScope newScope = scopes.get(node);
+
+            if (newScope != null)
+                scope = newScope;
+
+            final SqlCall call = (SqlCall)node;
+            final SqlOperandTypeInference operandTypeInference = 
call.getOperator().getOperandTypeInference();
+            final SqlOperandTypeChecker operandTypeChecker = 
call.getOperator().getOperandTypeChecker();
+            final SqlCallBinding callBinding = new SqlCallBinding(this, scope, 
call);
+            final List<SqlNode> operands = callBinding.operands();
+            final RelDataType[] operandTypes = new 
RelDataType[operands.size()];
+
+            Arrays.fill(operandTypes, unknownType);
+
+            if (operandTypeInference != null)
+                operandTypeInference.inferOperandTypes(callBinding, 
inferredType, operandTypes);
+            else if (operandTypeChecker instanceof FamilyOperandTypeChecker) {
+                // Infer operand types from checker for dynamic parameters if 
it's possible.
+                FamilyOperandTypeChecker checker = 
(FamilyOperandTypeChecker)operandTypeChecker;
+
+                for (int i = 0; i < checker.getOperandCountRange().getMax(); 
i++) {
+                    if (i >= operandTypes.length)
+                        break;
+
+                    SqlTypeFamily family = checker.getOperandSqlTypeFamily(i);
+                    RelDataType type = 
family.getDefaultConcreteType(typeFactory());
+
+                    if (type != null && operands.get(i) instanceof 
SqlDynamicParam)
+                        operandTypes[i] = type;
+                }
+            }
+
+            for (int i = 0; i < operands.size(); ++i) {
+                final SqlNode operand = operands.get(i);
+
+                if (operand != null)
+                    inferUnknownTypes(operandTypes[i], scope, operand);
+            }
+        }
+        else
+            super.inferUnknownTypes(inferredType, scope, node);
+    }
 }
diff --git 
a/modules/calcite/src/main/java/org/apache/ignite/internal/processors/query/calcite/type/IgniteTypeFactory.java
 
b/modules/calcite/src/main/java/org/apache/ignite/internal/processors/query/calcite/type/IgniteTypeFactory.java
index 2ede484e599..d5b4a62d4d2 100644
--- 
a/modules/calcite/src/main/java/org/apache/ignite/internal/processors/query/calcite/type/IgniteTypeFactory.java
+++ 
b/modules/calcite/src/main/java/org/apache/ignite/internal/processors/query/calcite/type/IgniteTypeFactory.java
@@ -55,6 +55,9 @@ public class IgniteTypeFactory extends JavaTypeFactoryImpl {
     private static final SqlIntervalQualifier INTERVAL_QUALIFIER_DAY_TIME = 
new SqlIntervalQualifier(TimeUnit.DAY,
         TimeUnit.SECOND, SqlParserPos.ZERO);
 
+    /** */
+    private final RelDataType unknownType;
+
     /** */
     private final Charset charset;
 
@@ -77,6 +80,8 @@ public class IgniteTypeFactory extends JavaTypeFactoryImpl {
             // If JVM default charset is not supported by Calcite - use UTF-8.
             charset = StandardCharsets.UTF_8;
         }
+
+        unknownType = createUnknownType();
     }
 
     /** {@inheritDoc} */
@@ -294,6 +299,11 @@ public class IgniteTypeFactory extends JavaTypeFactoryImpl 
{
 
     /** {@inheritDoc} */
     @Override public RelDataType createTypeWithNullability(RelDataType type, 
boolean nullable) {
+        // TODO workaround for 
https://issues.apache.org/jira/browse/CALCITE-4872
+        // Remove this after update to Calcite 1.30.
+        if (unknownType.equals(type))
+            return type;
+
         if (type instanceof IgniteCustomType && type.isNullable() != nullable)
             return createCustomType(((IgniteCustomType)type).storageType(), 
nullable);
 
diff --git 
a/modules/calcite/src/test/java/org/apache/ignite/internal/processors/query/calcite/FunctionsTest.java
 
b/modules/calcite/src/test/java/org/apache/ignite/internal/processors/query/calcite/integration/FunctionsTest.java
similarity index 52%
rename from 
modules/calcite/src/test/java/org/apache/ignite/internal/processors/query/calcite/FunctionsTest.java
rename to 
modules/calcite/src/test/java/org/apache/ignite/internal/processors/query/calcite/integration/FunctionsTest.java
index 3508d6d2afc..7d27d4a156e 100644
--- 
a/modules/calcite/src/test/java/org/apache/ignite/internal/processors/query/calcite/FunctionsTest.java
+++ 
b/modules/calcite/src/test/java/org/apache/ignite/internal/processors/query/calcite/integration/FunctionsTest.java
@@ -15,65 +15,50 @@
  * limitations under the License.
  */
 
-package org.apache.ignite.internal.processors.query.calcite;
+package org.apache.ignite.internal.processors.query.calcite.integration;
 
+import java.math.BigDecimal;
 import java.sql.Date;
 import java.sql.Time;
 import java.sql.Timestamp;
 import java.util.List;
 import java.util.function.LongFunction;
 import org.apache.calcite.sql.validate.SqlValidatorException;
-import org.apache.ignite.Ignite;
 import org.apache.ignite.IgniteCache;
 import org.apache.ignite.calcite.CalciteQueryEngineConfiguration;
 import org.apache.ignite.configuration.CacheConfiguration;
-import org.apache.ignite.internal.IgniteEx;
 import org.apache.ignite.internal.processors.query.IgniteSQLException;
-import org.apache.ignite.internal.processors.query.QueryEngine;
-import org.apache.ignite.internal.processors.query.calcite.util.Commons;
 import org.apache.ignite.internal.util.typedef.internal.U;
-import org.apache.ignite.testframework.GridTestUtils;
-import org.apache.ignite.testframework.junits.common.GridCommonAbstractTest;
 import org.junit.Test;
 
 /**
  * Test Ignite SQL functions.
  */
-public class FunctionsTest extends GridCommonAbstractTest {
-    /** */
-    private static QueryEngine qryEngine;
-
+public class FunctionsTest extends AbstractBasicIntegrationTest {
     /** */
     private static final Object[] NULL_RESULT = new Object[] { null };
 
-    /** {@inheritDoc} */
-    @Override protected void beforeTestsStarted() throws Exception {
-        Ignite grid = startGridsMultiThreaded(3);
-
-        qryEngine = Commons.lookupComponent(((IgniteEx)grid).context(), 
QueryEngine.class);
-    }
-
     /** */
     @Test
     public void testTimestampDiffWithFractionsOfSecond() {
-        checkQuery("SELECT TIMESTAMPDIFF(MICROSECOND, TIMESTAMP '2022-02-01 
10:30:28.000', " +
+        assertQuery("SELECT TIMESTAMPDIFF(MICROSECOND, TIMESTAMP '2022-02-01 
10:30:28.000', " +
             "TIMESTAMP '2022-02-01 10:30:28.128')").returns(128000).check();
 
-        checkQuery("SELECT TIMESTAMPDIFF(NANOSECOND, TIMESTAMP '2022-02-01 
10:30:28.000', " +
+        assertQuery("SELECT TIMESTAMPDIFF(NANOSECOND, TIMESTAMP '2022-02-01 
10:30:28.000', " +
             "TIMESTAMP '2022-02-01 
10:30:28.128')").returns(128000000L).check();
     }
 
     /** */
     @Test
     public void testLength() {
-        checkQuery("SELECT LENGTH('TEST')").returns(4).check();
-        checkQuery("SELECT LENGTH(NULL)").returns(NULL_RESULT).check();
+        assertQuery("SELECT LENGTH('TEST')").returns(4).check();
+        assertQuery("SELECT LENGTH(NULL)").returns(NULL_RESULT).check();
     }
 
     /** */
     @Test
     public void testQueryEngine() {
-        checkQuery("SELECT 
QUERY_ENGINE()").returns(CalciteQueryEngineConfiguration.ENGINE_NAME).check();
+        assertQuery("SELECT 
QUERY_ENGINE()").returns(CalciteQueryEngineConfiguration.ENGINE_NAME).check();
     }
 
     /** */
@@ -94,7 +79,7 @@ public class FunctionsTest extends GridCommonAbstractTest {
         while (true) {
             long tsBeg = U.currentTimeMillis();
 
-            List<List<?>> res = qryEngine.query(null, "PUBLIC", 
sql).get(0).getAll();
+            List<List<?>> res = sql(sql);
 
             long tsEnd = U.currentTimeMillis();
 
@@ -120,45 +105,43 @@ public class FunctionsTest extends GridCommonAbstractTest 
{
     /** */
     @Test
     public void testReplace() {
-        checkQuery("SELECT REPLACE('12341234', '1', 
'55')").returns("5523455234").check();
-        checkQuery("SELECT REPLACE(NULL, '1', 
'5')").returns(NULL_RESULT).check();
-        checkQuery("SELECT REPLACE('1', NULL, 
'5')").returns(NULL_RESULT).check();
-        checkQuery("SELECT REPLACE('11', '1', 
NULL)").returns(NULL_RESULT).check();
-        checkQuery("SELECT REPLACE('11', '1', '')").returns("").check();
+        assertQuery("SELECT REPLACE('12341234', '1', 
'55')").returns("5523455234").check();
+        assertQuery("SELECT REPLACE(NULL, '1', 
'5')").returns(NULL_RESULT).check();
+        assertQuery("SELECT REPLACE('1', NULL, 
'5')").returns(NULL_RESULT).check();
+        assertQuery("SELECT REPLACE('11', '1', 
NULL)").returns(NULL_RESULT).check();
+        assertQuery("SELECT REPLACE('11', '1', '')").returns("").check();
     }
 
     /** */
     @Test
     public void testRange() {
-        checkQuery("SELECT * FROM table(system_range(1, 4))")
+        assertQuery("SELECT * FROM table(system_range(1, 4))")
             .returns(1L)
             .returns(2L)
             .returns(3L)
             .returns(4L)
             .check();
 
-        checkQuery("SELECT * FROM table(system_range(1, 4, 2))")
+        assertQuery("SELECT * FROM table(system_range(1, 4, 2))")
             .returns(1L)
             .returns(3L)
             .check();
 
-        checkQuery("SELECT * FROM table(system_range(4, 1, -1))")
+        assertQuery("SELECT * FROM table(system_range(4, 1, -1))")
             .returns(4L)
             .returns(3L)
             .returns(2L)
             .returns(1L)
             .check();
 
-        checkQuery("SELECT * FROM table(system_range(4, 1, -2))")
+        assertQuery("SELECT * FROM table(system_range(4, 1, -2))")
             .returns(4L)
             .returns(2L)
             .check();
 
-        assertEquals(0, qryEngine.query(null, "PUBLIC",
-            "SELECT * FROM table(system_range(4, 1))").get(0).getAll().size());
+        assertEquals(0, sql("SELECT * FROM table(system_range(4, 1))").size());
 
-        assertEquals(0, qryEngine.query(null, "PUBLIC",
-            "SELECT * FROM table(system_range(null, 
1))").get(0).getAll().size());
+        assertEquals(0, sql("SELECT * FROM table(system_range(null, 
1))").size());
 
         assertThrows("SELECT * FROM table(system_range(1, 1, 0))", 
IllegalArgumentException.class,
             "Increment can't be 0");
@@ -182,7 +165,7 @@ public class FunctionsTest extends GridCommonAbstractTest {
         awaitPartitionMapExchange();
 
         // Correlated INNER join.
-        checkQuery("SELECT t._val FROM \"test\".Integer t WHERE t._val < 5 AND 
" +
+        assertQuery("SELECT t._val FROM \"test\".Integer t WHERE t._val < 5 
AND " +
             "t._key in (SELECT x FROM table(system_range(t._val, t._val))) ")
             .returns(0)
             .returns(1)
@@ -192,25 +175,24 @@ public class FunctionsTest extends GridCommonAbstractTest 
{
             .check();
 
         // Correlated LEFT joins.
-        checkQuery("SELECT t._val FROM \"test\".Integer t WHERE t._val < 5 AND 
" +
+        assertQuery("SELECT t._val FROM \"test\".Integer t WHERE t._val < 5 
AND " +
             "EXISTS (SELECT x FROM table(system_range(t._val, t._val)) WHERE 
mod(x, 2) = 0) ")
             .returns(0)
             .returns(2)
             .returns(4)
             .check();
 
-        checkQuery("SELECT t._val FROM \"test\".Integer t WHERE t._val < 5 AND 
" +
+        assertQuery("SELECT t._val FROM \"test\".Integer t WHERE t._val < 5 
AND " +
             "NOT EXISTS (SELECT x FROM table(system_range(t._val, t._val)) 
WHERE mod(x, 2) = 0) ")
             .returns(1)
             .returns(3)
             .check();
 
-        assertEquals(0, qryEngine.query(null, "PUBLIC",
-            "SELECT t._val FROM \"test\".Integer t WHERE " +
-                "EXISTS (SELECT x FROM table(system_range(t._val, null))) 
").get(0).getAll().size());
+        assertEquals(0, sql("SELECT t._val FROM \"test\".Integer t WHERE " +
+                "EXISTS (SELECT x FROM table(system_range(t._val, null))) 
").size());
 
         // Non-correlated join.
-        checkQuery("SELECT t._val FROM \"test\".Integer t JOIN 
table(system_range(1, 50)) as r ON t._key = r.x " +
+        assertQuery("SELECT t._val FROM \"test\".Integer t JOIN 
table(system_range(1, 50)) as r ON t._key = r.x " +
             "WHERE mod(r.x, 10) = 0")
             .returns(10)
             .returns(20)
@@ -223,45 +205,45 @@ public class FunctionsTest extends GridCommonAbstractTest 
{
     /** */
     @Test
     public void testPercentRemainder() {
-        checkQuery("SELECT 3 % 2").returns(1).check();
-        checkQuery("SELECT 4 % 2").returns(0).check();
-        checkQuery("SELECT NULL % 2").returns(NULL_RESULT).check();
-        checkQuery("SELECT 3 % NULL::int").returns(NULL_RESULT).check();
-        checkQuery("SELECT 3 % NULL").returns(NULL_RESULT).check();
+        assertQuery("SELECT 3 % 2").returns(1).check();
+        assertQuery("SELECT 4 % 2").returns(0).check();
+        assertQuery("SELECT NULL % 2").returns(NULL_RESULT).check();
+        assertQuery("SELECT 3 % NULL::int").returns(NULL_RESULT).check();
+        assertQuery("SELECT 3 % NULL").returns(NULL_RESULT).check();
     }
 
     /** */
     @Test
     public void testNullFunctionArguments() {
         // Don't infer result data type from arguments (result is always 
INTEGER_NULLABLE).
-        checkQuery("SELECT ASCII(NULL)").returns(NULL_RESULT).check();
+        assertQuery("SELECT ASCII(NULL)").returns(NULL_RESULT).check();
         // Inferring result data type from first STRING argument.
-        checkQuery("SELECT REPLACE(NULL, '1', 
'2')").returns(NULL_RESULT).check();
+        assertQuery("SELECT REPLACE(NULL, '1', 
'2')").returns(NULL_RESULT).check();
         // Inferring result data type from both arguments.
-        checkQuery("SELECT MOD(1, null)").returns(NULL_RESULT).check();
+        assertQuery("SELECT MOD(1, null)").returns(NULL_RESULT).check();
         // Inferring result data type from first NUMERIC argument.
-        checkQuery("SELECT TRUNCATE(NULL, 0)").returns(NULL_RESULT).check();
+        assertQuery("SELECT TRUNCATE(NULL, 0)").returns(NULL_RESULT).check();
         // Inferring arguments data types and then inferring result data type 
from all arguments.
-        checkQuery("SELECT FALSE AND NULL").returns(false).check();
+        assertQuery("SELECT FALSE AND NULL").returns(false).check();
     }
 
     /** */
     @Test
     public void testMonthnameDayname() {
-        checkQuery("SELECT MONTHNAME(DATE 
'2021-01-01')").returns("January").check();
-        checkQuery("SELECT DAYNAME(DATE 
'2021-01-01')").returns("Friday").check();
+        assertQuery("SELECT MONTHNAME(DATE 
'2021-01-01')").returns("January").check();
+        assertQuery("SELECT DAYNAME(DATE 
'2021-01-01')").returns("Friday").check();
     }
 
     /** */
     @Test
     public void testTypeOf() {
-        checkQuery("SELECT TYPEOF(1)").returns("INTEGER").check();
-        checkQuery("SELECT TYPEOF(1.1::DOUBLE)").returns("DOUBLE").check();
-        checkQuery("SELECT TYPEOF(1.1::DECIMAL(3, 2))").returns("DECIMAL(3, 
2)").check();
-        checkQuery("SELECT TYPEOF('a')").returns("CHAR(1)").check();
-        checkQuery("SELECT 
TYPEOF('a'::varchar(1))").returns("VARCHAR(1)").check();
-        checkQuery("SELECT TYPEOF(NULL)").returns("NULL").check();
-        checkQuery("SELECT 
TYPEOF(NULL::VARCHAR(100))").returns("VARCHAR(100)").check();
+        assertQuery("SELECT TYPEOF(1)").returns("INTEGER").check();
+        assertQuery("SELECT TYPEOF(1.1::DOUBLE)").returns("DOUBLE").check();
+        assertQuery("SELECT TYPEOF(1.1::DECIMAL(3, 2))").returns("DECIMAL(3, 
2)").check();
+        assertQuery("SELECT TYPEOF('a')").returns("CHAR(1)").check();
+        assertQuery("SELECT 
TYPEOF('a'::varchar(1))").returns("VARCHAR(1)").check();
+        assertQuery("SELECT TYPEOF(NULL)").returns("NULL").check();
+        assertQuery("SELECT 
TYPEOF(NULL::VARCHAR(100))").returns("VARCHAR(100)").check();
         assertThrows("SELECT TYPEOF()", SqlValidatorException.class, "Invalid 
number of arguments");
         assertThrows("SELECT TYPEOF(1, 2)", SqlValidatorException.class, 
"Invalid number of arguments");
     }
@@ -269,49 +251,42 @@ public class FunctionsTest extends GridCommonAbstractTest 
{
     /** */
     @Test
     public void testRegex() {
-        checkQuery("SELECT 'abcd' ~ 'ab[cd]'").returns(true).check();
-        checkQuery("SELECT 'abcd' ~ 'ab[cd]$'").returns(false).check();
-        checkQuery("SELECT 'abcd' ~ 'ab[CD]'").returns(false).check();
-        checkQuery("SELECT 'abcd' ~* 'ab[cd]'").returns(true).check();
-        checkQuery("SELECT 'abcd' ~* 'ab[cd]$'").returns(false).check();
-        checkQuery("SELECT 'abcd' ~* 'ab[CD]'").returns(true).check();
-        checkQuery("SELECT 'abcd' !~ 'ab[cd]'").returns(false).check();
-        checkQuery("SELECT 'abcd' !~ 'ab[cd]$'").returns(true).check();
-        checkQuery("SELECT 'abcd' !~ 'ab[CD]'").returns(true).check();
-        checkQuery("SELECT 'abcd' !~* 'ab[cd]'").returns(false).check();
-        checkQuery("SELECT 'abcd' !~* 'ab[cd]$'").returns(true).check();
-        checkQuery("SELECT 'abcd' !~* 'ab[CD]'").returns(false).check();
-        checkQuery("SELECT null ~ 'ab[cd]'").returns(NULL_RESULT).check();
-        checkQuery("SELECT 'abcd' ~ null").returns(NULL_RESULT).check();
-        checkQuery("SELECT null ~ null").returns(NULL_RESULT).check();
-        checkQuery("SELECT null ~* 'ab[cd]'").returns(NULL_RESULT).check();
-        checkQuery("SELECT 'abcd' ~* null").returns(NULL_RESULT).check();
-        checkQuery("SELECT null ~* null").returns(NULL_RESULT).check();
-        checkQuery("SELECT null !~ 'ab[cd]'").returns(NULL_RESULT).check();
-        checkQuery("SELECT 'abcd' !~ null").returns(NULL_RESULT).check();
-        checkQuery("SELECT null !~ null").returns(NULL_RESULT).check();
-        checkQuery("SELECT null !~* 'ab[cd]'").returns(NULL_RESULT).check();
-        checkQuery("SELECT 'abcd' !~* null").returns(NULL_RESULT).check();
-        checkQuery("SELECT null !~* null").returns(NULL_RESULT).check();
+        assertQuery("SELECT 'abcd' ~ 'ab[cd]'").returns(true).check();
+        assertQuery("SELECT 'abcd' ~ 'ab[cd]$'").returns(false).check();
+        assertQuery("SELECT 'abcd' ~ 'ab[CD]'").returns(false).check();
+        assertQuery("SELECT 'abcd' ~* 'ab[cd]'").returns(true).check();
+        assertQuery("SELECT 'abcd' ~* 'ab[cd]$'").returns(false).check();
+        assertQuery("SELECT 'abcd' ~* 'ab[CD]'").returns(true).check();
+        assertQuery("SELECT 'abcd' !~ 'ab[cd]'").returns(false).check();
+        assertQuery("SELECT 'abcd' !~ 'ab[cd]$'").returns(true).check();
+        assertQuery("SELECT 'abcd' !~ 'ab[CD]'").returns(true).check();
+        assertQuery("SELECT 'abcd' !~* 'ab[cd]'").returns(false).check();
+        assertQuery("SELECT 'abcd' !~* 'ab[cd]$'").returns(true).check();
+        assertQuery("SELECT 'abcd' !~* 'ab[CD]'").returns(false).check();
+        assertQuery("SELECT null ~ 'ab[cd]'").returns(NULL_RESULT).check();
+        assertQuery("SELECT 'abcd' ~ null").returns(NULL_RESULT).check();
+        assertQuery("SELECT null ~ null").returns(NULL_RESULT).check();
+        assertQuery("SELECT null ~* 'ab[cd]'").returns(NULL_RESULT).check();
+        assertQuery("SELECT 'abcd' ~* null").returns(NULL_RESULT).check();
+        assertQuery("SELECT null ~* null").returns(NULL_RESULT).check();
+        assertQuery("SELECT null !~ 'ab[cd]'").returns(NULL_RESULT).check();
+        assertQuery("SELECT 'abcd' !~ null").returns(NULL_RESULT).check();
+        assertQuery("SELECT null !~ null").returns(NULL_RESULT).check();
+        assertQuery("SELECT null !~* 'ab[cd]'").returns(NULL_RESULT).check();
+        assertQuery("SELECT 'abcd' !~* null").returns(NULL_RESULT).check();
+        assertQuery("SELECT null !~* null").returns(NULL_RESULT).check();
         assertThrows("SELECT 'abcd' ~ '[a-z'", IgniteSQLException.class, null);
     }
 
     /** */
-    private void assertThrows(String qry, Class<? extends Throwable> cls, 
String msg) {
-        GridTestUtils.assertThrowsAnyCause(
-            log,
-            () -> qryEngine.query(null, "PUBLIC", qry).get(0).getAll(),
-            cls,
-            msg
-        );
-    }
-
-    /** */
-    private QueryChecker checkQuery(String qry) {
-        return new QueryChecker(qry) {
-            @Override protected QueryEngine getEngine() {
-                return qryEngine;
-            }
-        };
+    @Test
+    public void testDynamicParameterTypesInference() {
+        assertQuery("SELECT 
lower(?)").withParams("ASD").returns("asd").check();
+        assertQuery("SELECT ? % ?").withParams(11, 
10).returns(BigDecimal.valueOf(1)).check();
+        assertQuery("SELECT sqrt(?)").withParams(4d).returns(2d).check();
+        assertQuery("SELECT 
last_day(?)").withParams(Date.valueOf("2022-01-01"))
+            .returns(Date.valueOf("2022-01-31")).check();
+        assertQuery("SELECT ?").withParams("asd").returns("asd").check();
+        assertQuery("SELECT coalesce(?, ?)").withParams("a", 
10).returns("a").check();
     }
 }
diff --git 
a/modules/calcite/src/test/java/org/apache/ignite/internal/processors/query/calcite/integration/UserDefinedFunctionsIntegrationTest.java
 
b/modules/calcite/src/test/java/org/apache/ignite/internal/processors/query/calcite/integration/UserDefinedFunctionsIntegrationTest.java
index 17cbd3f8fef..2f5796393cf 100644
--- 
a/modules/calcite/src/test/java/org/apache/ignite/internal/processors/query/calcite/integration/UserDefinedFunctionsIntegrationTest.java
+++ 
b/modules/calcite/src/test/java/org/apache/ignite/internal/processors/query/calcite/integration/UserDefinedFunctionsIntegrationTest.java
@@ -80,6 +80,7 @@ public class UserDefinedFunctionsIntegrationTest extends 
AbstractBasicIntegratio
         assertQuery("SELECT echo(name) FROM 
emp3").returns("Igor3").returns("Roman3").check();
         assertQuery("SELECT sq(salary) FROM 
EMP2_SCHEMA.emp2").returns(100d).returns(400d).check();
         assertQuery("SELECT sq(salary) FROM 
\"emp1\".emp1").returns(1d).returns(4d).check();
+        assertQuery("SELECT 
echo(?)").withParams("test").returns("test").check(); // Check type inference.
         assertThrows("SELECT add(1, 2)");
         assertThrows("SELECT mul(1, 2)");
         assertThrows("SELECT EMP2_SCHEMA.mul(1, 2)");
diff --git 
a/modules/calcite/src/test/java/org/apache/ignite/testsuites/IntegrationTestSuite.java
 
b/modules/calcite/src/test/java/org/apache/ignite/testsuites/IntegrationTestSuite.java
index bde32f8a45e..cd24f539df8 100644
--- 
a/modules/calcite/src/test/java/org/apache/ignite/testsuites/IntegrationTestSuite.java
+++ 
b/modules/calcite/src/test/java/org/apache/ignite/testsuites/IntegrationTestSuite.java
@@ -20,7 +20,6 @@ package org.apache.ignite.testsuites;
 import 
org.apache.ignite.internal.processors.query.calcite.CalciteQueryProcessorTest;
 import org.apache.ignite.internal.processors.query.calcite.CancelTest;
 import org.apache.ignite.internal.processors.query.calcite.DateTimeTest;
-import org.apache.ignite.internal.processors.query.calcite.FunctionsTest;
 import org.apache.ignite.internal.processors.query.calcite.LimitOffsetTest;
 import 
org.apache.ignite.internal.processors.query.calcite.SqlFieldsQueryUsageTest;
 import 
org.apache.ignite.internal.processors.query.calcite.UnstableTopologyTest;
@@ -29,6 +28,7 @@ import 
org.apache.ignite.internal.processors.query.calcite.integration.CalciteBa
 import 
org.apache.ignite.internal.processors.query.calcite.integration.CalciteErrorHandlilngIntegrationTest;
 import 
org.apache.ignite.internal.processors.query.calcite.integration.CorrelatesIntegrationTest;
 import 
org.apache.ignite.internal.processors.query.calcite.integration.DataTypesTest;
+import 
org.apache.ignite.internal.processors.query.calcite.integration.FunctionsTest;
 import 
org.apache.ignite.internal.processors.query.calcite.integration.HashSpoolIntegrationTest;
 import 
org.apache.ignite.internal.processors.query.calcite.integration.IndexDdlIntegrationTest;
 import 
org.apache.ignite.internal.processors.query.calcite.integration.IndexRebuildIntegrationTest;

Reply via email to