Skip to content

Commit dbb0574

Browse files
committed
sql: add ColumnGeneratedAsIdentity as a new schema change element
Previously, GeneratedAsIdentity was part of the Column element. Creating a new schema change element will allow the declarative schema changer to add/remove/update such columns without dropping the Column element. Epic: CRDB-31283 Part of #142918 Release note: None
1 parent 7625398 commit dbb0574

File tree

41 files changed

+469
-117
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

41 files changed

+469
-117
lines changed

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

Lines changed: 28 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -116,11 +116,10 @@ func alterTableAddColumn(
116116
spec := addColumnSpec{
117117
tbl: tbl,
118118
col: &scpb.Column{
119-
TableID: tbl.TableID,
120-
ColumnID: desc.ID,
121-
IsHidden: desc.Hidden,
122-
IsInaccessible: desc.Inaccessible,
123-
GeneratedAsIdentityType: desc.GeneratedAsIdentityType,
119+
TableID: tbl.TableID,
120+
ColumnID: desc.ID,
121+
IsHidden: desc.Hidden,
122+
IsInaccessible: desc.Inaccessible,
124123
},
125124
unique: d.Unique.IsUnique,
126125
notNull: !desc.Nullable,
@@ -139,9 +138,6 @@ func alterTableAddColumn(
139138
if pgAttNum := desc.GetPGAttributeNum(); pgAttNum != catid.PGAttributeNum(desc.ID) {
140139
spec.col.PgAttributeNum = pgAttNum
141140
}
142-
if ptr := desc.GeneratedAsIdentitySequenceOption; ptr != nil {
143-
spec.col.GeneratedAsIdentitySequenceOption = *ptr
144-
}
145141
spec.name = &scpb.ColumnName{
146142
TableID: tbl.TableID,
147143
ColumnID: spec.col.ColumnID,
@@ -290,6 +286,26 @@ func alterTableAddColumn(
290286
}
291287
b.IncrementSchemaChangeAddColumnQualificationCounter("on_update")
292288
}
289+
if d.GeneratedIdentity.IsGeneratedAsIdentity {
290+
generatedAsIdentityType := desc.GeneratedAsIdentityType
291+
seqOptions := ""
292+
if ptr := desc.GeneratedAsIdentitySequenceOption; ptr != nil {
293+
seqOptions = *ptr
294+
}
295+
// Versions from 26.1 GeneratedAsIdentity will have a separate element for
296+
// GeneratedAsIdentity. Older versios store it in the column element.
297+
if spec.colType.ElementCreationMetadata.In_26_1OrLater {
298+
spec.generatedAsID = &scpb.ColumnGeneratedAsIdentity{
299+
TableID: tbl.TableID,
300+
ColumnID: spec.col.ColumnID,
301+
Type: generatedAsIdentityType,
302+
SequenceOption: seqOptions,
303+
}
304+
} else {
305+
spec.col.GeneratedAsIdentityType = generatedAsIdentityType
306+
spec.col.GeneratedAsIdentitySequenceOption = seqOptions
307+
}
308+
}
293309
// Add secondary indexes for this column.
294310
backing := addColumn(b, spec, t)
295311
if idx != nil {
@@ -458,6 +474,7 @@ type addColumnSpec struct {
458474
compute *scpb.ColumnComputeExpression
459475
transientCompute *scpb.ColumnComputeExpression
460476
comment *scpb.ColumnComment
477+
generatedAsID *scpb.ColumnGeneratedAsIdentity
461478
unique bool
462479
notNull bool
463480
}
@@ -494,6 +511,9 @@ func addColumn(b BuildCtx, spec addColumnSpec, n tree.NodeFormatter) (backing *s
494511
if spec.comment != nil {
495512
b.Add(spec.comment)
496513
}
514+
if spec.generatedAsID != nil {
515+
b.Add(spec.generatedAsID)
516+
}
497517
// Don't need to modify primary indexes for virtual columns.
498518
if spec.colType.IsVirtual {
499519
return getLatestPrimaryIndex(b, spec.tbl.TableID)

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

Lines changed: 1 addition & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,6 @@
66
package scbuildstmt
77

88
import (
9-
"github.com/cockroachdb/cockroach/pkg/sql/catalog/catpb"
109
"github.com/cockroachdb/cockroach/pkg/sql/pgwire/pgcode"
1110
"github.com/cockroachdb/cockroach/pkg/sql/pgwire/pgerror"
1211
"github.com/cockroachdb/cockroach/pkg/sql/schemachanger/scpb"
@@ -37,8 +36,7 @@ func alterTableDropNotNull(
3736
`column "%s" is in a primary index`, colName.Name))
3837
}
3938
// Ensure that we are not dropping not-null on a generated column.
40-
colEl := mustRetrieveColumnElem(b, tbl.TableID, columnID)
41-
if colEl.GeneratedAsIdentityType != catpb.GeneratedAsIdentityType_NOT_IDENTITY_COLUMN {
39+
if isColumnGeneratedAsIdentity(b, tbl.TableID, columnID) {
4240
colName := mustRetrieveColumnName(b, tbl.TableID, columnID)
4341
panic(pgerror.Newf(pgcode.Syntax,
4442
`column "%s" of relation "%s" is an identity column`, colName.Name, tn.ObjectName))

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

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,6 @@ package scbuildstmt
88
import (
99
"context"
1010

11-
"github.com/cockroachdb/cockroach/pkg/sql/catalog/catpb"
1211
"github.com/cockroachdb/cockroach/pkg/sql/catalog/schemaexpr"
1312
"github.com/cockroachdb/cockroach/pkg/sql/catalog/seqexpr"
1413
"github.com/cockroachdb/cockroach/pkg/sql/parser"
@@ -75,7 +74,7 @@ func panicIfInvalidNonComputedColumnExpr(
7574
newExpr tree.Expr,
7675
schemaChange tree.SchemaExprContext,
7776
) tree.TypedExpr {
78-
if col.GeneratedAsIdentityType != catpb.GeneratedAsIdentityType_NOT_IDENTITY_COLUMN {
77+
if isColumnGeneratedAsIdentity(b, tbl.TableID, col.ColumnID) {
7978
panic(sqlerrors.NewSyntaxErrorf("column %q is an identity column", colName))
8079
}
8180

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

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,6 @@ import (
1010

1111
"github.com/cockroachdb/cockroach/pkg/build"
1212
"github.com/cockroachdb/cockroach/pkg/clusterversion"
13-
"github.com/cockroachdb/cockroach/pkg/sql/catalog/catpb"
1413
"github.com/cockroachdb/cockroach/pkg/sql/catalog/colinfo"
1514
"github.com/cockroachdb/cockroach/pkg/sql/catalog/schemaexpr"
1615
"github.com/cockroachdb/cockroach/pkg/sql/parser"
@@ -98,7 +97,7 @@ func alterTableAlterColumnType(
9897
var err error
9998
newColType.Type, err = schemachange.ValidateAlterColumnTypeChecks(
10099
b, t, b.ClusterSettings(), newColType.Type,
101-
col.GeneratedAsIdentityType != catpb.GeneratedAsIdentityType_NOT_IDENTITY_COLUMN,
100+
isColumnGeneratedAsIdentity(b, tbl.TableID, col.ColumnID),
102101
newColType.IsVirtual)
103102
if err != nil {
104103
panic(err)

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

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -326,7 +326,7 @@ func walkColumnDependencies(
326326
*scpb.UniqueWithoutIndexConstraint, *scpb.CheckConstraint,
327327
*scpb.UniqueWithoutIndexConstraintUnvalidated, *scpb.CheckConstraintUnvalidated,
328328
*scpb.RowLevelTTL, *scpb.PolicyUsingExpr, *scpb.PolicyWithCheckExpr,
329-
*scpb.TriggerDeps:
329+
*scpb.TriggerDeps, *scpb.ColumnGeneratedAsIdentity:
330330
fn(e, op, objType)
331331
case *scpb.ColumnType:
332332
if elt.ColumnID == col.ColumnID {

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

Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2218,3 +2218,30 @@ func isShardColumn(b BuildCtx, col *scpb.Column) bool {
22182218

22192219
return found
22202220
}
2221+
2222+
// retrieveColumnGeneratedAsIdentityType returns the GeneratedAsIdentityType.
2223+
// Handles versions before 26.1 that store it in Column.GeneratedAsIdentityType.
2224+
func retrieveColumnGeneratedAsIdentityType(
2225+
b BuildCtx, tableID catid.DescID, columnID catid.ColumnID,
2226+
) (generatedAsIdentityType catpb.GeneratedAsIdentityType) {
2227+
// First try to retrieve it from ColumnGeneratedAsIdentity. This may be nil
2228+
// if the column is not a generated identity column or the cluster version is older
2229+
// than 26.1. In that case, will return Column.GeneratedAsIdentityType.
2230+
colGeneratedAsID := b.QueryByID(tableID).FilterColumnGeneratedAsIdentity().Filter(
2231+
func(_ scpb.Status, _ scpb.TargetStatus, e *scpb.ColumnGeneratedAsIdentity) bool {
2232+
return e.ColumnID == columnID
2233+
}).MustGetZeroOrOneElement()
2234+
if colGeneratedAsID != nil {
2235+
return colGeneratedAsID.Type
2236+
}
2237+
// Check the ColumnType in case this is an older version.
2238+
col := mustRetrieveColumnElem(b, tableID, columnID)
2239+
return col.GeneratedAsIdentityType
2240+
}
2241+
2242+
func isColumnGeneratedAsIdentity(
2243+
b BuildCtx, tableID catid.DescID, columnID catid.ColumnID,
2244+
) (isGenerated bool) {
2245+
generatedAsIdentityType := retrieveColumnGeneratedAsIdentityType(b, tableID, columnID)
2246+
return generatedAsIdentityType != catpb.GeneratedAsIdentityType_NOT_IDENTITY_COLUMN
2247+
}

pkg/sql/schemachanger/scbuild/testdata/alter_table_add_column

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -354,13 +354,15 @@ ALTER TABLE defaultdb.foo ADD COLUMN j INT GENERATED ALWAYS AS IDENTITY
354354
- [[SequenceOwner:{DescID: 104, ColumnID: 2, ReferencedDescID: 107}, PUBLIC], ABSENT]
355355
{columnId: 2, sequenceId: 107, tableId: 104}
356356
- [[Column:{DescID: 104, ColumnID: 2}, PUBLIC], ABSENT]
357-
{columnId: 2, generatedAsIdentityType: 1, tableId: 104}
357+
{columnId: 2, tableId: 104}
358358
- [[ColumnName:{DescID: 104, Name: j, ColumnID: 2}, PUBLIC], ABSENT]
359359
{columnId: 2, name: j, tableId: 104}
360360
- [[ColumnType:{DescID: 104, ColumnFamilyID: 0, ColumnID: 2, TypeName: INT8}, PUBLIC], ABSENT]
361361
{columnId: 2, elementCreationMetadata: {in243OrLater: true, in261OrLater: true}, tableId: 104, type: {family: IntFamily, oid: 20, width: 64}, typeName: INT8}
362362
- [[ColumnDefaultExpression:{DescID: 104, ColumnID: 2, ReferencedSequenceIDs: [107], Expr: nextval(107:::REGCLASS)}, PUBLIC], ABSENT]
363363
{columnId: 2, expr: 'nextval(107:::REGCLASS)', tableId: 104, usesSequenceIds: [107]}
364+
- [[ColumnGeneratedAsIdentity:{DescID: 104, ColumnID: 2}, PUBLIC], ABSENT]
365+
{columnId: 2, tableId: 104, type: 1}
364366
- [[PrimaryIndex:{DescID: 104, IndexID: 2, ConstraintID: 2, TemporaryIndexID: 3, SourceIndexID: 1}, PUBLIC], ABSENT]
365367
{constraintId: 2, indexId: 2, isUnique: true, sourceIndexId: 1, tableId: 104, temporaryIndexId: 3}
366368
- [[IndexName:{DescID: 104, Name: foo_pkey, IndexID: 2}, PUBLIC], ABSENT]
@@ -396,13 +398,15 @@ ALTER TABLE defaultdb.foo ADD COLUMN j SERIAL GENERATED ALWAYS AS IDENTITY
396398
- [[TableData:{DescID: 104, ReferencedDescID: 100}, PUBLIC], PUBLIC]
397399
{databaseId: 100, tableId: 104}
398400
- [[Column:{DescID: 104, ColumnID: 2}, PUBLIC], ABSENT]
399-
{columnId: 2, generatedAsIdentityType: 1, tableId: 104}
401+
{columnId: 2, tableId: 104}
400402
- [[ColumnName:{DescID: 104, Name: j, ColumnID: 2}, PUBLIC], ABSENT]
401403
{columnId: 2, name: j, tableId: 104}
402404
- [[ColumnType:{DescID: 104, ColumnFamilyID: 0, ColumnID: 2, TypeName: INT8}, PUBLIC], ABSENT]
403405
{columnId: 2, elementCreationMetadata: {in243OrLater: true, in261OrLater: true}, tableId: 104, type: {family: IntFamily, oid: 20, width: 64}, typeName: INT8}
404406
- [[ColumnDefaultExpression:{DescID: 104, ColumnID: 2, Expr: unique_rowid()}, PUBLIC], ABSENT]
405407
{columnId: 2, expr: unique_rowid(), tableId: 104}
408+
- [[ColumnGeneratedAsIdentity:{DescID: 104, ColumnID: 2}, PUBLIC], ABSENT]
409+
{columnId: 2, tableId: 104, type: 1}
406410
- [[PrimaryIndex:{DescID: 104, IndexID: 2, ConstraintID: 2, TemporaryIndexID: 3, SourceIndexID: 1}, PUBLIC], ABSENT]
407411
{constraintId: 2, indexId: 2, isUnique: true, sourceIndexId: 1, tableId: 104, temporaryIndexId: 3}
408412
- [[IndexName:{DescID: 104, Name: foo_pkey, IndexID: 2}, PUBLIC], ABSENT]

pkg/sql/schemachanger/scdecomp/decomp.go

Lines changed: 22 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -541,13 +541,11 @@ func (w *walkCtx) walkColumn(tbl catalog.TableDescriptor, col catalog.Column) {
541541
col.GetName(), tbl.GetName(), tbl.GetID()))
542542
}
543543
column := &scpb.Column{
544-
TableID: tbl.GetID(),
545-
ColumnID: col.GetID(),
546-
IsHidden: col.IsHidden(),
547-
IsInaccessible: col.IsInaccessible(),
548-
GeneratedAsIdentityType: col.GetGeneratedAsIdentityType(),
549-
GeneratedAsIdentitySequenceOption: col.GetGeneratedAsIdentitySequenceOptionStr(),
550-
IsSystemColumn: col.IsSystemColumn(),
544+
TableID: tbl.GetID(),
545+
ColumnID: col.GetID(),
546+
IsHidden: col.IsHidden(),
547+
IsInaccessible: col.IsInaccessible(),
548+
IsSystemColumn: col.IsSystemColumn(),
551549
}
552550
// Only set PgAttributeNum if it differs from ColumnID.
553551
if pgAttNum := col.GetPGAttributeNum(); pgAttNum != catid.PGAttributeNum(col.GetID()) {
@@ -590,6 +588,23 @@ func (w *walkCtx) walkColumn(tbl catalog.TableDescriptor, col catalog.Column) {
590588
columnType.ComputeExpr = expr
591589
}
592590
}
591+
592+
if columnType.ElementCreationMetadata.In_26_1OrLater {
593+
if col.IsGeneratedAsIdentity() {
594+
w.ev(scpb.Status_PUBLIC,
595+
&scpb.ColumnGeneratedAsIdentity{
596+
TableID: tbl.GetID(),
597+
ColumnID: col.GetID(),
598+
Type: col.GetGeneratedAsIdentityType(),
599+
SequenceOption: col.GetGeneratedAsIdentitySequenceOptionStr(),
600+
})
601+
column.GeneratedAsIdentityType = catpb.GeneratedAsIdentityType_NOT_IDENTITY_COLUMN
602+
column.GeneratedAsIdentitySequenceOption = ""
603+
}
604+
} else {
605+
column.GeneratedAsIdentityType = col.GetGeneratedAsIdentityType()
606+
column.GeneratedAsIdentitySequenceOption = col.GetGeneratedAsIdentitySequenceOptionStr()
607+
}
593608
w.ev(scpb.Status_PUBLIC, columnType)
594609
}
595610
if !col.IsNullable() {

pkg/sql/schemachanger/scexec/scmutationexec/column.go

Lines changed: 46 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -162,6 +162,52 @@ func (i *immediateVisitor) updateColumnComputeExpression(
162162
return updateColumnExprFunctionsUsage(col)
163163
}
164164

165+
// AddColumnGeneratedAsIdentity will set generated as identity for a column.
166+
func (i *immediateVisitor) AddColumnGeneratedAsIdentity(
167+
ctx context.Context, op scop.AddColumnGeneratedAsIdentity,
168+
) error {
169+
return i.updateColumnGeneratedAsIdentity(
170+
ctx, op.GeneratedAsIdentity.TableID, op.GeneratedAsIdentity.ColumnID,
171+
op.GeneratedAsIdentity.Type, &op.GeneratedAsIdentity.SequenceOption)
172+
}
173+
174+
// RemoveColumnGeneratedAsIdentity will drop generated as identity from a column.
175+
func (i *immediateVisitor) RemoveColumnGeneratedAsIdentity(
176+
ctx context.Context, op scop.RemoveColumnGeneratedAsIdentity,
177+
) error {
178+
return i.updateColumnGeneratedAsIdentity(
179+
ctx, op.TableID, op.ColumnID, catpb.GeneratedAsIdentityType_NOT_IDENTITY_COLUMN, nil)
180+
}
181+
182+
// updateColumnGeneratedAsIdentity will handle add or removal of generated as identity
183+
func (i *immediateVisitor) updateColumnGeneratedAsIdentity(
184+
ctx context.Context,
185+
tableID descpb.ID,
186+
columnID descpb.ColumnID,
187+
genType catpb.GeneratedAsIdentityType,
188+
sequenceOption *string,
189+
) error {
190+
tbl, err := i.checkOutTable(ctx, tableID)
191+
if err != nil {
192+
return err
193+
}
194+
195+
catCol, err := catalog.MustFindColumnByID(tbl, columnID)
196+
if err != nil {
197+
return err
198+
}
199+
200+
col := catCol.ColumnDesc()
201+
col.GeneratedAsIdentityType = genType
202+
if sequenceOption != nil && *sequenceOption != "" {
203+
so := *sequenceOption
204+
col.GeneratedAsIdentitySequenceOption = &so
205+
} else {
206+
col.GeneratedAsIdentitySequenceOption = nil
207+
}
208+
return nil
209+
}
210+
165211
func (i *immediateVisitor) MakeDeleteOnlyColumnWriteOnly(
166212
ctx context.Context, op scop.MakeDeleteOnlyColumnWriteOnly,
167213
) error {

pkg/sql/schemachanger/scop/immediate_mutation.go

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -247,6 +247,19 @@ type RemoveColumnComputeExpression struct {
247247
ColumnID descpb.ColumnID
248248
}
249249

250+
// AddColumnGeneratedAsIdentity will add a new generated as identity to a column.
251+
type AddColumnGeneratedAsIdentity struct {
252+
immediateMutationOp
253+
GeneratedAsIdentity scpb.ColumnGeneratedAsIdentity
254+
}
255+
256+
// RemoveColumnGeneratedAsIdentity will remove the generated as identity from a column.
257+
type RemoveColumnGeneratedAsIdentity struct {
258+
immediateMutationOp
259+
TableID descpb.ID
260+
ColumnID descpb.ColumnID
261+
}
262+
250263
// MakeWriteOnlyColumnPublic moves a new column from its mutation to public.
251264
type MakeWriteOnlyColumnPublic struct {
252265
immediateMutationOp

0 commit comments

Comments
 (0)