createTablesInOrder creates tables in topological order (dependencies first based on foreign keys)
(diff *schema.MetadataDiff, buf *strings.Builder)
| 1270 | |
| 1271 | // createTablesInOrder creates tables in topological order (dependencies first based on foreign keys) |
| 1272 | func createTablesInOrder(diff *schema.MetadataDiff, buf *strings.Builder) { |
| 1273 | // Build dependency graph for tables being created |
| 1274 | graph := base.NewGraph() |
| 1275 | tableMap := make(map[string]*schema.TableDiff) |
| 1276 | |
| 1277 | // First pass: Add all tables to be created to the graph and tableMap |
| 1278 | // Sort for deterministic processing order |
| 1279 | var tablesToCreate []*schema.TableDiff |
| 1280 | for _, tableDiff := range diff.TableChanges { |
| 1281 | if tableDiff.Action == schema.MetadataDiffActionCreate { |
| 1282 | tablesToCreate = append(tablesToCreate, tableDiff) |
| 1283 | } |
| 1284 | } |
| 1285 | slices.SortFunc(tablesToCreate, func(i, j *schema.TableDiff) int { |
| 1286 | iFullName := getObjectID(i.SchemaName, i.TableName) |
| 1287 | jFullName := getObjectID(j.SchemaName, j.TableName) |
| 1288 | if iFullName < jFullName { |
| 1289 | return -1 |
| 1290 | } |
| 1291 | if iFullName > jFullName { |
| 1292 | return 1 |
| 1293 | } |
| 1294 | return 0 |
| 1295 | }) |
| 1296 | |
| 1297 | for _, tableDiff := range tablesToCreate { |
| 1298 | tableID := getObjectID(tableDiff.SchemaName, tableDiff.TableName) |
| 1299 | graph.AddNode(tableID) |
| 1300 | tableMap[tableID] = tableDiff |
| 1301 | } |
| 1302 | |
| 1303 | // Second pass: Add dependency edges based on foreign keys |
| 1304 | for _, tableDiff := range tablesToCreate { |
| 1305 | tableID := getObjectID(tableDiff.SchemaName, tableDiff.TableName) |
| 1306 | |
| 1307 | // Add edges based on foreign key dependencies |
| 1308 | if tableDiff.NewTable != nil { |
| 1309 | for _, fk := range tableDiff.NewTable.ForeignKeys { |
| 1310 | // Create dependency ID for the referenced table |
| 1311 | refTableID := getObjectID(fk.ReferencedSchema, fk.ReferencedTable) |
| 1312 | |
| 1313 | // Only add edge if the referenced table is also being created |
| 1314 | if _, exists := tableMap[refTableID]; exists { |
| 1315 | // Edge from referenced table to this table (referenced must be created first) |
| 1316 | graph.AddEdge(refTableID, tableID) |
| 1317 | } |
| 1318 | } |
| 1319 | } |
| 1320 | } |
| 1321 | |
| 1322 | // Get topological order |
| 1323 | orderedList, err := graph.TopologicalSort() |
| 1324 | if err != nil { |
| 1325 | // If there's a cycle or error, fall back to alphabetical order |
| 1326 | for _, tableDiff := range tablesToCreate { |
| 1327 | createTableSQL := generateCreateTable(tableDiff.SchemaName, tableDiff.TableName, tableDiff.NewTable) |
| 1328 | _, _ = buf.WriteString(createTableSQL) |
| 1329 | _, _ = buf.WriteString("\n") |
no test coverage detected