Skip to content

Commit 44ca2db

Browse files
authored
chore(go): Make PK order be breaking (#6021)
1 parent 35b2cfc commit 44ca2db

3 files changed

Lines changed: 367 additions & 6 deletions

File tree

scripts/table_diff/changes/changes.go

Lines changed: 45 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,7 @@ import (
1212

1313
var (
1414
columnRegex = regexp.MustCompile(`^\|(?P<name>.*)\|(?P<dataType>.*)\|`)
15+
pkRegex = regexp.MustCompile(`^The composite primary key for this table is \(([^)]+)\)\.`)
1516
)
1617

1718
type change struct {
@@ -47,11 +48,33 @@ func parseColumnChange(line string) (name string, dataType string, pk bool) {
4748
return cleanName, result["dataType"], result["name"] != cleanName
4849
}
4950

51+
func parsePKChange(line string) (names []string) {
52+
match := pkRegex.FindStringSubmatch(line)
53+
if len(match) != 2 {
54+
return nil
55+
}
56+
for _, part := range strings.Split(match[1], ", ") {
57+
names = append(names, strings.Trim(part, "*"))
58+
}
59+
return
60+
}
61+
5062
func getColumnChanges(file *gitdiff.File, table string) (changes []change) {
5163
addedColumns := make(map[string]column)
5264
deletedColumns := make(map[string]column)
65+
var addedPK, deletedPK []string
5366
for _, fragment := range file.TextFragments {
5467
for _, line := range fragment.Lines {
68+
pkChanges := parsePKChange(line.Line)
69+
if len(pkChanges) > 0 {
70+
switch line.Op {
71+
case gitdiff.OpAdd:
72+
addedPK = pkChanges
73+
case gitdiff.OpDelete:
74+
deletedPK = pkChanges
75+
}
76+
continue
77+
}
5578
name, dataType, pk := parseColumnChange(line.Line)
5679
if name == "" || dataType == "" {
5780
continue
@@ -115,16 +138,32 @@ func getColumnChanges(file *gitdiff.File, table string) (changes []change) {
115138
}
116139
}
117140

141+
// check PK:
142+
if len(addedPK) > 0 && len(addedPK) == len(deletedPK) {
143+
// if they are unequal the pk added/removed is correct.
144+
changes = append(changes, change{
145+
Text: fmt.Sprintf("Table %s: primary key order changed from %s to %s",
146+
backtickStrings(
147+
table,
148+
strings.Join(deletedPK, ", "),
149+
strings.Join(addedPK, ", "),
150+
)...,
151+
),
152+
Breaking: true,
153+
})
154+
}
155+
118156
sort.SliceStable(changes, func(i, j int) bool {
119-
iBreaking := changes[i].Breaking
120-
jBreaking := changes[j].Breaking
121-
if iBreaking && !jBreaking {
157+
chI := changes[i]
158+
chJ := changes[j]
159+
switch {
160+
case chI.Breaking && !chJ.Breaking:
122161
return true
123-
}
124-
if !iBreaking && jBreaking {
162+
case !chI.Breaking && chJ.Breaking:
125163
return false
164+
default:
165+
return chI.Text < chJ.Text
126166
}
127-
return changes[i].Text < changes[j].Text
128167
})
129168
return changes
130169
}

scripts/table_diff/changes/changes_test.go

Lines changed: 110 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -47,6 +47,26 @@ func Test_parseColumnChange(t *testing.T) {
4747
}
4848
}
4949

50+
func Test_parsePKChange(t *testing.T) {
51+
type args struct {
52+
line string
53+
}
54+
tests := []struct {
55+
name string
56+
args args
57+
wantNames []string
58+
}{
59+
{name: "PK present", args: args{line: "The composite primary key for this table is (**org**, **id**, **hook_id**)."}, wantNames: []string{"org", "id", "hook_id"}},
60+
{name: "no PK", args: args{}, wantNames: nil},
61+
}
62+
for _, tt := range tests {
63+
t.Run(tt.name, func(t *testing.T) {
64+
gotNames := parsePKChange(tt.args.line)
65+
require.Equal(t, tt.wantNames, gotNames)
66+
})
67+
}
68+
}
69+
5070
func Test_getChanges(t *testing.T) {
5171
tests := []struct {
5272
name string
@@ -201,6 +221,96 @@ func Test_getChanges(t *testing.T) {
201221
},
202222
},
203223
},
224+
{
225+
name: "Should mark PK order change as breaking",
226+
diffDataFile: "testdata/pr_6012_diff.txt",
227+
wantChanges: []change{
228+
{
229+
Text: "Table `github_external_groups`: column order changed for `updated_at`",
230+
Breaking: false,
231+
},
232+
{
233+
Text: "Table `github_hook_deliveries`: primary key order changed from `org, id, hook_id` to `org, hook_id, id`",
234+
Breaking: true,
235+
},
236+
{
237+
Text: "Table `github_hook_deliveries`: column order changed for `delivered_at`",
238+
Breaking: false,
239+
},
240+
{
241+
Text: "Table `github_hook_deliveries`: column order changed for `id`",
242+
Breaking: false,
243+
},
244+
{
245+
Text: "Table `github_hooks`: column order changed for `id`",
246+
Breaking: false,
247+
},
248+
{
249+
Text: "Table `github_issues`: column added with name `state_reason` and type `String`",
250+
Breaking: false,
251+
},
252+
{
253+
Text: "Table `github_organization_members`: column order changed for `id`",
254+
Breaking: false,
255+
},
256+
{
257+
Text: "Table `github_organizations`: column order changed for `id`",
258+
Breaking: false,
259+
},
260+
{
261+
Text: "Table `github_repositories`: column added with name `has_discussions` and type `Bool`",
262+
Breaking: false,
263+
},
264+
{
265+
Text: "Table `github_repositories`: column order changed for `created_at`",
266+
Breaking: false,
267+
},
268+
{
269+
Text: "Table `github_repositories`: column order changed for `pushed_at`",
270+
Breaking: false,
271+
},
272+
{
273+
Text: "Table `github_repositories`: column order changed for `updated_at`",
274+
Breaking: false,
275+
},
276+
{
277+
Text: "Table `github_team_members`: primary key order changed from `org, id, team_id` to `org, team_id, id`",
278+
Breaking: true,
279+
},
280+
{
281+
Text: "Table `github_team_members`: column order changed for `id`",
282+
Breaking: false,
283+
},
284+
{
285+
Text: "Table `github_team_repositories`: primary key order changed from `org, id, team_id` to `org, team_id, id`",
286+
Breaking: true,
287+
},
288+
{
289+
Text: "Table `github_team_repositories`: column added with name `has_discussions` and type `Bool`",
290+
Breaking: false,
291+
},
292+
{
293+
Text: "Table `github_team_repositories`: column order changed for `created_at`",
294+
Breaking: false,
295+
},
296+
{
297+
Text: "Table `github_team_repositories`: column order changed for `id`",
298+
Breaking: false,
299+
},
300+
{
301+
Text: "Table `github_team_repositories`: column order changed for `pushed_at`",
302+
Breaking: false,
303+
},
304+
{
305+
Text: "Table `github_team_repositories`: column order changed for `updated_at`",
306+
Breaking: false,
307+
},
308+
{
309+
Text: "Table `github_workflows`: column order changed for `id`",
310+
Breaking: false,
311+
},
312+
},
313+
},
204314
}
205315
for _, tt := range tests {
206316
t.Run(tt.name, func(t *testing.T) {

0 commit comments

Comments
 (0)