- bun: scanonly+generated for GENERATED columns; scanonly+identity for ALWAYS identity (PK gets identity only) - gorm: <-:false+generated / identity, same primary key rule - dbml: write GENERATED/IDENTITY column notes and read them back into the model - pgsql: emit generation/identity clauses in migration create-table and add-column, no DEFAULT - readmes updated
102 lines
2.7 KiB
Go
102 lines
2.7 KiB
Go
package pgsql
|
|
|
|
import (
|
|
"strings"
|
|
"testing"
|
|
|
|
"git.warky.dev/wdevs/relspecgo/pkg/models"
|
|
"git.warky.dev/wdevs/relspecgo/pkg/writers"
|
|
)
|
|
|
|
func generationTestTable(withColumns bool) *models.Table {
|
|
table := models.InitTable("people", "public")
|
|
|
|
first := models.InitColumn("first", "people", "public")
|
|
first.Type = "text"
|
|
first.Sequence = 1
|
|
table.Columns["first"] = first
|
|
|
|
if !withColumns {
|
|
return table
|
|
}
|
|
|
|
full := models.InitColumn("full_name", "people", "public")
|
|
full.Type = "text"
|
|
full.Sequence = 2
|
|
full.Generated = true
|
|
full.GenerationExpression = "first || ' ' || last"
|
|
full.Default = "ignored"
|
|
table.Columns["full_name"] = full
|
|
|
|
ident := models.InitColumn("seq", "people", "public")
|
|
ident.Type = "bigint"
|
|
ident.Sequence = 3
|
|
ident.NotNull = true
|
|
ident.Identity = true
|
|
ident.IdentityGeneration = "ALWAYS"
|
|
table.Columns["seq"] = ident
|
|
|
|
return table
|
|
}
|
|
|
|
func generationTestDB(table *models.Table) *models.Database {
|
|
db := models.InitDatabase("testdb")
|
|
schema := models.InitSchema("public")
|
|
schema.Tables = append(schema.Tables, table)
|
|
db.Schemas = append(db.Schemas, schema)
|
|
return db
|
|
}
|
|
|
|
func TestGeneratedColumns_MigrationCreateAndAddColumn(t *testing.T) {
|
|
want := []string{
|
|
"GENERATED ALWAYS AS (first || ' ' || last) STORED",
|
|
"GENERATED ALWAYS AS IDENTITY",
|
|
}
|
|
|
|
tests := []struct {
|
|
name string
|
|
current *models.Database
|
|
}{
|
|
{"new table", models.InitDatabase("testdb")},
|
|
{"new columns on existing table", generationTestDB(generationTestTable(false))},
|
|
}
|
|
for _, tt := range tests {
|
|
t.Run(tt.name, func(t *testing.T) {
|
|
w := NewWriter(&writers.WriterOptions{})
|
|
stmts, err := w.diffStatements(generationTestDB(generationTestTable(true)), tt.current)
|
|
if err != nil {
|
|
t.Fatalf("diffStatements failed: %v", err)
|
|
}
|
|
out := diffJoin(stmts)
|
|
for _, s := range want {
|
|
if !strings.Contains(out, s) {
|
|
t.Errorf("missing %q:\n%s", s, out)
|
|
}
|
|
}
|
|
if strings.Contains(out, "DEFAULT ignored") || strings.Contains(out, "DEFAULT 'ignored'") {
|
|
t.Errorf("generated column must not carry a DEFAULT:\n%s", out)
|
|
}
|
|
})
|
|
}
|
|
}
|
|
|
|
func TestGeneratedColumns_FullDDL(t *testing.T) {
|
|
w := NewWriter(&writers.WriterOptions{})
|
|
stmts, err := w.GenerateDatabaseStatements(generationTestDB(generationTestTable(true)))
|
|
if err != nil {
|
|
t.Fatalf("GenerateDatabaseStatements failed: %v", err)
|
|
}
|
|
out := diffJoin(stmts)
|
|
for _, s := range []string{
|
|
"full_name text GENERATED ALWAYS AS (first || ' ' || last) STORED",
|
|
"seq bigint GENERATED ALWAYS AS IDENTITY NOT NULL",
|
|
} {
|
|
if !strings.Contains(out, s) {
|
|
t.Errorf("missing %q:\n%s", s, out)
|
|
}
|
|
}
|
|
if strings.Contains(out, "DEFAULT 'ignored'") {
|
|
t.Errorf("generated column must not carry a DEFAULT:\n%s", out)
|
|
}
|
|
}
|