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 21f6b889989 IGNITE-23745 SQL Calcite: Add ability to extend SQL engine 
with new system functions/operators - Fixes #11684.
21f6b889989 is described below

commit 21f6b8899891469d508b3dd519f2049b899201fa
Author: Aleksey Plekhanov <[email protected]>
AuthorDate: Thu Dec 5 18:20:37 2024 +0300

    IGNITE-23745 SQL Calcite: Add ability to extend SQL engine with new system 
functions/operators - Fixes #11684.
    
    Signed-off-by: Aleksey Plekhanov <[email protected]>
---
 .../query/calcite/CalciteQueryProcessor.java       |  20 +-
 .../query/calcite/exec/ExecutionServiceImpl.java   |   6 +
 .../query/calcite/exec/exp/RexImpTable.java        |  11 +-
 .../calcite/prepare/IgniteConvertletTable.java     |   2 +-
 .../calcite/prepare/IgniteSqlCallRewriteTable.java |  21 ++-
 .../OperatorsExtensionIntegrationTest.java         | 208 +++++++++++++++++++++
 .../ignite/testsuites/IntegrationTestSuite.java    |   2 +
 7 files changed, 255 insertions(+), 15 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 c845efd27e3..7a8a68945b7 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
@@ -163,7 +163,7 @@ public class CalciteQueryProcessor extends 
GridProcessorAdapter implements Query
         .sqlValidatorConfig(SqlValidator.Config.DEFAULT
             .withIdentifierExpansion(true)
             .withDefaultNullCollation(NullCollation.LOW)
-            .withSqlConformance(IgniteSqlConformance.INSTANCE)
+            .withConformance(IgniteSqlConformance.INSTANCE)
             .withTypeCoercionFactory(IgniteTypeCoercion::new))
         // Dialects support.
         
.operatorTable(SqlOperatorTables.chain(IgniteStdSqlOperatorTable.INSTANCE, 
IgniteOwnSqlOperatorTable.instance()))
@@ -181,6 +181,9 @@ public class CalciteQueryProcessor extends 
GridProcessorAdapter implements Query
         })
         .build();
 
+    /** */
+    private final FrameworkConfig frameworkCfg;
+
     /** Query planner timeout. */
     private final long queryPlannerTimeout = 
getLong(IGNITE_CALCITE_PLANNER_TIMEOUT,
         DFLT_IGNITE_CALCITE_PLANNER_TIMEOUT);
@@ -257,6 +260,9 @@ public class CalciteQueryProcessor extends 
GridProcessorAdapter implements Query
         timeoutSvc = new TimeoutServiceImpl(ctx);
         qryReg = new QueryRegistryImpl(ctx);
 
+        FrameworkConfig customFrameworkCfg = 
ctx.plugins().createComponent(FrameworkConfig.class);
+        frameworkCfg = customFrameworkCfg != null ? customFrameworkCfg : 
FRAMEWORK_CONFIG;
+
         QueryEngineConfiguration[] qryEnginesCfg = 
ctx.config().getSqlConfiguration().getQueryEnginesConfiguration();
 
         if (F.isEmpty(qryEnginesCfg))
@@ -426,7 +432,7 @@ public class CalciteQueryProcessor extends 
GridProcessorAdapter implements Query
 
         assert schema != null : "Schema not found: " + schemaName;
 
-        SqlNodeList qryNodeList = Commons.parse(sql, 
FRAMEWORK_CONFIG.getParserConfig());
+        SqlNodeList qryNodeList = Commons.parse(sql, 
frameworkCfg.getParserConfig());
 
         if (qryNodeList.size() != 1) {
             throw new IgniteSQLException("Multiline statements are not 
supported in batched query",
@@ -510,7 +516,7 @@ public class CalciteQueryProcessor extends 
GridProcessorAdapter implements Query
 
         QueryProperties qryProps = qryCtx != null ? 
qryCtx.unwrap(QueryProperties.class) : null;
 
-        SqlNodeList qryList = Commons.parse(sql, 
FRAMEWORK_CONFIG.getParserConfig());
+        SqlNodeList qryList = Commons.parse(sql, 
frameworkCfg.getParserConfig());
 
         if (qryList.size() > 1 && qryProps != null && 
qryProps.isFailOnMultipleStmts()) {
             throw new IgniteSQLException("Multiple statements queries are not 
supported.",
@@ -641,6 +647,9 @@ public class CalciteQueryProcessor extends 
GridProcessorAdapter implements Query
         if (timeout <= 0)
             timeout = distrCfg.defaultQueryTimeout();
 
+        if (frameworkCfg != FRAMEWORK_CONFIG)
+            qryCtx = QueryContext.of(frameworkCfg, qryCtx);
+
         RootQuery<Object[]> qry = new RootQuery<>(
             sql,
             schemaHolder.schema(schema),
@@ -766,4 +775,9 @@ public class CalciteQueryProcessor extends 
GridProcessorAdapter implements Query
     public DistributedCalciteConfiguration distributedConfiguration() {
         return distrCfg;
     }
+
+    /** */
+    public FrameworkConfig frameworkConfig() {
+        return frameworkCfg;
+    }
 }
diff --git 
a/modules/calcite/src/main/java/org/apache/ignite/internal/processors/query/calcite/exec/ExecutionServiceImpl.java
 
b/modules/calcite/src/main/java/org/apache/ignite/internal/processors/query/calcite/exec/ExecutionServiceImpl.java
index 252358a870f..b3b49a4e1af 100644
--- 
a/modules/calcite/src/main/java/org/apache/ignite/internal/processors/query/calcite/exec/ExecutionServiceImpl.java
+++ 
b/modules/calcite/src/main/java/org/apache/ignite/internal/processors/query/calcite/exec/ExecutionServiceImpl.java
@@ -31,6 +31,7 @@ import org.apache.calcite.plan.RelOptUtil;
 import org.apache.calcite.rel.core.TableModify;
 import org.apache.calcite.sql.SqlInsert;
 import org.apache.calcite.sql.SqlKind;
+import org.apache.calcite.tools.FrameworkConfig;
 import org.apache.ignite.IgniteCheckedException;
 import org.apache.ignite.IgniteException;
 import org.apache.ignite.cache.query.FieldsQueryCursor;
@@ -192,6 +193,9 @@ public class ExecutionServiceImpl<Row> extends 
AbstractService implements Execut
     /** */
     private CalciteQueryEngineConfiguration cfg;
 
+    /** */
+    private FrameworkConfig frameworkCfg;
+
     /** */
     private MemoryTracker memoryTracker;
 
@@ -446,6 +450,7 @@ public class ExecutionServiceImpl<Row> extends 
AbstractService implements Execut
         ddlCmdHnd = new DdlCommandHandler(ctx.query(), ctx.cache(), 
ctx.security(), () -> schemaHolder().schema(null));
 
         cfg = proc.config();
+        frameworkCfg = proc.frameworkConfig();
 
         memoryTracker = cfg.getGlobalMemoryQuota() > 0 ? new 
GlobalMemoryTracker(cfg.getGlobalMemoryQuota()) :
             NoOpMemoryTracker.INSTANCE;
@@ -480,6 +485,7 @@ public class ExecutionServiceImpl<Row> extends 
AbstractService implements Execut
     private BaseQueryContext createQueryContext(Context parent, @Nullable 
String schema) {
         return BaseQueryContext.builder()
             .parentContext(parent)
+            .frameworkConfig(frameworkCfg)
             .defaultSchema(schemaHolder().schema(schema))
             .logger(log)
             .build();
diff --git 
a/modules/calcite/src/main/java/org/apache/ignite/internal/processors/query/calcite/exec/exp/RexImpTable.java
 
b/modules/calcite/src/main/java/org/apache/ignite/internal/processors/query/calcite/exec/exp/RexImpTable.java
index cd3a5752f94..cec141b16b3 100644
--- 
a/modules/calcite/src/main/java/org/apache/ignite/internal/processors/query/calcite/exec/exp/RexImpTable.java
+++ 
b/modules/calcite/src/main/java/org/apache/ignite/internal/processors/query/calcite/exec/exp/RexImpTable.java
@@ -579,18 +579,23 @@ public class RexImpTable {
         defineMethod(BITXOR, BuiltInMethod.BIT_XOR.method, NullPolicy.ANY);
     }
 
+    /** */
+    public void define(SqlOperator operator, RexCallImplementor implementor) {
+        map.put(operator, implementor);
+    }
+
     /** */
     private void defineMethod(SqlOperator operator, String functionName, 
NullPolicy nullPolicy) {
         map.put(operator, new MethodNameImplementor(functionName, nullPolicy, 
false));
     }
 
     /** */
-    private void defineMethod(SqlOperator operator, Method method, NullPolicy 
nullPolicy) {
+    public void defineMethod(SqlOperator operator, Method method, NullPolicy 
nullPolicy) {
         map.put(operator, new MethodImplementor(method, nullPolicy, false));
     }
 
     /** */
-    private ReflectiveImplementor defineReflective(SqlOperator operator, 
Method... methods) {
+    public ReflectiveImplementor defineReflective(SqlOperator operator, 
Method... methods) {
         final ReflectiveImplementor implementor = new 
ReflectiveImplementor(ImmutableList.copyOf(methods));
         map.put(operator, implementor);
         return implementor;
@@ -2513,7 +2518,7 @@ public class RexImpTable {
     }
 
     /** */
-    private static RexCallImplementor createRexCallImplementor(
+    public static RexCallImplementor createRexCallImplementor(
         final NotNullImplementor implementor,
         final NullPolicy nullPolicy,
         final boolean harmonize) {
diff --git 
a/modules/calcite/src/main/java/org/apache/ignite/internal/processors/query/calcite/prepare/IgniteConvertletTable.java
 
b/modules/calcite/src/main/java/org/apache/ignite/internal/processors/query/calcite/prepare/IgniteConvertletTable.java
index d5063b2b009..08d51500337 100644
--- 
a/modules/calcite/src/main/java/org/apache/ignite/internal/processors/query/calcite/prepare/IgniteConvertletTable.java
+++ 
b/modules/calcite/src/main/java/org/apache/ignite/internal/processors/query/calcite/prepare/IgniteConvertletTable.java
@@ -46,7 +46,7 @@ public class IgniteConvertletTable extends 
ReflectiveConvertletTable {
     public static final IgniteConvertletTable INSTANCE = new 
IgniteConvertletTable();
 
     /** */
-    private IgniteConvertletTable() {
+    protected IgniteConvertletTable() {
         // Replace Calcite's convertlet with our own.
         registerOp(SqlStdOperatorTable.TIMESTAMP_DIFF, new 
TimestampDiffConvertlet());
 
diff --git 
a/modules/calcite/src/main/java/org/apache/ignite/internal/processors/query/calcite/prepare/IgniteSqlCallRewriteTable.java
 
b/modules/calcite/src/main/java/org/apache/ignite/internal/processors/query/calcite/prepare/IgniteSqlCallRewriteTable.java
index 80052ed8454..de76cc64ce5 100644
--- 
a/modules/calcite/src/main/java/org/apache/ignite/internal/processors/query/calcite/prepare/IgniteSqlCallRewriteTable.java
+++ 
b/modules/calcite/src/main/java/org/apache/ignite/internal/processors/query/calcite/prepare/IgniteSqlCallRewriteTable.java
@@ -24,7 +24,6 @@ import java.util.function.BiFunction;
 import org.apache.calcite.sql.SqlCall;
 import org.apache.calcite.sql.SqlNode;
 import org.apache.calcite.sql.SqlNodeList;
-import org.apache.calcite.sql.SqlOperator;
 import org.apache.calcite.sql.fun.SqlCase;
 import org.apache.calcite.sql.fun.SqlLibraryOperators;
 import org.apache.calcite.sql.fun.SqlStdOperatorTable;
@@ -41,23 +40,29 @@ public class IgniteSqlCallRewriteTable {
     /** Instance. */
     public static final IgniteSqlCallRewriteTable INSTANCE = new 
IgniteSqlCallRewriteTable();
 
-    /** Registered rewriters map. */
-    private final Map<SqlOperator, BiFunction<SqlValidator, SqlCall, SqlCall>> 
map = new ConcurrentHashMap<>();
+    /**
+     * Registered rewriters map.
+     * If there are function overloads exists, validator can't resolve 
SqlOperator only by name, before unconditinal
+     * rewrite. SqlCall contains SqlUnresolvedFunction as an operator. We can 
find a rewriter for such a call only by
+     * operator name (string). Rewriter should ensure that it's a correct 
operator to rewrite (for example,
+     * additionally checking operands count) and skip operators with the 
unknown signature.
+     */
+    private final Map<String, BiFunction<SqlValidator, SqlCall, SqlCall>> map 
= new ConcurrentHashMap<>();
 
     /** */
     private IgniteSqlCallRewriteTable() {
-        register(SqlLibraryOperators.NVL, 
IgniteSqlCallRewriteTable::nvlRewriter);
-        register(SqlLibraryOperators.DECODE, 
IgniteSqlCallRewriteTable::decodeRewriter);
+        register(SqlLibraryOperators.NVL.getName(), 
IgniteSqlCallRewriteTable::nvlRewriter);
+        register(SqlLibraryOperators.DECODE.getName(), 
IgniteSqlCallRewriteTable::decodeRewriter);
     }
 
     /** Registers rewriter for SQL operator. */
-    public void register(SqlOperator operator, BiFunction<SqlValidator, 
SqlCall, SqlCall> rewriter) {
-        map.put(operator, rewriter);
+    public void register(String operatorName, BiFunction<SqlValidator, 
SqlCall, SqlCall> rewriter) {
+        map.put(operatorName, rewriter);
     }
 
     /** Rewrites SQL call. */
     SqlCall rewrite(SqlValidator validator, SqlCall call) {
-        BiFunction<SqlValidator, SqlCall, SqlCall> rewriter = 
map.get(call.getOperator());
+        BiFunction<SqlValidator, SqlCall, SqlCall> rewriter = 
map.get(call.getOperator().getName());
 
         return rewriter == null ? call : rewriter.apply(validator, call);
     }
diff --git 
a/modules/calcite/src/test/java/org/apache/ignite/internal/processors/query/calcite/integration/OperatorsExtensionIntegrationTest.java
 
b/modules/calcite/src/test/java/org/apache/ignite/internal/processors/query/calcite/integration/OperatorsExtensionIntegrationTest.java
new file mode 100644
index 00000000000..d2513ad9f3b
--- /dev/null
+++ 
b/modules/calcite/src/test/java/org/apache/ignite/internal/processors/query/calcite/integration/OperatorsExtensionIntegrationTest.java
@@ -0,0 +1,208 @@
+/*
+ * 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.ignite.internal.processors.query.calcite.integration;
+
+import java.math.BigDecimal;
+import java.sql.Timestamp;
+import com.google.common.collect.ImmutableList;
+import org.apache.calcite.adapter.enumerable.NullPolicy;
+import org.apache.calcite.avatica.util.TimeUnitRange;
+import org.apache.calcite.linq4j.tree.Expressions;
+import org.apache.calcite.rex.RexBuilder;
+import org.apache.calcite.rex.RexNode;
+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.fun.SqlStdOperatorTable;
+import org.apache.calcite.sql.fun.SqlTrimFunction;
+import org.apache.calcite.sql.parser.SqlParserPos;
+import org.apache.calcite.sql.type.OperandTypes;
+import org.apache.calcite.sql.type.ReturnTypes;
+import org.apache.calcite.sql.type.SqlTypeName;
+import org.apache.calcite.sql.util.ReflectiveSqlOperatorTable;
+import org.apache.calcite.sql.util.SqlOperatorTables;
+import org.apache.calcite.sql.validate.SqlValidator;
+import org.apache.calcite.sql2rel.SqlRexContext;
+import org.apache.calcite.sql2rel.SqlRexConvertlet;
+import org.apache.calcite.tools.FrameworkConfig;
+import org.apache.calcite.tools.Frameworks;
+import org.apache.calcite.util.BuiltInMethod;
+import org.apache.ignite.configuration.IgniteConfiguration;
+import 
org.apache.ignite.internal.processors.query.calcite.CalciteQueryProcessor;
+import 
org.apache.ignite.internal.processors.query.calcite.exec.exp.RexImpTable;
+import 
org.apache.ignite.internal.processors.query.calcite.prepare.IgniteConvertletTable;
+import 
org.apache.ignite.internal.processors.query.calcite.prepare.IgniteSqlCallRewriteTable;
+import org.apache.ignite.plugin.AbstractTestPluginProvider;
+import org.apache.ignite.plugin.PluginContext;
+import org.jetbrains.annotations.Nullable;
+import org.junit.Test;
+
+/**
+ * Tests SQL engine extension with plugin.
+ */
+public class OperatorsExtensionIntegrationTest extends 
AbstractBasicIntegrationTest {
+    /** {@inheritDoc} */
+    @Override protected IgniteConfiguration getConfiguration(String 
igniteInstanceName) throws Exception {
+        return super.getConfiguration(igniteInstanceName)
+            .setPluginProviders(new AbstractTestPluginProvider() {
+                @Override public String name() {
+                    return "Test operators extension plugin";
+                }
+
+                @Override public <T> @Nullable T createComponent(PluginContext 
ctx, Class<T> cls) {
+                    if (FrameworkConfig.class.equals(cls)) {
+                        FrameworkConfig cfg = 
Frameworks.newConfigBuilder(CalciteQueryProcessor.FRAMEWORK_CONFIG)
+                            .convertletTable(new ConvertletTable())
+                            .operatorTable(SqlOperatorTables.chain(
+                                new OperatorTable().init(), 
CalciteQueryProcessor.FRAMEWORK_CONFIG.getOperatorTable()))
+                            .build();
+
+                        return (T)cfg;
+                    }
+
+                    return super.createComponent(ctx, cls);
+                }
+
+                @Override public void start(PluginContext ctx) {
+                    // Tests operator extension via method implementor.
+                    try {
+                        RexImpTable.INSTANCE.defineMethod(
+                            OperatorTable.TO_NUMBER,
+                            
OperatorsExtensionIntegrationTest.class.getMethod("toNumber", String.class),
+                            NullPolicy.STRICT
+                        );
+                    }
+                    catch (NoSuchMethodException e) {
+                        throw new RuntimeException(e);
+                    }
+
+                    // Tests operator extension via custom implementor.
+                    RexImpTable.INSTANCE.define(OperatorTable.RTRIM, 
RexImpTable.createRexCallImplementor(
+                        (translator, call, translatedOperands) -> 
Expressions.call(
+                            BuiltInMethod.TRIM.method,
+                            RexImpTable.FALSE_EXPR,
+                            RexImpTable.TRUE_EXPR,
+                            translatedOperands.get(1),
+                            translatedOperands.get(0),
+                            RexImpTable.FALSE_EXPR
+                        ), NullPolicy.ARG0, false
+                    ));
+
+                    // Tests operator extension via SQL rewrite.
+                    IgniteSqlCallRewriteTable.INSTANCE.register("LTRIM",
+                        OperatorsExtensionIntegrationTest::rewriteLtrim);
+                }
+            });
+    }
+
+    /** Tests extended functions. */
+    @Test
+    public void test() throws Exception {
+        assertQuery("SELECT substr('12345', 3, 2)").returns("34").check();
+        assertQuery("SELECT to_number('12.34')").returns(new 
BigDecimal("12.34")).check();
+        assertQuery("SELECT ltrim('aabcda', 'a')").returns("bcda").check();
+        assertQuery("SELECT rtrim('aabcda', 'ad')").returns("aabc").check();
+        assertQuery("SELECT trunc(TIMESTAMP '2021-01-01 01:02:03')")
+            .returns(Timestamp.valueOf("2021-01-01 00:00:00")).check();
+    }
+
+    /** Rewrites LTRIM with 2 parameters. */
+    public static SqlCall rewriteLtrim(SqlValidator validator, SqlCall call) {
+        if (call.operandCount() != 2)
+            return call;
+
+        return SqlStdOperatorTable.TRIM.createCall(
+            call.getParserPosition(),
+            SqlTrimFunction.Flag.LEADING.symbol(SqlParserPos.ZERO),
+            call.operand(1),
+            call.operand(0)
+        );
+    }
+
+    /** Implementor for {@code TO_NUMBER} function. */
+    public static BigDecimal toNumber(String s) {
+        return new BigDecimal(s);
+    }
+
+    /** Extended operator table. */
+    public static class OperatorTable extends ReflectiveSqlOperatorTable {
+        /** */
+        public static final SqlFunction SUBSTR =
+            new SqlFunction(
+                "SUBSTR",
+                SqlKind.OTHER_FUNCTION,
+                ReturnTypes.ARG0_NULLABLE_VARYING,
+                null,
+                OperandTypes.STRING_INTEGER_INTEGER,
+                SqlFunctionCategory.STRING);
+
+        /** */
+        public static final SqlFunction TRUNC =
+            new SqlFunction(
+                "TRUNC",
+                SqlKind.OTHER_FUNCTION,
+                ReturnTypes.ARG0_OR_EXACT_NO_SCALE,
+                null,
+                OperandTypes.TIMESTAMP,
+                SqlFunctionCategory.TIMEDATE);
+
+        /** */
+        public static final SqlFunction TO_NUMBER =
+            new SqlFunction(
+                "TO_NUMBER",
+                SqlKind.OTHER_FUNCTION,
+                opBinding -> 
opBinding.getTypeFactory().createSqlType(SqlTypeName.DECIMAL),
+                null,
+                OperandTypes.STRING,
+                SqlFunctionCategory.NUMERIC);
+
+        /** */
+        public static final SqlFunction RTRIM = new SqlFunction(
+            "RTRIM",
+            SqlKind.RTRIM,
+            ReturnTypes.ARG0_NULLABLE_VARYING,
+            null,
+            OperandTypes.STRING_STRING,
+            SqlFunctionCategory.STRING
+        );
+    }
+
+    /** Extended convertlet table. */
+    private static class ConvertletTable extends IgniteConvertletTable {
+        /** */
+        public ConvertletTable() {
+            // Tests operator extension as an alias.
+            addAlias(OperatorTable.SUBSTR, SqlStdOperatorTable.SUBSTRING);
+            // Tests operator extension via covnertlet.
+            registerOp(OperatorTable.TRUNC, new TruncConvertlet());
+        }
+
+        /**
+         * Convertlet that handles the {@code TRUNC} function and convert it 
to FLOOR function.
+         */
+        private static class TruncConvertlet implements SqlRexConvertlet {
+            /** {@inheritDoc} */
+            @Override public RexNode convertCall(SqlRexContext cx, SqlCall 
call) {
+                final RexBuilder rexBuilder = cx.getRexBuilder();
+                RexNode day = rexBuilder.makeLiteral(TimeUnitRange.DAY, 
cx.getTypeFactory().createSqlType(SqlTypeName.SYMBOL));
+                return rexBuilder.makeCall(SqlStdOperatorTable.FLOOR,
+                    ImmutableList.of(cx.convertExpression(call.operand(0)), 
day));
+            }
+        }
+    }
+}
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 dc27a636e77..a062d3d3169 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
@@ -51,6 +51,7 @@ import 
org.apache.ignite.internal.processors.query.calcite.integration.LocalDate
 import 
org.apache.ignite.internal.processors.query.calcite.integration.LocalQueryIntegrationTest;
 import 
org.apache.ignite.internal.processors.query.calcite.integration.MemoryQuotasIntegrationTest;
 import 
org.apache.ignite.internal.processors.query.calcite.integration.MetadataIntegrationTest;
+import 
org.apache.ignite.internal.processors.query.calcite.integration.OperatorsExtensionIntegrationTest;
 import 
org.apache.ignite.internal.processors.query.calcite.integration.PartitionPruneTest;
 import 
org.apache.ignite.internal.processors.query.calcite.integration.QueryEngineConfigurationIntegrationTest;
 import 
org.apache.ignite.internal.processors.query.calcite.integration.QueryMetadataIntegrationTest;
@@ -143,6 +144,7 @@ import org.junit.runners.Suite;
     DdlTransactionCalciteSelfTest.class,
     MultiLineQueryTest.class,
     ViewsIntegrationTest.class,
+    OperatorsExtensionIntegrationTest.class,
 })
 public class IntegrationTestSuite {
 }

Reply via email to