feat(writer): 🎉 Enhance primary key handling and add tests
All checks were successful
CI / Test (1.24) (push) Successful in -26m18s
CI / Test (1.25) (push) Successful in -26m11s
CI / Build (push) Successful in -26m43s
CI / Lint (push) Successful in -26m34s
Release / Build and Release (push) Successful in -26m31s
Integration Tests / Integration Tests (push) Successful in -26m20s
All checks were successful
CI / Test (1.24) (push) Successful in -26m18s
CI / Test (1.25) (push) Successful in -26m11s
CI / Build (push) Successful in -26m43s
CI / Lint (push) Successful in -26m34s
Release / Build and Release (push) Successful in -26m31s
Integration Tests / Integration Tests (push) Successful in -26m20s
* Implement checks for existing primary keys before adding new ones. * Drop auto-generated primary keys if they exist. * Add tests for primary key existence and column size specifiers. * Improve type conversion handling for PostgreSQL compatibility.
This commit is contained in:
@@ -305,3 +305,136 @@ func TestTypeConversion(t *testing.T) {
|
||||
t.Errorf("Output missing 'smallint' type (converted from 'int16')\nFull output:\n%s", output)
|
||||
}
|
||||
}
|
||||
|
||||
func TestPrimaryKeyExistenceCheck(t *testing.T) {
|
||||
db := models.InitDatabase("testdb")
|
||||
schema := models.InitSchema("public")
|
||||
table := models.InitTable("products", "public")
|
||||
|
||||
idCol := models.InitColumn("id", "products", "public")
|
||||
idCol.Type = "integer"
|
||||
idCol.IsPrimaryKey = true
|
||||
table.Columns["id"] = idCol
|
||||
|
||||
nameCol := models.InitColumn("name", "products", "public")
|
||||
nameCol.Type = "text"
|
||||
table.Columns["name"] = nameCol
|
||||
|
||||
schema.Tables = append(schema.Tables, table)
|
||||
db.Schemas = append(db.Schemas, schema)
|
||||
|
||||
var buf bytes.Buffer
|
||||
options := &writers.WriterOptions{}
|
||||
writer := NewWriter(options)
|
||||
writer.writer = &buf
|
||||
|
||||
err := writer.WriteDatabase(db)
|
||||
if err != nil {
|
||||
t.Fatalf("WriteDatabase failed: %v", err)
|
||||
}
|
||||
|
||||
output := buf.String()
|
||||
t.Logf("Generated SQL:\n%s", output)
|
||||
|
||||
// Verify our naming convention is used
|
||||
if !strings.Contains(output, "pk_public_products") {
|
||||
t.Errorf("Output missing expected primary key name 'pk_public_products'\nFull output:\n%s", output)
|
||||
}
|
||||
|
||||
// Verify it drops auto-generated primary keys
|
||||
if !strings.Contains(output, "products_pkey") || !strings.Contains(output, "DROP CONSTRAINT") {
|
||||
t.Errorf("Output missing logic to drop auto-generated primary key\nFull output:\n%s", output)
|
||||
}
|
||||
|
||||
// Verify it checks for our specific named constraint before adding it
|
||||
if !strings.Contains(output, "constraint_name = 'pk_public_products'") {
|
||||
t.Errorf("Output missing check for our named primary key constraint\nFull output:\n%s", output)
|
||||
}
|
||||
}
|
||||
|
||||
func TestColumnSizeSpecifiers(t *testing.T) {
|
||||
db := models.InitDatabase("testdb")
|
||||
schema := models.InitSchema("public")
|
||||
table := models.InitTable("test_sizes", "public")
|
||||
|
||||
// Integer with invalid size specifier - should ignore size
|
||||
integerCol := models.InitColumn("int_col", "test_sizes", "public")
|
||||
integerCol.Type = "integer"
|
||||
integerCol.Length = 32
|
||||
table.Columns["int_col"] = integerCol
|
||||
|
||||
// Bigint with invalid size specifier - should ignore size
|
||||
bigintCol := models.InitColumn("bigint_col", "test_sizes", "public")
|
||||
bigintCol.Type = "bigint"
|
||||
bigintCol.Length = 64
|
||||
table.Columns["bigint_col"] = bigintCol
|
||||
|
||||
// Smallint with invalid size specifier - should ignore size
|
||||
smallintCol := models.InitColumn("smallint_col", "test_sizes", "public")
|
||||
smallintCol.Type = "smallint"
|
||||
smallintCol.Length = 16
|
||||
table.Columns["smallint_col"] = smallintCol
|
||||
|
||||
// Text with length - should convert to varchar
|
||||
textCol := models.InitColumn("text_col", "test_sizes", "public")
|
||||
textCol.Type = "text"
|
||||
textCol.Length = 100
|
||||
table.Columns["text_col"] = textCol
|
||||
|
||||
// Varchar with length - should keep varchar with length
|
||||
varcharCol := models.InitColumn("varchar_col", "test_sizes", "public")
|
||||
varcharCol.Type = "varchar"
|
||||
varcharCol.Length = 50
|
||||
table.Columns["varchar_col"] = varcharCol
|
||||
|
||||
// Decimal with precision and scale - should keep them
|
||||
decimalCol := models.InitColumn("decimal_col", "test_sizes", "public")
|
||||
decimalCol.Type = "decimal"
|
||||
decimalCol.Precision = 19
|
||||
decimalCol.Scale = 4
|
||||
table.Columns["decimal_col"] = decimalCol
|
||||
|
||||
schema.Tables = append(schema.Tables, table)
|
||||
db.Schemas = append(db.Schemas, schema)
|
||||
|
||||
var buf bytes.Buffer
|
||||
options := &writers.WriterOptions{}
|
||||
writer := NewWriter(options)
|
||||
writer.writer = &buf
|
||||
|
||||
err := writer.WriteDatabase(db)
|
||||
if err != nil {
|
||||
t.Fatalf("WriteDatabase failed: %v", err)
|
||||
}
|
||||
|
||||
output := buf.String()
|
||||
t.Logf("Generated SQL:\n%s", output)
|
||||
|
||||
// Verify invalid size specifiers are NOT present
|
||||
invalidPatterns := []string{
|
||||
"integer(32)",
|
||||
"bigint(64)",
|
||||
"smallint(16)",
|
||||
"text(100)",
|
||||
}
|
||||
for _, pattern := range invalidPatterns {
|
||||
if strings.Contains(output, pattern) {
|
||||
t.Errorf("Output contains invalid pattern '%s' - PostgreSQL doesn't support this\nFull output:\n%s", pattern, output)
|
||||
}
|
||||
}
|
||||
|
||||
// Verify valid patterns ARE present
|
||||
validPatterns := []string{
|
||||
"integer", // without size
|
||||
"bigint", // without size
|
||||
"smallint", // without size
|
||||
"varchar(100)", // text converted to varchar with length
|
||||
"varchar(50)", // varchar with length
|
||||
"decimal(19,4)", // decimal with precision and scale
|
||||
}
|
||||
for _, pattern := range validPatterns {
|
||||
if !strings.Contains(output, pattern) {
|
||||
t.Errorf("Output missing expected pattern '%s'\nFull output:\n%s", pattern, output)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user