SQL Writer
This commit is contained in:
243
pkg/writers/pgsql/writer_test.go
Normal file
243
pkg/writers/pgsql/writer_test.go
Normal file
@@ -0,0 +1,243 @@
|
||||
package pgsql
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"strings"
|
||||
"testing"
|
||||
|
||||
"git.warky.dev/wdevs/relspecgo/pkg/models"
|
||||
"git.warky.dev/wdevs/relspecgo/pkg/writers"
|
||||
)
|
||||
|
||||
func TestWriteDatabase(t *testing.T) {
|
||||
// Create a test database
|
||||
db := models.InitDatabase("testdb")
|
||||
schema := models.InitSchema("public")
|
||||
|
||||
// Create a test table
|
||||
table := models.InitTable("users", "public")
|
||||
table.Description = "User accounts table"
|
||||
|
||||
// Add columns
|
||||
idCol := models.InitColumn("id", "users", "public")
|
||||
idCol.Type = "integer"
|
||||
idCol.Description = "Primary key"
|
||||
idCol.Default = "nextval('public.identity_users_id'::regclass)"
|
||||
table.Columns["id"] = idCol
|
||||
|
||||
nameCol := models.InitColumn("name", "users", "public")
|
||||
nameCol.Type = "text"
|
||||
nameCol.Description = "User name"
|
||||
table.Columns["name"] = nameCol
|
||||
|
||||
emailCol := models.InitColumn("email", "users", "public")
|
||||
emailCol.Type = "text"
|
||||
emailCol.Description = "Email address"
|
||||
table.Columns["email"] = emailCol
|
||||
|
||||
// Add primary key constraint
|
||||
pkConstraint := &models.Constraint{
|
||||
Name: "pk_users",
|
||||
Type: models.PrimaryKeyConstraint,
|
||||
Columns: []string{"id"},
|
||||
}
|
||||
table.Constraints["pk_users"] = pkConstraint
|
||||
|
||||
// Add unique index
|
||||
uniqueEmailIndex := &models.Index{
|
||||
Name: "uk_users_email",
|
||||
Unique: true,
|
||||
Columns: []string{"email"},
|
||||
}
|
||||
table.Indexes["uk_users_email"] = uniqueEmailIndex
|
||||
|
||||
schema.Tables = append(schema.Tables, table)
|
||||
db.Schemas = append(db.Schemas, schema)
|
||||
|
||||
// Create writer with output to buffer
|
||||
var buf bytes.Buffer
|
||||
options := &writers.WriterOptions{}
|
||||
writer := NewWriter(options)
|
||||
writer.writer = &buf
|
||||
|
||||
// Write the database
|
||||
err := writer.WriteDatabase(db)
|
||||
if err != nil {
|
||||
t.Fatalf("WriteDatabase failed: %v", err)
|
||||
}
|
||||
|
||||
output := buf.String()
|
||||
|
||||
// Print output for debugging
|
||||
t.Logf("Generated SQL:\n%s", output)
|
||||
|
||||
// Verify output contains expected elements
|
||||
expectedStrings := []string{
|
||||
"CREATE TABLE",
|
||||
"PRIMARY KEY",
|
||||
"UNIQUE INDEX",
|
||||
"COMMENT ON TABLE",
|
||||
"COMMENT ON COLUMN",
|
||||
}
|
||||
|
||||
for _, expected := range expectedStrings {
|
||||
if !strings.Contains(output, expected) {
|
||||
t.Errorf("Output missing expected string: %s\nFull output:\n%s", expected, output)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func TestWriteForeignKeys(t *testing.T) {
|
||||
// Create a test database with two related tables
|
||||
db := models.InitDatabase("testdb")
|
||||
schema := models.InitSchema("public")
|
||||
|
||||
// Create parent table (users)
|
||||
usersTable := models.InitTable("users", "public")
|
||||
idCol := models.InitColumn("id", "users", "public")
|
||||
idCol.Type = "integer"
|
||||
usersTable.Columns["id"] = idCol
|
||||
|
||||
// Create child table (posts)
|
||||
postsTable := models.InitTable("posts", "public")
|
||||
postIdCol := models.InitColumn("id", "posts", "public")
|
||||
postIdCol.Type = "integer"
|
||||
postsTable.Columns["id"] = postIdCol
|
||||
|
||||
userIdCol := models.InitColumn("user_id", "posts", "public")
|
||||
userIdCol.Type = "integer"
|
||||
postsTable.Columns["user_id"] = userIdCol
|
||||
|
||||
// Add foreign key constraint
|
||||
fkConstraint := &models.Constraint{
|
||||
Name: "fk_posts_users",
|
||||
Type: models.ForeignKeyConstraint,
|
||||
Columns: []string{"user_id"},
|
||||
ReferencedTable: "users",
|
||||
ReferencedSchema: "public",
|
||||
ReferencedColumns: []string{"id"},
|
||||
OnDelete: "CASCADE",
|
||||
OnUpdate: "CASCADE",
|
||||
}
|
||||
postsTable.Constraints["fk_posts_users"] = fkConstraint
|
||||
|
||||
// Add relationship
|
||||
relationship := &models.Relationship{
|
||||
Name: "fk_posts_users",
|
||||
FromTable: "posts",
|
||||
FromSchema: "public",
|
||||
ToTable: "users",
|
||||
ToSchema: "public",
|
||||
ForeignKey: "fk_posts_users",
|
||||
}
|
||||
postsTable.Relationships["fk_posts_users"] = relationship
|
||||
|
||||
schema.Tables = append(schema.Tables, usersTable, postsTable)
|
||||
db.Schemas = append(db.Schemas, schema)
|
||||
|
||||
// Create writer with output to buffer
|
||||
var buf bytes.Buffer
|
||||
options := &writers.WriterOptions{}
|
||||
writer := NewWriter(options)
|
||||
writer.writer = &buf
|
||||
|
||||
// Write the database
|
||||
err := writer.WriteDatabase(db)
|
||||
if err != nil {
|
||||
t.Fatalf("WriteDatabase failed: %v", err)
|
||||
}
|
||||
|
||||
output := buf.String()
|
||||
|
||||
// Print output for debugging
|
||||
t.Logf("Generated SQL:\n%s", output)
|
||||
|
||||
// Verify foreign key is present
|
||||
if !strings.Contains(output, "FOREIGN KEY") {
|
||||
t.Errorf("Output missing FOREIGN KEY statement\nFull output:\n%s", output)
|
||||
}
|
||||
if !strings.Contains(output, "ON DELETE CASCADE") {
|
||||
t.Errorf("Output missing ON DELETE CASCADE\nFull output:\n%s", output)
|
||||
}
|
||||
if !strings.Contains(output, "ON UPDATE CASCADE") {
|
||||
t.Errorf("Output missing ON UPDATE CASCADE\nFull output:\n%s", output)
|
||||
}
|
||||
}
|
||||
|
||||
func TestWriteTable(t *testing.T) {
|
||||
// Create a single table
|
||||
table := models.InitTable("products", "public")
|
||||
|
||||
idCol := models.InitColumn("id", "products", "public")
|
||||
idCol.Type = "integer"
|
||||
table.Columns["id"] = idCol
|
||||
|
||||
nameCol := models.InitColumn("name", "products", "public")
|
||||
nameCol.Type = "text"
|
||||
table.Columns["name"] = nameCol
|
||||
|
||||
// Create writer with output to buffer
|
||||
var buf bytes.Buffer
|
||||
options := &writers.WriterOptions{}
|
||||
writer := NewWriter(options)
|
||||
writer.writer = &buf
|
||||
|
||||
// Write the table
|
||||
err := writer.WriteTable(table)
|
||||
if err != nil {
|
||||
t.Fatalf("WriteTable failed: %v", err)
|
||||
}
|
||||
|
||||
output := buf.String()
|
||||
|
||||
// Verify output contains table creation
|
||||
if !strings.Contains(output, "CREATE TABLE") {
|
||||
t.Error("Output missing CREATE TABLE statement")
|
||||
}
|
||||
if !strings.Contains(output, "products") {
|
||||
t.Error("Output missing table name 'products'")
|
||||
}
|
||||
}
|
||||
|
||||
func TestEscapeQuote(t *testing.T) {
|
||||
tests := []struct {
|
||||
input string
|
||||
expected string
|
||||
}{
|
||||
{"simple text", "simple text"},
|
||||
{"text with 'quote'", "text with ''quote''"},
|
||||
{"multiple 'quotes' here", "multiple ''quotes'' here"},
|
||||
{"", ""},
|
||||
}
|
||||
|
||||
for _, tt := range tests {
|
||||
result := escapeQuote(tt.input)
|
||||
if result != tt.expected {
|
||||
t.Errorf("escapeQuote(%q) = %q, want %q", tt.input, result, tt.expected)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func TestIsIntegerType(t *testing.T) {
|
||||
tests := []struct {
|
||||
input string
|
||||
expected bool
|
||||
}{
|
||||
{"integer", true},
|
||||
{"INTEGER", true},
|
||||
{"bigint", true},
|
||||
{"smallint", true},
|
||||
{"serial", true},
|
||||
{"bigserial", true},
|
||||
{"text", false},
|
||||
{"varchar", false},
|
||||
{"uuid", false},
|
||||
}
|
||||
|
||||
for _, tt := range tests {
|
||||
result := isIntegerType(tt.input)
|
||||
if result != tt.expected {
|
||||
t.Errorf("isIntegerType(%q) = %v, want %v", tt.input, result, tt.expected)
|
||||
}
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user