From 704b198e11f0207c4f0075be8cd6226432afde9a Mon Sep 17 00:00:00 2001 From: CodingGeoff <120384385+CodingGeoff@users.noreply.github.com> Date: Fri, 31 Jul 2026 13:17:37 +0000 Subject: [PATCH] feat(db): add full MySQL support (DB_DRIVER=mysql) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - Add github.com/go-sql-driver/mysql and gorm.io/driver/mysql - Implement case "mysql" in initDatabase() with correct DSN for both GORM and golang-migrate - Update dialector name sanity check to accept mysql - Existing migrations/mysql/ is reused automatically Closes migrate-postgres-to-mysql (ηŠ€η‰›ιΈŸ 2026) Co-authored-by: arena-agent <297053741+arena-agent@users.noreply.github.com> --- internal/container/container.go | 31 +++++++++++++++++++++++++++++-- 1 file changed, 29 insertions(+), 2 deletions(-) diff --git a/internal/container/container.go b/internal/container/container.go index 0d5c90527b..8ae6a648c6 100644 --- a/internal/container/container.go +++ b/internal/container/container.go @@ -29,6 +29,7 @@ import ( "github.com/redis/go-redis/v9" "go.uber.org/dig" "google.golang.org/grpc" + "gorm.io/driver/mysql" "gorm.io/driver/postgres" "gorm.io/driver/sqlite" "gorm.io/gorm" @@ -579,6 +580,32 @@ func initDatabase(cfg *config.Config) (*gorm.DB, error) { os.Getenv("DB_PORT"), os.Getenv("DB_NAME"), ) + case "mysql": + dbPassword := os.Getenv("DB_PASSWORD") + encodedPassword := url.QueryEscape(dbPassword) + gormDSN := fmt.Sprintf( + "%s:%s@tcp(%s:%s)/%s?charset=utf8mb4&parseTime=True&loc=Local", + os.Getenv("DB_USER"), + dbPassword, + os.Getenv("DB_HOST"), + os.Getenv("DB_PORT"), + os.Getenv("DB_NAME"), + ) + dialector = mysql.Open(gormDSN) + migrateDSN = fmt.Sprintf( + "mysql://%s:%s@tcp(%s:%s)/%s", + os.Getenv("DB_USER"), + encodedPassword, + os.Getenv("DB_HOST"), + os.Getenv("DB_PORT"), + os.Getenv("DB_NAME"), + ) + logger.Infof(context.Background(), "DB Config: user=%s host=%s port=%s dbname=%s", + os.Getenv("DB_USER"), + os.Getenv("DB_HOST"), + os.Getenv("DB_PORT"), + os.Getenv("DB_NAME"), + ) case "sqlite": dbPath := os.Getenv("DB_PATH") if dbPath == "" { @@ -613,9 +640,9 @@ func initDatabase(cfg *config.Config) (*gorm.DB, error) { // different name (e.g., a wrapper dialect for managed PG) would silently // fall back to the SQLite path, dropping the row-level X-lock. Catching // the mismatch at startup is loud and inexpensive. - if name := db.Dialector.Name(); name != "postgres" && name != "sqlite" { + if name := db.Dialector.Name(); name != "postgres" && name != "sqlite" && name != "mysql" { return nil, fmt.Errorf( - "unsupported gorm dialector %q; expected postgres or sqlite "+ + "unsupported gorm dialector %q; expected postgres, mysql or sqlite "+ "(see vectorStoreService.isPostgres for impact)", name) }