Skip to content

Commit

Permalink
feat: allow dbconfig options
Browse files Browse the repository at this point in the history
application_name and default_transaction_read_only to be configurable

Closes: #966
  • Loading branch information
iwpnd committed Feb 17, 2024
1 parent b7ad33b commit 6258da4
Show file tree
Hide file tree
Showing 3 changed files with 164 additions and 42 deletions.
118 changes: 78 additions & 40 deletions provider/postgis/postgis.go
Original file line number Diff line number Diff line change
Expand Up @@ -175,41 +175,45 @@ const (
)

const (
DefaultURI = ""
DefaultPort = 5432
DefaultSRID = tegola.WebMercator
DefaultMaxConn = 100
DefaultMaxConnIdleTime = "30m"
DefaultMaxConnLifetime = "1h"
DefaultSSLMode = "prefer"
DefaultSSLKey = ""
DefaultSSLCert = ""
DefaultURI = ""
DefaultPort = 5432
DefaultSRID = tegola.WebMercator
DefaultMaxConn = 100
DefaultMaxConnIdleTime = "30m"
DefaultMaxConnLifetime = "1h"
DefaultSSLMode = "prefer"
DefaultSSLKey = ""
DefaultSSLCert = ""
DefaultApplicationName = "tegola"
DefaultDefaultTransactionReadOnly = "TRUE"
)

const (
ConfigKeyName = "name"
ConfigKeyURI = "uri"
ConfigKeyHost = "host"
ConfigKeyPort = "port"
ConfigKeyDB = "database"
ConfigKeyUser = "user"
ConfigKeyPassword = "password"
ConfigKeySSLMode = "ssl_mode"
ConfigKeySSLKey = "ssl_key"
ConfigKeySSLCert = "ssl_cert"
ConfigKeySSLRootCert = "ssl_root_cert"
ConfigKeyMaxConn = "max_connections"
ConfigKeyMaxConnIdleTime = "max_connection_idle_time"
ConfigKeyMaxConnLifetime = "max_connection_lifetime"
ConfigKeySRID = "srid"
ConfigKeyLayers = "layers"
ConfigKeyLayerName = "name"
ConfigKeyTablename = "tablename"
ConfigKeySQL = "sql"
ConfigKeyFields = "fields"
ConfigKeyGeomField = "geometry_fieldname"
ConfigKeyGeomIDField = "id_fieldname"
ConfigKeyGeomType = "geometry_type"
ConfigKeyName = "name"
ConfigKeyURI = "uri"
ConfigKeyHost = "host"
ConfigKeyPort = "port"
ConfigKeyDB = "database"
ConfigKeyUser = "user"
ConfigKeyPassword = "password"
ConfigKeySSLMode = "ssl_mode"
ConfigKeySSLKey = "ssl_key"
ConfigKeySSLCert = "ssl_cert"
ConfigKeySSLRootCert = "ssl_root_cert"
ConfigKeyMaxConn = "max_connections"
ConfigKeyMaxConnIdleTime = "max_connection_idle_time"
ConfigKeyMaxConnLifetime = "max_connection_lifetime"
ConfigKeySRID = "srid"
ConfigKeyLayers = "layers"
ConfigKeyLayerName = "name"
ConfigKeyTablename = "tablename"
ConfigKeySQL = "sql"
ConfigKeyFields = "fields"
ConfigKeyGeomField = "geometry_fieldname"
ConfigKeyGeomIDField = "id_fieldname"
ConfigKeyGeomType = "geometry_type"
ConfigKeyApplicationName = "application_name"
ConfigKeyDefaultTransactionReadOnly = "default_transaction_read_only"
)

// isSelectQuery is a regexp to check if a query starts with `SELECT`,
Expand Down Expand Up @@ -361,19 +365,36 @@ func BuildURI(config dict.Dicter) (*url.URL, *url.Values, error) {
return u, params, nil
}

type DBConfigOptions struct {
Uri string
DefaultTransactionReadOnly string
ApplicationName string
}

func (opts *DBConfigOptions) GetRuntimeParams() map[string]string {
pr := map[string]string{
"application_name": opts.ApplicationName,
}

// as per https://www.postgresql.org/docs/current/runtime-config-client.html#GUC-DEFAULT-TRANSACTION-READ-ONLY
// default_transaction_read_only accepts boolean, and is not set by default
// hence if OFF, we do not add it to RuntimeParams
if opts.DefaultTransactionReadOnly != "" && opts.DefaultTransactionReadOnly != "OFF" {
pr["default_transaction_read_only"] = opts.DefaultTransactionReadOnly
}

return pr
}

// BuildDBConfig build db config with defaults
func BuildDBConfig(uri string) (*pgxpool.Config, error) {
dbconfig, err := pgxpool.ParseConfig(uri)
func BuildDBConfig(opts *DBConfigOptions) (*pgxpool.Config, error) {
dbconfig, err := pgxpool.ParseConfig(opts.Uri)
if err != nil {
return nil, err
}

dbconfig.ConnConfig.LogLevel = pgx.LogLevelWarn
dbconfig.ConnConfig.RuntimeParams = map[string]string{
"default_transaction_read_only": "TRUE",
"application_name": "tegola",
}

dbconfig.ConnConfig.RuntimeParams = opts.GetRuntimeParams()
var hstore hstoreOID

dbconfig.AfterConnect = func(ctx context.Context, conn *pgx.Conn) error {
Expand Down Expand Up @@ -466,7 +487,24 @@ func CreateProvider(config dict.Dicter, maps []provider.Map, providerType string
return nil, err
}

dbconfig, err := BuildDBConfig(uri.String())
default_transaction_read_only := DefaultDefaultTransactionReadOnly
default_transaction_read_only, err = config.String(ConfigKeyDefaultTransactionReadOnly, &default_transaction_read_only)
if err != nil {
return nil, err
}

application_name := DefaultApplicationName
application_name, err = config.String(ConfigKeyApplicationName, &application_name)
if err != nil {
return nil, err
}

dbconfig, err := BuildDBConfig(
&DBConfigOptions{
Uri: uri.String(),
DefaultTransactionReadOnly: default_transaction_read_only,
ApplicationName: application_name,
})
if err != nil {
return nil, fmt.Errorf("failed while building db config: %w", err)
}
Expand Down
81 changes: 80 additions & 1 deletion provider/postgis/postgis_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ package postgis_test

import (
"fmt"
"strconv"
"testing"

"context"
Expand All @@ -13,6 +14,79 @@ import (
"github.com/jackc/pgx/v4/pgxpool"
)

func TestDBConfig(t *testing.T) {
host := ttools.GetEnvDefault("PGHOST", "localhost")
port, err := strconv.Atoi(ttools.GetEnvDefault("PGPORT", "5432"))
// if port is anything but int, fallback to default
if err != nil {
port = 5432
}
database := ttools.GetEnvDefault("PGDATABASE", "tegola")
user := ttools.GetEnvDefault("PGUSER", "postgres")
password := ttools.GetEnvDefault("PGPASSWORD", "postgres")

cs := fmt.Sprintf("postgres://%v:%v@%v:%v/%v", user, password, host, port, database)

type tcase struct {
opts *postgis.DBConfigOptions
expApplicationName string
expDefaultTransactionReadOnly string
}

fn := func(tc tcase) func(t *testing.T) {
return func(t *testing.T) {
dbconfig, err := postgis.BuildDBConfig(
tc.opts)
if err != nil {
t.Errorf("unable to build config: %v", err)
}

applicationName := dbconfig.ConnConfig.RuntimeParams["application_name"]
if applicationName != tc.expApplicationName {
t.Errorf("expected application name: %s, got: %s", tc.expApplicationName, applicationName)
}

defaultTransactionReadOnly := dbconfig.ConnConfig.RuntimeParams["default_transaction_read_only"]
if defaultTransactionReadOnly != tc.expDefaultTransactionReadOnly {
t.Errorf("expected transaction read only: %s, got: %s", tc.expDefaultTransactionReadOnly, defaultTransactionReadOnly)
}
}
}
tests := map[string]tcase{
"1": {
opts: &postgis.DBConfigOptions{
Uri: cs,
ApplicationName: "tegola",
DefaultTransactionReadOnly: "TRUE",
},
expApplicationName: "tegola",
expDefaultTransactionReadOnly: "TRUE",
},
"2": {
opts: &postgis.DBConfigOptions{
Uri: cs,
ApplicationName: "aloget",
DefaultTransactionReadOnly: "OFF",
},
expApplicationName: "aloget",
expDefaultTransactionReadOnly: "",
},
"3": {
opts: &postgis.DBConfigOptions{
Uri: cs,
ApplicationName: "tegola",
DefaultTransactionReadOnly: "FALSE",
},
expApplicationName: "tegola",
expDefaultTransactionReadOnly: "FALSE",
},
}

for name, tc := range tests {
t.Run(name, fn(tc))
}
}

func TestTLSConfig(t *testing.T) {

var (
Expand All @@ -24,7 +98,12 @@ func TestTLSConfig(t *testing.T) {
)

cs := fmt.Sprintf("postgres://%v:%v@%v:%v/%v", user, password, host, port, database)
testConnConfig, err := postgis.BuildDBConfig(cs)
testConnConfig, err := postgis.BuildDBConfig(
&postgis.DBConfigOptions{
Uri: cs,
DefaultTransactionReadOnly: "TRUE",
ApplicationName: "tegola",
})

if err != nil {
t.Fatalf("unable to build db config: %v", err)
Expand Down
7 changes: 6 additions & 1 deletion provider/postgis/util_internal_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -135,7 +135,12 @@ func TestDecipherFields(t *testing.T) {
password := ttools.GetEnvDefault("PGPASSWORD", "postgres")

cs := fmt.Sprintf("postgres://%v:%v@%v:%v/%v", user, password, host, port, db)
dbconfig, err := BuildDBConfig(cs)
dbconfig, err := BuildDBConfig(
&DBConfigOptions{
Uri: cs,
DefaultTransactionReadOnly: "TRUE",
ApplicationName: "tegola",
})

if err != nil {
t.Fatalf("unable to build db config: %v", err)
Expand Down

0 comments on commit 6258da4

Please sign in to comment.