Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion service/entityresolution/multi-strategy/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -691,4 +691,4 @@ See [`example-config.yaml`](./example-config.yaml) for a comprehensive configura
- Cross-backend failover scenarios
- Health check configuration

For implementation details and architecture decisions, see the [Multi-Strategy ERS ADR](../../../adr/decisions/2025-07-31-multi-strategy-entity-resolution-service.md).
For implementation details and architecture decisions, see the [Multi-Strategy ERS ADR](../../../adr/decisions/2025-07-31-multi-strategy-entity-resolution-service.md).
Original file line number Diff line number Diff line change
Expand Up @@ -276,4 +276,4 @@ services:
#
# 5. No matching strategy:
# - JWT contains: {"aud": ["unknown"]}
# - Result: Error - no matching strategy found (regardless of failure_strategy)
# - Result: Error - no matching strategy found (regardless of failure_strategy)
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,10 @@ import (

const (
// Default SQL configuration values
defaultPostgreSQLDriver = "postgres"
canonicalPGXDriver = "pgx/v5"
pgxDriverAlias = "pgx"
postgresQLDriverAlias = "postgresql"
defaultPostgreSQLPort = 5432
defaultMaxOpenConnections = 25
defaultMaxIdleConnections = 5
Expand All @@ -17,7 +21,7 @@ const (
// SQLConfig defines configuration for SQL database providers
type Config struct {
// Database connection configuration
Driver string `mapstructure:"driver"` // "postgres", "mysql", "sqlite"
Driver string `mapstructure:"driver"` // "postgres", "mysql", "sqlite" ("pgx", "pgx/v5", and "postgresql" are accepted as aliases)
Host string `mapstructure:"host"`
Port int `mapstructure:"port"`
Database string `mapstructure:"database"`
Expand Down Expand Up @@ -45,7 +49,7 @@ type Config struct {
// DefaultConfig returns a default SQL configuration
func DefaultConfig() Config {
return Config{
Driver: "postgres",
Driver: defaultPostgreSQLDriver,
Port: defaultPostgreSQLPort,
SSLMode: "require",
MaxOpenConnections: defaultMaxOpenConnections,
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,76 @@
package sql

import (
"testing"

"github.com/stretchr/testify/require"
)

func TestDefaultConfigUsesPostgreSQLDriver(t *testing.T) {
config := DefaultConfig()
require.Equal(t, defaultPostgreSQLDriver, config.Driver)
}

func TestNormalizeDriverName(t *testing.T) {
tests := []struct {
name string
driver string
want string
}{
{
name: "pgx",
driver: pgxDriverAlias,
want: canonicalPGXDriver,
},
{
name: "postgres default",
driver: defaultPostgreSQLDriver,
want: canonicalPGXDriver,
},
{
name: "postgresql alias with whitespace and case",
driver: " PostgreSQL ",
want: canonicalPGXDriver,
},
{
name: "other driver",
driver: "mysql",
want: "mysql",
},
{
name: "sqlite driver",
driver: "sqlite3",
want: "sqlite3",
},
}

for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
require.Equal(t, tt.want, normalizeDriverName(tt.driver))
})
}
}

func TestBuildConnectionStringSupportsPostgresAliases(t *testing.T) {
tests := []string{canonicalPGXDriver, defaultPostgreSQLDriver, pgxDriverAlias, postgresQLDriverAlias, "Postgres"}

for _, driver := range tests {
t.Run(driver, func(t *testing.T) {
provider := &Provider{
config: Config{
Driver: driver,
Host: "localhost",
Port: 5432,
Database: "identity_db",
Username: "ers_user",
Password: "ers_password",
SSLMode: "require",
},
}

connStr, err := provider.buildConnectionString()
require.NoError(t, err)
require.Contains(t, connStr, "dbname=identity_db")
})
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -6,14 +6,21 @@ import (
"fmt"
"strings"

// Database drivers would be imported here:
// _ "github.com/lib/pq" // PostgreSQL driver
// _ "github.com/go-sql-driver/mysql" // MySQL driver
// _ "github.com/mattn/go-sqlite3" // SQLite driver

// Register the pgx/v5 database/sql driver for SQL providers.
_ "github.com/jackc/pgx/v5/stdlib"
Comment thread
strantalis marked this conversation as resolved.
"github.com/opentdf/platform/service/entityresolution/multi-strategy/types"
)

func normalizeDriverName(driver string) string {
driver = strings.ToLower(strings.TrimSpace(driver))
switch driver {
case defaultPostgreSQLDriver, pgxDriverAlias, postgresQLDriverAlias:
return canonicalPGXDriver
default:
return driver
}
}

// Provider implements the Provider interface for SQL databases
type Provider struct {
name string
Expand All @@ -24,6 +31,10 @@ type Provider struct {

// NewProvider creates a new SQL provider
func NewProvider(ctx context.Context, name string, config Config) (*Provider, error) {
// Normalize aliases so "pgx", "postgres", and "postgresql" use the
// registered pgx/v5 database/sql driver name.
config.Driver = normalizeDriverName(config.Driver)

provider := &Provider{
name: name,
config: config,
Expand Down Expand Up @@ -253,8 +264,8 @@ func (p *Provider) Close() error {

// buildConnectionString creates a connection string based on the driver
func (p *Provider) buildConnectionString() (string, error) {
switch strings.ToLower(p.config.Driver) {
case "postgres":
switch normalizeDriverName(p.config.Driver) {
case canonicalPGXDriver:
return fmt.Sprintf("host=%s port=%d user=%s password=%s dbname=%s sslmode=%s",
p.config.Host, p.config.Port, p.config.Username, p.config.Password,
p.config.Database, p.config.SSLMode), nil
Expand Down
Loading