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 37c16f3e229a11b4d13e3f1b60aac40a65b45505 Author: amashenkov <amashen...@apache.org> AuthorDate: Thu Jul 3 22:42:02 2025 +0300 wip. --- .../internal/benchmark/SqlSelectAllBenchmark.java | 9 +++- .../engine/exec/TableRowConverterFactoryImpl.java | 20 ++------ .../engine/rule/logical/ProjectScanMergeRule.java | 4 +- .../sql/engine/schema/IgniteTableImpl.java | 56 ++++++---------------- .../sql/engine/schema/TableDescriptor.java | 10 ++++ .../sql/engine/schema/TableDescriptorImpl.java | 23 +++++++++ .../ignite/internal/sql/engine/util/Commons.java | 15 ++++++ .../ignite/internal/sql/engine/util/RexUtils.java | 7 ++- .../exec/ExecutableTableRegistrySelfTest.java | 1 - .../exec/ProjectedTableRowConverterSelfTest.java | 1 - .../sql/engine/framework/TestBuilders.java | 8 ---- .../sql/engine/planner/AbstractPlannerTest.java | 10 ++++ .../sql/engine/planner/PlannerTimeoutTest.java | 1 - 13 files changed, 89 insertions(+), 76 deletions(-) diff --git a/modules/runner/src/integrationTest/java/org/apache/ignite/internal/benchmark/SqlSelectAllBenchmark.java b/modules/runner/src/integrationTest/java/org/apache/ignite/internal/benchmark/SqlSelectAllBenchmark.java index 1b62824dd32..5bd893251f1 100644 --- a/modules/runner/src/integrationTest/java/org/apache/ignite/internal/benchmark/SqlSelectAllBenchmark.java +++ b/modules/runner/src/integrationTest/java/org/apache/ignite/internal/benchmark/SqlSelectAllBenchmark.java @@ -85,7 +85,7 @@ public class SqlSelectAllBenchmark extends AbstractTpcBenchmark { } @Param({ - "IDENTITY", "RESHUFFLING" + "IDENTITY", "TRIMMING", "RESHUFFLING" }) private Projection projection; @@ -110,6 +110,13 @@ public class SqlSelectAllBenchmark extends AbstractTpcBenchmark { new Runner(opt).run(); } + /** + * Projection types for the benchmark. + * + * <p>IDENTITY - selects all columns in the original order. + * TRIMMING - selects all columns except few ones (preserving related order). + * RESHUFFLING - selects all columns in a different order. + */ public enum Projection { IDENTITY { @Override diff --git a/modules/sql-engine/src/main/java/org/apache/ignite/internal/sql/engine/exec/TableRowConverterFactoryImpl.java b/modules/sql-engine/src/main/java/org/apache/ignite/internal/sql/engine/exec/TableRowConverterFactoryImpl.java index cf67297f027..824e2a64f96 100644 --- a/modules/sql-engine/src/main/java/org/apache/ignite/internal/sql/engine/exec/TableRowConverterFactoryImpl.java +++ b/modules/sql-engine/src/main/java/org/apache/ignite/internal/sql/engine/exec/TableRowConverterFactoryImpl.java @@ -97,13 +97,13 @@ public class TableRowConverterFactoryImpl implements TableRowConverterFactory { ? tableColumnSet : projection.toIntArray(); - Int2ObjectMap<VirtualColumn> extraColumns = createVirtualColumns(mapping, partId); - - // TODO: IGNITE-22703 Ensure this check is correct. - if (extraColumns.isEmpty() && isFullIdentityMapping(mapping)) { + // TODO: IGNITE-22703 Can we opmitimize this? + if (Commons.isIdentityMapping(mapping, schemaDescriptor.length())) { return fullRowConverter; } + Int2ObjectMap<VirtualColumn> extraColumns = createVirtualColumns(mapping, partId); + return new ProjectedTableRowConverterImpl( schemaRegistry, schemaDescriptor, @@ -112,18 +112,6 @@ public class TableRowConverterFactoryImpl implements TableRowConverterFactory { ); } - private boolean isFullIdentityMapping(int[] mapping) { - if (mapping.length != schemaDescriptor.length()) { - return false; - } - for (int i = 0; i < mapping.length; i++) { - if (mapping[i] != i) { - return false; - } - } - return true; - } - private Int2ObjectMap<VirtualColumn> createVirtualColumns(int[] requiredColumns, int partId) { if (virtualColumnsFactory.isEmpty()) { return Int2ObjectMaps.emptyMap(); 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 528c92685fc..54d503718fe 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,9 +17,7 @@ package org.apache.ignite.internal.sql.engine.rule.logical; -import it.unimi.dsi.fastutil.ints.IntArrayList; import it.unimi.dsi.fastutil.ints.IntLinkedOpenHashSet; -import it.unimi.dsi.fastutil.ints.IntList; import it.unimi.dsi.fastutil.ints.IntSet; import java.util.List; import org.apache.calcite.plan.RelOptCluster; @@ -148,7 +146,7 @@ public abstract class ProjectScanMergeRule<T extends ProjectableFilterableTableS } // TODO: IGNITE-22703 revisit required columns usage. - if (RexUtils.isIdentity(projects, tbl.getRowType(typeFactory, requiredColumns), true)) { + if (RexUtils.isIdentity(projects, tbl.getRowType(typeFactory, requiredColumns))) { projects = null; } diff --git a/modules/sql-engine/src/main/java/org/apache/ignite/internal/sql/engine/schema/IgniteTableImpl.java b/modules/sql-engine/src/main/java/org/apache/ignite/internal/sql/engine/schema/IgniteTableImpl.java index 17e70aae638..af0b57c80be 100644 --- a/modules/sql-engine/src/main/java/org/apache/ignite/internal/sql/engine/schema/IgniteTableImpl.java +++ b/modules/sql-engine/src/main/java/org/apache/ignite/internal/sql/engine/schema/IgniteTableImpl.java @@ -29,7 +29,6 @@ import org.apache.calcite.plan.RelTraitSet; import org.apache.calcite.rel.core.TableScan; import org.apache.calcite.rel.hint.RelHint; import org.apache.calcite.rel.type.RelDataType; -import org.apache.calcite.rel.type.RelDataTypeFactory; import org.apache.calcite.schema.Statistic; import org.apache.calcite.util.ImmutableIntList; import org.apache.ignite.internal.sql.engine.rel.logical.IgniteLogicalTableScan; @@ -77,21 +76,6 @@ public class IgniteTableImpl extends AbstractIgniteDataSource implements IgniteT colocationColumnTypes = new Lazy<>(this::evaluateTypes); } - private static RelDataType deriveDeleteRowType( - IgniteTypeFactory typeFactory, - TableDescriptor desc, - ImmutableIntList keyColumns - ) { - var builder = new RelDataTypeFactory.Builder(typeFactory); - - RelDataType fullRow = desc.rowType(typeFactory, null); - for (int i : keyColumns) { - builder.add(fullRow.getFieldList().get(i)); - } - - return builder.build(); - } - private static @Nullable ImmutableIntList deriveColumnsToInsert(TableDescriptor desc) { /* Columns to insert are columns which will be expanded in case user omit @@ -108,45 +92,35 @@ public class IgniteTableImpl extends AbstractIgniteDataSource implements IgniteT See org.apache.ignite.internal.sql.engine.util.Commons.implicitPkEnabled, and org.apache.ignite.internal.sql.engine.schema.SqlSchemaManagerImpl.injectDefault for details. */ + if (!desc.hasHiddenColumns()) { + return null; // 'null' means that full projection will be used for insert. + } + IntList columnsToInsert = new IntArrayList(desc.columnsCount()); - boolean hiddenColumnFound = false; for (ColumnDescriptor columnDescriptor : desc) { - if (columnDescriptor.hidden()) { - hiddenColumnFound = true; - - continue; + if (!columnDescriptor.hidden()) { + columnsToInsert.add(columnDescriptor.logicalIndex()); } - - columnsToInsert.add(columnDescriptor.logicalIndex()); - } - - if (hiddenColumnFound) { - return ImmutableIntList.of(columnsToInsert.toIntArray()); } - return null; + return ImmutableIntList.of(columnsToInsert.toIntArray()); } private static @Nullable ImmutableIntList deriveColumnsToUpdate(TableDescriptor desc) { + if (!desc.hasVirtualColumns()) { + return null; // 'null' means that full projection will be used for update. + } + IntList columnsToUpdate = new IntArrayList(desc.columnsCount()); - boolean virtualColumnFound = false; for (ColumnDescriptor columnDescriptor : desc) { - if (columnDescriptor.virtual()) { - virtualColumnFound = true; - - continue; + if (!columnDescriptor.virtual()) { + columnsToUpdate.add(columnDescriptor.logicalIndex()); } - - columnsToUpdate.add(columnDescriptor.logicalIndex()); - } - - if (virtualColumnFound) { - return ImmutableIntList.of(columnsToUpdate.toIntArray()); } - return null; + return ImmutableIntList.of(columnsToUpdate.toIntArray()); } /** {@inheritDoc} */ @@ -220,6 +194,6 @@ public class IgniteTableImpl extends AbstractIgniteDataSource implements IgniteT /** {@inheritDoc} */ @Override public RelDataType rowTypeForDelete(IgniteTypeFactory factory) { - return deriveDeleteRowType(factory, descriptor(), keyColumns); + return descriptor().rowType(factory, keyColumns); } } diff --git a/modules/sql-engine/src/main/java/org/apache/ignite/internal/sql/engine/schema/TableDescriptor.java b/modules/sql-engine/src/main/java/org/apache/ignite/internal/sql/engine/schema/TableDescriptor.java index 47f408060e8..6946c581757 100644 --- a/modules/sql-engine/src/main/java/org/apache/ignite/internal/sql/engine/schema/TableDescriptor.java +++ b/modules/sql-engine/src/main/java/org/apache/ignite/internal/sql/engine/schema/TableDescriptor.java @@ -64,4 +64,14 @@ public interface TableDescriptor extends InitializerExpressionFactory, Iterable< * @return Actual count of columns. */ int columnsCount(); + + /** + * Returns {@code true} if table has hidden columns, {@code false} otherwise. + */ + boolean hasHiddenColumns(); + + /** + * Returns {@code true} if table has virtual columns, {@code false} otherwise. + */ + boolean hasVirtualColumns(); } diff --git a/modules/sql-engine/src/main/java/org/apache/ignite/internal/sql/engine/schema/TableDescriptorImpl.java b/modules/sql-engine/src/main/java/org/apache/ignite/internal/sql/engine/schema/TableDescriptorImpl.java index 3ae5b01b3c2..b0879684ba7 100644 --- a/modules/sql-engine/src/main/java/org/apache/ignite/internal/sql/engine/schema/TableDescriptorImpl.java +++ b/modules/sql-engine/src/main/java/org/apache/ignite/internal/sql/engine/schema/TableDescriptorImpl.java @@ -58,6 +58,9 @@ public class TableDescriptorImpl extends NullInitializerExpressionFactory implem private final RelDataType rowType; private final RelDataType rowTypeSansHidden; + private final boolean hasHiddenColumns; + private final boolean hasVirtualColumns; + /** * Constructor. * @@ -73,6 +76,8 @@ public class TableDescriptorImpl extends NullInitializerExpressionFactory implem RelDataTypeFactory.Builder typeBuilder = new RelDataTypeFactory.Builder(factory); RelDataTypeFactory.Builder typeSansHiddenBuilder = new RelDataTypeFactory.Builder(factory); + boolean hasHiddenColumns = false; + boolean hasVirtualColumns = false; for (ColumnDescriptor descriptor : columnDescriptors) { RelDataType columnType = deriveLogicalType(factory, descriptor); @@ -80,6 +85,12 @@ public class TableDescriptorImpl extends NullInitializerExpressionFactory implem if (!descriptor.hidden()) { typeSansHiddenBuilder.add(descriptor.name(), columnType); + } else { + hasHiddenColumns = true; + } + + if (descriptor.virtual()) { + hasVirtualColumns = true; } descriptorsMap.put(descriptor.name(), descriptor); @@ -89,6 +100,8 @@ public class TableDescriptorImpl extends NullInitializerExpressionFactory implem this.descriptorsMap = descriptorsMap; this.rowType = typeBuilder.build(); this.rowTypeSansHidden = typeSansHiddenBuilder.build(); + this.hasHiddenColumns = hasHiddenColumns; + this.hasVirtualColumns = hasVirtualColumns; } @Override @@ -190,6 +203,16 @@ public class TableDescriptorImpl extends NullInitializerExpressionFactory implem return descriptors.length; } + @Override + public boolean hasHiddenColumns() { + return hasHiddenColumns; + } + + @Override + public boolean hasVirtualColumns() { + return hasVirtualColumns; + } + private RelDataType deriveLogicalType(RelDataTypeFactory factory, ColumnDescriptor desc) { return native2relationalType(factory, desc.physicalType(), desc.nullable()); } diff --git a/modules/sql-engine/src/main/java/org/apache/ignite/internal/sql/engine/util/Commons.java b/modules/sql-engine/src/main/java/org/apache/ignite/internal/sql/engine/util/Commons.java index 32de6f50e26..b276a5432e5 100644 --- a/modules/sql-engine/src/main/java/org/apache/ignite/internal/sql/engine/util/Commons.java +++ b/modules/sql-engine/src/main/java/org/apache/ignite/internal/sql/engine/util/Commons.java @@ -829,4 +829,19 @@ public final class Commons { // Create a non-strict equijoin condition that treats IS NOT DISTINCT_FROM as an equi join condition. return JoinInfo.of(join.getLeft(), join.getRight(), join.getCondition()); } + + /** + * Checks whether the given mapping is an identity mapping. + */ + public static boolean isIdentityMapping(int[] mapping, int length) { + if (mapping.length != length) { + return false; + } + for (int i = 0; i < mapping.length; i++) { + if (mapping[i] != i) { + return false; + } + } + return true; + } } 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 55c3a138ec3..aa6e7ab99bc 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 @@ -162,16 +162,15 @@ public class RexUtils { } /** Returns whether a list of expressions projects the incoming fields. */ - public static boolean isIdentity(List<? extends RexNode> projects, RelDataType inputRowType, boolean local) { + public static boolean isIdentity(List<? extends RexNode> projects, RelDataType inputRowType) { if (inputRowType.getFieldCount() != projects.size()) { return false; } - final List<RelDataTypeField> fields = inputRowType.getFieldList(); - Class<? extends RexSlot> clazz = local ? RexLocalRef.class : RexInputRef.class; + List<RelDataTypeField> fields = inputRowType.getFieldList(); for (int i = 0; i < fields.size(); i++) { - if (!clazz.isInstance(projects.get(i))) { + if (!(projects.get(i) instanceof RexLocalRef)) { return false; } diff --git a/modules/sql-engine/src/test/java/org/apache/ignite/internal/sql/engine/exec/ExecutableTableRegistrySelfTest.java b/modules/sql-engine/src/test/java/org/apache/ignite/internal/sql/engine/exec/ExecutableTableRegistrySelfTest.java index 4f3600f3043..ac7b579cedb 100644 --- a/modules/sql-engine/src/test/java/org/apache/ignite/internal/sql/engine/exec/ExecutableTableRegistrySelfTest.java +++ b/modules/sql-engine/src/test/java/org/apache/ignite/internal/sql/engine/exec/ExecutableTableRegistrySelfTest.java @@ -24,7 +24,6 @@ import static org.mockito.Mockito.when; import java.util.Collections; import java.util.Map; -import java.util.Spliterators; import org.apache.calcite.util.ImmutableIntList; import org.apache.ignite.internal.TestHybridClock; import org.apache.ignite.internal.components.SystemPropertiesNodeProperties; diff --git a/modules/sql-engine/src/test/java/org/apache/ignite/internal/sql/engine/exec/ProjectedTableRowConverterSelfTest.java b/modules/sql-engine/src/test/java/org/apache/ignite/internal/sql/engine/exec/ProjectedTableRowConverterSelfTest.java index 20c7f254a56..36e18de50ec 100644 --- a/modules/sql-engine/src/test/java/org/apache/ignite/internal/sql/engine/exec/ProjectedTableRowConverterSelfTest.java +++ b/modules/sql-engine/src/test/java/org/apache/ignite/internal/sql/engine/exec/ProjectedTableRowConverterSelfTest.java @@ -25,7 +25,6 @@ import java.util.List; import java.util.Map; import java.util.UUID; import java.util.stream.Collectors; -import org.apache.calcite.util.BitSets; import org.apache.ignite.internal.binarytuple.BinaryTupleBuilder; import org.apache.ignite.internal.schema.BinaryRow; import org.apache.ignite.internal.schema.BinaryRowImpl; diff --git a/modules/sql-engine/src/test/java/org/apache/ignite/internal/sql/engine/framework/TestBuilders.java b/modules/sql-engine/src/test/java/org/apache/ignite/internal/sql/engine/framework/TestBuilders.java index c5d930617ba..2140a1a3497 100644 --- a/modules/sql-engine/src/test/java/org/apache/ignite/internal/sql/engine/framework/TestBuilders.java +++ b/modules/sql-engine/src/test/java/org/apache/ignite/internal/sql/engine/framework/TestBuilders.java @@ -32,7 +32,6 @@ import java.time.Clock; import java.time.ZoneId; import java.util.ArrayList; import java.util.Arrays; -import java.util.BitSet; import java.util.Collection; import java.util.HashMap; import java.util.HashSet; @@ -1712,13 +1711,6 @@ public class TestBuilders { return builder.build(); } - @Deprecated - private static Object[] project(Object[] row, @Nullable BitSet requiredElements) { - if (requiredElements == null) { - return row; - } - return project(row, ImmutableIntList.copyOf(requiredElements.stream().iterator())); - } private static Object[] project(Object[] row, @Nullable ImmutableIntList requiredElements) { if (requiredElements == null) { return row; diff --git a/modules/sql-engine/src/test/java/org/apache/ignite/internal/sql/engine/planner/AbstractPlannerTest.java b/modules/sql-engine/src/test/java/org/apache/ignite/internal/sql/engine/planner/AbstractPlannerTest.java index f62124ade13..a473faa77df 100644 --- a/modules/sql-engine/src/test/java/org/apache/ignite/internal/sql/engine/planner/AbstractPlannerTest.java +++ b/modules/sql-engine/src/test/java/org/apache/ignite/internal/sql/engine/planner/AbstractPlannerTest.java @@ -891,6 +891,16 @@ public abstract class AbstractPlannerTest extends IgniteAbstractTest { return rowType.getFieldCount(); } + @Override + public boolean hasHiddenColumns() { + return false; + } + + @Override + public boolean hasVirtualColumns() { + return false; + } + /** {@inheritDoc} */ @Override public boolean isGeneratedAlways(RelOptTable table, int idxColumn) { diff --git a/modules/sql-engine/src/test/java/org/apache/ignite/internal/sql/engine/planner/PlannerTimeoutTest.java b/modules/sql-engine/src/test/java/org/apache/ignite/internal/sql/engine/planner/PlannerTimeoutTest.java index c7cdc4b988f..48bbe7cb1e5 100644 --- a/modules/sql-engine/src/test/java/org/apache/ignite/internal/sql/engine/planner/PlannerTimeoutTest.java +++ b/modules/sql-engine/src/test/java/org/apache/ignite/internal/sql/engine/planner/PlannerTimeoutTest.java @@ -35,7 +35,6 @@ import org.apache.calcite.plan.volcano.VolcanoPlanner; import org.apache.calcite.plan.volcano.VolcanoTimeoutException; import org.apache.calcite.rel.RelNode; import org.apache.calcite.rel.RelVisitor; -import org.apache.calcite.util.ImmutableBitSet; import org.apache.calcite.util.ImmutableIntList; import org.apache.ignite.internal.metrics.MetricManagerImpl; import org.apache.ignite.internal.sql.engine.SqlOperationContext;