Connect with postgreSQL schema - postgresql

I am looking to connect and query to a PostgreSQL. But I only want to connect to a particular Schema.
As per the doc (JDBC) we can use
jdbc:postgresql://localhost:5432/mydatabase?searchpath=myschema
or update As of 9.4 you can specify the url with the new currentSchema parameter like so:
jdbc:postgresql://localhost:5432/mydatabase?currentSchema=myschema
But I am unable to do so with golang SQL driver;
As per the documents, we can also use SET search_path TO myschema,public;
But I only want to declare it for once during initializing but I think this needs to be executed every time for new connection.
Also I am using following code please help me identify the correct parameters to be passed to this in order to only connect with schema
db, err := sql.Open("postgres", `dbname=`+s.settings.Database+
` user=`+s.settings.Username+` password=`+s.settings.Password+
` host=`+s.settings.Url+` sslmode=disable`)
Adding currentSchema=myschema or searchpath=myschema is not working!
Is there a way I can only connect to a particular database-schema in GO

You should add search_path=myschema to dataSourceName
P.S. better use fmt.Sprintf("host=%s port=%d dbname=%s user=%s password='%s' sslmode=disable search_path=%s", ...) instead ``+``

Set Search_path is right and you do it once. ie:
db, err := sql.Open("postgres",
"host=localhost dbname=Test sslmode=disable user=postgres password=secret")
if err != nil {
log.Fatal("cannot connect ...")
}
defer db.Close()
db.Exec(`set search_path='mySchema'`)
rows, err := db.Query(`select blah,blah2 from myTable`)
...

Related

AWS SAM golang lambda localhost connection refused to postgres

I'm unable to connect an AWS SAM lambda function to a local postgres instance. I'll be specific in a moment, but first let me say that the same code works for my coworker and that I've tried using Postgres within a docker container as well as installed manually. To simplify the problem I started over with the SAM helloworld golang example and added the following:
import (
_ "github.com/lib/pq"
"database/sql"
)
.
.
.
const (
host = "localhost"
port = 5432
user = "postgres"
password = "postgres"
dbname = "postgres"
)
.
.
.
.
psqlInfo := fmt.Sprintf("host=%s port=%d user=%s "+
"password=%s dbname=%s sslmode=disable",
host, port, user, password, dbname)
db, err := sql.Open("postgres", psqlInfo)
if err != nil {
panic(err)
}
defer db.Close()
err = db.Ping()
if err != nil {
panic(err)
}
fmt.Println("Successfully connected!")
And I get the following error:
dial tcp 127.0.0.1:5432: connect: connection refused: OpError
[{"path":"github.com/aws/aws-lambda-go#v1.13.3/lambda/function.go","line":35,"label":"(*Function).Invoke.func1"},{"path":"runtime/panic.go","line":969,"label":"gopanic"},{"path":"hello-world/main.go","line":67,"label":"handler"},{"path":"reflect/value.go","line":475,"label":"Value.call"},{"path":"reflect/value.go","line":336,"label":"Value.Call"},{"path":"github.com/aws/aws-lambda-go#v1.13.3/lambda/handler.go","line":124,"label":"NewHandler.func1"},{"path":"github.com/aws/aws-lambda-go#v1.13.3/lambda/handler.go","line":24,"label":"lambdaHandler.Invoke"},{"path":"github.com/aws/aws-lambda-go#v1.13.3/lambda/function.go","line":67,"label":"(*Function).Invoke"},{"path":"reflect/value.go","line":475,"label":"V
alue.call"},{"path":"reflect/value.go","line":336,"label":"Value.Call"},{"path":"net/rpc/server.go","line":377,"label":"(*service).call"},{"path":"runtime/asm_amd64.s","line":1374,"label":"goexit"}]
SAM CLI, version 1.21.1
I've now tried this on two machines and get the same error. Is there there something that I'm just missing there? I can confirm that the the database is receiving connections fine. I hit it every day from a node app. Also, I can build the golang code outside of SAM and it will work fine. So there's something with my SAM setup that's wrong.
Figured it out. Within the lambda I needed to set the postgres connection string to hit host.docker.internal
I spend a lot of time figuring out how to connect using AWS SAM to a local Postgres and finally found that changing the dbhostname from localhost to host.docker.internal works.
connectionString = 'postgresql://dbuser:dbpassword#host.docker.internal:5432/dbname';

Gorm can't connect to local postgres db

I'm new to GoLang and I`ve an issue with connecting my Go webserver with Postgres Database.
Can someone tell me what I'm doing wrong here?
All these credentials are correct btw. User exists, Password is correct, DB exists and belongs to the user.
package app
import (
"github.com/jinzhu/gorm"
_ "github.com/jinzhu/gorm/dialects/postgres"
)
func connectDB(){
db, err := gorm.Open("postgres", "host=localhost port=5432 user=power_user dbname=local_db password=power_user")
if err != nil {
log.Fatal("DB Connection failed")
}
}
If you're sure about psql server is running, try to modify pg_hba.conf, locates at /etc/postgresql/${version}/main/pg_hba.conf usually:
# TYPE DATABASE USER ADDRESS METHOD
local all all trust

How to connect to Cloud-SQL from Cloud Function in Go?

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.

How to set application name in golang lib/pq postgresql driver?

I'm writing a golang application and using the golang postgres driver - https://github.com/lib/pq/
I use a connection string like this
'name:pass#host:port/dbname'
I try to add aplication_name param in conn string, but this doesn't work
'name:pass#host:port/dbname?application_name=myapp'
Is it possible to set the application name from golang? (standard way)
Even though it's not mentioned in the documentation, if you look at the lib/pq source code you will find that application_name is supported.
This style connection works as desired:
connstring := fmt.Sprintf("user='%s' password='%s' dbname='%s' host='%s' application_name='%s'", user, password, dbname, host, application_name)
db, err := sql.Open("postgres", connstring)
If you look to the documentation a application_name option is not suuported. Maybe you could use:
fallback_application_name - An application_name to fall back to if
one isn't provided.
name:pass#host:port/dbname?fallback_application_name=myapp
You can set the application name one of two ways.
// Application name as space-separated list of options.
sql.Open("postgres", "user=myuser password=mypass host=localhost port=5432 dbname=mydb sslmode=disable application_name=myapp")
or
// Application name as query param.
sql.Open("postgres", "postgres://myuser:mypass#localhost:5432/mydb?sslmode=disable&application_name=myapp")

pq driver: prepared statement does not exist

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")