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

korlov 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 50ad9453c8 IGNITE-20905 Make it possible to add an explicitly NULL 
column via ADD COLUMN
50ad9453c8 is described below

commit 50ad9453c81b00147393e06e66d624a53aa46d93
Author: Max Zhuravkov <shh...@gmail.com>
AuthorDate: Wed Jan 10 14:53:52 2024 +0200

    IGNITE-20905 Make it possible to add an explicitly NULL column via ADD 
COLUMN
---
 .../internal/sql/engine/ItCreateTableDdlTest.java  | 14 +++++
 .../src/main/codegen/includes/parserImpls.ftl      |  4 ++
 .../prepare/ddl/DdlSqlToCommandConverter.java      |  3 +-
 .../internal/sql/engine/sql/SqlDdlParserTest.java  | 59 ++++++++++++++++++++++
 4 files changed, 79 insertions(+), 1 deletion(-)

diff --git 
a/modules/sql-engine/src/integrationTest/java/org/apache/ignite/internal/sql/engine/ItCreateTableDdlTest.java
 
b/modules/sql-engine/src/integrationTest/java/org/apache/ignite/internal/sql/engine/ItCreateTableDdlTest.java
index 0f7ed762e5..f2548291cf 100644
--- 
a/modules/sql-engine/src/integrationTest/java/org/apache/ignite/internal/sql/engine/ItCreateTableDdlTest.java
+++ 
b/modules/sql-engine/src/integrationTest/java/org/apache/ignite/internal/sql/engine/ItCreateTableDdlTest.java
@@ -199,6 +199,20 @@ public class ItCreateTableDdlTest extends 
BaseSqlIntegrationTest {
                 .check();
     }
 
+    /** Test that adding nullable column via ALTER TABLE ADD name type NULL 
works. */
+    @Test
+    public void testNullableColumn() {
+        sql("CREATE TABLE my (c1 INT PRIMARY KEY, c2 INT)");
+        sql("INSERT INTO my VALUES (1, 1)");
+        sql("ALTER TABLE my ADD COLUMN c3 INT NULL");
+        sql("INSERT INTO my VALUES (2, 2, NULL)");
+
+        assertQuery("SELECT * FROM my ORDER by c1 ASC")
+                .returns(1, 1, null)
+                .returns(2, 2, null)
+                .check();
+    }
+
     /**
      * Adds columns of all supported types and checks that the row
      * created on the old schema version is read correctly.
diff --git a/modules/sql-engine/src/main/codegen/includes/parserImpls.ftl 
b/modules/sql-engine/src/main/codegen/includes/parserImpls.ftl
index ba18c9c40b..933c8c4789 100644
--- a/modules/sql-engine/src/main/codegen/includes/parserImpls.ftl
+++ b/modules/sql-engine/src/main/codegen/includes/parserImpls.ftl
@@ -378,6 +378,10 @@ SqlNode ColumnWithType() :
         <NOT> <NULL> {
             nullable = false;
         }
+        |
+        <NULL> {
+            nullable = true;
+        }
     ]
     (
         <DEFAULT_> { s.add(this); } dflt = Literal() {
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 8455b69071..2e226debb0 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
@@ -390,7 +390,8 @@ public class DdlSqlToCommandConverter {
 
             assert col.name.isSimple();
 
-            RelDataType relType = ctx.planner().convert(col.dataType, true);
+            Boolean nullable = col.dataType.getNullable();
+            RelDataType relType = ctx.planner().convert(col.dataType, nullable 
!= null ? nullable : true);
             DefaultValueDefinition dflt = convertDefault(col.expression, 
relType);
 
             String name = col.name.getSimple();
diff --git 
a/modules/sql-engine/src/test/java/org/apache/ignite/internal/sql/engine/sql/SqlDdlParserTest.java
 
b/modules/sql-engine/src/test/java/org/apache/ignite/internal/sql/engine/sql/SqlDdlParserTest.java
index 340d00ab43..8c07f714ab 100644
--- 
a/modules/sql-engine/src/test/java/org/apache/ignite/internal/sql/engine/sql/SqlDdlParserTest.java
+++ 
b/modules/sql-engine/src/test/java/org/apache/ignite/internal/sql/engine/sql/SqlDdlParserTest.java
@@ -24,6 +24,8 @@ import static org.hamcrest.CoreMatchers.instanceOf;
 import static org.hamcrest.CoreMatchers.is;
 import static org.hamcrest.MatcherAssert.assertThat;
 import static org.hamcrest.Matchers.equalTo;
+import static org.hamcrest.Matchers.nullValue;
+import static org.junit.jupiter.api.Assertions.assertInstanceOf;
 import static org.junit.jupiter.api.Assertions.assertNull;
 
 import java.util.List;
@@ -31,6 +33,7 @@ import java.util.Objects;
 import java.util.Set;
 import java.util.function.Consumer;
 import java.util.stream.Collectors;
+import org.apache.calcite.schema.ColumnStrategy;
 import org.apache.calcite.sql.SqlBasicCall;
 import org.apache.calcite.sql.SqlIdentifier;
 import org.apache.calcite.sql.SqlKind;
@@ -650,6 +653,51 @@ public class SqlDdlParserTest extends 
AbstractDdlParserTest {
         return (IgniteSqlCreateTable) node;
     }
 
+    @Test
+    public void alterTableAddColumn() {
+        SqlNode sqlNode = parse("ALTER TABLE t ADD COLUMN c INT");
+
+        IgniteSqlAlterTableAddColumn addColumn = 
assertInstanceOf(IgniteSqlAlterTableAddColumn.class, sqlNode);
+        SqlColumnDeclaration declaration = (SqlColumnDeclaration) 
addColumn.columns().get(0);
+
+        assertThat(addColumn.name.names, is(List.of("T")));
+
+        expectColumnBasic(declaration, "C", ColumnStrategy.NULLABLE, 
"INTEGER", true);
+        assertThat(declaration.expression, is(nullValue()));
+
+        expectUnparsed(addColumn, "ALTER TABLE \"T\" ADD COLUMN \"C\" 
INTEGER");
+    }
+
+    @Test
+    public void alterTableAddColumnNull() {
+        SqlNode sqlNode = parse("ALTER TABLE t ADD COLUMN c INT NULL");
+
+        IgniteSqlAlterTableAddColumn addColumn = 
assertInstanceOf(IgniteSqlAlterTableAddColumn.class, sqlNode);
+        SqlColumnDeclaration column = (SqlColumnDeclaration) 
addColumn.columns().get(0);
+
+        assertThat(addColumn.name.names, is(List.of("T")));
+
+        expectColumnBasic(column, "C", ColumnStrategy.NULLABLE, "INTEGER", 
true);
+        assertThat(column.expression, is(nullValue()));
+
+        expectUnparsed(addColumn, "ALTER TABLE \"T\" ADD COLUMN \"C\" 
INTEGER");
+    }
+
+    @Test
+    public void alterTableAddColumnNotNull() {
+        SqlNode sqlNode = parse("ALTER TABLE t ADD COLUMN c INT NOT NULL");
+
+        IgniteSqlAlterTableAddColumn addColumn = 
assertInstanceOf(IgniteSqlAlterTableAddColumn.class, sqlNode);
+        SqlColumnDeclaration column = (SqlColumnDeclaration) 
addColumn.columns().get(0);
+
+        assertThat(addColumn.name.names, is(List.of("T")));
+
+        expectColumnBasic(column, "C", ColumnStrategy.NOT_NULLABLE, "INTEGER", 
false);
+        assertThat(column.expression, is(nullValue()));
+
+        expectUnparsed(addColumn, "ALTER TABLE \"T\" ADD COLUMN \"C\" INTEGER 
NOT NULL");
+    }
+
     /**
      * Matcher to verify name in the column declaration.
      *
@@ -667,6 +715,17 @@ public class SqlDdlParserTest extends 
AbstractDdlParserTest {
         };
     }
 
+    /** Checks basic column properties such as name, type name and type's 
nullability. */
+    private static void expectColumnBasic(SqlColumnDeclaration declaration,
+            String columnName, ColumnStrategy columnStrategy,
+            String typeName, Boolean nullable) {
+
+        assertThat(List.of(columnName), is(declaration.name.names));
+        assertThat(columnStrategy, is(declaration.strategy));
+        assertThat(List.of(typeName), 
is(declaration.dataType.getTypeName().names));
+        assertThat(nullable, is(declaration.dataType.getNullable()));
+    }
+
     private void assertThatOptionPresent(List<SqlNode> optionList, String 
option, Object expVal) {
         assertThat(optionList, hasItem(ofTypeMatching(
                 option + "=" + expVal,

Reply via email to