(metadata *storepb.DatabaseSchemaMetadata)
| 2542 | } |
| 2543 | |
| 2544 | func getSDLFormat(metadata *storepb.DatabaseSchemaMetadata) (string, error) { |
| 2545 | var buf strings.Builder |
| 2546 | |
| 2547 | tablesMissingColumns := collectTables(metadata.Schemas, tableMissingColumnMetadata) |
| 2548 | tablesWithoutColumns := collectTables(metadata.Schemas, tableHasNoColumns) |
| 2549 | |
| 2550 | // Write CREATE SCHEMA statements first for non-public schemas |
| 2551 | for _, schema := range metadata.Schemas { |
| 2552 | if schema.SkipDump { |
| 2553 | continue |
| 2554 | } |
| 2555 | if err := writeSchema(&buf, schema); err != nil { |
| 2556 | return "", err |
| 2557 | } |
| 2558 | |
| 2559 | // Write schema comment if present |
| 2560 | if len(schema.Comment) > 0 { |
| 2561 | if err := writeSchemaCommentSDL(&buf, schema); err != nil { |
| 2562 | return "", err |
| 2563 | } |
| 2564 | } |
| 2565 | } |
| 2566 | |
| 2567 | // Write extensions (before enum types and tables as they might provide types used in definitions) |
| 2568 | for _, extension := range metadata.Extensions { |
| 2569 | if err := writeExtension(&buf, extension); err != nil { |
| 2570 | return "", err |
| 2571 | } |
| 2572 | } |
| 2573 | |
| 2574 | // Build a map of serial and identity sequences that should be skipped |
| 2575 | // Serial sequences are identified by checking if their owner columns match the serial pattern |
| 2576 | // Identity sequences are identified by checking if their owner columns have IdentityGeneration set |
| 2577 | skipSequences := make(map[string]bool) |
| 2578 | for _, schema := range metadata.Schemas { |
| 2579 | if schema.SkipDump { |
| 2580 | continue |
| 2581 | } |
| 2582 | for _, table := range schema.Tables { |
| 2583 | if table.SkipDump { |
| 2584 | continue |
| 2585 | } |
| 2586 | for _, column := range table.Columns { |
| 2587 | // Check for serial columns |
| 2588 | isSerial, _ := isSerialColumn(column, table.Name, schema.Sequences) |
| 2589 | if isSerial { |
| 2590 | // Extract the sequence name from the DEFAULT clause to match the exact sequence |
| 2591 | // This ensures we skip the correct sequence, especially when multiple sequences |
| 2592 | // claim ownership of the same column. |
| 2593 | sequenceName := extractSequenceNameFromNextval(column.Default) |
| 2594 | |
| 2595 | // Find the sequence that belongs to this serial column |
| 2596 | for _, sequence := range schema.Sequences { |
| 2597 | // Match by sequence name AND ownership to ensure we skip the exact sequence |
| 2598 | // referenced in the DEFAULT clause |
| 2599 | if sequence.Name == sequenceName && sequence.OwnerTable == table.Name && sequence.OwnerColumn == column.Name { |
| 2600 | sequenceKey := schema.Name + "." + sequence.Name |
| 2601 | skipSequences[sequenceKey] = true |
no test coverage detected