I am having an issue with Go and performing standard operations on my PostgreSQL database.
I first started coding with GORM, and was getting the following error message while connecting:
dial tcp: lookup tcp/fullstack_api: getaddrinfow: The specified class was not found.
After switching to the standard "database/sql" package with the _ "github.com/lib/pq" postgreSQL dialect, connecting was no longer throwing this error. However, now I get this error when trying to perform any query on the connected database, which I assume GORM was doing initially.
The following code causes this error on my system:
// Connect initiates a DB connection.
func (dbConn *PostgresConnection) Connect() error {
handle, connErr := sql.Open("postgres", dbConn.getConnectionString())
if connErr != nil { // Does NOT cause an error
return connErr
}
if pingErr := handle.Ping(); pingErr != nil { // Causes the above error
return pingErr
}
dbConn.handle = handle
return nil
}
I have checked that the PostgreSQL service is running, and the database exists.
While writing this question, I checked my connection string / env variables again.
I realized that I had a stupid copy/paste error from the day before that I hadn't validated:
Connection string: host=127.0.0.1 port=5432 port=new_database user=db_user password=XXXXXX
As you can see, there is an additional port variable that should have been the dbname. After fixing this issue, everything worked as expected.
Connection string: host=127.0.0.1 port=5432 dbname=new_database user=db_user password=XXXXXX
TLDR: Always re-validate every piece of your connection information when getting this (cryptic) error!
Related
GO application failed to connect to local PostgreSQL database using environment variables in Windows.
After setting the environment variables using the windows command prompt like the following:
set DATABASE_HOST=localhost
set DATABASE_USER=postgres
set DATABASE_PASSWORD=password
set DATABASE_NAME=db
set DATABASE_PORT=5432
The following command was tried to run the go application:
go run main.go
I get the following error:
←[0m←[31m[error] ←[0mfailed to initialize database, got error cannot parse `host= user= password=xxxxx dbname= port=`: invalid port (strconv.ParseUint: parsing "": invalid syntax)
panic: Failed to connect to database!
goroutine 1 [running]:
C:/Users/user/go/src/code/db.go:12 +0xb4
This is the code for the db.go
import (
"gorm.io/driver/postgres"
"gorm.io/gorm"
)
func ConnectDatabase(dsn string) *gorm.DB {
database, err := gorm.Open(postgres.Open(dsn))
if err != nil {
panic("Failed to connect to database!")
}
return database
}
But when echo command was tried it does return the correct value in the command prompt. Example echo %DATABASE_PORT% command returns 5432.
Note: main.go has the database migration related to code to initialize the database tables and schemas and works fine in Linux and Mac OS.
For a project i'm trying to connection a cloud function to a cloud sql database setup as described in this quickstart guide.
The function is configured in the same region, the service account has the Role Cloud SQL-Client. I called the function through my computer like this:
gcloud functions call <function-name> --region=<region> --data '{"recipient":"hello","requester":"hello","message":"test"}'
The connection to the function is working, it seems like just the authentication to the database doesn't work but i don't get where i failed.
I checked the password, user and connection name multiple times, reset the password and it still doesn't work.
I found the issue here related to connecting cloud functions to cloud sql.
I tried surrounding the password in the dsn-string with single-quotes just to be sure escaping of characters in the password isn't a problem.
I also checked the environment variables coming in and they are the ones i entered in the configuration.
The function just pings the database for test purposes:
package receiver
import (
"database/sql"
"fmt"
"net/http"
"os"
// Import Postgres SQL driver
_ "github.com/lib/pq"
)
// Receives a message and stores it
func Receive(w http.ResponseWriter, r *http.Request) {
connectionName := os.Getenv("POSTGRES_INSTANCE_CONNECTION_NAME")
dbUser := os.Getenv("POSTGRES_USER")
dbPassword := os.Getenv("POSTGRES_PASSWORD")
dsn := fmt.Sprintf("user=%s password='%s' host=/cloudsql/%s dbname=messages", dbUser, dbPassword, connectionName)
var err error
db, err := sql.Open("postgres", dsn)
if err != nil {
fmt.Fprintf(w, "Could not open db: %v \n", err)
}
// Only allow 1 connection to the database to avoid overloading
db.SetMaxIdleConns(1)
db.SetMaxOpenConns(1)
defer db.Close()
if pingerror := db.Ping(); pingerror != nil {
fmt.Fprintf(w, "Failed to ping database: %s \n", pingerror)
return
}
}
The variable POSTGRES_INSTANCE_CONNECTION_NAME is formatted as described here as ProjectID:Region:InstanceID.
Expected is a success message or no error and i'm actually getting this message:
pq: password authentication failed for user "postgres"
Note: I also created a function containing the demo code from here with my sql database settings and the error is the same. It seems like i missed some step while setting up the user or sql instance. But i can't find out which.
Feels strange to answer my own question but here it is: For some reason connecting with the postgres user doesn't work. Finally i created a new database user for the function and a password containing only alphanumeric characters.
The unix socket at /cloudsql/{connectionName} is only provided in the GCF runtime. When running locally, you either need change your connection string or use the Cloud SQL proxy to simulate a unix socket at the same path.
I'm trying to connect to my localhost postgresql server without SSL and I'm getting this error:
pq: SSL is not enabled on the server
That's fine, I know how to fix it:
type App struct {
Router *mux.Router
DB *sql.DB
}
func (a *App) Initialize(dbname string) {
connectionString := fmt.Sprintf("dbname=%s sslmode=disable", dbname)
var err error
a.DB, err = sql.Open("postgres", connectionString)
if err != nil {
log.Fatal(err)
}
defer a.DB.Close()
}
However I'm still getting the error!
I was able to recreate your error with a fresh install of postgres. While the error output was
pq: SSL is not enabled on the server
the real error was not having any databases created. To create a testdb let's run
createdb testdb
in your terminal with postgres already running in the background.
I think the answer comes more just to assign a parameter flag to your Postgres connection string url.
I was connecting to an AWS RDS by URL and I've just change to localhost on 5432 default port.
http://127.0.0.1:5432?sslmode=disable
or
http://localhost:5432?sslmode=disable
I stumbled upon this trying to connect to Postgresql server from my Go program with wrong password.
I am making a web app in Go and PostgreSQL using two different computers. The setup is the same on both computers (Ubuntu with last versions of Go and PostgreSQL). The problem is that I cannot get my app to connect to the database on my laptop.
I use this piece of code:
func (db *Database) Dial(user string, password string, dbname string) {
var err error
db.Conn, err = sql.Open("postgres", "user="+user+" password="+password+" dbname="+dbname+" sslmode=require")
if err != nil {
fmt.Println("Connection to " + dbname + " not possible!")
log.Fatal(err)
}
err = db.Conn.Ping()
if err != nil {
fmt.Println("Ping to " + dbname + " not possible!")
fmt.Println(err)
}
}
And I get:
Ping to my_database not possible!
driver: bad connection
I found many questions on SO with the same error, but I found no solution that would solve my case.
Also, on my laptop, just like on my desktop computer, there is a user postgres and I can connect to the database through psql, so the daemon is active and the password is right. I use the exact same setup and code on both computers.
My question is: how do I get more information about the error? I find "bad connection" to be too vague. I'm sure that a bit more of information would help me a lot.
Also, do you have an idea of would could cause the error?
Update
The PostgreSQL log says this:
2014-09-29 14:23:26 EDT FATAL: password authentication failed for user "postgres"
2014-09-29 14:23:26 EDT DETAIL: Connection matched pg_hba.conf line 92: "host all all 127.0.0.1/32 md5"
But I double checked the password and it shoud be fine. I can also log in as the posgres user, run the psql command and execute queries.
I found a way to fix this.
I log in as postgres and run psql postgres. In other words, I connect to the postgres database. Then I run the command \password and enter a new password.
I entered the exact same password that I have been using since the beginning and somehow now it works.
The problem is solved, but if someone has an idea about what could have been the cause, I'm interested. Maybe it has something to do with password expiration?
I'm trying to connect to a postresql database with the pq driver in Go. When I do it on a local copy of the database, with a connection string like
DB, err = sql.Open("postgres", "user=user password=pwd dbname=mydb sslmode=disable")
it all works well.
However, when I switch to a production server where the connection goes through pgbouncer:
DB, err = sql.Open("postgres", "user=user password=pwd host=/var/run/pgbouncer port=port dbname=mydb sslmode=disable")
I keep getting the same error for all queries, however simple:
Database error: pq: S:"ERROR" M:"prepared statement \"1\" does not exist" C:"26000" F:"prepare.c" L:"519" R:"FetchPreparedStatement"
(it's always "prepared statement \"1\"", independent of the query I'm trying to pass)
The query in both cases is run simply as follows:
res_rows, err := DB.Query(query)
if err != nil {
log.Printf("Database error: %s\n", err)
}
for res_rows.Next() {
...
}
Googling suggests to turn off prepared statements, but I don't know how to do that in Go and I'm not sure it is supported at all. Any help (even a suggestion to use something else entirely) would be greatly appreciated.
Package driver
type Queryer
type Queryer interface {
Query(query string, args []Value) (Rows, error)
}
Queryer is an optional interface that may be implemented by a
Conn.
If a Conn does not implement Queryer, the sql package's
DB.Query will first prepare a query, execute the statement, and then
close the statement.
I don't see where the lib/pq PostgreSQL driver implements Queryer. Therefore, the DB.Query query is prepared before execution.
PgBouncer doesn't support the PREPARE feature for all pooling methods: Feature matrix for pooling modes.
The Postgres driver now has a solution to fix this issue: https://github.com/lib/pq/issues/389
It isn't in the documentation but works as expected, including with PgBouncer and Transaction pooling enabled.
If you're using PgBouncer you need to set binary_parameters=yes to your database dsn connection as a query parameter
try this:
DB, err = sql.Open("postgres", "user=user password=pwd dbname=mydb sslmode=disable, binary_parameters=yes")