Skip to content

Commit 5aac329

Browse files
craig[bot]fqazi
andcommitted
Merge #148038
148038: sql/schemachanger: add support for DROP NOT NULL r=fqazi a=fqazi Previously, ALTER TABLE ... ALTER COLUMN ... DROP NOT NULL was only supported in the legacy schema changer. This patch adds support for dropping not null constraints in the declarative schema changer. Fixes: #139602 Release note: None Co-authored-by: Faizan Qazi <[email protected]>
2 parents 603ca22 + 20f6b6b commit 5aac329

File tree

14 files changed

+457
-8
lines changed

14 files changed

+457
-8
lines changed

pkg/ccl/logictestccl/testdata/logic_test/redact_descriptor

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -47,6 +47,7 @@ CREATE VIEW redacted_descriptors AS
4747
# descriptor. We will skip the config that uses legacy schema changer.
4848
skipif config local-schema-locked
4949
skipif config local-legacy-schema-changer
50+
skipif config local-mixed-25.2
5051
query T
5152
SELECT descriptor from redacted_descriptors where id = 'collate_partition'::REGCLASS;
5253
----

pkg/ccl/schemachangerccl/sctestbackupccl/backup_base_generated_test.go

Lines changed: 28 additions & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

pkg/cmd/roachtest/tests/django_blocklist.go

Lines changed: 0 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -158,9 +158,6 @@ var enabledDjangoTests = []string{
158158

159159
// Maintain that this list is alphabetized.
160160
var djangoBlocklist = blocklist{
161-
// Schema change used by this test:
162-
// ALTER TABLE schema_author ALTER COLUMN name SET DATA TYPE STRING, ALTER COLUMN name DROP NOT NULL
163-
`schema.tests.SchemaTests.test_alter`: "ALTER COLUMN ... DROP NOT NULL is not supported in declarative schema changer (prevents from working with schema_locked)",
164161
`schema.tests.SchemaTests.test_alter_text_field_to_date_field`: "alter type requires USING",
165162
`schema.tests.SchemaTests.test_alter_text_field_to_datetime_field`: "alter type requires USING",
166163
`schema.tests.SchemaTests.test_alter_text_field_to_time_field`: "alter type requires USING",

pkg/sql/schemachanger/scbuild/internal/scbuildstmt/BUILD.bazel

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@ go_library(
77
"alter_table.go",
88
"alter_table_add_column.go",
99
"alter_table_add_constraint.go",
10+
"alter_table_alter_column_drop_not_null.go",
1011
"alter_table_alter_column_set_default.go",
1112
"alter_table_alter_column_set_not_null.go",
1213
"alter_table_alter_column_type.go",

pkg/sql/schemachanger/scbuild/internal/scbuildstmt/alter_table.go

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -40,6 +40,7 @@ var supportedAlterTableStatements = map[reflect.Type]supportedAlterTableCommand{
4040
reflect.TypeOf((*tree.AlterTableSetDefault)(nil)): {fn: alterTableSetDefault, on: true, checks: nil},
4141
reflect.TypeOf((*tree.AlterTableAlterColumnType)(nil)): {fn: alterTableAlterColumnType, on: true, checks: nil},
4242
reflect.TypeOf((*tree.AlterTableSetRLSMode)(nil)): {fn: alterTableSetRLSMode, on: true, checks: isV252Active},
43+
reflect.TypeOf((*tree.AlterTableDropNotNull)(nil)): {fn: alterTableDropNotNull, on: true, checks: isV253Active},
4344
}
4445

4546
func init() {
Lines changed: 45 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,45 @@
1+
// Copyright 2025 The Cockroach Authors.
2+
//
3+
// Use of this software is governed by the CockroachDB Software License
4+
// included in the /LICENSE file.
5+
6+
package scbuildstmt
7+
8+
import (
9+
"github.com/cockroachdb/cockroach/pkg/sql/pgwire/pgcode"
10+
"github.com/cockroachdb/cockroach/pkg/sql/pgwire/pgerror"
11+
"github.com/cockroachdb/cockroach/pkg/sql/schemachanger/scpb"
12+
"github.com/cockroachdb/cockroach/pkg/sql/sem/tree"
13+
)
14+
15+
func alterTableDropNotNull(
16+
b BuildCtx,
17+
tn *tree.TableName,
18+
tbl *scpb.Table,
19+
stmt tree.Statement,
20+
t *tree.AlterTableDropNotNull,
21+
) {
22+
alterColumnPreChecks(b, tn, tbl, t.Column)
23+
columnID := getColumnIDFromColumnName(b, tbl.TableID, t.Column, true /*required */)
24+
// Block alters on system columns.
25+
panicIfSystemColumn(mustRetrieveColumnElem(b, tbl.TableID, columnID), t.Column.String())
26+
// Ensure that this column is not in the primary indexes key.
27+
primaryIdx := getLatestPrimaryIndex(b, tbl.TableID)
28+
idxColumns := mustRetrieveIndexColumnElements(b, tbl.TableID, primaryIdx.IndexID)
29+
for _, idxCol := range idxColumns {
30+
if idxCol.ColumnID != columnID ||
31+
idxCol.Kind != scpb.IndexColumn_KEY {
32+
continue
33+
}
34+
colName := mustRetrieveColumnName(b, tbl.TableID, columnID)
35+
panic(pgerror.Newf(pgcode.InvalidTableDefinition,
36+
`column "%s" is in a primary index`, colName.Name))
37+
}
38+
columNotNull := b.QueryByID(tbl.TableID).FilterColumnNotNull().Filter(func(current scpb.Status, target scpb.TargetStatus, e *scpb.ColumnNotNull) bool {
39+
return e.ColumnID == columnID
40+
}).MustGetZeroOrOneElement()
41+
if columNotNull == nil {
42+
return
43+
}
44+
b.Drop(columNotNull)
45+
}

pkg/sql/schemachanger/scbuild/internal/scbuildstmt/process.go

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -217,3 +217,7 @@ var isV251Active = func(_ tree.NodeFormatter, _ sessiondatapb.NewSchemaChangerMo
217217
var isV252Active = func(_ tree.NodeFormatter, _ sessiondatapb.NewSchemaChangerMode, activeVersion clusterversion.ClusterVersion) bool {
218218
return activeVersion.IsActive(clusterversion.V25_2)
219219
}
220+
221+
var isV253Active = func(_ tree.NodeFormatter, _ sessiondatapb.NewSchemaChangerMode, activeVersion clusterversion.ClusterVersion) bool {
222+
return activeVersion.IsActive(clusterversion.V25_3)
223+
}

pkg/sql/schemachanger/scbuild/testdata/unimplemented_alter_table

Lines changed: 0 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -12,10 +12,6 @@ CREATE TABLE defaultdb.foo (
1212
);
1313
----
1414

15-
unimplemented
16-
ALTER TABLE defaultdb.foo ALTER COLUMN i DROP NOT NULL
17-
----
18-
1915
unimplemented
2016
ALTER TABLE defaultdb.foo ALTER COLUMN i DROP STORED
2117
----

pkg/sql/schemachanger/sctest_generated_test.go

Lines changed: 42 additions & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.
Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,28 @@
1+
setup
2+
CREATE TABLE t (i INT PRIMARY KEY, j INT NOT NULL);
3+
----
4+
5+
# Ensure that inserts with non-null values will succeed.
6+
stage-exec phase=PostCommitNonRevertiblePhase stage=:
7+
INSERT INTO t VALUES ($stageKey, $stageKey);
8+
DELETE FROM t WHERE j = $stageKey;
9+
INSERT INTO t VALUES ($stageKey, $stageKey);
10+
UPDATE t SET j = j + 1;
11+
----
12+
13+
# Validate the not null constraint is enforced initially
14+
stage-exec phase=PostCommitNonRevertiblePhase stage=1
15+
INSERT INTO t(i) VALUES(-1)
16+
----
17+
pq: failed to satisfy CHECK constraint .*
18+
19+
20+
# One row is expected to be added after each stage.
21+
stage-query phase=PostCommitNonRevertiblePhase stage=:
22+
SELECT count(*)=$successfulStageCount FROM t;
23+
----
24+
true
25+
26+
test
27+
ALTER TABLE t ALTER COLUMN j DROP NOT NULL
28+
----

0 commit comments

Comments
 (0)