Migrate from github.com/jinzhu/gorm (v1) to gorm.io/gorm (v2) with PostgreSQL support#36
Open
ZPascal wants to merge 5 commits intocloudfoundry:mainfrom
Open
Migrate from github.com/jinzhu/gorm (v1) to gorm.io/gorm (v2) with PostgreSQL support#36ZPascal wants to merge 5 commits intocloudfoundry:mainfrom
github.com/jinzhu/gorm (v1) to gorm.io/gorm (v2) with PostgreSQL support#36ZPascal wants to merge 5 commits intocloudfoundry:mainfrom
Conversation
Closed
9 tasks
github.com/jinzhu/gorm (v1) to gorm.io/gorm (v2) with PostgreSQL support
9448b17 to
290a85e
Compare
ameowlia
reviewed
Mar 9, 2026
ameowlia
reviewed
Mar 9, 2026
Member
|
Initial notes
|
Author
Hi @ameowlia, thank you for the review:
Should we handle 2 & 3 in separate PRs or completely ignore them? |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Migrate from
github.com/jinzhu/gorm(v1) togorm.io/gorm(v2) with PostgreSQL supportSummary
This PR upgrades the routing-api from GORM v1 (
github.com/jinzhu/gorm) to GORM v2 (gorm.io/gorm) and adds full PostgreSQL support alongside the existing MySQL/MariaDB support. The migration issues in the database schema migrations were diagnosed and fixed with the assistance of Claude (Anthropic).Motivation
github.com/lib/pqPostgreSQL driver has been replaced by thepgxdriver (github.com/jackc/pgx/v5), which is the recommended modern driver for PostgreSQL in Go.Changes
Core: GORM v1 → v2 Migration (
db/client.go,db/db_sql.go)github.com/jinzhu/gormimports withgorm.io/gormgithub.com/jinzhu/gorm/dialects/*withgorm.io/driver/mysqlandgorm.io/driver/postgresNewSqlDBto use the new GORM v2gorm.Open(dialector, &gorm.Config{})API with explicit dialect selectiondb.DB().SetMaxIdleConns(...)→sqlDB, _ := db.DB(); sqlDB.SetMaxIdleConns(...)Clientinterface:AddUniqueIndex(name string, columns ...string) (Client, error)→AddUniqueIndex(name string, columns interface{}) errorRemoveIndex(name string) (Client, error)→RemoveIndex(name string, columns interface{}) errorUpdate(attrs ...interface{})→Update(column string, value interface{})Dialect() gorm.Dialect→Dialect() gorm.DialectorExecWithError(query string, args ...interface{}) errorfor migrations that need to handle SQL errorsMigrator() gorm.Migratorto expose GORM v2 migration utilitiesHasTable(value interface{}) boolnow usesdb.Migrator().HasTable(value)AutoMigrate(values ...interface{}) errornow returns an error directly (GORM v2 changed the signature)Execto correctly pass variadic args:c.db.Exec(query, args)→c.db.Exec(query, args...)errorschannel variable toerrorListto avoid shadowing theerrorspackageclockvariable toclockVarto avoid shadowing theclockpackage importDeleteRouterGroupto use an explicitWHEREclause: GORM v2 requires conditions forDeleteto prevent accidental full-table deletesPostgreSQL Driver (
cmd/routing-api/testrunner/db.go)sql.Open("postgres", ...)withsql.Open("pgx", ...)— thepgxdriver registers itself under the"pgx"driver namegithub.com/lib/pqimport fromdb/db_suite_test.goSchema Migrations: PostgreSQL Compatibility (diagnosed with Claude)
The migration code contained several MySQL-specific SQL constructs that failed on PostgreSQL. These were identified and fixed:
migration/migration.go—dropIndex()helperAdded a helper function to abstract the database-specific
DROP INDEXsyntax:migration/V2_update_rg_migration.goAddUniqueIndex/RemoveIndexwith raw SQLname(191)length prefix forTEXTcolumns in indexes; PostgreSQL does not support this syntaxmigration/V3_update_tcp_route_migration.gosqlDB.Client.Model(...).AutoMigrate(...)call tosqlDB.Client.AutoMigrate(&models.TcpRouteMapping{})DropColumn(which panicked in v2) with a directALTER TABLE ... DROP COLUMNSQL statementmigration/V4, V5, V6, V7— Unique index recreationReplaced GORM v1
AddUniqueIndex/RemoveIndexchain with explicit, dialect-aware SQL:migration/V7_instance_id_defaults.goFixed
instance_idcolumn nullability change:MODIFY COLUMN instance_id varchar(255) DEFAULT NULLALTER COLUMN instance_id SET DEFAULT NULLFixed dialect detection:
Dialect().GetName()(GORM v1) →Dialect().Name()(GORM v2)migration/V8_host_tls_port_tcp_default_zero.goUPDATE tcp_routes SET host_tls_port = 0 WHERE host_tls_port IS NULLbefore theDROP INDEXto ensure data is correct before index recreationALTER COLUMNsyntax per dialect:MODIFY COLUMN host_tls_port int DEFAULT 0ALTER COLUMN host_tls_port SET DEFAULT 0PostgreSQL Port Column Type Fix (diagnosed with Claude)
Root cause: GORM v2's
DataTypeOfin the PostgreSQL driver maps Go types to SQL types based onfield.Size:uint16fields havefield.Size = 16in GORM, which maps tosmallint(max 32767). Since TCP/UDP ports can be up to 65535, this causedpgxto fail with:Fix: Added
size:32to all port column GORM tags to forceinteger(int4) instead ofsmallint(int2):Affected files:
models/tcp_route.go,models/route.go,migration/v0/models.go,migration/v5/models.goTest Infrastructure
cmd/routing-api/testrunner/db.go: AddedpostgresAllocatorusingpgxdrivermigration/migration_suite_test.go: AddedBeforeSuite/AfterSuite/BeforeEachlifecycle for database allocation and reset, enabling the migration tests to run against a real databasedb/db_sql_test.go:Client.Delete(&model{})calls updated toClient.Where("guid = ?", ...).Delete(&Model{})(GORM v2 requires explicitWHEREconditions)backupErrorstring check from"Database unavailable..."to"database unavailable..."(lowercase)db/fakes/fake_client.go: Regenerated to match updatedClientinterfaceTesting
Integration tests
Both MySQL/MariaDB and PostgreSQL are tested. Run via:
Routing acceptance tests
I've used the following setup to handle the RATS on a local cf on kind environment.
RATS execution (verbose) | RUN 1
RATS execution | RUN 2
Notes
go.modfile is excluded from version control (added to.gitignore) as this repository uses a workspace-levelgo.modmanaged by the BOSH release toolchain.Related issues
fix: cloudfoundry/routing-release#164
Open points