Skip to content

Conversation

@maxtheaxe
Copy link

@maxtheaxe maxtheaxe commented Nov 27, 2025

Draws on this issue (which I ran into myself), in which sql_insert doesn't actually support Postgres array columns. I was left trying to manually escape convoluted strings using regex, and handcraft array literals, which is really brittle.

This is a different approach to the other PR, in which I add pgx as an alternate driver. In this case, as discussed here, I'm replacing lib/pq directly, and adding a shim that retains support for referencing the new postgres driver with postgres. Given that pgx/v4 was already used here, I stuck with that, though obviously you may choose to upgrade to v5.

It doesn't redefine any settings otherwise, just reuses everything from the original postgres driver.


I've run go test on internal/impl/sql and built a docker image, and everything seems to be fully working, at least for my somewhat narrow use case (that in the issue referenced above).

That being said, I would like to state for the record that this was LLM-assisted, though obviously the change is pretty straightforward. I figure it doesn't hurt to mention in case I've missed something obvious.

@@ -0,0 +1,18 @@
package postgrespgx
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Why do we need this driver approach? Can we not just directly swap out lib/pq usage with "github.com/jackc/pgx/v4/stdlib"?

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Unfortunately, the pgx driver is just not called postgres, it's called pgx or pgx/vX:

https://github.com/jackc/pgx/blob/ae204a414cbdd6fdb503808221dda22335cf4fd9/stdlib/sql.go#L107-L117

func init() {
	pgxDriver = &Driver{
		configs: make(map[string]*pgx.ConnConfig),
	}


	// if pgx driver was already registered by different pgx major version then we
	// skip registration under the default name.
	if !slices.Contains(sql.Drivers(), "pgx") {
		sql.Register("pgx", pgxDriver)
	}
	sql.Register("pgx/v5", pgxDriver)

	// extra stuff
}

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

In the other PR I refer to the driver directly as pgx, if you want to see that option.

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Ahh I see. So by removing lib/pq we lose the postgres plugin, meaning we have ensure it's registered if we want the sql.Open("postgres", "<conn>") to work.

I've done some reading on this and it seems that even the lib/pq maintainers suggest using the pgx driver 🤔

See lib/pq/README.md#status:

For users that require new features or reliable resolution of reported bugs, we recommend using pgx which is under active development.

Here's what I think we should do:

  1. Register pgx as normal, and add an additonal postgres_v2 driver to our SQL components, which acts as an alias to the underlying pgx driver.
    • driver: postgres => lib/pq::postgres
    • driver: postgres_v2 => github.com/jackc/pgx/v4/stdlib::pgx
input:
  sql_select:
    driver: postgres_v2 # will use pgx
  1. We can then add an integration test using this pgx driver (aliased in config by postgres_v2) in our integration_test.go.

func TestIntegrationPostgres(t *testing.T) {

  1. Then, in the next release, we can change the default postgres to point to pgx and deprecate lib/pq support:

    • driver: postgres_legacy => lib/pq::postgres
    • driver: postgres => github.com/jackc/pgx/v4/stdlib::pgx
    • driver: postgres_v2 => github.com/jackc/pgx/v4/stdlib::pgx

    Note: specifying this driver: postgres_v2 should probably log a warning saying it's being removed in next minor release, else we just keep it around if it's not too much extra complexity.

})
}

func getDriver(conf *service.ParsedConfig, log *service.Logger) (string, error) {
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Let's log this in sqlOpenWithReworks rather? Then we wont need to use the getDriver in each component

func sqlOpenWithReworks(ctx context.Context, logger *service.Logger, driver, dsn string, connSettings *connSettings) (*sql.DB, error) {

@@ -0,0 +1,18 @@
package postgrespgx

import (
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Can we not register pgx as a driver in public?

// Import all (supported) sql drivers.
_ "github.com/ClickHouse/clickhouse-go/v2"

var warnPostgresV2Once sync.Once

func warnIfPostgresV2(driver string, log *service.Logger) {
if driver != "postgres_v2" || log == nil {
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Can we add postgres_v2 as a driver in the conn_fields? It should be in

var driverField = service.NewStringEnumField("driver", "mysql", "postgres", "clickhouse", "mssql", "sqlite", "oracle", "snowflake", "trino", "gocosmos", "spanner").
Description("A database [driver](#drivers) to use.")

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants