You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@ignite.apache.org by zs...@apache.org on 2022/02/07 16:26:44 UTC

[ignite-3] branch main updated: IGNITE-16442 Upgrade to Apache Calcite 1.29.0

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

zstan pushed a commit to branch main
in repository https://gitbox.apache.org/repos/asf/ignite-3.git


The following commit(s) were added to refs/heads/main by this push:
     new c06f4c4  IGNITE-16442 Upgrade to Apache Calcite 1.29.0
c06f4c4 is described below

commit c06f4c416c756cdbfd525745cdddf8c5c873d4cf
Author: zstan <st...@gmail.com>
AuthorDate: Mon Feb 7 19:22:50 2022 +0300

    IGNITE-16442 Upgrade to Apache Calcite 1.29.0
    
    Signed-off-by: zstan <st...@gmail.com>
---
 modules/runner/pom.xml                             |  6 ++
 modules/sql-engine/pom.xml                         | 15 ++++
 .../sql/engine/metadata/IgniteMdCollation.java     |  5 +-
 .../engine/metadata/IgniteMdCumulativeCost.java    |  5 +-
 .../internal/sql/engine/prepare/PlannerPhase.java  | 12 ++-
 .../rule/FilterSpoolMergeToHashIndexSpoolRule.java |  8 +-
 .../FilterSpoolMergeToSortedIndexSpoolRule.java    |  9 +-
 .../sql/engine/rule/SortConverterRule.java         | 11 +--
 .../sql/engine/rule/UnionConverterRule.java        |  8 +-
 .../sql/engine/rule/logical/ExposeIndexRule.java   | 14 ++--
 .../engine/rule/logical/FilterScanMergeRule.java   | 95 +++++++++++-----------
 .../engine/rule/logical/LogicalOrToUnionRule.java  | 18 ++--
 .../engine/rule/logical/ProjectScanMergeRule.java  | 33 ++++----
 .../sql/engine/rule/logical/RuleFactoryConfig.java | 35 ++++++++
 .../internal/sql/engine/rule/package-info.java     | 25 ++++++
 parent/pom.xml                                     |  2 +-
 16 files changed, 190 insertions(+), 111 deletions(-)

diff --git a/modules/runner/pom.xml b/modules/runner/pom.xml
index a5aa970..d037ca6 100644
--- a/modules/runner/pom.xml
+++ b/modules/runner/pom.xml
@@ -113,6 +113,12 @@
         </dependency>
 
         <dependency>
+            <groupId>org.immutables</groupId>
+            <artifactId>value-annotations</artifactId>
+            <scope>test</scope>
+        </dependency>
+
+        <dependency>
             <groupId>com.github.npathai</groupId>
             <artifactId>hamcrest-optional</artifactId>
             <scope>test</scope>
diff --git a/modules/sql-engine/pom.xml b/modules/sql-engine/pom.xml
index 8520a4e..b974e0b 100644
--- a/modules/sql-engine/pom.xml
+++ b/modules/sql-engine/pom.xml
@@ -289,14 +289,29 @@
                         <artifactId>ignite-network-annotation-processor</artifactId>
                         <version>${project.version}</version>
                     </dependency>
+
+                    <dependency>
+                        <groupId>org.immutables</groupId>
+                        <artifactId>value</artifactId>
+                        <version>${immutables.version}</version>
+                    </dependency>
                 </dependencies>
                 <configuration>
+<!--                    <compilerArgs>
+                        <arg>-verbose</arg> <arg>-XprintRounds</arg> <arg>-XprintProcessorInfo</arg> <arg>-Xlint</arg> <arg>-J-verbose</arg>
+                    </compilerArgs>-->
                     <annotationProcessorPaths>
                         <path>
                             <groupId>org.apache.ignite</groupId>
                             <artifactId>ignite-network-annotation-processor</artifactId>
                             <version>${project.version}</version>
                         </path>
+
+                        <path>
+                            <groupId>org.immutables</groupId>
+                            <artifactId>value</artifactId>
+                            <version>${immutables.version}</version>
+                        </path>
                     </annotationProcessorPaths>
                 </configuration>
             </plugin>
diff --git a/modules/sql-engine/src/main/java/org/apache/ignite/internal/sql/engine/metadata/IgniteMdCollation.java b/modules/sql-engine/src/main/java/org/apache/ignite/internal/sql/engine/metadata/IgniteMdCollation.java
index 0163996..a50fbb6 100644
--- a/modules/sql-engine/src/main/java/org/apache/ignite/internal/sql/engine/metadata/IgniteMdCollation.java
+++ b/modules/sql-engine/src/main/java/org/apache/ignite/internal/sql/engine/metadata/IgniteMdCollation.java
@@ -76,7 +76,6 @@ import org.apache.calcite.rex.RexNode;
 import org.apache.calcite.rex.RexProgram;
 import org.apache.calcite.rex.RexSlot;
 import org.apache.calcite.sql.validate.SqlMonotonicity;
-import org.apache.calcite.util.BuiltInMethod;
 import org.apache.calcite.util.ImmutableBitSet;
 import org.apache.calcite.util.ImmutableIntList;
 import org.apache.calcite.util.Pair;
@@ -90,10 +89,8 @@ import org.apache.ignite.internal.sql.engine.util.Commons;
  */
 @SuppressWarnings("unused") // actually all methods are used by runtime generated classes
 public class IgniteMdCollation implements MetadataHandler<BuiltInMetadata.Collation> {
-
     public static final RelMetadataProvider SOURCE =
-            ReflectiveRelMetadataProvider.reflectiveSource(
-                    BuiltInMethod.COLLATIONS.method, new IgniteMdCollation());
+            ReflectiveRelMetadataProvider.reflectiveSource(new IgniteMdCollation(), BuiltInMetadata.Collation.Handler.class);
 
     //~ Constructors -----------------------------------------------------------
     private IgniteMdCollation() {
diff --git a/modules/sql-engine/src/main/java/org/apache/ignite/internal/sql/engine/metadata/IgniteMdCumulativeCost.java b/modules/sql-engine/src/main/java/org/apache/ignite/internal/sql/engine/metadata/IgniteMdCumulativeCost.java
index 699f30c..64dd978 100644
--- a/modules/sql-engine/src/main/java/org/apache/ignite/internal/sql/engine/metadata/IgniteMdCumulativeCost.java
+++ b/modules/sql-engine/src/main/java/org/apache/ignite/internal/sql/engine/metadata/IgniteMdCumulativeCost.java
@@ -34,7 +34,6 @@ import org.apache.calcite.rel.metadata.MetadataHandler;
 import org.apache.calcite.rel.metadata.ReflectiveRelMetadataProvider;
 import org.apache.calcite.rel.metadata.RelMetadataProvider;
 import org.apache.calcite.rel.metadata.RelMetadataQuery;
-import org.apache.calcite.util.BuiltInMethod;
 import org.apache.ignite.internal.sql.engine.rel.IgniteCorrelatedNestedLoopJoin;
 
 /**
@@ -43,8 +42,8 @@ import org.apache.ignite.internal.sql.engine.rel.IgniteCorrelatedNestedLoopJoin;
  */
 @SuppressWarnings("unused") // actually all methods are used by runtime generated classes
 public class IgniteMdCumulativeCost implements MetadataHandler<BuiltInMetadata.CumulativeCost> {
-    public static final RelMetadataProvider SOURCE = ReflectiveRelMetadataProvider.reflectiveSource(
-            BuiltInMethod.CUMULATIVE_COST.method, new IgniteMdCumulativeCost());
+    public static final RelMetadataProvider SOURCE =
+            ReflectiveRelMetadataProvider.reflectiveSource(new IgniteMdCumulativeCost(), BuiltInMetadata.CumulativeCost.Handler.class);
 
     /** {@inheritDoc} */
     @Override
diff --git a/modules/sql-engine/src/main/java/org/apache/ignite/internal/sql/engine/prepare/PlannerPhase.java b/modules/sql-engine/src/main/java/org/apache/ignite/internal/sql/engine/prepare/PlannerPhase.java
index 417e31e..5b43d2a 100644
--- a/modules/sql-engine/src/main/java/org/apache/ignite/internal/sql/engine/prepare/PlannerPhase.java
+++ b/modules/sql-engine/src/main/java/org/apache/ignite/internal/sql/engine/prepare/PlannerPhase.java
@@ -23,13 +23,13 @@ import static org.apache.ignite.internal.sql.engine.prepare.IgnitePrograms.hep;
 import java.util.ArrayList;
 import java.util.List;
 import org.apache.calcite.plan.RelOptRule;
+import org.apache.calcite.plan.RelRule;
 import org.apache.calcite.rel.core.Aggregate;
 import org.apache.calcite.rel.logical.LogicalAggregate;
 import org.apache.calcite.rel.logical.LogicalFilter;
 import org.apache.calcite.rel.logical.LogicalJoin;
 import org.apache.calcite.rel.logical.LogicalProject;
 import org.apache.calcite.rel.logical.LogicalSort;
-import org.apache.calcite.rel.rules.AggregateExpandDistinctAggregatesRule;
 import org.apache.calcite.rel.rules.AggregateMergeRule;
 import org.apache.calcite.rel.rules.CoreRules;
 import org.apache.calcite.rel.rules.FilterJoinRule.FilterIntoJoinRule;
@@ -132,11 +132,11 @@ public enum PlannerPhase {
             JoinPushExpressionsRule.Config.DEFAULT
                     .withOperandFor(LogicalJoin.class).toRule(),
 
-            JoinConditionPushRule.Config.DEFAULT
+            JoinConditionPushRule.JoinConditionPushRuleConfig.DEFAULT
                     .withOperandSupplier(b -> b.operand(LogicalJoin.class)
                             .anyInputs()).toRule(),
 
-            FilterIntoJoinRule.Config.DEFAULT
+            FilterIntoJoinRule.FilterIntoJoinRuleConfig.DEFAULT
                     .withOperandSupplier(b0 ->
                             b0.operand(LogicalFilter.class).oneInput(b1 ->
                                     b1.operand(LogicalJoin.class).anyInputs())).toRule(),
@@ -165,7 +165,7 @@ public enum PlannerPhase {
                                                     .predicate(Aggregate::isSimple)
                                                     .anyInputs())).toRule(),
 
-            AggregateExpandDistinctAggregatesRule.Config.JOIN.toRule(),
+            CoreRules.AGGREGATE_EXPAND_DISTINCT_AGGREGATES_TO_JOIN,
 
             SortRemoveRule.Config.DEFAULT
                     .withOperandSupplier(b ->
@@ -183,11 +183,9 @@ public enum PlannerPhase {
             // Useful of this rule is not clear now.
             // CoreRules.AGGREGATE_REDUCE_FUNCTIONS,
 
-            PruneEmptyRules.SortFetchZeroRuleConfig.EMPTY
+            ((RelRule<?>) PruneEmptyRules.SORT_FETCH_ZERO_INSTANCE).config
                     .withOperandSupplier(b ->
                             b.operand(LogicalSort.class).anyInputs())
-                    .withDescription("PruneSortLimit0")
-                    .as(PruneEmptyRules.SortFetchZeroRuleConfig.class)
                     .toRule(),
 
             ExposeIndexRule.INSTANCE,
diff --git a/modules/sql-engine/src/main/java/org/apache/ignite/internal/sql/engine/rule/FilterSpoolMergeToHashIndexSpoolRule.java b/modules/sql-engine/src/main/java/org/apache/ignite/internal/sql/engine/rule/FilterSpoolMergeToHashIndexSpoolRule.java
index ad006a3..2ba46ec 100644
--- a/modules/sql-engine/src/main/java/org/apache/ignite/internal/sql/engine/rule/FilterSpoolMergeToHashIndexSpoolRule.java
+++ b/modules/sql-engine/src/main/java/org/apache/ignite/internal/sql/engine/rule/FilterSpoolMergeToHashIndexSpoolRule.java
@@ -30,7 +30,6 @@ import org.apache.calcite.plan.RelTraitSet;
 import org.apache.calcite.rel.RelCollations;
 import org.apache.calcite.rel.RelNode;
 import org.apache.calcite.rel.core.Filter;
-import org.apache.calcite.rel.core.RelFactories;
 import org.apache.calcite.rel.core.Spool;
 import org.apache.calcite.rex.RexBuilder;
 import org.apache.calcite.rex.RexNode;
@@ -41,10 +40,12 @@ import org.apache.ignite.internal.sql.engine.rel.IgniteTableSpool;
 import org.apache.ignite.internal.sql.engine.trait.CorrelationTrait;
 import org.apache.ignite.internal.sql.engine.trait.TraitUtils;
 import org.apache.ignite.internal.sql.engine.util.RexUtils;
+import org.immutables.value.Value;
 
 /**
  * Rule that pushes filter into the spool.
  */
+@Value.Enclosing
 public class FilterSpoolMergeToHashIndexSpoolRule extends RelRule<FilterSpoolMergeToHashIndexSpoolRule.Config> {
     /** Instance. */
     public static final RelOptRule INSTANCE = Config.DEFAULT.toRule();
@@ -110,11 +111,10 @@ public class FilterSpoolMergeToHashIndexSpoolRule extends RelRule<FilterSpoolMer
      * TODO Documentation https://issues.apache.org/jira/browse/IGNITE-15859
      */
     @SuppressWarnings("ClassNameSameAsAncestorName")
+    @Value.Immutable
     public interface Config extends RelRule.Config {
-        Config DEFAULT = RelRule.Config.EMPTY
-                .withRelBuilderFactory(RelFactories.LOGICAL_BUILDER)
+        Config DEFAULT = ImmutableFilterSpoolMergeToHashIndexSpoolRule.Config.of()
                 .withDescription("FilterSpoolMergeToHashIndexSpoolRule")
-                .as(FilterSpoolMergeToHashIndexSpoolRule.Config.class)
                 .withOperandFor(IgniteFilter.class, IgniteTableSpool.class);
 
         /** Defines an operand tree for the given classes. */
diff --git a/modules/sql-engine/src/main/java/org/apache/ignite/internal/sql/engine/rule/FilterSpoolMergeToSortedIndexSpoolRule.java b/modules/sql-engine/src/main/java/org/apache/ignite/internal/sql/engine/rule/FilterSpoolMergeToSortedIndexSpoolRule.java
index 74539d1..6339e23 100644
--- a/modules/sql-engine/src/main/java/org/apache/ignite/internal/sql/engine/rule/FilterSpoolMergeToSortedIndexSpoolRule.java
+++ b/modules/sql-engine/src/main/java/org/apache/ignite/internal/sql/engine/rule/FilterSpoolMergeToSortedIndexSpoolRule.java
@@ -27,7 +27,6 @@ import org.apache.calcite.plan.RelTraitSet;
 import org.apache.calcite.rel.RelCollation;
 import org.apache.calcite.rel.RelNode;
 import org.apache.calcite.rel.core.Filter;
-import org.apache.calcite.rel.core.RelFactories;
 import org.apache.calcite.rel.core.Spool;
 import org.apache.ignite.internal.sql.engine.rel.IgniteFilter;
 import org.apache.ignite.internal.sql.engine.rel.IgniteSortedIndexSpool;
@@ -36,10 +35,12 @@ import org.apache.ignite.internal.sql.engine.trait.CorrelationTrait;
 import org.apache.ignite.internal.sql.engine.trait.TraitUtils;
 import org.apache.ignite.internal.sql.engine.util.IndexConditions;
 import org.apache.ignite.internal.sql.engine.util.RexUtils;
+import org.immutables.value.Value;
 
 /**
  * Rule that pushes filter into the spool.
  */
+@Value.Enclosing
 public class FilterSpoolMergeToSortedIndexSpoolRule extends RelRule<FilterSpoolMergeToSortedIndexSpoolRule.Config> {
     /** Instance. */
     public static final RelOptRule INSTANCE = Config.DEFAULT.toRule();
@@ -96,12 +97,10 @@ public class FilterSpoolMergeToSortedIndexSpoolRule extends RelRule<FilterSpoolM
      * TODO Documentation https://issues.apache.org/jira/browse/IGNITE-15859
      */
     @SuppressWarnings("ClassNameSameAsAncestorName")
+    @Value.Immutable
     public interface Config extends RelRule.Config {
-
-        Config DEFAULT = RelRule.Config.EMPTY
-                .withRelBuilderFactory(RelFactories.LOGICAL_BUILDER)
+        Config DEFAULT = ImmutableFilterSpoolMergeToSortedIndexSpoolRule.Config.of()
                 .withDescription("FilterSpoolMergeToSortedIndexSpoolRule")
-                .as(FilterSpoolMergeToSortedIndexSpoolRule.Config.class)
                 .withOperandFor(IgniteFilter.class, IgniteTableSpool.class);
 
         /** Defines an operand tree for the given classes. */
diff --git a/modules/sql-engine/src/main/java/org/apache/ignite/internal/sql/engine/rule/SortConverterRule.java b/modules/sql-engine/src/main/java/org/apache/ignite/internal/sql/engine/rule/SortConverterRule.java
index 7bf2958..9342853 100644
--- a/modules/sql-engine/src/main/java/org/apache/ignite/internal/sql/engine/rule/SortConverterRule.java
+++ b/modules/sql-engine/src/main/java/org/apache/ignite/internal/sql/engine/rule/SortConverterRule.java
@@ -29,13 +29,14 @@ import org.apache.ignite.internal.sql.engine.rel.IgniteConvention;
 import org.apache.ignite.internal.sql.engine.rel.IgniteLimit;
 import org.apache.ignite.internal.sql.engine.rel.IgniteSort;
 import org.apache.ignite.internal.sql.engine.trait.IgniteDistributions;
+import org.immutables.value.Value;
 
 /**
  * Converter rule for sort operator.
  */
+@Value.Enclosing
 public class SortConverterRule extends RelRule<SortConverterRule.Config> {
-    public static final RelOptRule INSTANCE = SortConverterRule.Config.DEFAULT
-            .as(SortConverterRule.Config.class).toRule();
+    public static final RelOptRule INSTANCE = SortConverterRule.Config.DEFAULT.toRule();
 
     /** Creates a LimitConverterRule. */
     protected SortConverterRule(SortConverterRule.Config config) {
@@ -43,11 +44,11 @@ public class SortConverterRule extends RelRule<SortConverterRule.Config> {
     }
 
     /** Rule configuration. */
+    @Value.Immutable
     public interface Config extends RelRule.Config {
-        SortConverterRule.Config DEFAULT = EMPTY
+        SortConverterRule.Config DEFAULT = ImmutableSortConverterRule.Config.of()
                 .withOperandSupplier(b ->
-                        b.operand(LogicalSort.class).anyInputs())
-                .as(SortConverterRule.Config.class);
+                        b.operand(LogicalSort.class).anyInputs());
 
         /** {@inheritDoc} */
         @Override
diff --git a/modules/sql-engine/src/main/java/org/apache/ignite/internal/sql/engine/rule/UnionConverterRule.java b/modules/sql-engine/src/main/java/org/apache/ignite/internal/sql/engine/rule/UnionConverterRule.java
index 36d6389..c5e4d5d 100644
--- a/modules/sql-engine/src/main/java/org/apache/ignite/internal/sql/engine/rule/UnionConverterRule.java
+++ b/modules/sql-engine/src/main/java/org/apache/ignite/internal/sql/engine/rule/UnionConverterRule.java
@@ -24,18 +24,19 @@ import org.apache.calcite.plan.RelOptRuleCall;
 import org.apache.calcite.plan.RelRule;
 import org.apache.calcite.plan.RelTraitSet;
 import org.apache.calcite.rel.RelNode;
-import org.apache.calcite.rel.core.RelFactories;
 import org.apache.calcite.rel.logical.LogicalUnion;
 import org.apache.calcite.tools.RelBuilder;
 import org.apache.calcite.util.ImmutableBitSet;
 import org.apache.ignite.internal.sql.engine.rel.IgniteConvention;
 import org.apache.ignite.internal.sql.engine.rel.IgniteUnionAll;
 import org.apache.ignite.internal.sql.engine.util.Commons;
+import org.immutables.value.Value;
 
 /**
  * UnionConverterRule.
  * TODO Documentation https://issues.apache.org/jira/browse/IGNITE-15859
  */
+@Value.Enclosing
 public class UnionConverterRule extends RelRule<UnionConverterRule.Config> {
     /** Instance. */
     public static final RelOptRule INSTANCE = Config.DEFAULT.toRule();
@@ -72,11 +73,10 @@ public class UnionConverterRule extends RelRule<UnionConverterRule.Config> {
      * Config interface.
      * TODO Documentation https://issues.apache.org/jira/browse/IGNITE-15859
      */
+    @Value.Immutable
     public interface Config extends RelRule.Config {
-        UnionConverterRule.Config DEFAULT = RelRule.Config.EMPTY
-                .withRelBuilderFactory(RelFactories.LOGICAL_BUILDER)
+        UnionConverterRule.Config DEFAULT = ImmutableUnionConverterRule.Config.of()
                 .withDescription("UnionConverterRule")
-                .as(UnionConverterRule.Config.class)
                 .withOperandFor(LogicalUnion.class);
 
         /** Defines an operand tree for the given classes. */
diff --git a/modules/sql-engine/src/main/java/org/apache/ignite/internal/sql/engine/rule/logical/ExposeIndexRule.java b/modules/sql-engine/src/main/java/org/apache/ignite/internal/sql/engine/rule/logical/ExposeIndexRule.java
index a3644b1..b25cefe 100644
--- a/modules/sql-engine/src/main/java/org/apache/ignite/internal/sql/engine/rule/logical/ExposeIndexRule.java
+++ b/modules/sql-engine/src/main/java/org/apache/ignite/internal/sql/engine/rule/logical/ExposeIndexRule.java
@@ -27,17 +27,18 @@ import org.apache.calcite.plan.RelOptRuleCall;
 import org.apache.calcite.plan.RelOptTable;
 import org.apache.calcite.plan.RelRule;
 import org.apache.calcite.rel.RelNode;
-import org.apache.calcite.rel.core.RelFactories;
 import org.apache.calcite.rex.RexNode;
 import org.apache.calcite.util.ImmutableBitSet;
 import org.apache.ignite.internal.sql.engine.rel.logical.IgniteLogicalIndexScan;
 import org.apache.ignite.internal.sql.engine.rel.logical.IgniteLogicalTableScan;
 import org.apache.ignite.internal.sql.engine.schema.InternalIgniteTable;
+import org.immutables.value.Value;
 
 /**
  * ExposeIndexRule.
  * TODO Documentation https://issues.apache.org/jira/browse/IGNITE-15859
  */
+@Value.Enclosing
 public class ExposeIndexRule extends RelRule<ExposeIndexRule.Config> {
     public static final RelOptRule INSTANCE = Config.DEFAULT.toRule();
 
@@ -82,14 +83,13 @@ public class ExposeIndexRule extends RelRule<ExposeIndexRule.Config> {
      * Rule's configuration.
      */
     @SuppressWarnings("ClassNameSameAsAncestorName")
+    @Value.Immutable
     public interface Config extends RelRule.Config {
-        Config DEFAULT = EMPTY
-                .withRelBuilderFactory(RelFactories.LOGICAL_BUILDER)
+        Config DEFAULT = ImmutableExposeIndexRule.Config.of()
                 .withOperandSupplier(b ->
-                        b.operand(IgniteLogicalTableScan.class)
-                                .predicate(ExposeIndexRule::preMatch)
-                                .anyInputs())
-                .as(Config.class);
+                                b.operand(IgniteLogicalTableScan.class)
+                                        .predicate(ExposeIndexRule::preMatch)
+                                        .anyInputs());
 
         /** {@inheritDoc} */
         @Override default ExposeIndexRule toRule() {
diff --git a/modules/sql-engine/src/main/java/org/apache/ignite/internal/sql/engine/rule/logical/FilterScanMergeRule.java b/modules/sql-engine/src/main/java/org/apache/ignite/internal/sql/engine/rule/logical/FilterScanMergeRule.java
index 7e53455..b100aa4 100644
--- a/modules/sql-engine/src/main/java/org/apache/ignite/internal/sql/engine/rule/logical/FilterScanMergeRule.java
+++ b/modules/sql-engine/src/main/java/org/apache/ignite/internal/sql/engine/rule/logical/FilterScanMergeRule.java
@@ -18,19 +18,16 @@
 package org.apache.ignite.internal.sql.engine.rule.logical;
 
 import static java.util.Arrays.asList;
-import static org.apache.ignite.internal.util.CollectionUtils.nullOrEmpty;
 
 import java.util.ArrayList;
 import java.util.List;
-import java.util.Set;
 import org.apache.calcite.plan.RelOptCluster;
+import org.apache.calcite.plan.RelOptRule;
 import org.apache.calcite.plan.RelOptRuleCall;
 import org.apache.calcite.plan.RelOptUtil;
 import org.apache.calcite.plan.RelRule;
 import org.apache.calcite.plan.RelTraitSet;
 import org.apache.calcite.rel.RelNode;
-import org.apache.calcite.rel.core.CorrelationId;
-import org.apache.calcite.rel.core.RelFactories;
 import org.apache.calcite.rel.logical.LogicalFilter;
 import org.apache.calcite.rel.type.RelDataType;
 import org.apache.calcite.rex.RexBuilder;
@@ -49,51 +46,18 @@ import org.apache.ignite.internal.sql.engine.trait.TraitUtils;
 import org.apache.ignite.internal.sql.engine.type.IgniteTypeFactory;
 import org.apache.ignite.internal.sql.engine.util.Commons;
 import org.apache.ignite.internal.sql.engine.util.RexUtils;
+import org.immutables.value.Value;
 
 /**
  * Rule that pushes filter into the scan. This might be useful for index range scans.
  */
+@Value.Enclosing
 public abstract class FilterScanMergeRule<T extends ProjectableFilterableTableScan>
         extends RelRule<FilterScanMergeRule.Config> {
-    /** Instance. */
-    public static final FilterScanMergeRule<IgniteLogicalIndexScan> INDEX_SCAN =
-            new FilterScanMergeRule<IgniteLogicalIndexScan>(Config.INDEX_SCAN) {
-                /** {@inheritDoc} */
-                @Override protected IgniteLogicalIndexScan createNode(
-                        RelOptCluster cluster,
-                        IgniteLogicalIndexScan scan,
-                        RelTraitSet traits,
-                        RexNode cond) {
-                    Set<CorrelationId> corrIds = RexUtils.extractCorrelationIds(cond);
-
-                        if (!nullOrEmpty(corrIds)) {
-                            traits = traits.replace(CorrelationTrait.correlations(corrIds));
-                        }
-
-                        return IgniteLogicalIndexScan.create(cluster, traits, scan.getTable(), scan.indexName(),
-                                scan.projects(), cond, scan.requiredColumns());
-                    }
-                };
-
-    /** Instance. */
-    public static final FilterScanMergeRule<IgniteLogicalTableScan> TABLE_SCAN =
-            new FilterScanMergeRule<IgniteLogicalTableScan>(Config.TABLE_SCAN) {
-                /** {@inheritDoc} */
-                @Override protected IgniteLogicalTableScan createNode(
-                        RelOptCluster cluster,
-                        IgniteLogicalTableScan scan,
-                        RelTraitSet traits,
-                        RexNode cond) {
-                        Set<CorrelationId> corrIds = RexUtils.extractCorrelationIds(cond);
-
-                        if (!nullOrEmpty(corrIds)) {
-                            traits = traits.replace(CorrelationTrait.correlations(corrIds));
-                        }
-
-                        return IgniteLogicalTableScan.create(cluster, traits, scan.getTable(), scan.projects(),
-                                cond, scan.requiredColumns());
-                    }
-                };
+
+    public static final RelOptRule INDEX_SCAN = Config.INDEX_SCAN.toRule();
+
+    public static final RelOptRule TABLE_SCAN = Config.TABLE_SCAN.toRule();
 
     /**
      * Constructor.
@@ -182,16 +146,55 @@ public abstract class FilterScanMergeRule<T extends ProjectableFilterableTableSc
 
     protected abstract T createNode(RelOptCluster cluster, T scan, RelTraitSet traits, RexNode cond);
 
+    private static class FilterIndexScanMergeRule extends FilterScanMergeRule<IgniteLogicalIndexScan> {
+        private FilterIndexScanMergeRule(FilterScanMergeRule.Config cfg) {
+            super(cfg);
+        }
+
+        /** {@inheritDoc} */
+        @Override protected IgniteLogicalIndexScan createNode(
+                RelOptCluster cluster,
+                IgniteLogicalIndexScan scan,
+                RelTraitSet traits,
+                RexNode cond
+        ) {
+            return IgniteLogicalIndexScan.create(cluster, traits, scan.getTable(), scan.indexName(),
+                    scan.projects(), cond, scan.requiredColumns());
+        }
+    }
+
+    private static class FilterTableScanMergeRule extends FilterScanMergeRule<IgniteLogicalTableScan> {
+        private FilterTableScanMergeRule(FilterScanMergeRule.Config cfg) {
+            super(cfg);
+        }
+
+        /** {@inheritDoc} */
+        @Override protected IgniteLogicalTableScan createNode(
+                RelOptCluster cluster,
+                IgniteLogicalTableScan scan,
+                RelTraitSet traits,
+                RexNode cond
+        ) {
+            return IgniteLogicalTableScan.create(cluster, traits, scan.getTable(), scan.projects(),
+                    cond, scan.requiredColumns());
+        }
+    }
+
     /**
      * Rule's configuration.
      */
     @SuppressWarnings("ClassNameSameAsAncestorName")
-    public interface Config extends RelRule.Config {
-        Config DEFAULT = EMPTY.withRelBuilderFactory(RelFactories.LOGICAL_BUILDER).as(Config.class);
+    @Value.Immutable(singleton = false)
+    public interface Config extends RuleFactoryConfig<Config> {
+        Config DEFAULT = ImmutableFilterScanMergeRule.Config.builder()
+                .withRuleFactory(FilterTableScanMergeRule::new)
+                .build();
 
         Config TABLE_SCAN = DEFAULT.withScanRuleConfig(IgniteLogicalTableScan.class, "FilterTableScanMergeRule");
 
-        Config INDEX_SCAN = DEFAULT.withScanRuleConfig(IgniteLogicalIndexScan.class, "FilterIndexScanMergeRule");
+        Config INDEX_SCAN = DEFAULT
+                .withRuleFactory(FilterIndexScanMergeRule::new)
+                .withScanRuleConfig(IgniteLogicalIndexScan.class, "FilterIndexScanMergeRule");
 
         /**
          * Create configuration for specified scan.
diff --git a/modules/sql-engine/src/main/java/org/apache/ignite/internal/sql/engine/rule/logical/LogicalOrToUnionRule.java b/modules/sql-engine/src/main/java/org/apache/ignite/internal/sql/engine/rule/logical/LogicalOrToUnionRule.java
index adc10c3..58c2b03 100644
--- a/modules/sql-engine/src/main/java/org/apache/ignite/internal/sql/engine/rule/logical/LogicalOrToUnionRule.java
+++ b/modules/sql-engine/src/main/java/org/apache/ignite/internal/sql/engine/rule/logical/LogicalOrToUnionRule.java
@@ -28,7 +28,6 @@ import org.apache.calcite.plan.RelRule;
 import org.apache.calcite.plan.RelTraitSet;
 import org.apache.calcite.rel.RelFieldCollation;
 import org.apache.calcite.rel.RelNode;
-import org.apache.calcite.rel.core.RelFactories;
 import org.apache.calcite.rex.RexBuilder;
 import org.apache.calcite.rex.RexLocalRef;
 import org.apache.calcite.rex.RexNode;
@@ -43,11 +42,13 @@ import org.apache.ignite.internal.sql.engine.schema.InternalIgniteTable;
 import org.apache.ignite.internal.sql.engine.type.IgniteTypeFactory;
 import org.apache.ignite.internal.sql.engine.util.Commons;
 import org.apache.ignite.internal.util.CollectionUtils;
+import org.immutables.value.Value;
 import org.jetbrains.annotations.Nullable;
 
 /**
  * Converts OR to UNION ALL.
  */
+@Value.Enclosing
 public class LogicalOrToUnionRule extends RelRule<LogicalOrToUnionRule.Config> {
     /** Instance. */
     public static final RelOptRule INSTANCE = new LogicalOrToUnionRule(Config.SCAN);
@@ -191,17 +192,14 @@ public class LogicalOrToUnionRule extends RelRule<LogicalOrToUnionRule.Config> {
      * Config interface.
      * TODO Documentation https://issues.apache.org/jira/browse/IGNITE-15859
      */
-    public interface Config extends RelRule.Config {
-        Config DEFAULT = RelRule.Config.EMPTY
-                .withRelBuilderFactory(RelFactories.LOGICAL_BUILDER)
-                .as(Config.class);
-
-        Config SCAN = DEFAULT
+    @Value.Immutable(singleton = false)
+    public interface Config extends RuleFactoryConfig<Config> {
+        Config SCAN = ImmutableLogicalOrToUnionRule.Config.builder()
+                .withRuleFactory(LogicalOrToUnionRule::new)
                 .withDescription("ScanLogicalOrToUnionRule")
                 .withOperandSupplier(o -> o.operand(IgniteLogicalTableScan.class)
                         .predicate(scan -> scan.condition() != null)
-                        .noInputs()
-                )
-                .as(Config.class);
+                        .noInputs())
+                .build();
     }
 }
diff --git a/modules/sql-engine/src/main/java/org/apache/ignite/internal/sql/engine/rule/logical/ProjectScanMergeRule.java b/modules/sql-engine/src/main/java/org/apache/ignite/internal/sql/engine/rule/logical/ProjectScanMergeRule.java
index d11a385..a32d7a5 100644
--- a/modules/sql-engine/src/main/java/org/apache/ignite/internal/sql/engine/rule/logical/ProjectScanMergeRule.java
+++ b/modules/sql-engine/src/main/java/org/apache/ignite/internal/sql/engine/rule/logical/ProjectScanMergeRule.java
@@ -19,10 +19,10 @@ package org.apache.ignite.internal.sql.engine.rule.logical;
 
 import java.util.List;
 import org.apache.calcite.plan.RelOptCluster;
+import org.apache.calcite.plan.RelOptRule;
 import org.apache.calcite.plan.RelOptRuleCall;
 import org.apache.calcite.plan.RelRule;
 import org.apache.calcite.plan.RelTraitSet;
-import org.apache.calcite.rel.core.RelFactories;
 import org.apache.calcite.rel.logical.LogicalProject;
 import org.apache.calcite.rex.RexInputRef;
 import org.apache.calcite.rex.RexLocalRef;
@@ -38,28 +38,26 @@ import org.apache.ignite.internal.sql.engine.trait.TraitUtils;
 import org.apache.ignite.internal.sql.engine.type.IgniteTypeFactory;
 import org.apache.ignite.internal.sql.engine.util.Commons;
 import org.apache.ignite.internal.sql.engine.util.RexUtils;
+import org.immutables.value.Value;
 
 /**
  * ProjectScanMergeRule.
  * TODO Documentation https://issues.apache.org/jira/browse/IGNITE-15859
  */
+@Value.Enclosing
 public abstract class ProjectScanMergeRule<T extends ProjectableFilterableTableScan>
         extends RelRule<ProjectScanMergeRule.Config> {
     /** Instance. */
-    public static final ProjectScanMergeRule<IgniteLogicalIndexScan> INDEX_SCAN =
-            new ProjectIndexScanMergeRule(Config.INDEX_SCAN);
+    public static final RelOptRule INDEX_SCAN = Config.INDEX_SCAN.toRule();
 
     /** Instance. */
-    public static final ProjectScanMergeRule<IgniteLogicalIndexScan> INDEX_SCAN_SKIP_CORRELATED =
-            new ProjectIndexScanMergeRule(Config.INDEX_SCAN_SKIP_CORRELATED);
+    public static final RelOptRule INDEX_SCAN_SKIP_CORRELATED = Config.INDEX_SCAN_SKIP_CORRELATED.toRule();
 
     /** Instance. */
-    public static final ProjectScanMergeRule<IgniteLogicalTableScan> TABLE_SCAN =
-            new ProjectTableScanMergeRule(Config.TABLE_SCAN);
+    public static final RelOptRule TABLE_SCAN = Config.TABLE_SCAN.toRule();
 
     /** Instance. */
-    public static final ProjectScanMergeRule<IgniteLogicalTableScan> TABLE_SCAN_SKIP_CORRELATED =
-            new ProjectTableScanMergeRule(Config.TABLE_SCAN_SKIP_CORRELATED);
+    public static final RelOptRule TABLE_SCAN_SKIP_CORRELATED = Config.TABLE_SCAN_SKIP_CORRELATED.toRule();
 
     protected abstract T createNode(
             RelOptCluster cluster,
@@ -213,8 +211,11 @@ public abstract class ProjectScanMergeRule<T extends ProjectableFilterableTableS
      * Rule's configuration.
      */
     @SuppressWarnings("ClassNameSameAsAncestorName")
-    public interface Config extends RelRule.Config {
-        Config DEFAULT = EMPTY.withRelBuilderFactory(RelFactories.LOGICAL_BUILDER).as(Config.class);
+    @Value.Immutable(singleton = false)
+    public interface Config extends RuleFactoryConfig<Config> {
+        Config DEFAULT = ImmutableProjectScanMergeRule.Config.builder()
+                .withRuleFactory(ProjectTableScanMergeRule::new)
+                .build();
 
         Config TABLE_SCAN = DEFAULT.withScanRuleConfig(
                 IgniteLogicalTableScan.class, "ProjectTableScanMergeRule", false);
@@ -222,11 +223,13 @@ public abstract class ProjectScanMergeRule<T extends ProjectableFilterableTableS
         Config TABLE_SCAN_SKIP_CORRELATED = DEFAULT.withScanRuleConfig(
                 IgniteLogicalTableScan.class, "ProjectTableScanMergeSkipCorrelatedRule", true);
 
-        Config INDEX_SCAN = DEFAULT.withScanRuleConfig(
-                IgniteLogicalIndexScan.class, "ProjectIndexScanMergeRule", false);
+        Config INDEX_SCAN = DEFAULT
+                .withRuleFactory(ProjectIndexScanMergeRule::new)
+                .withScanRuleConfig(IgniteLogicalIndexScan.class, "ProjectIndexScanMergeRule", false);
 
-        Config INDEX_SCAN_SKIP_CORRELATED = DEFAULT.withScanRuleConfig(
-                IgniteLogicalIndexScan.class, "ProjectIndexScanMergeSkipCorrelatedRule", true);
+        Config INDEX_SCAN_SKIP_CORRELATED = DEFAULT
+                .withRuleFactory(ProjectIndexScanMergeRule::new)
+                .withScanRuleConfig(IgniteLogicalIndexScan.class, "ProjectIndexScanMergeRule", true);
 
         /**
          * Create rule's configuration.
diff --git a/modules/sql-engine/src/main/java/org/apache/ignite/internal/sql/engine/rule/logical/RuleFactoryConfig.java b/modules/sql-engine/src/main/java/org/apache/ignite/internal/sql/engine/rule/logical/RuleFactoryConfig.java
new file mode 100644
index 0000000..4818d32
--- /dev/null
+++ b/modules/sql-engine/src/main/java/org/apache/ignite/internal/sql/engine/rule/logical/RuleFactoryConfig.java
@@ -0,0 +1,35 @@
+/*
+ * 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.sql.engine.rule.logical;
+
+import java.util.function.Function;
+import org.apache.calcite.plan.RelOptRule;
+import org.apache.calcite.plan.RelRule;
+
+/**
+ * Rule config with rule factory methods.
+ */
+public interface RuleFactoryConfig<T extends RelRule.Config> extends RelRule.Config {
+    Function<T, RelOptRule> ruleFactory();
+
+    T withRuleFactory(Function<T, RelOptRule> factory);
+
+    default RelOptRule toRule() {
+        return ruleFactory().apply((T) this);
+    }
+}
\ No newline at end of file
diff --git a/modules/sql-engine/src/main/java/org/apache/ignite/internal/sql/engine/rule/package-info.java b/modules/sql-engine/src/main/java/org/apache/ignite/internal/sql/engine/rule/package-info.java
new file mode 100644
index 0000000..4d06f19
--- /dev/null
+++ b/modules/sql-engine/src/main/java/org/apache/ignite/internal/sql/engine/rule/package-info.java
@@ -0,0 +1,25 @@
+/*
+ * 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.
+ */
+
+/**
+ * Contains plan transformation rules.
+ */
+
+@CalciteImmutable
+package org.apache.ignite.internal.sql.engine.rule;
+
+import org.apache.calcite.CalciteImmutable;
\ No newline at end of file
diff --git a/parent/pom.xml b/parent/pom.xml
index 763c0c6..2872831 100644
--- a/parent/pom.xml
+++ b/parent/pom.xml
@@ -70,7 +70,7 @@
         <hamcrest.version>2.2</hamcrest.version>
         <hamcrest.optional.version>2.0.0</hamcrest.optional.version>
         <scalecube.version>2.6.12</scalecube.version>
-        <calcite.version>1.28.0</calcite.version>
+        <calcite.version>1.29.0</calcite.version>
         <immutables.version>2.8.8</immutables.version>
         <janino.version>3.1.6</janino.version>
         <avatica.version>1.19.0</avatica.version>