Skip to content

Commit 2b1dd5f

Browse files
craig[bot]fqazi
andcommitted
Merge #145219
145219: workload/schemachanger: add testing for schema_locked tables r=fqazi a=fqazi Previously, the schema changer workload lacked randomized testing for schema_locked tables. This resulted in a lack of coverage for schema changes involving these tables. This patch adds support for creating and using schema_locked tables within the declarative schema changer tests. This patch also adds support for setting creating tables with schema_locked with in a transaction to simplify testing. Fixes: #144591 Release note: None Co-authored-by: Faizan Qazi <[email protected]>
2 parents a85bae0 + f05cfb5 commit 2b1dd5f

File tree

6 files changed

+67
-20
lines changed

6 files changed

+67
-20
lines changed

pkg/sql/alter_table.go

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -731,7 +731,7 @@ func (n *alterTableNode) startExec(params runParams) error {
731731
}
732732

733733
case *tree.AlterTableSetStorageParams:
734-
setter := tablestorageparam.NewSetter(n.tableDesc)
734+
setter := tablestorageparam.NewSetter(n.tableDesc, false /* isNewObject */)
735735
if err := storageparam.Set(
736736
params.ctx,
737737
params.p.SemaCtx(),
@@ -761,7 +761,7 @@ func (n *alterTableNode) startExec(params runParams) error {
761761
}
762762

763763
case *tree.AlterTableResetStorageParams:
764-
setter := tablestorageparam.NewSetter(n.tableDesc)
764+
setter := tablestorageparam.NewSetter(n.tableDesc, false /* isNewObject */)
765765
if err := storageparam.Reset(
766766
params.ctx,
767767
params.EvalContext(),

pkg/sql/create_table.go

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1420,8 +1420,7 @@ func NewTableDesc(
14201420
desc := tabledesc.InitTableDescriptor(
14211421
id, dbID, sc.GetID(), n.Table.Table(), creationTime, privileges, persistence,
14221422
)
1423-
1424-
setter := tablestorageparam.NewSetter(&desc)
1423+
setter := tablestorageparam.NewSetter(&desc, true /* isNewObject */)
14251424
if err := storageparam.Set(
14261425
ctx,
14271426
semaCtx,

pkg/sql/storageparam/indexstorageparam/index_storage_param.go

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -223,3 +223,9 @@ func (po *Setter) RunPostChecks() error {
223223

224224
return nil
225225
}
226+
227+
// IsNewTableObject implements the Setter interface.
228+
func (po *Setter) IsNewTableObject() bool {
229+
//Not applicable to indexes.
230+
panic(errors.AssertionFailedf("not-implemented for indexes"))
231+
}

pkg/sql/storageparam/storage_param.go

Lines changed: 15 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -34,6 +34,9 @@ type Setter interface {
3434
// This allows checking whether multiple storage parameters together
3535
// form a valid configuration.
3636
RunPostChecks() error
37+
// IsNewTableObject returns true if the storage parameter is being set on a new
38+
// table.
39+
IsNewTableObject() bool
3740
}
3841

3942
// Set sets the given storage parameters using the
@@ -45,7 +48,7 @@ func Set(
4548
params tree.StorageParams,
4649
setter Setter,
4750
) error {
48-
if err := storageParamPreChecks(ctx, evalCtx, params, nil /* resetParams */); err != nil {
51+
if err := storageParamPreChecks(ctx, evalCtx, setter, params, nil /* resetParams */); err != nil {
4952
return err
5053
}
5154
for _, sp := range params {
@@ -92,7 +95,7 @@ func Set(
9295
func Reset(
9396
ctx context.Context, evalCtx *eval.Context, params []string, paramObserver Setter,
9497
) error {
95-
if err := storageParamPreChecks(ctx, evalCtx, nil /* setParam */, params); err != nil {
98+
if err := storageParamPreChecks(ctx, evalCtx, paramObserver, nil /* setParam */, params); err != nil {
9699
return err
97100
}
98101
for _, p := range params {
@@ -126,7 +129,11 @@ func SetFillFactor(ctx context.Context, evalCtx *eval.Context, key string, datum
126129
// storageParamPreChecks is where we specify pre-conditions for setting/resetting
127130
// storage parameters `param`.
128131
func storageParamPreChecks(
129-
ctx context.Context, evalCtx *eval.Context, setParams tree.StorageParams, resetParams []string,
132+
ctx context.Context,
133+
evalCtx *eval.Context,
134+
setter Setter,
135+
setParams tree.StorageParams,
136+
resetParams []string,
130137
) error {
131138
if setParams != nil && resetParams != nil {
132139
return errors.AssertionFailedf("only one of setParams and resetParams should be non-nil.")
@@ -152,7 +159,11 @@ func storageParamPreChecks(
152159
// change we make to the descriptor in the transaction, so we can uphold
153160
// the "one-version invariant" as discussed further in RFC
154161
// https://github.com/ajwerner/cockroach/blob/ajwerner/low-latency-rfc-take-3/docs/RFCS/20230328_low_latency_changefeeds.md
155-
if len(keys) > 1 || !evalCtx.TxnImplicit || !evalCtx.TxnIsSingleStmt {
162+
// For newly created tables we will allow schema_locked to be set upon creation,
163+
// since later operations cannot unset schema_locked (i.e. only implicit single
164+
// statement transactions are allowed to manipulate schema_locked, see
165+
// checkSchemaChangeIsAllowed).
166+
if !setter.IsNewTableObject() && (len(keys) > 1 || !evalCtx.TxnImplicit || !evalCtx.TxnIsSingleStmt) {
156167
return pgerror.Newf(pgcode.InvalidParameterValue, "%q can only be set/reset on "+
157168
"its own without other parameters in a single-statement implicit transaction.", key)
158169
}

pkg/sql/storageparam/tablestorageparam/table_storage_param.go

Lines changed: 10 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -36,18 +36,22 @@ type Setter struct {
3636
// UpdatedRowLevelTTL is kept separate from the RowLevelTTL in TableDesc
3737
// in case changes need to be made in schema changer.
3838
UpdatedRowLevelTTL *catpb.RowLevelTTL
39+
40+
// NewObject bool tracks if this is a newly created object.
41+
NewObject bool
3942
}
4043

4144
var _ storageparam.Setter = (*Setter)(nil)
4245

4346
// NewSetter returns a new Setter.
44-
func NewSetter(tableDesc *tabledesc.Mutable) *Setter {
47+
func NewSetter(tableDesc *tabledesc.Mutable, isNewObject bool) *Setter {
4548
var updatedRowLevelTTL *catpb.RowLevelTTL
4649
if tableDesc.HasRowLevelTTL() {
4750
updatedRowLevelTTL = protoutil.Clone(tableDesc.GetRowLevelTTL()).(*catpb.RowLevelTTL)
4851
}
4952
return &Setter{
5053
TableDesc: tableDesc,
54+
NewObject: isNewObject,
5155
UpdatedRowLevelTTL: updatedRowLevelTTL,
5256
}
5357
}
@@ -60,6 +64,11 @@ func (po *Setter) RunPostChecks() error {
6064
return nil
6165
}
6266

67+
// IsNewTableObject implements the Setter interface.
68+
func (po *Setter) IsNewTableObject() bool {
69+
return po.NewObject
70+
}
71+
6372
func boolFromDatum(
6473
ctx context.Context, evalCtx *eval.Context, key string, datum tree.Datum,
6574
) (bool, error) {

pkg/workload/schemachange/operation_generator.go

Lines changed: 33 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -1306,6 +1306,14 @@ func (og *operationGenerator) createTable(ctx context.Context, tx pgx.Tx) (*opSt
13061306
return false
13071307
}()
13081308

1309+
// Randomly create as schema locked table.
1310+
if og.params.rng.Intn(2) == 0 {
1311+
stmt.StorageParams = append(stmt.StorageParams, tree.StorageParam{
1312+
Key: "schema_locked",
1313+
Value: tree.DBoolTrue,
1314+
})
1315+
}
1316+
13091317
tableExists, err := og.tableExists(ctx, tx, tableName)
13101318
if err != nil {
13111319
return nil, err
@@ -3821,6 +3829,14 @@ func (og *operationGenerator) randTypeName(
38213829
func (og *operationGenerator) randTable(
38223830
ctx context.Context, tx pgx.Tx, pctExisting int, desiredSchema string,
38233831
) (*tree.TableName, error) {
3832+
// Because the declarative schema change can automatically set / unset
3833+
// schema_locked on tables, we will allow random table selection include
3834+
// schema_locked tables. When working with the legacy schema changer, we
3835+
// will intentionally only select non-schema locked tables.
3836+
excludeSchemaLocked := " AND create_statement NOT LIKE '%schema_locked%' "
3837+
if og.useDeclarativeSchemaChanger {
3838+
excludeSchemaLocked = ""
3839+
}
38243840
if err := og.setSeedInDB(ctx, tx); err != nil {
38253841
return nil, err
38263842
}
@@ -3833,13 +3849,15 @@ func (og *operationGenerator) randTable(
38333849
return &treeTableName, nil
38343850
}
38353851
q := fmt.Sprintf(`
3836-
SELECT table_name
3837-
FROM [SHOW TABLES]
3838-
WHERE table_name SIMILAR TO 'table_w[0-9]_+%%'
3852+
SELECT descriptor_name
3853+
FROM crdb_internal.create_statements
3854+
WHERE descriptor_name SIMILAR TO 'table_w[0-9]_+%%'
38393855
AND schema_name = '%s'
3856+
AND descriptor_type='table'
3857+
%s
38403858
ORDER BY random()
38413859
LIMIT 1;
3842-
`, desiredSchema)
3860+
`, desiredSchema, excludeSchemaLocked)
38433861

38443862
var tableName string
38453863
if err := tx.QueryRow(ctx, q).Scan(&tableName); err != nil {
@@ -3870,13 +3888,17 @@ func (og *operationGenerator) randTable(
38703888
return &treeTableName, nil
38713889
}
38723890

3873-
const q = `
3874-
SELECT schema_name, table_name
3875-
FROM [SHOW TABLES]
3876-
WHERE table_name SIMILAR TO 'table_w[0-9]_+%'
3877-
ORDER BY random()
3878-
LIMIT 1;
3879-
`
3891+
q := fmt.Sprintf(`
3892+
SELECT schema_name, descriptor_name
3893+
FROM crdb_internal.create_statements
3894+
WHERE descriptor_name SIMILAR TO 'table_w[0-9]_+%%'
3895+
AND descriptor_type='table'
3896+
%s
3897+
ORDER BY random()
3898+
LIMIT 1;
3899+
`,
3900+
excludeSchemaLocked)
3901+
38803902
var schemaName string
38813903
var tableName string
38823904
if err := tx.QueryRow(ctx, q).Scan(&schemaName, &tableName); err != nil {

0 commit comments

Comments
 (0)