You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@ignite.apache.org by am...@apache.org on 2025/05/14 08:09:26 UTC
(ignite-3) branch main updated: IGNITE-24936 Sql. Allow access of virtual column "__part" without quoting (#5796)
This is an automated email from the ASF dual-hosted git repository.
amashenkov 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 4a12fb66cde IGNITE-24936 Sql. Allow access of virtual column "__part" without quoting (#5796)
4a12fb66cde is described below
commit 4a12fb66cde0a75a3f9b09eb017d912691f9062f
Author: Andrew V. Mashenkov <AM...@users.noreply.github.com>
AuthorDate: Wed May 14 11:09:20 2025 +0300
IGNITE-24936 Sql. Allow access of virtual column "__part" without quoting (#5796)
---
.../sql/group1/syscolumns/system_columns.test | 26 ++++++++++++++++
.../engine/exec/TableRowConverterFactoryImpl.java | 36 ++++++++++++++++------
.../sql/engine/prepare/IgniteSqlValidator.java | 10 +++---
.../prepare/ddl/DdlSqlToCommandConverter.java | 4 +--
.../sql/engine/schema/SqlSchemaManagerImpl.java | 12 ++++----
.../ignite/internal/sql/engine/util/Commons.java | 4 ++-
.../sql/engine/framework/TestBuilders.java | 36 ++++++++++++++--------
.../internal/sql/engine/util/QueryCheckerTest.java | 2 +-
8 files changed, 94 insertions(+), 36 deletions(-)
diff --git a/modules/sql-engine/src/integrationTest/sql/group1/syscolumns/system_columns.test b/modules/sql-engine/src/integrationTest/sql/group1/syscolumns/system_columns.test
index a7bc0c296e2..a15d1ef01ec 100644
--- a/modules/sql-engine/src/integrationTest/sql/group1/syscolumns/system_columns.test
+++ b/modules/sql-engine/src/integrationTest/sql/group1/syscolumns/system_columns.test
@@ -12,6 +12,11 @@ insert into t0 values (101, 'val1'), (102, 'val2');
statement ok
insert into t0 values (103, 'val3');
+# statement error: Failed to validate query:
+statement error
+----
+insert into t0 (id, val, __part) values (104, 'val4', 1)
+
# statement error: Failed to validate query:
statement error
----
@@ -26,6 +31,21 @@ select * from t0
102 val2
103 val3
+query II rowsort
+select __part, id from t0
+----
+19 101
+17 102
+11 103
+
+query I rowsort
+select __part from t0
+----
+19
+17
+11
+
+# Select legacy partition system column
query II rowsort
select "__part", id from t0
----
@@ -40,6 +60,12 @@ select "__part" from t0
17
11
+query II rowsort
+select __part, "__part" id from t0
+----
+19 19
+17 17
+11 11
# Partition system column in WHERE
query IT
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 f187a47a049..a7425a02762 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
@@ -17,6 +17,7 @@
package org.apache.ignite.internal.sql.engine.exec;
+import it.unimi.dsi.fastutil.ints.Int2ObjectArrayMap;
import it.unimi.dsi.fastutil.ints.Int2ObjectMap;
import it.unimi.dsi.fastutil.ints.Int2ObjectMaps;
import java.util.BitSet;
@@ -37,7 +38,7 @@ public class TableRowConverterFactoryImpl implements TableRowConverterFactory {
private final SchemaDescriptor schemaDescriptor;
private final TableRowConverter fullRowConverter;
private final BitSet tableColumnSet;
- private IntFunction<VirtualColumn> virtualColumnFactory;
+ private final Int2ObjectArrayMap<IntFunction<VirtualColumn>> virtualColumnsFactory = new Int2ObjectArrayMap<>();
/**
* Creates a factory from given schema and indexes of primary key.
@@ -64,13 +65,20 @@ public class TableRowConverterFactoryImpl implements TableRowConverterFactory {
tableColumnSet = new BitSet();
tableColumnSet.set(0, tableDescriptor.columnsCount());
- ColumnDescriptor columnDescriptor = tableDescriptor.columnDescriptor(Commons.PART_COL_NAME);
-
- if (columnDescriptor != null) {
- assert columnDescriptor.virtual();
+ addVirtualColumn(tableDescriptor.columnDescriptor(Commons.PART_COL_NAME));
+ addVirtualColumn(tableDescriptor.columnDescriptor(Commons.PART_COL_NAME_LEGACY));
+ }
- virtualColumnFactory = (partId) -> new VirtualColumn(columnDescriptor.logicalIndex(), NativeTypes.INT32, false, partId);
+ private void addVirtualColumn(@Nullable ColumnDescriptor columnDescriptor) {
+ if (columnDescriptor == null) {
+ return;
}
+
+ assert columnDescriptor.virtual();
+
+ int columnIndex = columnDescriptor.logicalIndex();
+
+ virtualColumnsFactory.put(columnIndex, (partId) -> new VirtualColumn(columnIndex, NativeTypes.INT32, false, partId));
}
@Override
@@ -99,13 +107,21 @@ public class TableRowConverterFactoryImpl implements TableRowConverterFactory {
schemaRegistry,
schemaDescriptor,
requiredColumns,
- requireVirtualColumn ? createVirtualColumns(partId) : Int2ObjectMaps.emptyMap()
+ requireVirtualColumn ? createVirtualColumns(requiredColumns, partId) : Int2ObjectMaps.emptyMap()
);
}
- private Int2ObjectMap<VirtualColumn> createVirtualColumns(int partId) {
- VirtualColumn column = virtualColumnFactory.apply(partId);
+ private Int2ObjectMap<VirtualColumn> createVirtualColumns(BitSet requiredColumns, int partId) {
+ Int2ObjectMap<VirtualColumn> columnsMap = new Int2ObjectArrayMap<>(virtualColumnsFactory.size());
+
+ for (int i = requiredColumns.nextSetBit(schemaDescriptor.length()); i >= 0; i = requiredColumns.nextSetBit(i + 1)) {
+ columnsMap.put(i, virtualColumnsFactory.get(i).apply(partId));
+
+ if (i == Integer.MAX_VALUE) {
+ break; // Avoid overflow.
+ }
+ }
- return Int2ObjectMaps.singleton(column.columnIndex(), column);
+ return columnsMap;
}
}
diff --git a/modules/sql-engine/src/main/java/org/apache/ignite/internal/sql/engine/prepare/IgniteSqlValidator.java b/modules/sql-engine/src/main/java/org/apache/ignite/internal/sql/engine/prepare/IgniteSqlValidator.java
index cd7dc32fd07..c1fce8c4618 100644
--- a/modules/sql-engine/src/main/java/org/apache/ignite/internal/sql/engine/prepare/IgniteSqlValidator.java
+++ b/modules/sql-engine/src/main/java/org/apache/ignite/internal/sql/engine/prepare/IgniteSqlValidator.java
@@ -672,7 +672,7 @@ public class IgniteSqlValidator extends SqlValidatorImpl {
/** {@inheritDoc} */
@Override protected void addToSelectList(List<SqlNode> list, Set<String> aliases,
List<Map.Entry<String, RelDataType>> fieldList, SqlNode exp, SelectScope scope, boolean includeSystemVars) {
- if (includeSystemVars || exp.getKind() != SqlKind.IDENTIFIER || !isSystemFieldName(deriveAlias(exp, 0))) {
+ if (includeSystemVars || exp.getKind() != SqlKind.IDENTIFIER || !isSystemColumnName(deriveAlias(exp, 0))) {
super.addToSelectList(list, aliases, fieldList, exp, scope, includeSystemVars);
}
}
@@ -1289,9 +1289,11 @@ public class IgniteSqlValidator extends SqlValidatorImpl {
return (IgniteTypeFactory) typeFactory;
}
- public static boolean isSystemFieldName(String alias) {
+ /** Returns {@code true} if the given alias is a system column name, {@code false} otherwise. */
+ public static boolean isSystemColumnName(String alias) {
return (Commons.implicitPkEnabled() && Commons.IMPLICIT_PK_COL_NAME.equals(alias))
- || alias.equals(Commons.PART_COL_NAME);
+ || alias.equals(Commons.PART_COL_NAME)
+ || alias.equals(Commons.PART_COL_NAME_LEGACY);
}
// We use these scopes to filter out valid usages of a ROW operator.
@@ -1365,7 +1367,7 @@ public class IgniteSqlValidator extends SqlValidatorImpl {
if (call.getKind() == SqlKind.AS) {
String alias = deriveAlias(call, 0);
- if (isSystemFieldName(alias)) {
+ if (isSystemColumnName(alias)) {
throw newValidationError(call, IgniteResource.INSTANCE.illegalAlias(alias));
}
}
diff --git a/modules/sql-engine/src/main/java/org/apache/ignite/internal/sql/engine/prepare/ddl/DdlSqlToCommandConverter.java b/modules/sql-engine/src/main/java/org/apache/ignite/internal/sql/engine/prepare/ddl/DdlSqlToCommandConverter.java
index 84795431af7..cce60463dce 100644
--- a/modules/sql-engine/src/main/java/org/apache/ignite/internal/sql/engine/prepare/ddl/DdlSqlToCommandConverter.java
+++ b/modules/sql-engine/src/main/java/org/apache/ignite/internal/sql/engine/prepare/ddl/DdlSqlToCommandConverter.java
@@ -318,7 +318,7 @@ public class DdlSqlToCommandConverter {
if (sqlNode instanceof SqlColumnDeclaration) {
String colName = ((SqlColumnDeclaration) sqlNode).name.getSimple();
- if (IgniteSqlValidator.isSystemFieldName(colName)) {
+ if (IgniteSqlValidator.isSystemColumnName(colName)) {
throw new SqlException(STMT_VALIDATION_ERR, "Failed to validate query. "
+ "Column '" + colName + "' is reserved name.");
}
@@ -494,7 +494,7 @@ public class DdlSqlToCommandConverter {
Boolean nullable = col.dataType.getNullable();
String colName = col.name.getSimple();
- if (IgniteSqlValidator.isSystemFieldName(colName)) {
+ if (IgniteSqlValidator.isSystemColumnName(colName)) {
throw new SqlException(STMT_VALIDATION_ERR, "Failed to validate query. "
+ "Column '" + colName + "' is reserved name.");
}
diff --git a/modules/sql-engine/src/main/java/org/apache/ignite/internal/sql/engine/schema/SqlSchemaManagerImpl.java b/modules/sql-engine/src/main/java/org/apache/ignite/internal/sql/engine/schema/SqlSchemaManagerImpl.java
index 6fe85ed9155..4fc375227d6 100644
--- a/modules/sql-engine/src/main/java/org/apache/ignite/internal/sql/engine/schema/SqlSchemaManagerImpl.java
+++ b/modules/sql-engine/src/main/java/org/apache/ignite/internal/sql/engine/schema/SqlSchemaManagerImpl.java
@@ -281,7 +281,7 @@ public class SqlSchemaManagerImpl implements SqlSchemaManager {
private static TableDescriptor createTableDescriptorForTable(CatalogTableDescriptor descriptor) {
List<CatalogTableColumnDescriptor> columns = descriptor.columns();
- List<ColumnDescriptor> colDescriptors = new ArrayList<>(columns.size() + 1);
+ List<ColumnDescriptor> colDescriptors = new ArrayList<>(columns.size() + 2);
Object2IntMap<String> columnToIndex = buildColumnToIndexMap(columns);
for (int i = 0; i < columns.size(); i++) {
@@ -301,8 +301,8 @@ public class SqlSchemaManagerImpl implements SqlSchemaManager {
}
// Add virtual column.
- ColumnDescriptorImpl partVirtualColumn = createPartitionVirtualColumn(columns.size());
- colDescriptors.add(partVirtualColumn);
+ colDescriptors.add(createPartitionVirtualColumn(columns.size(), Commons.PART_COL_NAME));
+ colDescriptors.add(createPartitionVirtualColumn(columns.size() + 1, Commons.PART_COL_NAME_LEGACY));
IgniteDistribution distribution = createDistribution(descriptor, columnToIndex);
@@ -321,7 +321,7 @@ public class SqlSchemaManagerImpl implements SqlSchemaManager {
}
private static Object2IntMap<String> buildColumnToIndexMap(List<CatalogTableColumnDescriptor> columns) {
- Object2IntMap<String> columnToIndex = new Object2IntOpenHashMap<>(columns.size() + 1);
+ Object2IntMap<String> columnToIndex = new Object2IntOpenHashMap<>(columns.size() + 2);
for (int i = 0; i < columns.size(); i++) {
CatalogTableColumnDescriptor col = columns.get(i);
@@ -331,9 +331,9 @@ public class SqlSchemaManagerImpl implements SqlSchemaManager {
return columnToIndex;
}
- private static ColumnDescriptorImpl createPartitionVirtualColumn(int logicalIndex) {
+ private static ColumnDescriptorImpl createPartitionVirtualColumn(int logicalIndex, String partColName) {
return new ColumnDescriptorImpl(
- Commons.PART_COL_NAME,
+ partColName,
false,
true,
true,
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 1f8d2b49cef..6bee87dc25a 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
@@ -128,7 +128,9 @@ import org.jetbrains.annotations.TestOnly;
*/
public final class Commons {
public static final String IMPLICIT_PK_COL_NAME = "__p_key";
- public static final String PART_COL_NAME = "__part";
+ public static final String PART_COL_NAME = "__PART";
+ // Old name for partition column. Kept for backward compatibility.
+ public static final String PART_COL_NAME_LEGACY = "__part";
public static final int IN_BUFFER_SIZE = 512;
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 fb01f62fabf..4f186e351d3 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
@@ -1075,18 +1075,30 @@ public class TestBuilders {
TableDescriptorImpl tableDescriptor = new TableDescriptorImpl(CollectionUtils.concat(columns,
List.of(new ColumnDescriptorImpl(
- Commons.PART_COL_NAME,
- false,
- true,
- true,
- false,
- columns.size(),
- NativeTypes.INT32,
- DefaultValueStrategy.DEFAULT_COMPUTED,
- () -> {
- throw new AssertionError("Partition virtual column is generated by a function");
- }
- ))), distribution);
+ Commons.PART_COL_NAME,
+ false,
+ true,
+ true,
+ false,
+ columns.size(),
+ NativeTypes.INT32,
+ DefaultValueStrategy.DEFAULT_COMPUTED,
+ () -> {
+ throw new AssertionError("Partition virtual column is generated by a function");
+ }),
+ new ColumnDescriptorImpl(
+ Commons.PART_COL_NAME_LEGACY,
+ false,
+ true,
+ true,
+ false,
+ columns.size() + 1,
+ NativeTypes.INT32,
+ DefaultValueStrategy.DEFAULT_COMPUTED,
+ () -> {
+ throw new AssertionError("Partition virtual column is generated by a function");
+ }
+ ))), distribution);
Map<String, IgniteIndex> indexes = indexBuilders.stream()
.map(idx -> idx.build(tableDescriptor))
diff --git a/modules/sql-engine/src/test/java/org/apache/ignite/internal/sql/engine/util/QueryCheckerTest.java b/modules/sql-engine/src/test/java/org/apache/ignite/internal/sql/engine/util/QueryCheckerTest.java
index e805f1492b8..00f50fc318b 100644
--- a/modules/sql-engine/src/test/java/org/apache/ignite/internal/sql/engine/util/QueryCheckerTest.java
+++ b/modules/sql-engine/src/test/java/org/apache/ignite/internal/sql/engine/util/QueryCheckerTest.java
@@ -85,7 +85,7 @@ public class QueryCheckerTest extends BaseIgniteAbstractTest {
.mapToObj(i -> List.of("N1"))
.collect(Collectors.toList()));
CLUSTER.setDataProvider("T1", TestBuilders.tableScan(DataProvider.fromCollection(
- List.of(new Object[]{1, 1, 1}, new Object[]{2, 2, 1})
+ List.of(new Object[]{1, 1, 1, 1}, new Object[]{2, 2, 1, 1})
)));
}