This is an automated email from the ASF dual-hosted git repository.
ppa 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 7495e1a044 IGNITE-23073 Sql. Support UUID default as cast from varchar
(#4463)
7495e1a044 is described below
commit 7495e1a044b1d34cc0039373339056e5f7b3bef1
Author: Pavel Pereslegin <[email protected]>
AuthorDate: Wed Oct 2 16:22:25 2024 +0300
IGNITE-23073 Sql. Support UUID default as cast from varchar (#4463)
---
.../internal/sql/engine/ItAlterTableDdlTest.java | 114 ++++++++++++++++++++-
.../sql/engine/schema/TableDescriptorImpl.java | 14 +++
2 files changed, 127 insertions(+), 1 deletion(-)
diff --git
a/modules/sql-engine/src/integrationTest/java/org/apache/ignite/internal/sql/engine/ItAlterTableDdlTest.java
b/modules/sql-engine/src/integrationTest/java/org/apache/ignite/internal/sql/engine/ItAlterTableDdlTest.java
index 9bbd1e98a8..1009b7743b 100644
---
a/modules/sql-engine/src/integrationTest/java/org/apache/ignite/internal/sql/engine/ItAlterTableDdlTest.java
+++
b/modules/sql-engine/src/integrationTest/java/org/apache/ignite/internal/sql/engine/ItAlterTableDdlTest.java
@@ -21,13 +21,17 @@ import static
org.apache.ignite.internal.lang.IgniteStringFormatter.format;
import static
org.apache.ignite.internal.sql.engine.util.SqlTestUtils.assertThrowsSqlException;
import static org.apache.ignite.lang.ErrorGroups.Sql.STMT_PARSE_ERR;
import static org.hamcrest.MatcherAssert.assertThat;
+import static org.hamcrest.Matchers.equalTo;
import static org.hamcrest.Matchers.is;
+import static org.junit.jupiter.api.Assertions.assertNotNull;
+import static org.junit.jupiter.api.Assertions.assertNull;
import java.time.LocalDate;
import java.time.LocalDateTime;
import java.time.LocalTime;
import java.time.Month;
import java.util.List;
+import java.util.UUID;
import org.apache.calcite.rel.type.RelDataType;
import org.apache.ignite.internal.lang.IgniteStringBuilder;
import org.apache.ignite.internal.schema.SchemaTestUtils;
@@ -35,6 +39,11 @@ import org.apache.ignite.internal.sql.BaseSqlIntegrationTest;
import org.apache.ignite.internal.sql.engine.util.Commons;
import org.apache.ignite.internal.sql.engine.util.TypeUtils;
import org.apache.ignite.internal.type.NativeType;
+import org.apache.ignite.lang.ErrorGroups.Sql;
+import org.apache.ignite.lang.NullableValue;
+import org.apache.ignite.table.KeyValueView;
+import org.apache.ignite.table.RecordView;
+import org.apache.ignite.table.Tuple;
import org.junit.jupiter.api.AfterEach;
import org.junit.jupiter.api.Test;
@@ -195,6 +204,7 @@ public class ItAlterTableDdlTest extends
BaseSqlIntegrationTest {
sql("ALTER TABLE test ADD COLUMN valts TIMESTAMP(3) DEFAULT TIMESTAMP
'2001-12-21 11:22:33.444555'");
sql("ALTER TABLE test ADD COLUMN valstr VARCHAR DEFAULT 'string'");
sql("ALTER TABLE test ADD COLUMN valbin VARBINARY DEFAULT x'ff'");
+ sql("ALTER TABLE test ADD COLUMN valuuid UUID DEFAULT
'00000000-0000-0000-0000-000000000000'");
sql("INSERT INTO test (id) VALUES (0)");
@@ -205,7 +215,8 @@ public class ItAlterTableDdlTest extends
BaseSqlIntegrationTest {
LocalTime.of(11, 22, 33, 444000000),
LocalDateTime.of(2001, Month.DECEMBER, 21, 11, 22, 33,
444000000),
"string",
- new byte[]{(byte) 0xff}
+ new byte[]{(byte) 0xff},
+ UUID.fromString("00000000-0000-0000-0000-000000000000")
)
.check();
}
@@ -222,4 +233,105 @@ public class ItAlterTableDdlTest extends
BaseSqlIntegrationTest {
() -> sql("ALTER TABLE t ADD COLUMN val2 VARCHAR DEFAULT
rand_uuid")
);
}
+
+ @Test
+ public void uuidDefault() {
+ UUID defaultUuid = UUID.randomUUID();
+ sql("CREATE TABLE test(id INT PRIMARY KEY)");
+
+ RecordView<Tuple> recView =
CLUSTER.aliveNode().tables().table("test").recordView();
+ KeyValueView<Tuple, Tuple> kvBinaryView =
CLUSTER.aliveNode().tables().table("test").keyValueView();
+ KeyValueView<Integer, UUID> kvView =
CLUSTER.aliveNode().tables().table("test").keyValueView(Integer.class,
UUID.class);
+
+ // Ensure that invalid UUIDs are rejected.
+ {
+ //noinspection ThrowableNotThrown
+ assertThrowsSqlException(
+ Sql.STMT_VALIDATION_ERR,
+ "Invalid default value for column 'VAL'",
+ () -> sql("ALTER TABLE test ADD COLUMN (val UUID DEFAULT
'00000000-0000-0000-0000-')")
+ );
+
+ //noinspection ThrowableNotThrown
+ assertThrowsSqlException(
+ Sql.STMT_VALIDATION_ERR,
+ "Invalid default value for column 'VAL'",
+ () -> sql("ALTER TABLE test ADD COLUMN (val UUID DEFAULT
911)")
+ );
+ }
+
+ // Add column with UUID default value.
+ sql(format("ALTER TABLE test ADD COLUMN (val UUID DEFAULT '{}')",
defaultUuid));
+
+ // Put some data.
+ sql("INSERT INTO test VALUES (1, DEFAULT), (2, DEFAULT)");
+ sql("INSERT INTO test (id) VALUES (3)");
+ recView.upsert(null, Tuple.create().set("id", 4));
+ kvBinaryView.put(null, Tuple.create().set("id", 5), Tuple.create());
+ sql("INSERT INTO test VALUES (6, NULL)");
+ kvView.put(null, 7, null);
+
+ // Verify UUID value using SQL.
+ {
+ assertQuery("SELECT id, val FROM test ORDER BY id")
+ .returns(1, defaultUuid)
+ .returns(2, defaultUuid)
+ .returns(3, defaultUuid)
+ .returns(4, defaultUuid)
+ .returns(5, defaultUuid)
+ .returns(6, null)
+ .returns(7, null)
+ .check();
+ }
+
+ // Verify UUID values using record and key-value view.
+ {
+ List<Integer> ids = List.of(1, 2, 3, 4, 5);
+
+ ids.forEach(id -> {
+ Tuple record = recView.get(null, Tuple.create().set("id", id));
+ assertThat("id=" + id, record.uuidValue("val"),
equalTo(defaultUuid));
+
+ Tuple row = kvBinaryView.get(null, Tuple.create().set("id",
id));
+ assertNotNull(row);
+ assertThat("id=" + id, row.uuidValue("val"),
equalTo(defaultUuid));
+
+ UUID val = kvView.get(null, id);
+ assertThat("id=" + id, val, equalTo(defaultUuid));
+ });
+
+ List<Integer> nullIds = List.of(6, 7);
+
+ nullIds.forEach(id -> {
+ Tuple record = recView.get(null, Tuple.create().set("id", id));
+ assertNull(record.uuidValue("val"), "id=" + id);
+
+ Tuple row = kvBinaryView.get(null, Tuple.create().set("id",
id));
+ assertNotNull(row);
+ assertNull(row.uuidValue("val"), "id=" + id);
+
+ NullableValue<UUID> val = kvView.getNullable(null, id);
+ assertNotNull(val, "id=" + id);
+ assertNull(val.get());
+ });
+ }
+
+ // Verify NULL as default value.
+ {
+ sql("ALTER TABLE test ALTER COLUMN val SET DEFAULT NULL");
+ sql("INSERT INTO test VALUES (8, DEFAULT)");
+ sql("INSERT INTO test (id) VALUES (9)");
+ assertQuery("SELECT id, val FROM test ORDER BY id")
+ .returns(1, defaultUuid)
+ .returns(2, defaultUuid)
+ .returns(3, defaultUuid)
+ .returns(4, defaultUuid)
+ .returns(5, defaultUuid)
+ .returns(6, null)
+ .returns(7, null)
+ .returns(8, null)
+ .returns(9, null)
+ .check();
+ }
+ }
}
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 a789665403..d50ffa413d 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
@@ -24,6 +24,7 @@ import java.util.Arrays;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
+import java.util.UUID;
import org.apache.calcite.plan.RelOptTable;
import org.apache.calcite.rel.type.RelDataType;
import org.apache.calcite.rel.type.RelDataTypeFactory;
@@ -31,12 +32,14 @@ import
org.apache.calcite.rel.type.RelDataTypeFactory.Builder;
import org.apache.calcite.rel.type.RelDataTypeField;
import org.apache.calcite.rex.RexNode;
import org.apache.calcite.schema.ColumnStrategy;
+import org.apache.calcite.sql.type.SqlTypeName;
import org.apache.calcite.sql2rel.InitializerContext;
import org.apache.calcite.sql2rel.NullInitializerExpressionFactory;
import org.apache.calcite.util.ImmutableBitSet;
import org.apache.ignite.internal.sql.engine.sql.fun.IgniteSqlOperatorTable;
import org.apache.ignite.internal.sql.engine.trait.IgniteDistribution;
import org.apache.ignite.internal.sql.engine.type.IgniteTypeFactory;
+import org.apache.ignite.internal.sql.engine.type.UuidType;
import org.apache.ignite.internal.sql.engine.util.Commons;
import org.apache.ignite.internal.sql.engine.util.TypeUtils;
import org.jetbrains.annotations.Nullable;
@@ -132,6 +135,17 @@ public class TableDescriptorImpl extends
NullInitializerExpressionFactory implem
Object internalValue = TypeUtils.toInternal(defaultVal,
storageType);
RelDataType relDataType =
deriveLogicalType(rexBuilder.getTypeFactory(), descriptor);
+ // UUID literals are not supported, so we replace it with
CAST(uuid.toString() AS UUID)
+ if (internalValue != null && relDataType instanceof UuidType) {
+ assert internalValue instanceof UUID;
+
+ RelDataType charType =
rexBuilder.getTypeFactory().createSqlType(SqlTypeName.VARCHAR);
+
+ RexNode literal =
rexBuilder.makeLiteral(internalValue.toString(), charType, false);
+
+ return rexBuilder.makeCast(relDataType, literal);
+ }
+
return rexBuilder.makeLiteral(internalValue, relDataType,
false);
}
case DEFAULT_COMPUTED: {