fix(sqlite): emit inline foreign keys, bare-name default schema, direct exec

SQLite can't ALTER TABLE ADD CONSTRAINT, so foreign keys are now written
as inline FOREIGN KEY clauses in CREATE TABLE instead of commented-out
ALTER statements. The default schema (public/main) now produces bare
table names instead of a "public_" prefix; other schemas are still
prefixed to avoid collisions. Also adds direct-to-file execution: the
sqlite writer can now apply generated DDL straight to a .db file via
Metadata["connection_string"], wired into `relspec merge --output-conn`.
This commit is contained in:
Hein
2026-08-24 11:52:24 +02:00
parent 51b63f659e
commit 2b6bb7f948
7 changed files with 217 additions and 106 deletions
+44 -18
View File
@@ -40,10 +40,22 @@ func NewTemplateExecutor(opts *writers.WriterOptions) (*TemplateExecutor, error)
// TableTemplateData contains data for table template
type TableTemplateData struct {
Schema string
Name string
Columns []*models.Column
PrimaryKey *models.Constraint
Schema string
Name string
Columns []*models.Column
PrimaryKey *models.Constraint
ForeignKeys []ForeignKeyTemplateData
}
// ForeignKeyTemplateData contains data for an inline FOREIGN KEY clause
type ForeignKeyTemplateData struct {
Name string
Columns []string
ForeignSchema string
ForeignTable string
ForeignColumns []string
OnDelete string
OnUpdate string
}
// IndexTemplateData contains data for index template
@@ -120,16 +132,6 @@ func (te *TemplateExecutor) ExecuteCreateCheckConstraint(data ConstraintTemplate
return buf.String(), nil
}
// ExecuteCreateForeignKey executes the create foreign key template
func (te *TemplateExecutor) ExecuteCreateForeignKey(data ConstraintTemplateData) (string, error) {
var buf bytes.Buffer
err := te.templates.ExecuteTemplate(&buf, "create_foreign_key.tmpl", data)
if err != nil {
return "", fmt.Errorf("failed to execute create_foreign_key template: %w", err)
}
return buf.String(), nil
}
// Helper functions to build template data from models
// BuildTableTemplateData builds TableTemplateData from a models.Table
@@ -162,11 +164,35 @@ func BuildTableTemplateData(schema string, table *models.Table) TableTemplateDat
}
}
// Collect foreign keys for inline FOREIGN KEY clauses
var fks []ForeignKeyTemplateData
for _, constraint := range sortConstraints(table.Constraints) {
if constraint.Type != models.ForeignKeyConstraint {
continue
}
refSchema := tableSchemaName(constraint.ReferencedSchema)
if refSchema == "" {
refSchema = schema
}
fks = append(fks, ForeignKeyTemplateData{
Name: constraint.Name,
Columns: constraint.Columns,
ForeignSchema: refSchema,
ForeignTable: constraint.ReferencedTable,
ForeignColumns: constraint.ReferencedColumns,
OnDelete: constraint.OnDelete,
OnUpdate: constraint.OnUpdate,
})
}
return TableTemplateData{
Schema: schema,
Name: table.Name,
Columns: columns,
PrimaryKey: pk,
Schema: schema,
Name: table.Name,
Columns: columns,
PrimaryKey: pk,
ForeignKeys: fks,
}
}