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

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

commit 5eb10da63c324c6d2afba58a3c517310f5993619
Author: amashenkov <amashen...@apache.org>
AuthorDate: Thu Jul 3 18:22:35 2025 +0300

    Make logical nodes operates with projects instead of bitsets.
---
 .../sql/engine/exec/LogicalRelImplementor.java     | 21 ++++++++----------
 .../sql/engine/metadata/IgniteMdColumnOrigins.java |  7 +++---
 .../sql/engine/metadata/IgniteMdSelectivity.java   |  5 +++--
 .../sql/engine/prepare/KeyValueGetPlan.java        | 16 ++++++--------
 .../pruning/PartitionPruningMetadataExtractor.java | 18 ++++------------
 .../internal/sql/engine/rel/AbstractIndexScan.java |  4 ++--
 .../internal/sql/engine/rel/IgniteIndexScan.java   |  6 +++---
 .../internal/sql/engine/rel/IgniteKeyValueGet.java |  4 ++--
 .../sql/engine/rel/IgniteSystemViewScan.java       | 17 +++++++++------
 .../internal/sql/engine/rel/IgniteTableScan.java   |  6 +++---
 .../engine/rel/ProjectableFilterableTableScan.java | 15 +++++++------
 .../engine/rel/logical/IgniteLogicalIndexScan.java | 16 ++++++++------
 .../rel/logical/IgniteLogicalSystemViewScan.java   |  6 +++---
 .../engine/rel/logical/IgniteLogicalTableScan.java |  6 +++---
 .../sql/engine/rule/LogicalScanConverterRule.java  |  8 +++----
 .../engine/rule/TableScanToKeyValueGetRule.java    |  5 +++--
 .../sql/engine/rule/logical/ExposeIndexRule.java   |  4 ++--
 .../engine/rule/logical/LogicalOrToUnionRule.java  |  2 +-
 .../engine/rule/logical/ProjectScanMergeRule.java  | 25 ++++++++++++----------
 .../internal/sql/engine/schema/IgniteIndex.java    |  4 ++--
 .../ignite/internal/sql/engine/util/RexUtils.java  | 11 ++++++----
 .../engine/exec/exp/ExpressionFactoryImplTest.java |  3 +--
 22 files changed, 105 insertions(+), 104 deletions(-)

diff --git 
a/modules/sql-engine/src/main/java/org/apache/ignite/internal/sql/engine/exec/LogicalRelImplementor.java
 
b/modules/sql-engine/src/main/java/org/apache/ignite/internal/sql/engine/exec/LogicalRelImplementor.java
index d375f7c6d1b..79bf47e35bf 100644
--- 
a/modules/sql-engine/src/main/java/org/apache/ignite/internal/sql/engine/exec/LogicalRelImplementor.java
+++ 
b/modules/sql-engine/src/main/java/org/apache/ignite/internal/sql/engine/exec/LogicalRelImplementor.java
@@ -442,10 +442,9 @@ public class LogicalRelImplementor<RowT> implements 
IgniteRelVisitor<Node<RowT>>
         IgniteTable tbl = rel.getTable().unwrap(IgniteTable.class);
 
         IgniteTypeFactory typeFactory = ctx.getTypeFactory();
-        ImmutableBitSet requiredColumns = rel.requiredColumns();
+        ImmutableIntList requiredColumns = rel.requiredColumns();
 
-        ImmutableIntList requiredColumns0 = requiredColumns == null ? null : 
ImmutableIntList.copyOf(requiredColumns.asList());
-        RelDataType rowType = tbl.getRowType(typeFactory, requiredColumns0);
+        RelDataType rowType = tbl.getRowType(typeFactory, requiredColumns);
         ScannableTable scannableTable = 
resolvedDependencies.scannableTable(tbl.id());
 
         IgniteIndex idx = tbl.indexes().get(rel.indexName());
@@ -531,7 +530,7 @@ public class LogicalRelImplementor<RowT> implements 
IgniteRelVisitor<Node<RowT>>
                 ranges,
                 filters,
                 prj,
-                requiredColumns0
+                requiredColumns
         );
     }
 
@@ -540,15 +539,14 @@ public class LogicalRelImplementor<RowT> implements 
IgniteRelVisitor<Node<RowT>>
     public Node<RowT> visit(IgniteTableScan rel) {
         RexNode condition = rel.condition();
         List<RexNode> projects = rel.projects();
-        ImmutableBitSet requiredColumns = rel.requiredColumns();
+        ImmutableIntList requiredColumns = rel.requiredColumns();
 
         IgniteTable tbl = rel.getTable().unwrapOrThrow(IgniteTable.class);
         ScannableTable scannableTable = 
resolvedDependencies.scannableTable(tbl.id());
 
         IgniteTypeFactory typeFactory = ctx.getTypeFactory();
 
-        ImmutableIntList requiredColumns0 = requiredColumns == null ? null : 
ImmutableIntList.copyOf(requiredColumns.asList());
-        RelDataType rowType = tbl.getRowType(typeFactory, requiredColumns0);
+        RelDataType rowType = tbl.getRowType(typeFactory, requiredColumns);
 
         Predicate<RowT> filters = null;
         if (condition != null) {
@@ -598,7 +596,7 @@ public class LogicalRelImplementor<RowT> implements 
IgniteRelVisitor<Node<RowT>>
                 partitionProvider,
                 filters,
                 prj,
-                requiredColumns0
+                requiredColumns
         );
     }
 
@@ -607,7 +605,7 @@ public class LogicalRelImplementor<RowT> implements 
IgniteRelVisitor<Node<RowT>>
     public Node<RowT> visit(IgniteSystemViewScan rel) {
         RexNode condition = rel.condition();
         List<RexNode> projects = rel.projects();
-        ImmutableBitSet requiredColumns = rel.requiredColumns();
+        ImmutableIntList requiredColumns = rel.requiredColumns();
         IgniteDataSource igniteDataSource = 
rel.getTable().unwrapOrThrow(IgniteDataSource.class);
 
         BinaryTupleSchema schema = 
fromTableDescriptor(igniteDataSource.descriptor());
@@ -616,8 +614,7 @@ public class LogicalRelImplementor<RowT> implements 
IgniteRelVisitor<Node<RowT>>
 
         IgniteTypeFactory typeFactory = ctx.getTypeFactory();
 
-        ImmutableIntList requiredColumns0 = requiredColumns == null ? null : 
ImmutableIntList.copyOf(requiredColumns.asList());
-        RelDataType rowType = igniteDataSource.getRowType(typeFactory, 
requiredColumns0);
+        RelDataType rowType = igniteDataSource.getRowType(typeFactory, 
requiredColumns);
 
         Predicate<RowT> filters = null;
         if (condition != null) {
@@ -640,7 +637,7 @@ public class LogicalRelImplementor<RowT> implements 
IgniteRelVisitor<Node<RowT>>
                 dataSource,
                 filters,
                 prj,
-                requiredColumns0
+                requiredColumns
         );
     }
 
diff --git 
a/modules/sql-engine/src/main/java/org/apache/ignite/internal/sql/engine/metadata/IgniteMdColumnOrigins.java
 
b/modules/sql-engine/src/main/java/org/apache/ignite/internal/sql/engine/metadata/IgniteMdColumnOrigins.java
index f9632ddb8b6..eecad7e652d 100644
--- 
a/modules/sql-engine/src/main/java/org/apache/ignite/internal/sql/engine/metadata/IgniteMdColumnOrigins.java
+++ 
b/modules/sql-engine/src/main/java/org/apache/ignite/internal/sql/engine/metadata/IgniteMdColumnOrigins.java
@@ -37,7 +37,7 @@ import org.apache.calcite.rel.metadata.RelMetadataProvider;
 import org.apache.calcite.rel.metadata.RelMetadataQuery;
 import org.apache.calcite.rex.RexInputRef;
 import org.apache.calcite.rex.RexNode;
-import org.apache.calcite.util.ImmutableBitSet;
+import org.apache.calcite.util.ImmutableIntList;
 import org.apache.calcite.util.ReflectUtil;
 import org.apache.calcite.util.mapping.Mapping;
 import 
org.apache.ignite.internal.sql.engine.rel.ProjectableFilterableTableScan;
@@ -97,9 +97,10 @@ public class IgniteMdColumnOrigins implements 
MetadataHandler<ColumnOrigin> {
             }
         }
 
-        ImmutableBitSet requiredColumns = scan.requiredColumns();
+        ImmutableIntList requiredColumns = scan.requiredColumns();
         if (requiredColumns != null) {
-            Mapping trimming = 
Commons.trimmingMapping(table.getRowType().getFieldCount(), requiredColumns);
+            // TODO: IGNITE-27703 check required columns usage.
+            Mapping trimming = 
Commons.projectedMapping(table.getRowType().getFieldCount(), requiredColumns);
 
             outputColumn = trimming.getSourceOpt(outputColumn);
 
diff --git 
a/modules/sql-engine/src/main/java/org/apache/ignite/internal/sql/engine/metadata/IgniteMdSelectivity.java
 
b/modules/sql-engine/src/main/java/org/apache/ignite/internal/sql/engine/metadata/IgniteMdSelectivity.java
index af00d9faa93..a4e3e81bf70 100644
--- 
a/modules/sql-engine/src/main/java/org/apache/ignite/internal/sql/engine/metadata/IgniteMdSelectivity.java
+++ 
b/modules/sql-engine/src/main/java/org/apache/ignite/internal/sql/engine/metadata/IgniteMdSelectivity.java
@@ -197,9 +197,10 @@ public class IgniteMdSelectivity extends RelMdSelectivity {
 
         // sys view is possible here
         if (table != null) {
+            // TODO: IGNITE-27703 recheck required columns usage.
             int colCount = 
table.getRowType(Commons.typeFactory()).getFieldCount();
-            ImmutableBitSet requiredCols = rel.requiredColumns() == null ? 
ImmutableBitSet.range(colCount) : rel.requiredColumns();
-            columnMapping = Commons.trimmingMapping(colCount, requiredCols);
+            ImmutableIntList requiredCols = rel.requiredColumns() == null ? 
ImmutableIntList.identity(colCount) : rel.requiredColumns();
+            columnMapping = Commons.projectedMapping(colCount, requiredCols);
 
             keyColumns = table.keyColumns();
             primaryKeys = new BitSet();
diff --git 
a/modules/sql-engine/src/main/java/org/apache/ignite/internal/sql/engine/prepare/KeyValueGetPlan.java
 
b/modules/sql-engine/src/main/java/org/apache/ignite/internal/sql/engine/prepare/KeyValueGetPlan.java
index c31f1fe62aa..12c09ae0ec5 100644
--- 
a/modules/sql-engine/src/main/java/org/apache/ignite/internal/sql/engine/prepare/KeyValueGetPlan.java
+++ 
b/modules/sql-engine/src/main/java/org/apache/ignite/internal/sql/engine/prepare/KeyValueGetPlan.java
@@ -19,7 +19,6 @@ package org.apache.ignite.internal.sql.engine.prepare;
 
 import static org.apache.ignite.internal.sql.engine.util.Commons.cast;
 
-import java.util.BitSet;
 import java.util.Collections;
 import java.util.Iterator;
 import java.util.List;
@@ -28,7 +27,6 @@ import java.util.concurrent.Executor;
 import org.apache.calcite.plan.RelOptUtil;
 import org.apache.calcite.rel.type.RelDataType;
 import org.apache.calcite.rex.RexNode;
-import org.apache.calcite.util.ImmutableBitSet;
 import org.apache.calcite.util.ImmutableIntList;
 import org.apache.ignite.internal.logger.IgniteLogger;
 import org.apache.ignite.internal.logger.Loggers;
@@ -150,7 +148,7 @@ public class KeyValueGetPlan implements ExplainablePlan, 
ExecutablePlan {
         ExecutableTable executableTable = 
tableRegistry.getTable(catalogVersion, sqlTable.id());
         ScannableTable scannableTable = executableTable.scannableTable();
 
-        ImmutableBitSet requiredColumns = lookupNode.requiredColumns();
+        ImmutableIntList requiredColumns = lookupNode.requiredColumns();
         RexNode filterExpr = lookupNode.condition();
         List<RexNode> projectionExpr = lookupNode.projects();
 
@@ -170,9 +168,9 @@ public class KeyValueGetPlan implements ExplainablePlan, 
ExecutablePlan {
         SchemaAwareConverter<Object, Object> internalTypeConverter = 
TypeUtils.resultTypeConverter(ctx, resultType);
 
         operation = filter == null && projection == null ? new 
SimpleLookupExecution<>(scannableTable, rowHandler, rowFactory,
-                keySupplier, requiredColumns.toBitSet(), internalTypeConverter)
+                keySupplier, requiredColumns, internalTypeConverter)
                 : new FilterableProjectableLookupExecution<>(scannableTable, 
rowHandler, rowFactory, keySupplier,
-                        filter, projection, requiredColumns.toBitSet(), 
internalTypeConverter);
+                        filter, projection, requiredColumns, 
internalTypeConverter);
 
         this.operation = operation;
 
@@ -206,12 +204,12 @@ public class KeyValueGetPlan implements ExplainablePlan, 
ExecutablePlan {
         private final SchemaAwareConverter<Object, Object> 
internalTypeConverter;
 
         private SimpleLookupExecution(ScannableTable table, RowHandler<RowT> 
rowHandler, RowFactory<RowT> tableRowFactory,
-                SqlRowProvider<RowT> keySupplier, BitSet requiredColumns, 
SchemaAwareConverter<Object, Object> internalTypeConverter) {
+                SqlRowProvider<RowT> keySupplier, ImmutableIntList 
requiredColumns, SchemaAwareConverter<Object, Object> internalTypeConverter) {
             this.table = table;
             this.rowHandler = rowHandler;
             this.tableRowFactory = tableRowFactory;
             this.keySupplier = keySupplier;
-            this.requiredColumns = requiredColumns == null ? null : 
ImmutableIntList.copyOf(requiredColumns.stream().iterator());
+            this.requiredColumns = requiredColumns;
             this.internalTypeConverter = internalTypeConverter;
         }
 
@@ -245,7 +243,7 @@ public class KeyValueGetPlan implements ExplainablePlan, 
ExecutablePlan {
                 SqlRowProvider<RowT> keySupplier,
                 @Nullable SqlPredicate<RowT> filter,
                 @Nullable SqlProjection<RowT> projection,
-                @Nullable BitSet requiredColumns,
+                @Nullable ImmutableIntList requiredColumns,
                 SchemaAwareConverter<Object, Object> internalTypeConverter
         ) {
             this.table = table;
@@ -254,7 +252,7 @@ public class KeyValueGetPlan implements ExplainablePlan, 
ExecutablePlan {
             this.keySupplier = keySupplier;
             this.filter = filter;
             this.projection = projection;
-            this.requiredColumns = requiredColumns == null ? null : 
ImmutableIntList.copyOf(requiredColumns.stream().iterator());
+            this.requiredColumns = requiredColumns;
             this.internalTypeConverter = internalTypeConverter;
         }
 
diff --git 
a/modules/sql-engine/src/main/java/org/apache/ignite/internal/sql/engine/prepare/pruning/PartitionPruningMetadataExtractor.java
 
b/modules/sql-engine/src/main/java/org/apache/ignite/internal/sql/engine/prepare/pruning/PartitionPruningMetadataExtractor.java
index 759cd6d9a12..3c64ff84bd6 100644
--- 
a/modules/sql-engine/src/main/java/org/apache/ignite/internal/sql/engine/prepare/pruning/PartitionPruningMetadataExtractor.java
+++ 
b/modules/sql-engine/src/main/java/org/apache/ignite/internal/sql/engine/prepare/pruning/PartitionPruningMetadataExtractor.java
@@ -20,8 +20,6 @@ package org.apache.ignite.internal.sql.engine.prepare.pruning;
 import static org.apache.calcite.rel.core.TableModify.Operation.INSERT;
 import static org.apache.ignite.internal.util.CollectionUtils.nullOrEmpty;
 
-import it.unimi.dsi.fastutil.ints.Int2IntArrayMap;
-import it.unimi.dsi.fastutil.ints.Int2IntMap;
 import it.unimi.dsi.fastutil.ints.Int2ObjectArrayMap;
 import it.unimi.dsi.fastutil.ints.Int2ObjectMap;
 import it.unimi.dsi.fastutil.ints.Int2ObjectMap.Entry;
@@ -45,7 +43,7 @@ import org.apache.calcite.rex.RexUtil;
 import org.apache.calcite.sql.SqlKind;
 import org.apache.calcite.sql.fun.SqlStdOperatorTable;
 import org.apache.calcite.sql.type.SqlTypeName;
-import org.apache.calcite.util.ImmutableBitSet;
+import org.apache.calcite.util.ImmutableIntList;
 import org.apache.ignite.internal.sql.engine.prepare.IgniteRelShuttle;
 import org.apache.ignite.internal.sql.engine.rel.IgniteIndexScan;
 import org.apache.ignite.internal.sql.engine.rel.IgniteRel;
@@ -223,7 +221,7 @@ public class PartitionPruningMetadataExtractor extends 
IgniteRelShuttle {
     private void extractFromTable(
             long sourceId,
             IgniteTable table,
-            @Nullable ImmutableBitSet requiredColumns,
+            @Nullable ImmutableIntList requiredColumns,
             @Nullable RexNode condition,
             RexBuilder rexBuilder) {
 
@@ -247,22 +245,14 @@ public class PartitionPruningMetadataExtractor extends 
IgniteRelShuttle {
         }
     }
 
-    private static RexNode remapColumns(IgniteTable table, ImmutableBitSet 
requiredColumns, RexNode condition, RexBuilder rexBuilder) {
-        Int2IntMap mapping  = new 
Int2IntArrayMap(requiredColumns.cardinality());
-
-        int i = 0;
-        for (int r : requiredColumns) {
-            mapping.put(i, r);
-            i++;
-        }
-
+    private static RexNode remapColumns(IgniteTable table, ImmutableIntList 
requiredColumns, RexNode condition, RexBuilder rexBuilder) {
         RelDataType rowType = table.getRowType(Commons.typeFactory(), 
requiredColumns);
 
         return condition.accept(new RexShuttle() {
             @Override
             public RexNode visitLocalRef(RexLocalRef localRef) {
                 int fieldIdx = localRef.getIndex();
-                int index = mapping.get(fieldIdx);
+                int index = requiredColumns.get(fieldIdx);
                 RelDataType fieldType = 
rowType.getFieldList().get(fieldIdx).getType();
 
                 return rexBuilder.makeLocalRef(fieldType, index);
diff --git 
a/modules/sql-engine/src/main/java/org/apache/ignite/internal/sql/engine/rel/AbstractIndexScan.java
 
b/modules/sql-engine/src/main/java/org/apache/ignite/internal/sql/engine/rel/AbstractIndexScan.java
index 0dc9ae66d28..efb0d83b327 100644
--- 
a/modules/sql-engine/src/main/java/org/apache/ignite/internal/sql/engine/rel/AbstractIndexScan.java
+++ 
b/modules/sql-engine/src/main/java/org/apache/ignite/internal/sql/engine/rel/AbstractIndexScan.java
@@ -33,7 +33,7 @@ import org.apache.calcite.rex.RexBuilder;
 import org.apache.calcite.rex.RexNode;
 import org.apache.calcite.rex.RexShuttle;
 import org.apache.calcite.rex.RexUtil;
-import org.apache.calcite.util.ImmutableBitSet;
+import org.apache.calcite.util.ImmutableIntList;
 import org.apache.ignite.internal.sql.engine.externalize.RelInputEx;
 import org.apache.ignite.internal.sql.engine.metadata.cost.IgniteCost;
 import org.apache.ignite.internal.sql.engine.prepare.bounds.MultiBounds;
@@ -82,7 +82,7 @@ public abstract class AbstractIndexScan extends 
ProjectableFilterableTableScan {
             @Nullable List<RexNode> proj,
             @Nullable RexNode cond,
             @Nullable List<SearchBounds> searchBounds,
-            @Nullable ImmutableBitSet reqColumns
+            @Nullable ImmutableIntList reqColumns
     ) {
         super(cluster, traitSet, hints, table, names, proj, cond, reqColumns);
 
diff --git 
a/modules/sql-engine/src/main/java/org/apache/ignite/internal/sql/engine/rel/IgniteIndexScan.java
 
b/modules/sql-engine/src/main/java/org/apache/ignite/internal/sql/engine/rel/IgniteIndexScan.java
index 2d8f1075ca9..e2df4cd70fe 100644
--- 
a/modules/sql-engine/src/main/java/org/apache/ignite/internal/sql/engine/rel/IgniteIndexScan.java
+++ 
b/modules/sql-engine/src/main/java/org/apache/ignite/internal/sql/engine/rel/IgniteIndexScan.java
@@ -27,7 +27,7 @@ import org.apache.calcite.rel.RelCollation;
 import org.apache.calcite.rel.RelInput;
 import org.apache.calcite.rel.RelWriter;
 import org.apache.calcite.rex.RexNode;
-import org.apache.calcite.util.ImmutableBitSet;
+import org.apache.calcite.util.ImmutableIntList;
 import org.apache.ignite.internal.sql.engine.prepare.bounds.SearchBounds;
 import org.apache.ignite.internal.sql.engine.rel.explain.IgniteRelWriter;
 import org.apache.ignite.internal.sql.engine.schema.IgniteIndex;
@@ -89,7 +89,7 @@ public class IgniteIndexScan extends AbstractIndexScan 
implements SourceAwareIgn
             @Nullable List<RexNode> proj,
             @Nullable RexNode cond,
             @Nullable List<SearchBounds> searchBounds,
-            @Nullable ImmutableBitSet requiredCols
+            @Nullable ImmutableIntList requiredCols
     ) {
         this(-1L, cluster, traits, tbl, idxName, type, collation, names, proj, 
cond, searchBounds, requiredCols);
     }
@@ -122,7 +122,7 @@ public class IgniteIndexScan extends AbstractIndexScan 
implements SourceAwareIgn
             @Nullable List<RexNode> proj,
             @Nullable RexNode cond,
             @Nullable List<SearchBounds> searchBounds,
-            @Nullable ImmutableBitSet requiredCols
+            @Nullable ImmutableIntList requiredCols
     ) {
         super(cluster, traits, List.of(), tbl, idxName, type, names, proj, 
cond, searchBounds, requiredCols);
 
diff --git 
a/modules/sql-engine/src/main/java/org/apache/ignite/internal/sql/engine/rel/IgniteKeyValueGet.java
 
b/modules/sql-engine/src/main/java/org/apache/ignite/internal/sql/engine/rel/IgniteKeyValueGet.java
index 9ab1de2f56d..27a2690cdc2 100644
--- 
a/modules/sql-engine/src/main/java/org/apache/ignite/internal/sql/engine/rel/IgniteKeyValueGet.java
+++ 
b/modules/sql-engine/src/main/java/org/apache/ignite/internal/sql/engine/rel/IgniteKeyValueGet.java
@@ -25,7 +25,7 @@ import org.apache.calcite.rel.RelInput;
 import org.apache.calcite.rel.RelWriter;
 import org.apache.calcite.rel.hint.RelHint;
 import org.apache.calcite.rex.RexNode;
-import org.apache.calcite.util.ImmutableBitSet;
+import org.apache.calcite.util.ImmutableIntList;
 import org.apache.ignite.internal.sql.engine.exec.TxAttributes;
 import org.apache.ignite.internal.sql.engine.exec.mapping.MappingService;
 import org.apache.ignite.internal.sql.engine.rel.explain.IgniteRelWriter;
@@ -73,7 +73,7 @@ public class IgniteKeyValueGet extends 
ProjectableFilterableTableScan implements
             @Nullable List<String> names,
             @Nullable List<RexNode> proj,
             @Nullable RexNode cond,
-            @Nullable ImmutableBitSet requiredColumns
+            @Nullable ImmutableIntList requiredColumns
     ) {
         super(cluster, traits, hints, table, names, proj, cond, 
requiredColumns);
 
diff --git 
a/modules/sql-engine/src/main/java/org/apache/ignite/internal/sql/engine/rel/IgniteSystemViewScan.java
 
b/modules/sql-engine/src/main/java/org/apache/ignite/internal/sql/engine/rel/IgniteSystemViewScan.java
index 94ce468aa92..f1d1b744cfc 100644
--- 
a/modules/sql-engine/src/main/java/org/apache/ignite/internal/sql/engine/rel/IgniteSystemViewScan.java
+++ 
b/modules/sql-engine/src/main/java/org/apache/ignite/internal/sql/engine/rel/IgniteSystemViewScan.java
@@ -27,7 +27,7 @@ import org.apache.calcite.rel.RelInput;
 import org.apache.calcite.rel.RelWriter;
 import org.apache.calcite.rel.hint.RelHint;
 import org.apache.calcite.rex.RexNode;
-import org.apache.calcite.util.ImmutableBitSet;
+import org.apache.calcite.util.ImmutableIntList;
 import org.apache.ignite.internal.sql.engine.rel.explain.IgniteRelWriter;
 import org.jetbrains.annotations.Nullable;
 
@@ -51,14 +51,16 @@ public class IgniteSystemViewScan extends 
ProjectableFilterableTableScan impleme
      * @param table Target system view to read data from.
      * @param reqColumns Participating columns.
      */
-    public IgniteSystemViewScan(RelOptCluster cluster, RelTraitSet traitSet,
+    public IgniteSystemViewScan(
+            RelOptCluster cluster,
+            RelTraitSet traitSet,
             List<RelHint> hints,
             RelOptTable table,
             @Nullable List<String> names,
             @Nullable List<RexNode> projections,
             @Nullable RexNode condition,
-            @Nullable ImmutableBitSet reqColumns) {
-
+            @Nullable ImmutableIntList reqColumns
+    ) {
         this(-1, cluster, traitSet, hints, table, names, projections, 
condition, reqColumns);
     }
 
@@ -78,7 +80,8 @@ public class IgniteSystemViewScan extends 
ProjectableFilterableTableScan impleme
         }
     }
 
-    private IgniteSystemViewScan(long sourceId,
+    private IgniteSystemViewScan(
+            long sourceId,
             RelOptCluster cluster,
             RelTraitSet traitSet,
             List<RelHint> hints,
@@ -86,8 +89,8 @@ public class IgniteSystemViewScan extends 
ProjectableFilterableTableScan impleme
             @Nullable List<String> names,
             @Nullable List<RexNode> proj,
             @Nullable RexNode cond,
-            @Nullable ImmutableBitSet reqColumns) {
-
+            @Nullable ImmutableIntList reqColumns
+    ) {
         super(cluster, traitSet, hints, table, names, proj, cond, reqColumns);
 
         this.sourceId = sourceId;
diff --git 
a/modules/sql-engine/src/main/java/org/apache/ignite/internal/sql/engine/rel/IgniteTableScan.java
 
b/modules/sql-engine/src/main/java/org/apache/ignite/internal/sql/engine/rel/IgniteTableScan.java
index 6991a31f9e5..cc446ae8060 100644
--- 
a/modules/sql-engine/src/main/java/org/apache/ignite/internal/sql/engine/rel/IgniteTableScan.java
+++ 
b/modules/sql-engine/src/main/java/org/apache/ignite/internal/sql/engine/rel/IgniteTableScan.java
@@ -27,7 +27,7 @@ import org.apache.calcite.rel.RelInput;
 import org.apache.calcite.rel.RelWriter;
 import org.apache.calcite.rel.hint.RelHint;
 import org.apache.calcite.rex.RexNode;
-import org.apache.calcite.util.ImmutableBitSet;
+import org.apache.calcite.util.ImmutableIntList;
 import org.apache.ignite.internal.sql.engine.rel.explain.IgniteRelWriter;
 import org.jetbrains.annotations.Nullable;
 
@@ -90,7 +90,7 @@ public class IgniteTableScan extends 
ProjectableFilterableTableScan implements S
             @Nullable List<String> names,
             @Nullable List<RexNode> proj,
             @Nullable RexNode cond,
-            @Nullable ImmutableBitSet requiredColumns
+            @Nullable ImmutableIntList requiredColumns
     ) {
         this(-1L, cluster, traits, hints, tbl, names, proj, cond, 
requiredColumns);
     }
@@ -117,7 +117,7 @@ public class IgniteTableScan extends 
ProjectableFilterableTableScan implements S
             @Nullable List<String> names,
             @Nullable List<RexNode> proj,
             @Nullable RexNode cond,
-            @Nullable ImmutableBitSet requiredColumns
+            @Nullable ImmutableIntList requiredColumns
     ) {
         super(cluster, traits, hints, tbl, names, proj, cond, requiredColumns);
         this.sourceId = sourceId;
diff --git 
a/modules/sql-engine/src/main/java/org/apache/ignite/internal/sql/engine/rel/ProjectableFilterableTableScan.java
 
b/modules/sql-engine/src/main/java/org/apache/ignite/internal/sql/engine/rel/ProjectableFilterableTableScan.java
index 7956b24ae05..9f7e01322b7 100644
--- 
a/modules/sql-engine/src/main/java/org/apache/ignite/internal/sql/engine/rel/ProjectableFilterableTableScan.java
+++ 
b/modules/sql-engine/src/main/java/org/apache/ignite/internal/sql/engine/rel/ProjectableFilterableTableScan.java
@@ -44,7 +44,7 @@ import org.apache.calcite.rex.RexShuttle;
 import org.apache.calcite.rex.RexUtil;
 import org.apache.calcite.sql.SqlKind;
 import org.apache.calcite.util.ControlFlowException;
-import org.apache.calcite.util.ImmutableBitSet;
+import org.apache.calcite.util.ImmutableIntList;
 import org.apache.calcite.util.mapping.Mappings;
 import org.apache.ignite.internal.sql.engine.metadata.cost.IgniteCost;
 import org.apache.ignite.internal.sql.engine.rel.explain.IgniteRelWriter;
@@ -66,7 +66,7 @@ public abstract class ProjectableFilterableTableScan extends 
TableScan {
     protected final @Nullable List<String> names;
 
     /** Participating columns. */
-    protected final ImmutableBitSet requiredColumns;
+    protected final ImmutableIntList requiredColumns;
 
     protected ProjectableFilterableTableScan(
             RelOptCluster cluster,
@@ -76,7 +76,7 @@ public abstract class ProjectableFilterableTableScan extends 
TableScan {
             @Nullable List<String> names,
             @Nullable List<RexNode> projects,
             @Nullable RexNode condition,
-            @Nullable ImmutableBitSet requiredColumns
+            @Nullable ImmutableIntList requiredColumns
     ) {
         super(cluster, traitSet, hints, table);
 
@@ -91,7 +91,9 @@ public abstract class ProjectableFilterableTableScan extends 
TableScan {
         condition = input.getExpression("filters");
         names = input.get("names") == null ? null : 
input.getStringList("names");
         projects = input.get("projects") == null ? null : 
input.getExpressionList("projects");
-        requiredColumns = input.get("requiredColumns") == null ? null : 
input.getBitSet("requiredColumns");
+
+        List<Integer> requiredColumns0 = 
input.getIntegerList("requiredColumns");
+        requiredColumns = requiredColumns0 == null ? null : 
ImmutableIntList.copyOf(requiredColumns0);
     }
 
     /** Returns field names explicitly passed during object creation, if any. 
*/
@@ -116,7 +118,7 @@ public abstract class ProjectableFilterableTableScan 
extends TableScan {
     /**
      * Get participating columns.
      */
-    public ImmutableBitSet requiredColumns() {
+    public ImmutableIntList requiredColumns() {
         return requiredColumns;
     }
 
@@ -244,7 +246,8 @@ public abstract class ProjectableFilterableTableScan 
extends TableScan {
 
         if (condition != null || projects != null) {
             RelDataType rowType = getTable().getRowType();
-            if (requiredColumns != null && requiredColumns.cardinality() < 
rowType.getFieldCount()) {
+            // TODO IGNITE-22703 check requiredColumns usage
+            if (requiredColumns != null && requiredColumns.size() < 
rowType.getFieldCount()) {
                 RelDataTypeFactory tf = getCluster().getTypeFactory();
                 IgniteDataSource dataSource = 
getTable().unwrap(IgniteDataSource.class);
 
diff --git 
a/modules/sql-engine/src/main/java/org/apache/ignite/internal/sql/engine/rel/logical/IgniteLogicalIndexScan.java
 
b/modules/sql-engine/src/main/java/org/apache/ignite/internal/sql/engine/rel/logical/IgniteLogicalIndexScan.java
index 609cb8e19ea..85bdb25fbd5 100644
--- 
a/modules/sql-engine/src/main/java/org/apache/ignite/internal/sql/engine/rel/logical/IgniteLogicalIndexScan.java
+++ 
b/modules/sql-engine/src/main/java/org/apache/ignite/internal/sql/engine/rel/logical/IgniteLogicalIndexScan.java
@@ -23,7 +23,7 @@ import org.apache.calcite.plan.RelOptTable;
 import org.apache.calcite.plan.RelTraitSet;
 import org.apache.calcite.rel.RelCollation;
 import org.apache.calcite.rex.RexNode;
-import org.apache.calcite.util.ImmutableBitSet;
+import org.apache.calcite.util.ImmutableIntList;
 import org.apache.calcite.util.mapping.Mappings;
 import org.apache.ignite.internal.sql.engine.prepare.bounds.SearchBounds;
 import org.apache.ignite.internal.sql.engine.rel.AbstractIndexScan;
@@ -61,7 +61,7 @@ public class IgniteLogicalIndexScan extends AbstractIndexScan 
{
             @Nullable List<String> names,
             @Nullable List<RexNode> proj,
             @Nullable RexNode cond,
-            @Nullable ImmutableBitSet requiredColumns
+            @Nullable ImmutableIntList requiredColumns
     ) {
         IgniteTable tbl = table.unwrap(IgniteTable.class);
         IgniteTypeFactory typeFactory = Commons.typeFactory(cluster);
@@ -71,7 +71,8 @@ public class IgniteLogicalIndexScan extends AbstractIndexScan 
{
         List<SearchBounds> searchBounds;
         if (index.type() == Type.HASH) {
             if (requiredColumns != null) {
-                Mappings.TargetMapping targetMapping = Commons.trimmingMapping(
+                // TODO: IGNITE-22703 recheck required columns usage.
+                Mappings.TargetMapping targetMapping = 
Commons.projectedMapping(
                         tbl.getRowType(typeFactory).getFieldCount(), 
requiredColumns);
                 RelCollation outputCollation = collation.apply(targetMapping);
 
@@ -83,7 +84,8 @@ public class IgniteLogicalIndexScan extends AbstractIndexScan 
{
             }
         } else if (index.type() == Type.SORTED) {
             if (requiredColumns != null) {
-                Mappings.TargetMapping targetMapping = Commons.trimmingMapping(
+                // TODO: IGNITE-22703 recheck required columns usage.
+                Mappings.TargetMapping targetMapping = 
Commons.projectedMapping(
                         tbl.getRowType(typeFactory).getFieldCount(), 
requiredColumns);
                 collation = collation.apply(targetMapping);
             }
@@ -116,7 +118,7 @@ public class IgniteLogicalIndexScan extends 
AbstractIndexScan {
             @Nullable List<RexNode> proj,
             @Nullable RexNode cond,
             @Nullable List<SearchBounds> searchBounds,
-            @Nullable ImmutableBitSet requiredCols
+            @Nullable ImmutableIntList requiredCols
     ) {
         super(cluster, traits, List.of(), tbl, idxName, type, names, proj, 
cond, searchBounds, requiredCols);
     }
@@ -126,7 +128,7 @@ public class IgniteLogicalIndexScan extends 
AbstractIndexScan {
             IgniteTable table,
             RelCollation collation,
             @Nullable RexNode cond,
-            @Nullable ImmutableBitSet requiredColumns
+            @Nullable ImmutableIntList requiredColumns
     ) {
         if (collation.getFieldCollations().isEmpty()) {
             return null;
@@ -146,7 +148,7 @@ public class IgniteLogicalIndexScan extends 
AbstractIndexScan {
             IgniteTable table,
             RelCollation collation,
             RexNode cond,
-            @Nullable ImmutableBitSet requiredColumns
+            @Nullable ImmutableIntList requiredColumns
     ) {
         return RexUtils.buildHashSearchBounds(
                 cluster,
diff --git 
a/modules/sql-engine/src/main/java/org/apache/ignite/internal/sql/engine/rel/logical/IgniteLogicalSystemViewScan.java
 
b/modules/sql-engine/src/main/java/org/apache/ignite/internal/sql/engine/rel/logical/IgniteLogicalSystemViewScan.java
index 5bcf508ac68..8b6fc3ef0fb 100644
--- 
a/modules/sql-engine/src/main/java/org/apache/ignite/internal/sql/engine/rel/logical/IgniteLogicalSystemViewScan.java
+++ 
b/modules/sql-engine/src/main/java/org/apache/ignite/internal/sql/engine/rel/logical/IgniteLogicalSystemViewScan.java
@@ -24,7 +24,7 @@ import org.apache.calcite.plan.RelOptTable;
 import org.apache.calcite.plan.RelTraitSet;
 import org.apache.calcite.rel.hint.RelHint;
 import org.apache.calcite.rex.RexNode;
-import org.apache.calcite.util.ImmutableBitSet;
+import org.apache.calcite.util.ImmutableIntList;
 import 
org.apache.ignite.internal.sql.engine.rel.ProjectableFilterableTableScan;
 import org.jetbrains.annotations.Nullable;
 
@@ -42,7 +42,7 @@ public class IgniteLogicalSystemViewScan extends 
ProjectableFilterableTableScan
             @Nullable List<String> names,
             @Nullable List<RexNode> projections,
             @Nullable RexNode condition,
-            @Nullable ImmutableBitSet reqColumns
+            @Nullable ImmutableIntList reqColumns
     ) {
         super(cluster, traitSet, hints, table, names, projections, condition, 
reqColumns);
     }
@@ -66,7 +66,7 @@ public class IgniteLogicalSystemViewScan extends 
ProjectableFilterableTableScan
             @Nullable List<String> names,
             @Nullable List<RexNode> projections,
             @Nullable RexNode condition,
-            @Nullable ImmutableBitSet requiredColumns
+            @Nullable ImmutableIntList requiredColumns
     ) {
         return new IgniteLogicalSystemViewScan(cluster, traits, hints, table, 
names, projections, condition, requiredColumns);
     }
diff --git 
a/modules/sql-engine/src/main/java/org/apache/ignite/internal/sql/engine/rel/logical/IgniteLogicalTableScan.java
 
b/modules/sql-engine/src/main/java/org/apache/ignite/internal/sql/engine/rel/logical/IgniteLogicalTableScan.java
index ff4a587f2b8..ca8525af17a 100644
--- 
a/modules/sql-engine/src/main/java/org/apache/ignite/internal/sql/engine/rel/logical/IgniteLogicalTableScan.java
+++ 
b/modules/sql-engine/src/main/java/org/apache/ignite/internal/sql/engine/rel/logical/IgniteLogicalTableScan.java
@@ -23,7 +23,7 @@ import org.apache.calcite.plan.RelOptTable;
 import org.apache.calcite.plan.RelTraitSet;
 import org.apache.calcite.rel.hint.RelHint;
 import org.apache.calcite.rex.RexNode;
-import org.apache.calcite.util.ImmutableBitSet;
+import org.apache.calcite.util.ImmutableIntList;
 import 
org.apache.ignite.internal.sql.engine.rel.ProjectableFilterableTableScan;
 import org.jetbrains.annotations.Nullable;
 
@@ -52,7 +52,7 @@ public class IgniteLogicalTableScan extends 
ProjectableFilterableTableScan {
             @Nullable List<String> names,
             @Nullable List<RexNode> projections,
             @Nullable RexNode condition,
-            @Nullable ImmutableBitSet requiredColumns
+            @Nullable ImmutableIntList requiredColumns
     ) {
         return new IgniteLogicalTableScan(cluster, traits, hints, table, 
names, projections, condition, requiredColumns);
     }
@@ -65,7 +65,7 @@ public class IgniteLogicalTableScan extends 
ProjectableFilterableTableScan {
             @Nullable List<String> names,
             @Nullable List<RexNode> proj,
             @Nullable RexNode cond,
-            @Nullable ImmutableBitSet requiredColumns
+            @Nullable ImmutableIntList requiredColumns
     ) {
         super(cluster, traits, hints, tbl, names, proj, cond, requiredColumns);
     }
diff --git 
a/modules/sql-engine/src/main/java/org/apache/ignite/internal/sql/engine/rule/LogicalScanConverterRule.java
 
b/modules/sql-engine/src/main/java/org/apache/ignite/internal/sql/engine/rule/LogicalScanConverterRule.java
index 2ca6491dbcc..b76d617265e 100644
--- 
a/modules/sql-engine/src/main/java/org/apache/ignite/internal/sql/engine/rule/LogicalScanConverterRule.java
+++ 
b/modules/sql-engine/src/main/java/org/apache/ignite/internal/sql/engine/rule/LogicalScanConverterRule.java
@@ -29,7 +29,7 @@ import org.apache.calcite.rel.RelDistribution;
 import org.apache.calcite.rel.metadata.RelMetadataQuery;
 import org.apache.calcite.rex.RexLocalRef;
 import org.apache.calcite.rex.RexNode;
-import org.apache.calcite.util.ImmutableBitSet;
+import org.apache.calcite.util.ImmutableIntList;
 import org.apache.calcite.util.mapping.IntPair;
 import org.apache.calcite.util.mapping.Mapping;
 import org.apache.calcite.util.mapping.Mappings;
@@ -177,12 +177,12 @@ public abstract class LogicalScanConverterRule<T extends 
ProjectableFilterableTa
     /** Creates column mapping regarding the projection. */
     public static Mappings.TargetMapping createMapping(
             @Nullable List<RexNode> projects,
-            ImmutableBitSet requiredColumns,
+            ImmutableIntList requiredColumns,
             int tableRowSize
     ) {
         if (projects != null) {
             Mapping trimmingMapping = requiredColumns != null
-                    ? 
Mappings.invert(Mappings.source(requiredColumns.asList(), tableRowSize))
+                    ? Mappings.invert(Mappings.source(requiredColumns, 
tableRowSize))
                     : Mappings.createIdentity(tableRowSize);
 
 
@@ -206,7 +206,7 @@ public abstract class LogicalScanConverterRule<T extends 
ProjectableFilterableTa
         }
 
         if (requiredColumns != null) {
-            return Mappings.target(requiredColumns.asList(), tableRowSize);
+            return Mappings.target(requiredColumns, tableRowSize);
         }
 
         return Mappings.createIdentity(tableRowSize);
diff --git 
a/modules/sql-engine/src/main/java/org/apache/ignite/internal/sql/engine/rule/TableScanToKeyValueGetRule.java
 
b/modules/sql-engine/src/main/java/org/apache/ignite/internal/sql/engine/rule/TableScanToKeyValueGetRule.java
index c48e8585654..0b5d4487273 100644
--- 
a/modules/sql-engine/src/main/java/org/apache/ignite/internal/sql/engine/rule/TableScanToKeyValueGetRule.java
+++ 
b/modules/sql-engine/src/main/java/org/apache/ignite/internal/sql/engine/rule/TableScanToKeyValueGetRule.java
@@ -36,6 +36,7 @@ import org.apache.calcite.rex.RexBuilder;
 import org.apache.calcite.rex.RexNode;
 import org.apache.calcite.rex.RexUtil;
 import org.apache.calcite.util.ImmutableBitSet;
+import org.apache.calcite.util.ImmutableIntList;
 import org.apache.calcite.util.mapping.Mappings;
 import org.apache.ignite.internal.sql.engine.prepare.bounds.ExactBounds;
 import org.apache.ignite.internal.sql.engine.prepare.bounds.SearchBounds;
@@ -145,11 +146,11 @@ public class TableScanToKeyValueGetRule extends 
RelRule<TableScanToKeyValueGetRu
 
         RelOptCluster cluster = scan.getCluster();
         RelCollation collation = primaryKeyIndex.collation();
-        ImmutableBitSet requiredColumns = scan.requiredColumns();
+        ImmutableIntList requiredColumns = scan.requiredColumns();
         RelDataType rowType = table.getRowType(cluster.getTypeFactory());
 
         if (requiredColumns != null) {
-            Mappings.TargetMapping targetMapping = Commons.trimmingMapping(
+            Mappings.TargetMapping targetMapping = Commons.projectedMapping(
                     rowType.getFieldCount(), requiredColumns
             );
 
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 94a305a0358..761dccc9200 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
@@ -39,7 +39,7 @@ import org.apache.calcite.rel.RelNode;
 import org.apache.calcite.rel.core.TableScan;
 import org.apache.calcite.rel.hint.RelHint;
 import org.apache.calcite.rex.RexNode;
-import org.apache.calcite.util.ImmutableBitSet;
+import org.apache.calcite.util.ImmutableIntList;
 import org.apache.ignite.internal.sql.engine.hint.IgniteHint;
 import org.apache.ignite.internal.sql.engine.prepare.bounds.SearchBounds;
 import org.apache.ignite.internal.sql.engine.rel.AbstractIndexScan;
@@ -83,7 +83,7 @@ public class ExposeIndexRule extends 
RelRule<ExposeIndexRule.Config> {
         List<String> names = scan.fieldNames();
         List<RexNode> proj = scan.projects();
         RexNode condition = scan.condition();
-        ImmutableBitSet requiredCols = scan.requiredColumns();
+        ImmutableIntList requiredCols = scan.requiredColumns();
 
         List<IgniteLogicalIndexScan> indexes = 
igniteTable.indexes().values().stream()
                 .map(idx -> idx.toRel(cluster, optTable, names, proj, 
condition, requiredCols))
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 240d3525fa1..8b61b36aab3 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
@@ -150,7 +150,7 @@ public class LogicalOrToUnionRule extends 
RelRule<LogicalOrToUnionRule.Config> {
         }
 
         Mappings.TargetMapping mapping = scan.requiredColumns() == null ? null 
:
-                Commons.trimmingMapping(fieldCnt, scan.requiredColumns());
+                Commons.projectedMapping(fieldCnt, scan.requiredColumns());
 
         for (RexNode op : operands) {
             BitSet conditionFields = new BitSet(fieldCnt);
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 db86ae729f4..16aaba4fd9e 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
@@ -17,6 +17,8 @@
 
 package org.apache.ignite.internal.sql.engine.rule.logical;
 
+import it.unimi.dsi.fastutil.ints.IntArrayList;
+import it.unimi.dsi.fastutil.ints.IntList;
 import java.util.List;
 import org.apache.calcite.plan.RelOptCluster;
 import org.apache.calcite.plan.RelOptRule;
@@ -28,7 +30,7 @@ import org.apache.calcite.rex.RexInputRef;
 import org.apache.calcite.rex.RexLocalRef;
 import org.apache.calcite.rex.RexNode;
 import org.apache.calcite.rex.RexShuttle;
-import org.apache.calcite.util.ImmutableBitSet;
+import org.apache.calcite.util.ImmutableIntList;
 import org.apache.calcite.util.mapping.Mappings;
 import 
org.apache.ignite.internal.sql.engine.rel.ProjectableFilterableTableScan;
 import 
org.apache.ignite.internal.sql.engine.rel.logical.IgniteLogicalIndexScan;
@@ -65,7 +67,7 @@ public abstract class ProjectScanMergeRule<T extends 
ProjectableFilterableTableS
             List<String> names,
             List<RexNode> projections,
             RexNode cond,
-            ImmutableBitSet requiredColumns
+            ImmutableIntList requiredColumns
     );
 
     /**
@@ -86,7 +88,7 @@ public abstract class ProjectScanMergeRule<T extends 
ProjectableFilterableTableS
         List<String> names = relProject.getRowType().getFieldNames();
         List<RexNode> projects = relProject.getProjects();
         RexNode cond = scan.condition();
-        ImmutableBitSet requiredColumns = scan.requiredColumns();
+        ImmutableIntList requiredColumns = scan.requiredColumns();
         List<RexNode> scanProjects = scan.projects();
 
         // Set default traits, real traits will be calculated for physical 
node.
@@ -95,28 +97,29 @@ public abstract class ProjectScanMergeRule<T extends 
ProjectableFilterableTableS
         IgniteDataSource tbl = scan.getTable().unwrap(IgniteDataSource.class);
         IgniteTypeFactory typeFactory = Commons.typeFactory(cluster);
 
+        // TODO: IGNITE-27703 revisit required columns usage.
         if (requiredColumns == null) {
             assert scanProjects == null;
 
-            ImmutableBitSet.Builder builder = ImmutableBitSet.builder();
+            IntList refs = new IntArrayList();
 
             new RexShuttle() {
                 @Override public RexNode visitInputRef(RexInputRef ref) {
-                    builder.set(ref.getIndex());
+                    refs.add(ref.getIndex());
                     return ref;
                 }
             }.apply(projects);
 
             new RexShuttle() {
                 @Override public RexNode visitLocalRef(RexLocalRef inputRef) {
-                    builder.set(inputRef.getIndex());
+                    refs.add(inputRef.getIndex());
                     return inputRef;
                 }
             }.apply(cond);
 
-            requiredColumns = builder.build();
+            requiredColumns = ImmutableIntList.copyOf(refs.toIntArray());
 
-            Mappings.TargetMapping targetMapping = Commons.trimmingMapping(
+            Mappings.TargetMapping targetMapping = Commons.projectedMapping(
                     tbl.getRowType(typeFactory).getFieldCount(), 
requiredColumns);
 
             projects = new RexShuttle() {
@@ -172,7 +175,7 @@ public abstract class ProjectScanMergeRule<T extends 
ProjectableFilterableTableS
                 List<String> names,
                 List<RexNode> projections,
                 RexNode cond,
-                ImmutableBitSet requiredColumns
+                ImmutableIntList requiredColumns
         ) {
             return IgniteLogicalTableScan.create(
                     cluster,
@@ -205,7 +208,7 @@ public abstract class ProjectScanMergeRule<T extends 
ProjectableFilterableTableS
                 List<String> names,
                 List<RexNode> projections,
                 RexNode cond,
-                ImmutableBitSet requiredColumns
+                ImmutableIntList requiredColumns
         ) {
             return IgniteLogicalIndexScan.create(
                 cluster,
@@ -237,7 +240,7 @@ public abstract class ProjectScanMergeRule<T extends 
ProjectableFilterableTableS
                 List<String> names,
                 List<RexNode> projections,
                 RexNode cond,
-                ImmutableBitSet requiredColumns
+                ImmutableIntList requiredColumns
         ) {
             return IgniteLogicalSystemViewScan.create(
                     cluster,
diff --git 
a/modules/sql-engine/src/main/java/org/apache/ignite/internal/sql/engine/schema/IgniteIndex.java
 
b/modules/sql-engine/src/main/java/org/apache/ignite/internal/sql/engine/schema/IgniteIndex.java
index f8e1c1fd1a5..1873de3833a 100644
--- 
a/modules/sql-engine/src/main/java/org/apache/ignite/internal/sql/engine/schema/IgniteIndex.java
+++ 
b/modules/sql-engine/src/main/java/org/apache/ignite/internal/sql/engine/schema/IgniteIndex.java
@@ -33,7 +33,7 @@ import org.apache.calcite.rel.RelFieldCollation.NullDirection;
 import org.apache.calcite.rel.type.RelDataType;
 import org.apache.calcite.rel.type.RelDataTypeFactory;
 import org.apache.calcite.rex.RexNode;
-import org.apache.calcite.util.ImmutableBitSet;
+import org.apache.calcite.util.ImmutableIntList;
 import 
org.apache.ignite.internal.catalog.descriptors.CatalogHashIndexDescriptor;
 import 
org.apache.ignite.internal.catalog.descriptors.CatalogIndexColumnDescriptor;
 import org.apache.ignite.internal.catalog.descriptors.CatalogIndexDescriptor;
@@ -151,7 +151,7 @@ public class IgniteIndex {
             @Nullable List<String> names,
             List<RexNode> proj,
             RexNode condition,
-            ImmutableBitSet requiredCols
+            ImmutableIntList requiredCols
     ) {
         RelTraitSet traitSet = cluster.traitSetOf(Convention.Impl.NONE)
                 .replace(tableDistribution)
diff --git 
a/modules/sql-engine/src/main/java/org/apache/ignite/internal/sql/engine/util/RexUtils.java
 
b/modules/sql-engine/src/main/java/org/apache/ignite/internal/sql/engine/util/RexUtils.java
index 2ad0bfb4d59..c671d0d0a26 100644
--- 
a/modules/sql-engine/src/main/java/org/apache/ignite/internal/sql/engine/util/RexUtils.java
+++ 
b/modules/sql-engine/src/main/java/org/apache/ignite/internal/sql/engine/util/RexUtils.java
@@ -92,6 +92,7 @@ import org.apache.calcite.sql.type.SqlTypeName.Limit;
 import org.apache.calcite.sql.type.SqlTypeUtil;
 import org.apache.calcite.util.ControlFlowException;
 import org.apache.calcite.util.ImmutableBitSet;
+import org.apache.calcite.util.ImmutableIntList;
 import org.apache.calcite.util.Litmus;
 import org.apache.calcite.util.Pair;
 import org.apache.calcite.util.Sarg;
@@ -313,7 +314,7 @@ public class RexUtils {
             RelCollation collation,
             @Nullable RexNode condition,
             RelDataType rowType,
-            @Nullable ImmutableBitSet requiredColumns
+            @Nullable ImmutableIntList requiredColumns
     ) {
         if (condition == null) {
             return null;
@@ -348,7 +349,8 @@ public class RexUtils {
         Mappings.TargetMapping mapping = null;
 
         if (requiredColumns != null) {
-            mapping = Commons.trimmingMapping(types.size(), requiredColumns);
+            // TODO: IGNITE-22703 recheck required columns usage.
+            mapping = Commons.projectedMapping(types.size(), requiredColumns);
         }
 
         List<SearchBounds> bounds = Arrays.asList(new 
SearchBounds[collation.getFieldCollations().size()]);
@@ -405,7 +407,7 @@ public class RexUtils {
             RelCollation collation,
             RexNode condition,
             RelDataType rowType,
-            @Nullable ImmutableBitSet requiredColumns
+            @Nullable ImmutableIntList requiredColumns
     ) {
         if (condition == null) {
             return null;
@@ -425,7 +427,8 @@ public class RexUtils {
 
         Mappings.TargetMapping toTrimmedRowMapping = null;
         if (requiredColumns != null) {
-            toTrimmedRowMapping = Commons.trimmingMapping(types.size(), 
requiredColumns);
+            // TODO: IGNITE-22703 recheck required columns usage.
+            toTrimmedRowMapping = Commons.projectedMapping(types.size(), 
requiredColumns);
         }
 
         List<RelFieldCollation> fieldCollations = 
collation.getFieldCollations();
diff --git 
a/modules/sql-engine/src/test/java/org/apache/ignite/internal/sql/engine/exec/exp/ExpressionFactoryImplTest.java
 
b/modules/sql-engine/src/test/java/org/apache/ignite/internal/sql/engine/exec/exp/ExpressionFactoryImplTest.java
index 8f578fe392f..71830db31f9 100644
--- 
a/modules/sql-engine/src/test/java/org/apache/ignite/internal/sql/engine/exec/exp/ExpressionFactoryImplTest.java
+++ 
b/modules/sql-engine/src/test/java/org/apache/ignite/internal/sql/engine/exec/exp/ExpressionFactoryImplTest.java
@@ -52,7 +52,6 @@ import org.apache.calcite.sql.fun.SqlStdOperatorTable;
 import org.apache.calcite.sql.type.BasicSqlType;
 import org.apache.calcite.sql.type.SqlTypeName;
 import org.apache.calcite.sql.type.SqlTypeName.Limit;
-import org.apache.calcite.util.ImmutableBitSet;
 import org.apache.calcite.util.ImmutableIntList;
 import org.apache.ignite.internal.network.ClusterNodeImpl;
 import org.apache.ignite.internal.sql.engine.exec.ExecutionContext;
@@ -548,7 +547,7 @@ public class ExpressionFactoryImplTest extends 
BaseIgniteAbstractTest {
 
         // build bounds for two sequential columns also belongs to index
         List<SearchBounds> bounds = 
RexUtils.buildSortedSearchBounds(Commons.emptyCluster(),
-                RelCollations.of(ImmutableIntList.of(1, 2)), andCondition, 
rowType, ImmutableBitSet.of(0, 1, 2));
+                RelCollations.of(ImmutableIntList.of(1, 2)), andCondition, 
rowType, ImmutableIntList.of(0, 1, 2));
 
         if (!conditionSatisfyIdx) {
             assertNull(bounds);

Reply via email to