package pgsql import ( "bytes" "strings" "testing" "git.warky.dev/wdevs/relspecgo/pkg/models" "git.warky.dev/wdevs/relspecgo/pkg/writers" ) func directiveTestDB(t *testing.T) *models.Database { t.Helper() db := models.InitDatabase("testdb") schema := models.InitSchema("public") table := models.InitTable("events", "public") id := models.InitColumn("id", "events", "public") id.Type = "bigint" id.IsPrimaryKey = true id.NotNull = true models.AddDirective(id.Metadata, models.Directive{Namespace: "postgres", Args: "identity always"}) models.AddDirective(id.Metadata, models.Directive{Namespace: "sqlite", Args: "collate NOCASE"}) table.Columns["id"] = id created := models.InitColumn("created_at", "events", "public") created.Type = "timestamp" created.NotNull = true table.Columns["created_at"] = created models.AddDirective(table.Metadata, models.Directive{Namespace: "postgres", Args: "partition by RANGE (created_at)"}) models.AddDirective(table.Metadata, models.Directive{Namespace: "postgres", Args: "tablespace fast_data"}) models.AddDirective(table.Metadata, models.Directive{Namespace: "sqlite", Args: "without rowid"}) idx := models.InitIndex("idx_events_created", "events", "public") idx.Columns = []string{"created_at"} models.AddDirective(idx.Metadata, models.Directive{Namespace: "postgres", Args: "with (fillfactor=90)"}) models.AddDirective(idx.Metadata, models.Directive{Namespace: "postgres", Args: "tablespace idx_space"}) table.Indexes["idx_events_created"] = idx schema.Tables = append(schema.Tables, table) db.Schemas = append(db.Schemas, schema) return db } func TestPgDirectives_WriteDatabasePath(t *testing.T) { var buf bytes.Buffer w := NewWriter(&writers.WriterOptions{}) w.writer = &buf if err := w.WriteDatabase(directiveTestDB(t)); err != nil { t.Fatalf("WriteDatabase: %v", err) } out := buf.String() for _, want := range []string{ ") PARTITION BY RANGE (created_at) TABLESPACE fast_data", "GENERATED ALWAYS AS IDENTITY", "WITH (fillfactor=90) TABLESPACE idx_space", } { if !strings.Contains(out, want) { t.Errorf("missing %q in:\n%s", want, out) } } // sqlite directives must never reach PG output. if strings.Contains(out, "WITHOUT ROWID") || strings.Contains(strings.ToUpper(out), "COLLATE NOCASE") { t.Errorf("sqlite directive leaked into PG output:\n%s", out) } } func TestPgDirectives_WriteSchemaPath(t *testing.T) { var buf bytes.Buffer w := NewWriter(&writers.WriterOptions{}) w.writer = &buf if err := w.WriteSchema(directiveTestDB(t).Schemas[0]); err != nil { t.Fatalf("WriteSchema: %v", err) } out := buf.String() if !strings.Contains(out, ") PARTITION BY RANGE (created_at) TABLESPACE fast_data;") { t.Errorf("table suffix missing from WriteSchema path:\n%s", out) } if !strings.Contains(out, "WITH (fillfactor=90) TABLESPACE idx_space") { t.Errorf("index clauses missing from WriteSchema path:\n%s", out) } } func TestPgDirectives_StrictUnknownKeyErrors(t *testing.T) { db := directiveTestDB(t) models.AddDirective(db.Schemas[0].Tables[0].Metadata, models.Directive{Namespace: "postgres", Args: "frobnicate x"}) var buf bytes.Buffer w := NewWriter(&writers.WriterOptions{StrictDirectives: true}) w.writer = &buf err := w.WriteSchema(db.Schemas[0]) if err == nil || !strings.Contains(err.Error(), "frobnicate") { t.Fatalf("want strict error for unknown postgres key, got %v", err) } } func TestPgDirectives_StrictIgnoresOtherNamespaces(t *testing.T) { // sqlite directives are present but must not trip PG strict mode. var buf bytes.Buffer w := NewWriter(&writers.WriterOptions{StrictDirectives: true}) w.writer = &buf if err := w.WriteSchema(directiveTestDB(t).Schemas[0]); err != nil { t.Fatalf("strict mode should ignore non-postgres directives, got %v", err) } }