Skip to content

Commit 9ff0250

Browse files
committed
sql/schemachanger: enforce LDR and schema_locked for truncate
Previously, the new implementation for TRUNCATE inside the declarative schema changer was not properly handling the schema_locked attribute. This patch modifies it to toggle schema_locked and enforce LDR. Fixes: #159097 Release note (bug fix): TRUNCATE is not blocked when LDR is in use and does not behave correctly with schema_locked.
1 parent 7a46bb0 commit 9ff0250

File tree

4 files changed

+93
-58
lines changed

4 files changed

+93
-58
lines changed

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

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -97,6 +97,9 @@ func Truncate(b BuildCtx, stmt *tree.Truncate) {
9797
}
9898

9999
func truncateTable(b BuildCtx, n *tree.Truncate, elts ElementResultSet) {
100+
// Enforce schema_locked / LDR for truncate.
101+
lockedCleanup := checkTableSchemaChangePrerequisites(b, elts, n)
102+
defer lockedCleanup()
100103
tbl := elts.FilterTable().MustGetOneElement()
101104
// Fall back to legacy schema changer if we need to rewrite index references.
102105
backRefs := b.BackReferences(tbl.TableID)

pkg/sql/schemachanger/testdata/end_to_end/truncate/truncate.explain

Lines changed: 29 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -19,11 +19,14 @@ Schema change plan for TRUNCATE TABLE ‹defaultdb›.‹public›.‹t›;
1919
│ │ ├── ABSENT → PUBLIC IndexColumn:{DescID: 104 (t), ColumnID: 2 (j), IndexID: 4 (t_j_key+)}
2020
│ │ ├── ABSENT → PUBLIC IndexColumn:{DescID: 104 (t), ColumnID: 1 (i), IndexID: 4 (t_j_key+)}
2121
│ │ └── ABSENT → PUBLIC IndexData:{DescID: 104 (t), IndexID: 4 (t_j_key+)}
22+
│ ├── 1 element transitioning toward TRANSIENT_PUBLIC
23+
│ │ └── PUBLIC → ABSENT TableSchemaLocked:{DescID: 104 (t)}
2224
│ ├── 3 elements transitioning toward ABSENT
2325
│ │ ├── PUBLIC → VALIDATED PrimaryIndex:{DescID: 104 (t), IndexID: 1 (t_pkey-), ConstraintID: 2}
2426
│ │ ├── PUBLIC → ABSENT IndexName:{DescID: 104 (t), Name: "t_pkey", IndexID: 1 (t_pkey-)}
2527
│ │ └── PUBLIC → VALIDATED SecondaryIndex:{DescID: 104 (t), IndexID: 2 (t_j_key-), ConstraintID: 1, RecreateSourceIndexID: 0, RecreateTargetIndexID: 0}
26-
│ └── 21 Mutation operations
28+
│ └── 22 Mutation operations
29+
│ ├── SetTableSchemaLocked {"TableID":104}
2730
│ ├── MakeAbsentIndexBackfilling {"Index":{"ConstraintID":3,"IndexID":3,"IsUnique":true,"SourceIndexID":1,"TableID":104}}
2831
│ ├── AddColumnToIndex {"ColumnID":1,"IndexID":3,"TableID":104}
2932
│ ├── AddColumnToIndex {"ColumnID":2,"IndexID":3,"Kind":2,"TableID":104}
@@ -58,6 +61,8 @@ Schema change plan for TRUNCATE TABLE ‹defaultdb›.‹public›.‹t›;
5861
│ │ │ ├── PUBLIC → ABSENT IndexColumn:{DescID: 104 (t), ColumnID: 2 (j), IndexID: 4 (t_j_key+)}
5962
│ │ │ ├── PUBLIC → ABSENT IndexColumn:{DescID: 104 (t), ColumnID: 1 (i), IndexID: 4 (t_j_key+)}
6063
│ │ │ └── PUBLIC → ABSENT IndexData:{DescID: 104 (t), IndexID: 4 (t_j_key+)}
64+
│ │ ├── 1 element transitioning toward TRANSIENT_PUBLIC
65+
│ │ │ └── ABSENT → PUBLIC TableSchemaLocked:{DescID: 104 (t)}
6166
│ │ ├── 3 elements transitioning toward ABSENT
6267
│ │ │ ├── VALIDATED → PUBLIC PrimaryIndex:{DescID: 104 (t), IndexID: 1 (t_pkey-), ConstraintID: 2}
6368
│ │ │ ├── ABSENT → PUBLIC IndexName:{DescID: 104 (t), Name: "t_pkey", IndexID: 1 (t_pkey-)}
@@ -76,11 +81,14 @@ Schema change plan for TRUNCATE TABLE ‹defaultdb›.‹public›.‹t›;
7681
│ │ ├── ABSENT → PUBLIC IndexColumn:{DescID: 104 (t), ColumnID: 2 (j), IndexID: 4 (t_j_key+)}
7782
│ │ ├── ABSENT → PUBLIC IndexColumn:{DescID: 104 (t), ColumnID: 1 (i), IndexID: 4 (t_j_key+)}
7883
│ │ └── ABSENT → PUBLIC IndexData:{DescID: 104 (t), IndexID: 4 (t_j_key+)}
84+
│ ├── 1 element transitioning toward TRANSIENT_PUBLIC
85+
│ │ └── PUBLIC → ABSENT TableSchemaLocked:{DescID: 104 (t)}
7986
│ ├── 3 elements transitioning toward ABSENT
8087
│ │ ├── PUBLIC → VALIDATED PrimaryIndex:{DescID: 104 (t), IndexID: 1 (t_pkey-), ConstraintID: 2}
8188
│ │ ├── PUBLIC → ABSENT IndexName:{DescID: 104 (t), Name: "t_pkey", IndexID: 1 (t_pkey-)}
8289
│ │ └── PUBLIC → VALIDATED SecondaryIndex:{DescID: 104 (t), IndexID: 2 (t_j_key-), ConstraintID: 1, RecreateSourceIndexID: 0, RecreateTargetIndexID: 0}
83-
│ └── 26 Mutation operations
90+
│ └── 27 Mutation operations
91+
│ ├── SetTableSchemaLocked {"TableID":104}
8492
│ ├── MakeAbsentIndexBackfilling {"Index":{"ConstraintID":3,"IndexID":3,"IsUnique":true,"SourceIndexID":1,"TableID":104}}
8593
│ ├── MaybeAddSplitForIndex {"CopyIndexID":1,"IndexID":3,"TableID":104}
8694
│ ├── AddColumnToIndex {"ColumnID":1,"IndexID":3,"TableID":104}
@@ -108,7 +116,7 @@ Schema change plan for TRUNCATE TABLE ‹defaultdb›.‹public›.‹t›;
108116
│ ├── SetJobStateOnDescriptor {"DescriptorID":104,"Initialize":true}
109117
│ └── CreateSchemaChangerJob {"NonCancelable":true,"RunningStatus":"Pending: Updatin..."}
110118
└── PostCommitNonRevertiblePhase
111-
├── Stage 1 of 2 in PostCommitNonRevertiblePhase
119+
├── Stage 1 of 3 in PostCommitNonRevertiblePhase
112120
│ ├── 7 elements transitioning toward ABSENT
113121
│ │ ├── PUBLIC → ABSENT IndexColumn:{DescID: 104 (t), ColumnID: 1 (i), IndexID: 1 (t_pkey-)}
114122
│ │ ├── PUBLIC → ABSENT IndexColumn:{DescID: 104 (t), ColumnID: 2 (j), IndexID: 1 (t_pkey-)}
@@ -127,16 +135,23 @@ Schema change plan for TRUNCATE TABLE ‹defaultdb›.‹public›.‹t›;
127135
│ ├── RemoveColumnFromIndex {"ColumnID":1,"IndexID":2,"Kind":1,"TableID":104}
128136
│ ├── SetJobStateOnDescriptor {"DescriptorID":104}
129137
│ └── UpdateSchemaChangerJob {"IsNonCancelable":true,"RunningStatus":"Pending: Updatin..."}
130-
└── Stage 2 of 2 in PostCommitNonRevertiblePhase
131-
├── 4 elements transitioning toward ABSENT
132-
│ ├── DELETE_ONLY → ABSENT PrimaryIndex:{DescID: 104 (t), IndexID: 1 (t_pkey-), ConstraintID: 2}
133-
│ ├── PUBLIC → ABSENT IndexData:{DescID: 104 (t), IndexID: 1 (t_pkey-)}
134-
│ ├── DELETE_ONLY → ABSENT SecondaryIndex:{DescID: 104 (t), IndexID: 2 (t_j_key-), ConstraintID: 1, RecreateSourceIndexID: 0, RecreateTargetIndexID: 0}
135-
│ └── PUBLIC → ABSENT IndexData:{DescID: 104 (t), IndexID: 2 (t_j_key-)}
136-
└── 6 Mutation operations
137-
├── MakeIndexAbsent {"IndexID":1,"TableID":104}
138-
├── CreateGCJobForIndex {"IndexID":1,"TableID":104}
139-
├── MakeIndexAbsent {"IndexID":2,"TableID":104}
140-
├── CreateGCJobForIndex {"IndexID":2,"TableID":104}
138+
├── Stage 2 of 3 in PostCommitNonRevertiblePhase
139+
│ ├── 4 elements transitioning toward ABSENT
140+
│ │ ├── DELETE_ONLY → ABSENT PrimaryIndex:{DescID: 104 (t), IndexID: 1 (t_pkey-), ConstraintID: 2}
141+
│ │ ├── PUBLIC → ABSENT IndexData:{DescID: 104 (t), IndexID: 1 (t_pkey-)}
142+
│ │ ├── DELETE_ONLY → ABSENT SecondaryIndex:{DescID: 104 (t), IndexID: 2 (t_j_key-), ConstraintID: 1, RecreateSourceIndexID: 0, RecreateTargetIndexID: 0}
143+
│ │ └── PUBLIC → ABSENT IndexData:{DescID: 104 (t), IndexID: 2 (t_j_key-)}
144+
│ └── 6 Mutation operations
145+
│ ├── MakeIndexAbsent {"IndexID":1,"TableID":104}
146+
│ ├── CreateGCJobForIndex {"IndexID":1,"TableID":104}
147+
│ ├── MakeIndexAbsent {"IndexID":2,"TableID":104}
148+
│ ├── CreateGCJobForIndex {"IndexID":2,"TableID":104}
149+
│ ├── SetJobStateOnDescriptor {"DescriptorID":104}
150+
│ └── UpdateSchemaChangerJob {"IsNonCancelable":true,"RunningStatus":"Pending: Updatin..."}
151+
└── Stage 3 of 3 in PostCommitNonRevertiblePhase
152+
├── 1 element transitioning toward TRANSIENT_PUBLIC
153+
│ └── ABSENT → TRANSIENT_PUBLIC TableSchemaLocked:{DescID: 104 (t)}
154+
└── 3 Mutation operations
155+
├── SetTableSchemaLocked {"Locked":true,"TableID":104}
141156
├── RemoveJobStateFromDescriptor {"DescriptorID":104}
142157
└── UpdateSchemaChangerJob {"IsNonCancelable":true,"RunningStatus":"all stages compl..."}

pkg/sql/schemachanger/testdata/end_to_end/truncate/truncate.explain_shape

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -6,4 +6,4 @@ INSERT INTO t VALUES (1, 1), (2, 2);
66
EXPLAIN (DDL, SHAPE) TRUNCATE TABLE t;
77
----
88
Schema change plan for TRUNCATE TABLE ‹defaultdb›.‹public›.‹t›;
9-
└── execute 3 system table mutations transactions
9+
└── execute 4 system table mutations transactions

pkg/sql/schemachanger/testdata/end_to_end/truncate/truncate.side_effects

Lines changed: 60 additions & 43 deletions
Original file line numberDiff line numberDiff line change
@@ -18,7 +18,7 @@ write *eventpb.TruncateTable to event log:
1818
tag: TRUNCATE
1919
user: root
2020
tableName: defaultdb.public.t
21-
## StatementPhase stage 1 of 1 with 21 MutationType ops
21+
## StatementPhase stage 1 of 1 with 22 MutationType ops
2222
upsert descriptor #104
2323
...
2424
id: 104
@@ -117,7 +117,9 @@ upsert descriptor #104
117117
interleave: {}
118118
keyColumnDirections:
119119
...
120-
schemaLocked: true
120+
replacementOf:
121+
time: {}
122+
- schemaLocked: true
121123
unexposedParentSchemaId: 101
122124
- version: "1"
123125
+ version: "2"
@@ -126,7 +128,7 @@ upsert descriptor #104
126128
## PreCommitPhase stage 1 of 2 with 1 MutationType op
127129
undo all catalog changes within txn #1
128130
persist all catalog changes to storage
129-
## PreCommitPhase stage 2 of 2 with 26 MutationType ops
131+
## PreCommitPhase stage 2 of 2 with 27 MutationType ops
130132
upsert descriptor #104
131133
...
132134
createAsOfTime:
@@ -257,7 +259,9 @@ upsert descriptor #104
257259
interleave: {}
258260
keyColumnDirections:
259261
...
260-
schemaLocked: true
262+
replacementOf:
263+
time: {}
264+
- schemaLocked: true
261265
unexposedParentSchemaId: 101
262266
- version: "1"
263267
+ version: "2"
@@ -272,7 +276,7 @@ notified job registry to adopt jobs: [1]
272276
begin transaction #2
273277
commit transaction #2
274278
begin transaction #3
275-
## PostCommitNonRevertiblePhase stage 1 of 2 with 9 MutationType ops
279+
## PostCommitNonRevertiblePhase stage 1 of 3 with 9 MutationType ops
276280
upsert descriptor #104
277281
...
278282
version: 4
@@ -296,48 +300,16 @@ upsert descriptor #104
296300
name: t
297301
nextColumnId: 3
298302
...
299-
schemaLocked: true
303+
time: {}
300304
unexposedParentSchemaId: 101
301305
- version: "2"
302306
+ version: "3"
303307
persist all catalog changes to storage
304-
update progress of schema change job #1: "Pending: Updating schema metadata (4 operations) — PostCommitNonRevertible phase (stage 2 of 2)."
308+
update progress of schema change job #1: "Pending: Updating schema metadata (4 operations) — PostCommitNonRevertible phase (stage 2 of 3)."
305309
commit transaction #3
306310
begin transaction #4
307-
## PostCommitNonRevertiblePhase stage 2 of 2 with 6 MutationType ops
311+
## PostCommitNonRevertiblePhase stage 2 of 3 with 6 MutationType ops
308312
upsert descriptor #104
309-
...
310-
createAsOfTime:
311-
wallTime: "1640995200000000000"
312-
- declarativeSchemaChangerState:
313-
- authorization:
314-
- userName: root
315-
- currentStatuses: <redacted>
316-
- jobId: "1"
317-
- nameMapping:
318-
- columns:
319-
- "1": i
320-
- "2": j
321-
- "4294967292": crdb_internal_origin_timestamp
322-
- "4294967293": crdb_internal_origin_id
323-
- "4294967294": tableoid
324-
- "4294967295": crdb_internal_mvcc_timestamp
325-
- families:
326-
- "0": primary
327-
- id: 104
328-
- indexes:
329-
- "3": t_pkey
330-
- "4": t_j_key
331-
- name: t
332-
- relevantStatements:
333-
- - statement:
334-
- redactedStatement: TRUNCATE TABLE ‹defaultdb›.‹public›.‹t›
335-
- statement: TRUNCATE TABLE t
336-
- statementTag: TRUNCATE
337-
- targetRanks: <redacted>
338-
- targets: <redacted>
339-
families:
340-
- columnIds:
341313
...
342314
version: 4
343315
modificationTime: {}
@@ -397,19 +369,64 @@ upsert descriptor #104
397369
name: t
398370
nextColumnId: 3
399371
...
400-
schemaLocked: true
372+
time: {}
401373
unexposedParentSchemaId: 101
402374
- version: "3"
403375
+ version: "4"
404376
persist all catalog changes to storage
405377
create job #2 (non-cancelable: true): "GC for TRUNCATE TABLE defaultdb.public.t"
406378
descriptor IDs: [104]
379+
update progress of schema change job #1: "Pending: Updating schema metadata (1 operation) — PostCommitNonRevertible phase (stage 3 of 3)."
380+
commit transaction #4
381+
notified job registry to adopt jobs: [2]
382+
begin transaction #5
383+
## PostCommitNonRevertiblePhase stage 3 of 3 with 3 MutationType ops
384+
upsert descriptor #104
385+
...
386+
createAsOfTime:
387+
wallTime: "1640995200000000000"
388+
- declarativeSchemaChangerState:
389+
- authorization:
390+
- userName: root
391+
- currentStatuses: <redacted>
392+
- jobId: "1"
393+
- nameMapping:
394+
- columns:
395+
- "1": i
396+
- "2": j
397+
- "4294967292": crdb_internal_origin_timestamp
398+
- "4294967293": crdb_internal_origin_id
399+
- "4294967294": tableoid
400+
- "4294967295": crdb_internal_mvcc_timestamp
401+
- families:
402+
- "0": primary
403+
- id: 104
404+
- indexes:
405+
- "3": t_pkey
406+
- "4": t_j_key
407+
- name: t
408+
- relevantStatements:
409+
- - statement:
410+
- redactedStatement: TRUNCATE TABLE ‹defaultdb›.‹public›.‹t›
411+
- statement: TRUNCATE TABLE t
412+
- statementTag: TRUNCATE
413+
- targetRanks: <redacted>
414+
- targets: <redacted>
415+
families:
416+
- columnIds:
417+
...
418+
replacementOf:
419+
time: {}
420+
+ schemaLocked: true
421+
unexposedParentSchemaId: 101
422+
- version: "4"
423+
+ version: "5"
424+
persist all catalog changes to storage
407425
update progress of schema change job #1: "all stages completed"
408426
set schema change job #1 to non-cancellable
409427
updated schema change job #1 descriptor IDs to []
410428
write *eventpb.FinishSchemaChange to event log:
411429
sc:
412430
descriptorId: 104
413-
commit transaction #4
414-
notified job registry to adopt jobs: [2]
431+
commit transaction #5
415432
# end PostCommitPhase

0 commit comments

Comments
 (0)