This is an automated email from the ASF dual-hosted git repository.
alexpl pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/ignite.git
The following commit(s) were added to refs/heads/master by this push:
new 149e094ffac IGNITE-20353 SQL Calcite: Fix CREATE TABLE ... WITH
affinity_key option validation - Fixes #10925.
149e094ffac is described below
commit 149e094ffac37bf4a42e4a62f6eac98185a9857b
Author: Aleksey Plekhanov <[email protected]>
AuthorDate: Thu Sep 14 12:28:54 2023 +0300
IGNITE-20353 SQL Calcite: Fix CREATE TABLE ... WITH affinity_key option
validation - Fixes #10925.
Signed-off-by: Aleksey Plekhanov <[email protected]>
---
.../prepare/ddl/DdlSqlToCommandConverter.java | 46 +++++++++++++++
.../integration/TableDdlIntegrationTest.java | 66 +++++++++++++++++++++-
2 files changed, 111 insertions(+), 1 deletion(-)
diff --git
a/modules/calcite/src/main/java/org/apache/ignite/internal/processors/query/calcite/prepare/ddl/DdlSqlToCommandConverter.java
b/modules/calcite/src/main/java/org/apache/ignite/internal/processors/query/calcite/prepare/ddl/DdlSqlToCommandConverter.java
index 1c8121445ff..c2c4f521d14 100644
---
a/modules/calcite/src/main/java/org/apache/ignite/internal/processors/query/calcite/prepare/ddl/DdlSqlToCommandConverter.java
+++
b/modules/calcite/src/main/java/org/apache/ignite/internal/processors/query/calcite/prepare/ddl/DdlSqlToCommandConverter.java
@@ -316,6 +316,52 @@ public class DdlSqlToCommandConverter {
IgniteQueryErrorCode.PARSING);
}
+ // Validate affinity key.
+ if (createTblCmd.affinityKey() != null) {
+ String affColName = null;
+ String val = createTblCmd.affinityKey();
+
+ if (val.startsWith("'")) {
+ if (val.length() == 1 || !val.endsWith("'")) {
+ throw new IgniteSQLException("Affinity key column name
does not have trailing quote: " + val,
+ IgniteQueryErrorCode.PARSING);
+ }
+
+ val = val.substring(1, val.length() - 1);
+
+ if (F.isEmpty(val))
+ throw new IgniteSQLException("Affinity key cannot be
empty", IgniteQueryErrorCode.PARSING);
+
+ affColName = val;
+ }
+ else {
+ for (ColumnDefinition col : createTblCmd.columns()) {
+ if (col.name().equalsIgnoreCase(val)) {
+ if (affColName != null) {
+ throw new IgniteSQLException("Ambiguous affinity
column name, use single quotes " +
+ "for case sensitivity: " + val,
IgniteQueryErrorCode.PARSING);
+ }
+
+ affColName = col.name();
+ }
+ }
+ }
+
+ String affColFinal = affColName;
+
+ if (affColName == null ||
createTblCmd.columns().stream().noneMatch(col ->
affColFinal.equals(col.name()))) {
+ throw new IgniteSQLException("Affinity key column with given
name not found: " + val,
+ IgniteQueryErrorCode.PARSING);
+ }
+
+ if (!createTblCmd.primaryKeyColumns().contains(affColName)) {
+ throw new IgniteSQLException("Affinity key column must be one
of key columns: " + affColName,
+ IgniteQueryErrorCode.PARSING);
+ }
+
+ createTblCmd.affinityKey(affColName);
+ }
+
return createTblCmd;
}
diff --git
a/modules/calcite/src/test/java/org/apache/ignite/internal/processors/query/calcite/integration/TableDdlIntegrationTest.java
b/modules/calcite/src/test/java/org/apache/ignite/internal/processors/query/calcite/integration/TableDdlIntegrationTest.java
index dc51b74eb75..f385132a7ca 100644
---
a/modules/calcite/src/test/java/org/apache/ignite/internal/processors/query/calcite/integration/TableDdlIntegrationTest.java
+++
b/modules/calcite/src/test/java/org/apache/ignite/internal/processors/query/calcite/integration/TableDdlIntegrationTest.java
@@ -37,7 +37,10 @@ import org.apache.ignite.configuration.CacheConfiguration;
import org.apache.ignite.internal.processors.cache.IgniteInternalCache;
import org.apache.ignite.internal.processors.query.IgniteSQLException;
import org.apache.ignite.internal.processors.query.QueryUtils;
+import
org.apache.ignite.internal.processors.query.calcite.CalciteQueryProcessor;
import org.apache.ignite.internal.processors.query.calcite.QueryChecker;
+import org.apache.ignite.internal.processors.query.calcite.schema.IgniteTable;
+import
org.apache.ignite.internal.processors.query.calcite.trait.IgniteDistribution;
import org.apache.ignite.internal.util.typedef.F;
import org.apache.ignite.testframework.GridTestUtils;
import org.hamcrest.CustomMatcher;
@@ -229,7 +232,7 @@ public class TableDdlIntegrationTest extends
AbstractDdlIntegrationTest {
assertThat(ccfg.getGroupName(), equalTo("my_cache_group"));
assertThat(ccfg.getName(), equalTo("my_cache_name"));
assertThat(ccfg.getDataRegionName(), equalTo(DATA_REGION_NAME));
- assertThat(ccfg.getKeyConfiguration()[0].getAffinityKeyFieldName(),
equalTo("id2"));
+ assertThat(ccfg.getKeyConfiguration()[0].getAffinityKeyFieldName(),
equalTo("ID2"));
QueryEntity ent = ccfg.getQueryEntities().iterator().next();
@@ -267,6 +270,67 @@ public class TableDdlIntegrationTest extends
AbstractDdlIntegrationTest {
ccfg -> "PART".equals(ccfg.getName()) && ccfg.getCacheMode() ==
CacheMode.PARTITIONED)));
}
+ /**
+ * Creates table with affinity key.
+ */
+ @Test
+ public void createTableWithAffinity() {
+ assertThrows("create table TBL0 (id1 int, id2 int, val varchar,
primary key(id1, id2)) with " +
+ "\"affinity_key=''\"", IgniteSQLException.class, "Affinity key
cannot be empty");
+
+ assertThrows("create table TBL0 (id1 int, id2 int, val varchar,
primary key(id1, id2)) with " +
+ "\"affinity_key='id\"", IgniteSQLException.class, "Affinity key
column name does not have trailing quote");
+
+ assertThrows("create table TBL0 (id1 int, id2 int, val varchar,
primary key(id1, id2)) with " +
+ "affinity_key=\"id3\"", IgniteSQLException.class, "Affinity key
column with given name not found: id3");
+
+ assertThrows("create table TBL0 (id1 int, id2 int, val varchar,
primary key(id1, id2)) with " +
+ "affinity_key=val", IgniteSQLException.class, "Affinity key column
must be one of key columns: VAL");
+
+ // Wrong case of quoted 'id1'.
+ assertThrows("create table TBL0 (id1 int, id2 int, val varchar,
primary key(id1, id2)) with " +
+ "\"affinity_key='id1'\"", IgniteSQLException.class, "Affinity key
column with given name not found: id1");
+
+ assertThrows("create table TBL0 (\"id\" int, \"iD\" int, val varchar,
primary key(\"id\", \"iD\")) with " +
+ " \"affinity_key=id\"", IgniteSQLException.class, "Ambiguous
affinity column name");
+
+ sql("create table TBL1 (id1 int, id2 int, val varchar, primary
key(id1, id2)) with " +
+ " affinity_key=id1");
+
+ checkAffinity("TBL1", "ID1");
+
+ sql("create table TBL2 (\"id1\" int, id2 int, val varchar, primary
key(\"id1\", id2)) with " +
+ " affinity_key=\"id1\"");
+
+ checkAffinity("TBL2", "id1");
+
+ sql("create table TBL3 (\"id1\" int, id2 int, val varchar, primary
key(\"id1\", id2)) with " +
+ " \"affinity_key='id1'\"");
+
+ checkAffinity("TBL3", "id1");
+
+ sql("create table TBL4 (id1 int, \"iD2\" int, val varchar, primary
key(id1, \"iD2\")) with " +
+ " affinity_key=id2");
+
+ checkAffinity("TBL4", "iD2");
+
+ sql("create table TBL5 (\"id\" int, \"iD\" int, val varchar, primary
key(\"id\", \"iD\")) with " +
+ " \"affinity_key='iD'\"");
+
+ checkAffinity("TBL5", "iD");
+ }
+
+ /** */
+ private void checkAffinity(String tableName, String affCol) {
+ CalciteQueryProcessor proc = queryProcessor(client);
+
+ IgniteTable tbl =
(IgniteTable)proc.schemaHolder().schema(QueryUtils.DFLT_SCHEMA).getTable(tableName);
+ IgniteDistribution distr = tbl.distribution();
+
+ assertEquals(1, distr.getKeys().size());
+ assertEquals(tbl.descriptor().columnDescriptor(affCol).fieldIndex(),
(int)distr.getKeys().get(0));
+ }
+
/**
* Tries to create several tables with the same name.
*/