Search code examples
postgresqlgogo-gorm

Gorm/PostgreSQL: How to Ensure Connection to Specific Database Instead of Default


When connecting to PostgreSQL using Gorm in Go, my application is connecting to the default postgres database instead of the specific database I've configured.

func (app *Application) ConnectToPostgres() error {
    dsn := fmt.Sprintf("host=%s user=%s password=%s dbname=%s port=%s sslmode=disable TimeZone=UTC",
        app.Config.DB.Host,
        app.Config.DB.User,
        app.Config.DB.Password,
        app.Config.DB.DBName,
        app.Config.DB.Port,
    )

    // Despite dsn specifying 'my_database_name', connection uses 'postgres'
    db, err := gorm.Open(postgres.Open(dsn), &gorm.Config{})
    if err != nil {
        return err
    }

    app.DB = db
    return nil
}

Configuration

.env file:

DB_HOST=localhost
DB_PORT=5432
DB_USER=postgres
DB_PASSWORD=
DB_NAME=my_database_name

What I've Verified

  • Database my_database_name exists
  • Connection string includes correct database name
  • DSN appears correctly formatted when printed
  • Database is accessible via psql

Why might Gorm be ignoring the specified database name?

Additional Context

  • Go version: 1.23.3
  • Gorm version: 1.25.12
  • PostgreSQL version: 16.3
  • Operating System: Arch Linux

More context

This is my main file

package main

import (
    "flag"
    "log"
    "os"

    "github.com/gin-gonic/gin"
    "github.com/joho/godotenv"

    "github.com/lordaris/aris-erp/api"
)

func main() {
    r := gin.Default()

    // Load environment variables from .env file
    err := godotenv.Load(".env")
    if err != nil {
        log.Fatal("Error loading .env file")
    }

    var cfg api.Config
    flag.StringVar(&cfg.DB.Host, "db-host", os.Getenv("DB_HOST"), "PostgreSQL host")
    flag.StringVar(&cfg.DB.Port, "db-port", os.Getenv("DB_PORT"), "PostgreSQL port")
    flag.StringVar(&cfg.DB.User, "db-user", os.Getenv("DB_USER"), "PostgreSQL user")
    flag.StringVar(&cfg.DB.Password, "db-password", os.Getenv("DB_PASSWORD"), "PostgreSQL password")
    flag.StringVar(&cfg.DB.DBName, "db-name", os.Getenv("DB_NAME"), "PostgreSQL database name")

    flag.Parse()

    app := api.NewApplication(cfg)

    // Connect to PostgreSQL
    if err := app.ConnectToPostgres(); err != nil {
        log.Fatal("Could not connect to PostgreSQL: ", err)
    }

    // Router
    api.Router(r, app)

    r.Run()
}

Last edit:

I encountered an issue when I modified the username for the database connection. The error indicated that the database with the username as its name didn't exist, which made sense. However, this led me to discover that the real problem was the lack of a password in my connection string. This caused the subsequent variables to shift positions, with the empty password being interpreted as the database name.

To resolve this, I removed the password placeholder entirely from the connection string. Alternatively, I could have used an actual password, but for now, I’ve decided not to include one.


Solution

  • The issue arises because the password field in your Data Source Name (DSN) is empty. In PostgreSQL connection strings, if the password is omitted or left empty, the subsequent parameters may not be correctly interpreted, leading to unexpected behavior. In your case, the empty password field causes the dbname parameter to be misinterpreted, resulting in a connection to the default postgres database instead of your intended my_database_name.

    try this :

     if password == "" {
            password = "''" // Use empty single quotes to represent an empty password
        }