Skip to content

Commit ada36ca

Browse files
craig[bot]fqazi
andcommitted
Merge #151549
151549: compose: deflake TestComposeCompare r=fqazi a=fqazi Previously, the compose test had a mutation that added partial indexes to random indexes. This could cause unique indexes to become unusable for foreign keys, an issue that was being incorrectly ignored in the schema changer. A recent change fixed this bug, which now causes these scenarios to fail correctly. To address this, this patch modifies the mutator inside compose to only add partial indexes on new, duplicate indexes so that original unique constraints are not lost. Fixes: #150817 Fixes: #149565 Release note: None Co-authored-by: Faizan Qazi <[email protected]>
2 parents 91a2138 + 9249104 commit ada36ca

File tree

2 files changed

+84
-1
lines changed

2 files changed

+84
-1
lines changed

pkg/compose/compare/compare/compare_test.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -93,7 +93,7 @@ func TestCompare(t *testing.T) {
9393
randgen.ForeignKeyMutator,
9494
randgen.ColumnFamilyMutator,
9595
randgen.IndexStoringMutator,
96-
randgen.PartialIndexMutator,
96+
randgen.DupPartialIndexMutator,
9797
},
9898
},
9999
},

pkg/sql/randgen/mutator.go

Lines changed: 83 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,7 @@ import (
99
"bytes"
1010
"context"
1111
"encoding/json"
12+
"fmt"
1213
"math/rand"
1314
"regexp"
1415
"sort"
@@ -44,6 +45,10 @@ var (
4445
// indexes.
4546
PartialIndexMutator MultiStatementMutation = partialIndexMutator
4647

48+
// DupPartialIndexMutator create a new random partial index based on an
49+
// existing index that is selected.
50+
DupPartialIndexMutator MultiStatementMutation = duplicatePartialIndexMutator
51+
4752
// PostgresMutator modifies strings such that they execute identically
4853
// in both Postgres and Cockroach (however this mutator does not remove
4954
// features not supported by Postgres; use PostgresCreateTableMutator
@@ -1164,6 +1169,84 @@ func partialIndexMutator(rng *rand.Rand, stmts []tree.Statement) ([]tree.Stateme
11641169
return stmts, changed
11651170
}
11661171

1172+
// duplicatePartialIndexMutator is a mutations.MultiStatementMutator that will
1173+
// copy a random index definition and make it a partial index. Unlike
1174+
// partialIndexMutator, the existing definition will stay the same.
1175+
func duplicatePartialIndexMutator(rng *rand.Rand, stmts []tree.Statement) ([]tree.Statement, bool) {
1176+
changed := false
1177+
tables := getTableInfoFromDDLStatements(stmts)
1178+
var newStmts []tree.Statement
1179+
for _, stmt := range stmts {
1180+
switch ast := stmt.(type) {
1181+
case *tree.CreateIndex:
1182+
info, ok := tables[ast.Table.ObjectName]
1183+
if !ok {
1184+
continue
1185+
}
1186+
1187+
// If the index is not already a partial index, make it a partial index
1188+
// with a 50% chance. Do not mutate an index that was created to satisfy a
1189+
// FK constraint.
1190+
if ast.Predicate == nil &&
1191+
!hasReferencingConstraint(info, ast.Columns) &&
1192+
rng.Intn(2) == 0 {
1193+
astString := tree.AsStringWithFlags(ast, tree.FmtParsableNumerics)
1194+
astCopy, err := parser.ParseOne(astString)
1195+
if err != nil {
1196+
panic(err)
1197+
}
1198+
createIndexCopy := astCopy.AST.(*tree.CreateIndex)
1199+
if len(createIndexCopy.Name) > 0 {
1200+
createIndexCopy.Name = tree.Name(fmt.Sprintf("%s_partial", createIndexCopy.Name))
1201+
}
1202+
tn := tree.MakeUnqualifiedTableName(createIndexCopy.Table.ObjectName)
1203+
createIndexCopy.Predicate = randPartialIndexPredicateFromCols(rng, info.columnsTableDefs, &tn)
1204+
changed = true
1205+
newStmts = append(newStmts, createIndexCopy)
1206+
}
1207+
case *tree.CreateTable:
1208+
info, ok := tables[ast.Table.ObjectName]
1209+
if !ok {
1210+
panic("table info could not be found")
1211+
}
1212+
var newDefs []tree.TableDef
1213+
for _, def := range ast.Defs {
1214+
var idx *tree.IndexTableDef
1215+
switch defType := def.(type) {
1216+
case *tree.IndexTableDef:
1217+
idx = defType
1218+
case *tree.UniqueConstraintTableDef:
1219+
if !defType.PrimaryKey && !defType.WithoutIndex {
1220+
idx = &defType.IndexTableDef
1221+
}
1222+
}
1223+
1224+
if idx == nil {
1225+
continue
1226+
}
1227+
1228+
// If the index is not already a partial index, make it a partial
1229+
// index with a 50% chance.
1230+
if idx.Predicate == nil &&
1231+
!hasReferencingConstraint(info, idx.Columns) &&
1232+
rng.Intn(2) == 0 {
1233+
idxCopy := *idx
1234+
if len(idxCopy.Name) > 0 {
1235+
idxCopy.Name = tree.Name(fmt.Sprintf("%s_partial", idxCopy.Name))
1236+
}
1237+
tn := tree.MakeUnqualifiedTableName(ast.Table.ObjectName)
1238+
idxCopy.Predicate = randPartialIndexPredicateFromCols(rng, info.columnsTableDefs, &tn)
1239+
changed = true
1240+
newDefs = append(newDefs, &idxCopy)
1241+
}
1242+
}
1243+
ast.Defs = append(ast.Defs, newDefs...)
1244+
}
1245+
}
1246+
stmts = append(stmts, newStmts...)
1247+
return stmts, changed
1248+
}
1249+
11671250
// hasReferencingConstraint returns true if the tableInfo has any referencing
11681251
// columns that match idxColumns.
11691252
func hasReferencingConstraint(info tableInfo, idxColumns tree.IndexElemList) bool {

0 commit comments

Comments
 (0)