feat(writer): 🎉 Implement add column statements for schema evolution
All checks were successful
CI / Test (1.24) (push) Successful in -26m24s
CI / Test (1.25) (push) Successful in -26m14s
CI / Lint (push) Successful in -26m30s
CI / Build (push) Successful in -26m41s
Release / Build and Release (push) Successful in -26m29s
Integration Tests / Integration Tests (push) Successful in -26m13s
All checks were successful
CI / Test (1.24) (push) Successful in -26m24s
CI / Test (1.25) (push) Successful in -26m14s
CI / Lint (push) Successful in -26m30s
CI / Build (push) Successful in -26m41s
Release / Build and Release (push) Successful in -26m29s
Integration Tests / Integration Tests (push) Successful in -26m13s
* Add functionality to generate ALTER TABLE ADD COLUMN statements for existing tables. * Introduce tests for generating and writing add column statements. * Enhance schema evolution capabilities when new columns are added.
This commit is contained in:
@@ -438,3 +438,130 @@ func TestColumnSizeSpecifiers(t *testing.T) {
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func TestGenerateAddColumnStatements(t *testing.T) {
|
||||
// Create a test database with tables that have new columns
|
||||
db := models.InitDatabase("testdb")
|
||||
schema := models.InitSchema("public")
|
||||
|
||||
// Create a table with columns
|
||||
table := models.InitTable("users", "public")
|
||||
|
||||
// Existing column
|
||||
idCol := models.InitColumn("id", "users", "public")
|
||||
idCol.Type = "integer"
|
||||
idCol.NotNull = true
|
||||
idCol.Sequence = 1
|
||||
table.Columns["id"] = idCol
|
||||
|
||||
// New column to be added
|
||||
emailCol := models.InitColumn("email", "users", "public")
|
||||
emailCol.Type = "varchar"
|
||||
emailCol.Length = 255
|
||||
emailCol.NotNull = true
|
||||
emailCol.Sequence = 2
|
||||
table.Columns["email"] = emailCol
|
||||
|
||||
// New column with default
|
||||
statusCol := models.InitColumn("status", "users", "public")
|
||||
statusCol.Type = "text"
|
||||
statusCol.Default = "active"
|
||||
statusCol.Sequence = 3
|
||||
table.Columns["status"] = statusCol
|
||||
|
||||
schema.Tables = append(schema.Tables, table)
|
||||
db.Schemas = append(db.Schemas, schema)
|
||||
|
||||
// Create writer
|
||||
options := &writers.WriterOptions{}
|
||||
writer := NewWriter(options)
|
||||
|
||||
// Generate ADD COLUMN statements
|
||||
statements, err := writer.GenerateAddColumnsForDatabase(db)
|
||||
if err != nil {
|
||||
t.Fatalf("GenerateAddColumnsForDatabase failed: %v", err)
|
||||
}
|
||||
|
||||
// Join all statements to verify content
|
||||
output := strings.Join(statements, "\n")
|
||||
t.Logf("Generated ADD COLUMN statements:\n%s", output)
|
||||
|
||||
// Verify expected elements
|
||||
expectedStrings := []string{
|
||||
"ALTER TABLE public.users ADD COLUMN id integer NOT NULL",
|
||||
"ALTER TABLE public.users ADD COLUMN email varchar(255) NOT NULL",
|
||||
"ALTER TABLE public.users ADD COLUMN status text DEFAULT 'active'",
|
||||
"information_schema.columns",
|
||||
"table_schema = 'public'",
|
||||
"table_name = 'users'",
|
||||
"column_name = 'id'",
|
||||
"column_name = 'email'",
|
||||
"column_name = 'status'",
|
||||
}
|
||||
|
||||
for _, expected := range expectedStrings {
|
||||
if !strings.Contains(output, expected) {
|
||||
t.Errorf("Output missing expected string: %s\nFull output:\n%s", expected, output)
|
||||
}
|
||||
}
|
||||
|
||||
// Verify DO blocks are present for conditional adds
|
||||
doBlockCount := strings.Count(output, "DO $$")
|
||||
if doBlockCount < 3 {
|
||||
t.Errorf("Expected at least 3 DO blocks (one per column), got %d", doBlockCount)
|
||||
}
|
||||
|
||||
// Verify IF NOT EXISTS logic
|
||||
ifNotExistsCount := strings.Count(output, "IF NOT EXISTS")
|
||||
if ifNotExistsCount < 3 {
|
||||
t.Errorf("Expected at least 3 IF NOT EXISTS checks (one per column), got %d", ifNotExistsCount)
|
||||
}
|
||||
}
|
||||
|
||||
func TestWriteAddColumnStatements(t *testing.T) {
|
||||
// Create a test database
|
||||
db := models.InitDatabase("testdb")
|
||||
schema := models.InitSchema("public")
|
||||
|
||||
// Create a table with a new column to be added
|
||||
table := models.InitTable("products", "public")
|
||||
|
||||
idCol := models.InitColumn("id", "products", "public")
|
||||
idCol.Type = "integer"
|
||||
table.Columns["id"] = idCol
|
||||
|
||||
// New column with various properties
|
||||
descCol := models.InitColumn("description", "products", "public")
|
||||
descCol.Type = "text"
|
||||
descCol.NotNull = false
|
||||
table.Columns["description"] = descCol
|
||||
|
||||
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 ADD COLUMN statements
|
||||
err := writer.WriteAddColumnStatements(db)
|
||||
if err != nil {
|
||||
t.Fatalf("WriteAddColumnStatements failed: %v", err)
|
||||
}
|
||||
|
||||
output := buf.String()
|
||||
t.Logf("Generated output:\n%s", output)
|
||||
|
||||
// Verify output contains expected elements
|
||||
if !strings.Contains(output, "ALTER TABLE public.products ADD COLUMN id integer") {
|
||||
t.Errorf("Output missing ADD COLUMN for id\nFull output:\n%s", output)
|
||||
}
|
||||
if !strings.Contains(output, "ALTER TABLE public.products ADD COLUMN description text") {
|
||||
t.Errorf("Output missing ADD COLUMN for description\nFull output:\n%s", output)
|
||||
}
|
||||
if !strings.Contains(output, "DO $$") {
|
||||
t.Errorf("Output missing DO block\nFull output:\n%s", output)
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user