[
https://issues.apache.org/jira/browse/IMPALA-15615?page=com.atlassian.jira.plugin.system.issuetabpanels:all-tabpanel
]
Arnab Karmakar resolved IMPALA-15615.
-------------------------------------
Fix Version/s: Impala 5.0.0
Resolution: Fixed
> Iceberg V3: ALTER TABLE ADD COLUMN(S) ... NOT NULL DEFAULT adds a nullable
> column
> ---------------------------------------------------------------------------------
>
> Key: IMPALA-15615
> URL: https://issues.apache.org/jira/browse/IMPALA-15615
> Project: IMPALA
> Issue Type: Bug
> Components: Catalog, Frontend
> Reporter: Zoltán Borók-Nagy
> Assignee: Arnab Karmakar
> Priority: Major
> Labels: impala-iceberg
> Fix For: Impala 5.0.0
>
>
> On Iceberg V3 tables, ALTER TABLE ... ADD COLUMN and ADD COLUMNS accept a NOT
> NULL column with a DEFAULT, but the new column is optional. NOT NULL is
> dropped without a warning: DESCRIBE shows the column as nullable, the Iceberg
> schema has "required":false, and NULL can be inserted into it.
> Repro on master:
> {code:sql}
> create table t (i int) stored by iceberg tblproperties('format-version'='3');
> insert into t values (1);
> alter table t add column c int not null default 7;
> alter table t add columns (d int not null default 8);
> describe t;
> {code}
> {noformat}
> name type comment nullable
> i int true
> c int true
> d int true
> {noformat}
> current-schema in DESCRIBE FORMATTED t (trimmed):
> {noformat}
> {\"id\":2,\"name\":\"c\",\"required\":false,\"type\":\"int\",\"initial-default\":7,\"write-default\":7},{\"id\":3,\"name\":\"d\",\"required\":false,\"type\":\"int\",\"initial-default\":8,\"write-default\":8}
> {noformat}
> {code:sql}
> insert into t (i, c, d) values (2, NULL, NULL);
> select i, c, d from t order by i;
> {code}
> {noformat}
> Modified 1 row(s) in 0.18s
> i c d
> 1 7 8
> 2 NULL NULL
> {noformat}
> Expected: c and d are required fields, and the INSERT fails. This is what
> happens when CREATE TABLE defines the same column:
> {code:sql}
> create table s (i int, c int not null default 7) stored by iceberg
> tblproperties('format-version'='3');
> describe s;
> insert into s (i, c) values (2, NULL);
> {code}
> {noformat}
> name type comment nullable
> i int true
> c int false
> ERROR: Query 884c335a4cc21f26:e8f205ea00000000 failed:
> Column 'c' is not nullable but during writing a Parquet page we found 1 null
> values.
> {noformat}
> (current-schema of s has {{"required":true}} for c.)
> *Analysis*
> AlterTableAddColsStmt passes NOT NULL to the catalog: ColumnDef.toThrift()
> sets TColumn.is_nullable to false. Since IMPALA-15364, analysis rejects a NOT
> NULL column without a DEFAULT ("A new non-null column must have a default
> value: ..."), and a DEFAULT needs 'format-version' >= 3. So a NOT NULL column
> reaches the catalog only on V3 tables, and always with a DEFAULT.
> CatalogOpExecutor.alterIcebergTable() then calls
> IcebergCatalogOpExecutor.addColumns(). That method ignores is_nullable and
> always calls UpdateSchema.addColumn(), with or without a default (the default
> branch came with IMPALA-14589), which adds an optional field. CREATE TABLE is
> not affected: IcebergSchemaConverter.createIcebergField() uses
> NestedField.required() when is_nullable is false.
> The IMPALA-15364 commit message suggests {{ALTER TABLE t ADD COLUMNS (j INT
> NOT NULL DEFAULT 0)}} on a V3 table as the way to add a NOT NULL column.
> Right now that statement adds a nullable column. The IMPALA-15364 tests cover
> only the case without a default, and no Iceberg test covers ADD COLUMN(S)
> with NOT NULL DEFAULT.
> *Suggested fix*
> In IcebergCatalogOpExecutor.addColumns(), call
> UpdateSchema.addRequiredColumn(name, type, doc, defaultValue) when
> column.isSetIs_nullable() && !column.isIs_nullable(), and keep addColumn()
> for the other columns. Analysis already guarantees that such a column has a
> default. With a default, Iceberg allows adding a required column without
> allowIncompatibleChanges(): in Iceberg 1.11.0, SchemaUpdate fails with
> "Incompatible change: cannot add required column without a default value"
> only when the default is null.
> *Testing*
> Add V3 end-to-end cases for ADD COLUMN and ADD COLUMNS with NOT NULL DEFAULT.
> They should check that DESCRIBE shows nullable false, old rows read the
> initial default, an INSERT that omits the column gets the write default, and
> an INSERT of NULL fails.
--
This message was sent by Atlassian Jira
(v10.3.26#10030026)