@@ -4,20 +4,12 @@ import (
4
4
"fmt"
5
5
"sort"
6
6
7
- "github.com/stripe/pg-schema-diff/internal/graph"
8
7
"github.com/stripe/pg-schema-diff/internal/schema"
9
8
)
10
9
11
10
var ErrNotImplemented = fmt .Errorf ("not implemented" )
12
11
var errDuplicateIdentifier = fmt .Errorf ("duplicate identifier" )
13
12
14
- type diffType string
15
-
16
- const (
17
- diffTypeDelete diffType = "DELETE"
18
- diffTypeAddAlter diffType = "ADDALTER"
19
- )
20
-
21
13
type (
22
14
diff [S schema.Object ] interface {
23
15
GetOld () S
@@ -32,79 +24,8 @@ type (
32
24
// provided diff. Alter, e.g., with a table, might produce add/delete statements
33
25
Alter (Diff ) ([]Statement , error )
34
26
}
35
-
36
- // dependency indicates an edge between the SQL to resolve a diff for a source schema object and the SQL to resolve
37
- // the diff of a target schema object
38
- //
39
- // Most SchemaObjects will have two nodes in the SQL graph: a node for delete SQL and a node for add/alter SQL.
40
- // These nodes will almost always be present in the sqlGraph even if the schema object is not being deleted (or added/altered).
41
- // If a node is present for a schema object where the "diffType" is NOT occurring, it will just be a no-op (no SQl statements)
42
- dependency struct {
43
- sourceObjId string
44
- sourceType diffType
45
-
46
- targetObjId string
47
- targetType diffType
48
- }
49
27
)
50
28
51
- type dependencyBuilder struct {
52
- valObjId string
53
- valType diffType
54
- }
55
-
56
- func mustRun (schemaObjId string , schemaDiffType diffType ) dependencyBuilder {
57
- return dependencyBuilder {
58
- valObjId : schemaObjId ,
59
- valType : schemaDiffType ,
60
- }
61
- }
62
-
63
- func (d dependencyBuilder ) before (valObjId string , valType diffType ) dependency {
64
- return dependency {
65
- sourceType : d .valType ,
66
- sourceObjId : d .valObjId ,
67
-
68
- targetType : valType ,
69
- targetObjId : valObjId ,
70
- }
71
- }
72
-
73
- func (d dependencyBuilder ) after (valObjId string , valType diffType ) dependency {
74
- return dependency {
75
- sourceObjId : valObjId ,
76
- sourceType : valType ,
77
-
78
- targetObjId : d .valObjId ,
79
- targetType : d .valType ,
80
- }
81
- }
82
-
83
- // sqlVertexGenerator is used to generate SQL statements for schema objects that have dependency webs
84
- // with other schema objects. The schema object represents a vertex in the graph.
85
- type sqlVertexGenerator [S schema.Object , Diff diff [S ]] interface {
86
- sqlGenerator [S , Diff ]
87
- // GetSQLVertexId gets the canonical vertex id to represent the schema object
88
- GetSQLVertexId (S ) string
89
-
90
- // GetAddAlterDependencies gets the dependencies of the SQL generated to resolve the AddAlter diff for the
91
- // schema objects. Dependencies can be formed on any other nodes in the SQL graph, even if the node has
92
- // no statements. If the diff is just an add, then old will be the zero value
93
- //
94
- // These dependencies can also be built in reverse: the SQL returned by the sqlVertexGenerator to resolve the
95
- // diff for the object must always be run before the SQL required to resolve another SQL vertex diff
96
- GetAddAlterDependencies (new S , old S ) ([]dependency , error )
97
-
98
- // GetDeleteDependencies is the same as above but for deletes.
99
- // Invariant to maintain:
100
- // - If an object X depends on the delete for an object Y (generated by the sqlVertexGenerator), immediately after the
101
- // the (Y, diffTypeDelete) sqlVertex's SQL is run, Y must no longer be present in the schema; either the
102
- // (Y, diffTypeDelete) statements deleted Y or something that vertex depended on deleted Y. In other words, if a
103
- // delete is cascaded by another delete (e.g., index dropped by table drop) and the index SQL is empty,
104
- // the index delete vertex must still have dependency from itself to the object from which the delete cascades down from
105
- GetDeleteDependencies (S ) ([]dependency , error )
106
- }
107
-
108
29
type (
109
30
// listDiff represents the differences between two lists.
110
31
listDiff [S schema.Object , Diff diff [S ]] struct {
@@ -158,120 +79,6 @@ func (ld listDiff[S, D]) resolveToSQLGroupedByEffect(sqlGenerator sqlGenerator[S
158
79
}, nil
159
80
}
160
81
161
- func (ld listDiff [S , D ]) resolveToSQLGraph (generator sqlVertexGenerator [S , D ]) (* sqlGraph , error ) {
162
- graph := graph .NewGraph [sqlVertex ]()
163
-
164
- for _ , a := range ld .adds {
165
- statements , err := generator .Add (a )
166
- if err != nil {
167
- return nil , fmt .Errorf ("generating SQL for add %s: %w" , a .GetName (), err )
168
- }
169
-
170
- deps , err := generator .GetAddAlterDependencies (a , * new (S ))
171
- if err != nil {
172
- return nil , fmt .Errorf ("getting dependencies for add %s: %w" , a .GetName (), err )
173
- }
174
- if err := addSQLVertexToGraph (graph , sqlVertex {
175
- ObjId : generator .GetSQLVertexId (a ),
176
- Statements : statements ,
177
- DiffType : diffTypeAddAlter ,
178
- }, deps ); err != nil {
179
- return nil , fmt .Errorf ("adding SQL Vertex for add %s: %w" , a .GetName (), err )
180
- }
181
- }
182
-
183
- for _ , a := range ld .alters {
184
- statements , err := generator .Alter (a )
185
- if err != nil {
186
- return nil , fmt .Errorf ("generating SQL for diff %+v: %w" , a , err )
187
- }
188
-
189
- vertexId := generator .GetSQLVertexId (a .GetOld ())
190
- vertexIdAfterAlter := generator .GetSQLVertexId (a .GetNew ())
191
- if vertexIdAfterAlter != vertexId {
192
- return nil , fmt .Errorf ("an alter lead to a node with a different id: old=%s, new=%s" , vertexId , vertexIdAfterAlter )
193
- }
194
-
195
- deps , err := generator .GetAddAlterDependencies (a .GetNew (), a .GetOld ())
196
- if err != nil {
197
- return nil , fmt .Errorf ("getting dependencies for alter %s: %w" , a .GetOld ().GetName (), err )
198
- }
199
-
200
- if err := addSQLVertexToGraph (graph , sqlVertex {
201
- ObjId : vertexId ,
202
- Statements : statements ,
203
- DiffType : diffTypeAddAlter ,
204
- }, deps ); err != nil {
205
- return nil , fmt .Errorf ("adding SQL Vertex for alter %s: %w" , a .GetOld ().GetName (), err )
206
- }
207
- }
208
-
209
- for _ , d := range ld .deletes {
210
- statements , err := generator .Delete (d )
211
- if err != nil {
212
- return nil , fmt .Errorf ("generating SQL for delete %s: %w" , d .GetName (), err )
213
- }
214
-
215
- deps , err := generator .GetDeleteDependencies (d )
216
- if err != nil {
217
- return nil , fmt .Errorf ("getting dependencies for delete %s: %w" , d .GetName (), err )
218
- }
219
-
220
- if err := addSQLVertexToGraph (graph , sqlVertex {
221
- ObjId : generator .GetSQLVertexId (d ),
222
- Statements : statements ,
223
- DiffType : diffTypeDelete ,
224
- }, deps ); err != nil {
225
- return nil , fmt .Errorf ("adding SQL Vertex for delete %s: %w" , d .GetName (), err )
226
- }
227
- }
228
-
229
- return (* sqlGraph )(graph ), nil
230
- }
231
-
232
- func addSQLVertexToGraph (graph * graph.Graph [sqlVertex ], vertex sqlVertex , dependencies []dependency ) error {
233
- // It's possible the node already exists. merge it if it does
234
- if graph .HasVertexWithId (vertex .GetId ()) {
235
- vertex = mergeSQLVertices (graph .GetVertex (vertex .GetId ()), vertex )
236
- }
237
- graph .AddVertex (vertex )
238
- for _ , dep := range dependencies {
239
- if err := addDependency (graph , dep ); err != nil {
240
- return fmt .Errorf ("adding dependencies for %s: %w" , vertex .GetId (), err )
241
- }
242
- }
243
- return nil
244
- }
245
-
246
- func addDependency (graph * graph.Graph [sqlVertex ], dep dependency ) error {
247
- sourceVertex := sqlVertex {
248
- ObjId : dep .sourceObjId ,
249
- DiffType : dep .sourceType ,
250
- Statements : nil ,
251
- }
252
- targetVertex := sqlVertex {
253
- ObjId : dep .targetObjId ,
254
- DiffType : dep .targetType ,
255
- Statements : nil ,
256
- }
257
-
258
- // To maintain the correctness of the graph, we will add a dummy vertex for the missing dependencies
259
- addVertexIfNotExists (graph , sourceVertex )
260
- addVertexIfNotExists (graph , targetVertex )
261
-
262
- if err := graph .AddEdge (sourceVertex .GetId (), targetVertex .GetId ()); err != nil {
263
- return fmt .Errorf ("adding edge from %s to %s: %w" , sourceVertex .GetId (), targetVertex .GetId (), err )
264
- }
265
-
266
- return nil
267
- }
268
-
269
- func addVertexIfNotExists (graph * graph.Graph [sqlVertex ], vertex sqlVertex ) {
270
- if ! graph .HasVertexWithId (vertex .GetId ()) {
271
- graph .AddVertex (vertex )
272
- }
273
- }
274
-
275
82
type schemaObjectEntry [S schema.Object ] struct {
276
83
index int // index is the index the schema object in the list
277
84
obj S
0 commit comments