From 3e2b8163f011d925677cc5e100b7c193d9836a02 Mon Sep 17 00:00:00 2001 From: sunary Date: Thu, 10 Oct 2024 18:35:02 +0700 Subject: [PATCH] strict comparison attributes --- README.md | 45 ++++++++++++++++++++++++++++++++++++++++++++- README_zh.md | 45 ++++++++++++++++++++++++++++++++++++++++++++- element/table.go | 43 +++++++++++++++++++++++++++++++++++++++---- 3 files changed, 127 insertions(+), 6 deletions(-) diff --git a/README.md b/README.md index 14bb373..eb3a6eb 100644 --- a/README.md +++ b/README.md @@ -111,7 +111,7 @@ CREATE TABLE sample ( */ ``` -3. Complete example: +3. Comparing SQL schema with Go struct: ```go package main @@ -197,3 +197,46 @@ func main() { _ = newMigration.WriteFiles("demo migration") } ``` + +4. Comparing Two SQL Schemas: + +```go +package main + +import ( + "github.com/sunary/sqlize" +) + +func main() { + sql1 := sqlize.NewSqlize() + sql1.FromString(` +CREATE TABLE user ( + id INT AUTO_INCREMENT PRIMARY KEY, + name VARCHAR(64), + age INT, + created_at DATETIME DEFAULT CURRENT_TIMESTAMP, + updated_at DATETIME DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP +); +CREATE UNIQUE INDEX idx_name_age ON user(name, age); + `) + + sql2 := sqlize.NewSqlize() + sql2.FromString(` +CREATE TABLE user ( + id INT, + name VARCHAR(64), + age INT, + created_at DATETIME DEFAULT CURRENT_TIMESTAMP, + updated_at DATETIME +);`) + + sql1.Diff(*sql2) + println(sql1.StringUp()) + //ALTER TABLE `user` MODIFY COLUMN `id` int(11) AUTO_INCREMENT PRIMARY KEY; + //ALTER TABLE `user` MODIFY COLUMN `updated_at` datetime DEFAULT CURRENT_TIMESTAMP() ON UPDATE CURRENT_TIMESTAMP(); + //CREATE UNIQUE INDEX `idx_name_age` ON `user`(`name`, `age`); + + println(sql1.StringDown()) + //DROP INDEX `idx_name_age` ON `user`; +} +``` \ No newline at end of file diff --git a/README_zh.md b/README_zh.md index a461a57..babf143 100644 --- a/README_zh.md +++ b/README_zh.md @@ -111,7 +111,7 @@ CREATE TABLE sample ( */ ``` -3. 完整示例: +3. 比较 SQL 架构与 Go 结构体: ```go package main @@ -196,4 +196,47 @@ func main() { _ = newMigration.WriteFiles("demo migration") } +``` + +4. 比较两个 SQL 架构: + +```go +package main + +import ( + "github.com/sunary/sqlize" +) + +func main() { + sql1 := sqlize.NewSqlize() + sql1.FromString(` +CREATE TABLE user ( + id INT AUTO_INCREMENT PRIMARY KEY, + name VARCHAR(64), + age INT, + created_at DATETIME DEFAULT CURRENT_TIMESTAMP, + updated_at DATETIME DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP +); +CREATE UNIQUE INDEX idx_name_age ON user(name, age); + `) + + sql2 := sqlize.NewSqlize() + sql2.FromString(` +CREATE TABLE user ( + id INT, + name VARCHAR(64), + age INT, + created_at DATETIME DEFAULT CURRENT_TIMESTAMP, + updated_at DATETIME +);`) + + sql1.Diff(*sql2) + println(sql1.StringUp()) + // ALTER TABLE `user` MODIFY COLUMN `id` int(11) AUTO_INCREMENT PRIMARY KEY; + // ALTER TABLE `user` MODIFY COLUMN `updated_at` datetime DEFAULT CURRENT_TIMESTAMP() ON UPDATE CURRENT_TIMESTAMP(); + // CREATE UNIQUE INDEX `idx_name_age` ON `user`(`name`, `age`); + + println(sql1.StringDown()) + // DROP INDEX `idx_name_age` ON `user`; +} ``` \ No newline at end of file diff --git a/element/table.go b/element/table.go index c606f59..417d27c 100644 --- a/element/table.go +++ b/element/table.go @@ -7,7 +7,9 @@ import ( "sort" "strings" + ptypes "github.com/auxten/postgresql-parser/pkg/sql/types" "github.com/pingcap/parser/ast" + "github.com/pingcap/parser/types" "github.com/sunary/sqlize/utils" ) @@ -252,16 +254,49 @@ func (t Table) getIndexForeignKey(fkName string) int { return -1 } +func hasChangedMysqlOptions(new, old []*ast.ColumnOption) bool { + if len(new) != len(old) { + return true + } + + mNew := map[ast.ColumnOptionType]int{} + for i := range old { + mNew[old[i].Tp] += 1 + } + + mOld := map[ast.ColumnOptionType]int{} + for i := range old { + mOld[old[i].Tp] += 1 + } + + for k, v := range mOld { + if mNew[k] != v { + return true + } + } + + return false +} + +func hasChangedMysqlType(new, old *types.FieldType) bool { + return new != nil && new.String() != old.String() +} + +func hasChangePostgresType(new, old *ptypes.T) bool { + return new != nil && new.SQLString() != old.SQLString() +} + // Diff differ between 2 migrations func (t *Table) Diff(old Table) { for i := range t.Columns { if j := old.getIndexColumn(t.Columns[i].Name); t.Columns[i].Action == MigrateAddAction && j >= 0 && old.Columns[j].Action != MigrateNoAction { - if (t.Columns[i].MysqlType != nil && t.Columns[i].MysqlType.String() == old.Columns[j].MysqlType.String()) || - (t.Columns[i].PgType != nil && t.Columns[i].PgType.SQLString() == old.Columns[j].PgType.SQLString()) { - t.Columns[i].Action = MigrateNoAction - } else { + if hasChangedMysqlOptions(t.Columns[i].Options, old.Columns[j].Options) || + hasChangedMysqlType(t.Columns[i].MysqlType, old.Columns[j].MysqlType) || + hasChangePostgresType(t.Columns[i].PgType, old.Columns[j].PgType) { t.Columns[i].Action = MigrateModifyAction + } else { + t.Columns[i].Action = MigrateNoAction } } }