pgx

package
v1.2.5 Latest Latest
Warning

This package is not in the latest version of its module.

Go to latest
Published: Aug 19, 2026 License: Apache-2.0 Imports: 5 Imported by: 0

README

pgx

PostgreSQL drivers that work under TinyGo as well as standard Go, so application code is shared between compilers. The layout mirrors upstream pgx:

Package Mirrors Use it for
database/pgx github.com/jackc/pgx/v5 The pgx-native API: Connect, Batch, CopyFrom, LISTEN/NOTIFY, row-collection helpers
database/pgx/pgxpool pgx/v5/pgxpool A concurrency-safe pool of native connections
database/pgx/stdlib pgx/v5/stdlib The database/sql adapter

On standard Go every exported name is an alias for the upstream pgx type, so values interoperate with third-party code that names pgx types. On TinyGo the same names bind to a vendored copy of pgx v5.10.0 with TLS rerouted, because TinyGo ships crypto/tls as a stub that cannot be linked. That is three patched files out of 145; see ../internal/PATCHES.md.

import (
	pgx "github.com/shibukawa/tinygodriver/database/pgx"
	"github.com/shibukawa/tinygodriver/database/pgx/pgxpool"
	"github.com/shibukawa/tinygodriver/database/pgx/stdlib"
)

// Native, one connection:
conn, err := pgx.Connect(ctx, dsn)

// Native, pooled:
pool, err := pgxpool.New(ctx, dsn)

// database/sql:
db, err := stdlib.Open(dsn)

ParseConfig in all three installs the same defaults: cancellation via CancelRequest, and on TinyGo the fd-carrying dialer that makes sslmode work. Prefer the native surface when performance matters: the database/sql layer costs a pool mutex and a per-connection mutex on every call plus one driver.Value boxing per parameter and result (measured: 15 vs 6 allocations per query).

TLS

sslmode works on all surfaces and both builds, including verify-full with a custom sslrootcert. On TinyGo the handshake runs on the already-connected socket after PostgreSQL's SSLRequest, using the platform's native TLS stack.

Platform Upgrade backend Max version
Standard Go crypto/tls TLS 1.3
macOS Secure Transport TLS 1.2
macOS with -tags darwinstarttlswith13 mbedTLS TLS 1.3
Linux mbedTLS TLS 1.3

Two differences from libpq are deliberate:

  • verify-ca is treated as verify-full. libpq skips the host name check there; the native backends cannot express that, and checking the name too is stricter, never weaker.
  • sslcert and sslkey are rejected rather than ignored, because the native backends cannot offer a client certificate.

A platform with no TLS backend refuses any mode but disable, and never falls back to plaintext silently. One known limit: CopyFrom over TLS on the TinyGo path can stall, because the native TLS sessions serialize reads against writes; plaintext CopyFrom is full duplex and verified.

TinyGo notes

Build with -scheduler=threads. Under the cooperative scheduler a blocking socket call holds the whole runtime, so background goroutines never run and query cancellation stops working without any error.

Blank-import netdev, as with any TinyGo program that uses the network:

import _ "github.com/shibukawa/tinygodriver/netdev"

Unix domain sockets and IPv6 are unavailable there, so connect over TCP to an IPv4 host.

Cancellation

context cancellation is wired to PostgreSQL's CancelRequest, which opens a second connection to ask the server to stop. pgx's default instead moves the deadline on the in-flight connection, which does nothing under TinyGo: netdev reads the deadline once when a read begins, so a later change cannot interrupt it and the query runs to completion with no error. ParseConfig installs the CancelRequest handler on both builds so behavior does not differ by compiler.

Reaching pgx from database/sql

Batch, CopyFrom and LISTEN/NOTIFY have no database/sql equivalent. For code that lives on database/sql, stdlib.WithConn leases a pooled connection and hands over the pgx connection behind it:

err := stdlib.WithConn(ctx, db, func(c *pgx.Conn) error {
	b := &pgx.Batch{}
	b.Queue("INSERT INTO t(a) VALUES ($1)", 1)
	b.Queue("INSERT INTO t(a) VALUES ($1)", 2)
	return c.SendBatch(ctx, b).Close()
})

Naming the types through database/pgx is mandatory rather than tidy: the TinyGo build uses the vendored pgx under database/internal/, which no package outside database/ may import, so hand-writing the sql.Conn.Raw assertion compiles on standard Go and fails on TinyGo with use of internal package not allowed. examples/pgxdemo and examples/pgxnativedemo are built on both paths and are what keep that from regressing.

c is only valid inside the callback, as with sql.Conn.Raw. Read and close BatchResults and Rows before returning.

Updating the vendored pgx

go mod download github.com/jackc/pgx/v5@vX.Y.Z   # after bumping PGX_VERSION
python3 ../internal/vendor.py && python3 ../internal/patch.py

patch.py anchors every edit on an exact upstream string and fails loudly if one is gone, so a version bump reports what needs attention instead of quietly producing a tree that still links crypto/tls.

Tests

The integration tests skip unless a server is configured:

docker run -d --name pgtest -e POSTGRES_PASSWORD=pass -e POSTGRES_USER=user \
    -e POSTGRES_DB=db -p 55432:5432 postgres:17

PGX_TEST_DSN='postgres://user:pass@localhost:55432/db?sslmode=disable' \
    go test ./database/pgx/...

Add -tags force_tinygo_logic to run the same suites against the vendored backend without a TinyGo toolchain. The TLS tests need a server with ssl=on; stdlib/tls_test.go documents the setup.

Documentation

Overview

Package pgx provides the pgx-native PostgreSQL API under both TinyGo and standard Go.

It is the native sibling of the stdlib adapter under database/pgx/stdlib, for code that wants pgx itself rather than database/sql: no pool mutex on the query path, no driver.Value boxing per parameter, and connection-oriented features such as Batch, CopyFrom and LISTEN/NOTIFY as first-class calls instead of an escape hatch behind a callback.

conn, err := pgx.Connect(ctx, "postgres://user:pass@localhost:5432/db?sslmode=disable")
if err != nil { ... }
defer conn.Close(ctx)

var n int
err = conn.QueryRow(ctx, "SELECT 1").Scan(&n)

On standard Go every name here is an alias for the upstream github.com/jackc/pgx/v5 type, so a *pgx.Conn from this package is upstream's *pgx.Conn and passes to third-party code unchanged. On TinyGo the same names bind to a vendored copy of pgx v5.10.0 with its TLS use rerouted onto the platform's native stack, because TinyGo ships crypto/tls as a stub that cannot be linked. See database/internal/PATCHES.md. Code written against this package compiles identically on both.

Defaults

ParseConfig and Connect install two defaults on every configuration:

  • Query cancellation is performed by sending a CancelRequest on a second connection, never by moving the read deadline. Under TinyGo's netdev a deadline change cannot interrupt a blocked read, so the deadline strategy would silently not cancel at all.
  • On the TinyGo build, the dialer returns a connection that carries its own file descriptor, which is what lets sslmode start TLS on the already-connected socket.

Both are plain fields on the returned ConnConfig, so a caller who needs different behavior may overwrite them before ConnectConfig.

sslmode

sslmode is honored on both builds with the same semantics as stdlib.Open. On TinyGo two differences from libpq are deliberate: verify-ca is treated as verify-full, and sslcert/sslkey are rejected rather than ignored, because the native TLS backends cannot offer a client certificate. A platform with no TLS backend refuses any mode but disable; it never falls back to plaintext silently.

TinyGo notes

Build with -scheduler=threads. Under the cooperative scheduler a blocking socket call holds the whole runtime, so background goroutines never run and query cancellation silently stops working.

Import netdev for its side effect, as with any TinyGo program using the network:

import _ "github.com/shibukawa/tinygodriver/netdev"

Unix domain sockets and IPv6 are unavailable there, so connect over TCP to an IPv4 host.

Registering custom pgtype codecs needs the pgtype package itself, which the TinyGo build keeps under internal/ and cannot re-export wholesale; that remains standard-Go-only for now. The pool lives in database/pgx/pgxpool, the database/sql adapter in database/pgx/stdlib.

Index

Constants

View Source
const (
	Serializable    = pgx.Serializable
	RepeatableRead  = pgx.RepeatableRead
	ReadCommitted   = pgx.ReadCommitted
	ReadUncommitted = pgx.ReadUncommitted
	ReadWrite       = pgx.ReadWrite
	ReadOnly        = pgx.ReadOnly
	Deferrable      = pgx.Deferrable
	NotDeferrable   = pgx.NotDeferrable
)

Transaction characteristics, forwarded as typed constants.

View Source
const (
	QueryExecModeCacheStatement = pgx.QueryExecModeCacheStatement
	QueryExecModeCacheDescribe  = pgx.QueryExecModeCacheDescribe
	QueryExecModeDescribeExec   = pgx.QueryExecModeDescribeExec
	QueryExecModeExec           = pgx.QueryExecModeExec
	QueryExecModeSimpleProtocol = pgx.QueryExecModeSimpleProtocol
)

Query execution modes, for ConnConfig.DefaultQueryExecMode or as the first query argument.

Variables

View Source
var (
	ErrNoRows           = pgx.ErrNoRows
	ErrTooManyRows      = pgx.ErrTooManyRows
	ErrTxClosed         = pgx.ErrTxClosed
	ErrTxCommitRollback = pgx.ErrTxCommitRollback
)

Sentinel errors. Vars because Go cannot alias a var; errors.Is works unchanged since these are the same values.

View Source
var (
	CopyFromRows  = pgx.CopyFromRows
	CopyFromSlice = pgx.CopyFromSlice
	CopyFromFunc  = pgx.CopyFromFunc
)

The CopyFrom source constructors, as variables because Go has no alias for a function.

View Source
var (
	RowToMap   = pgx.RowToMap
	ForEachRow = pgx.ForEachRow
)

Functions

func AppendRows

func AppendRows[T any, S ~[]T](slice S, rows Rows, fn RowToFunc[T]) (S, error)

func CollectExactlyOneRow

func CollectExactlyOneRow[T any](rows Rows, fn RowToFunc[T]) (T, error)

func CollectOneRow

func CollectOneRow[T any](rows Rows, fn RowToFunc[T]) (T, error)

func CollectRows

func CollectRows[T any](rows Rows, fn RowToFunc[T]) ([]T, error)

func RowTo

func RowTo[T any](row CollectableRow) (T, error)

func RowToAddrOf

func RowToAddrOf[T any](row CollectableRow) (*T, error)

func RowToAddrOfStructByName

func RowToAddrOfStructByName[T any](row CollectableRow) (*T, error)

func RowToAddrOfStructByNameLax

func RowToAddrOfStructByNameLax[T any](row CollectableRow) (*T, error)

func RowToAddrOfStructByPos

func RowToAddrOfStructByPos[T any](row CollectableRow) (*T, error)

func RowToStructByName

func RowToStructByName[T any](row CollectableRow) (T, error)

func RowToStructByNameLax

func RowToStructByNameLax[T any](row CollectableRow) (T, error)

func RowToStructByPos

func RowToStructByPos[T any](row CollectableRow) (T, error)

Types

type Batch

type Batch = pgx.Batch

The public surface, as aliases so every value is the upstream pgx value itself and satisfies upstream interfaces. The vendored backend defines the same names against its own copy; keeping the two sets identical is what makes code written against this package portable across compilers.

type BatchResults

type BatchResults = pgx.BatchResults

The public surface, as aliases so every value is the upstream pgx value itself and satisfies upstream interfaces. The vendored backend defines the same names against its own copy; keeping the two sets identical is what makes code written against this package portable across compilers.

type CollectableRow

type CollectableRow = pgx.CollectableRow

The row-collection helpers. Generic functions can be neither aliased nor bound to a variable, so unlike the types above they are one-line forwards.

type CommandTag

type CommandTag = pgconn.CommandTag

The public surface, as aliases so every value is the upstream pgx value itself and satisfies upstream interfaces. The vendored backend defines the same names against its own copy; keeping the two sets identical is what makes code written against this package portable across compilers.

type Conn

type Conn = pgx.Conn

The public surface, as aliases so every value is the upstream pgx value itself and satisfies upstream interfaces. The vendored backend defines the same names against its own copy; keeping the two sets identical is what makes code written against this package portable across compilers.

func Connect

func Connect(ctx context.Context, dsn string) (*Conn, error)

Connect opens a native pgx connection for a libpq-style URL or keyword DSN.

Unlike database/sql handles, the connection is real and singular: it is established eagerly, is not safe for concurrent use, and belongs to the caller until Close. Use one connection per goroutine, or pool above this package.

func ConnectConfig

func ConnectConfig(ctx context.Context, cfg *ConnConfig) (*Conn, error)

ConnectConfig opens a connection from a configuration built by ParseConfig. The config must originate from ParseConfig, which is pgx's own rule.

type ConnConfig

type ConnConfig = pgx.ConnConfig

The public surface, as aliases so every value is the upstream pgx value itself and satisfies upstream interfaces. The vendored backend defines the same names against its own copy; keeping the two sets identical is what makes code written against this package portable across compilers.

func ParseConfig

func ParseConfig(dsn string) (*ConnConfig, error)

ParseConfig parses a libpq-style URL or keyword DSN and applies this package's defaults; see the package documentation. The result may be adjusted before ConnectConfig.

type CopyFromSource

type CopyFromSource = pgx.CopyFromSource

The public surface, as aliases so every value is the upstream pgx value itself and satisfies upstream interfaces. The vendored backend defines the same names against its own copy; keeping the two sets identical is what makes code written against this package portable across compilers.

type FieldDescription

type FieldDescription = pgconn.FieldDescription

The public surface, as aliases so every value is the upstream pgx value itself and satisfies upstream interfaces. The vendored backend defines the same names against its own copy; keeping the two sets identical is what makes code written against this package portable across compilers.

type Identifier

type Identifier = pgx.Identifier

The public surface, as aliases so every value is the upstream pgx value itself and satisfies upstream interfaces. The vendored backend defines the same names against its own copy; keeping the two sets identical is what makes code written against this package portable across compilers.

type LargeObjects

type LargeObjects = pgx.LargeObjects

The public surface, as aliases so every value is the upstream pgx value itself and satisfies upstream interfaces. The vendored backend defines the same names against its own copy; keeping the two sets identical is what makes code written against this package portable across compilers.

type NamedArgs

type NamedArgs = pgx.NamedArgs

The public surface, as aliases so every value is the upstream pgx value itself and satisfies upstream interfaces. The vendored backend defines the same names against its own copy; keeping the two sets identical is what makes code written against this package portable across compilers.

type Notification

type Notification = pgconn.Notification

The public surface, as aliases so every value is the upstream pgx value itself and satisfies upstream interfaces. The vendored backend defines the same names against its own copy; keeping the two sets identical is what makes code written against this package portable across compilers.

type PgConn

type PgConn = pgconn.PgConn

The public surface, as aliases so every value is the upstream pgx value itself and satisfies upstream interfaces. The vendored backend defines the same names against its own copy; keeping the two sets identical is what makes code written against this package portable across compilers.

type PgError

type PgError = pgconn.PgError

The public surface, as aliases so every value is the upstream pgx value itself and satisfies upstream interfaces. The vendored backend defines the same names against its own copy; keeping the two sets identical is what makes code written against this package portable across compilers.

type QueryExecMode

type QueryExecMode = pgx.QueryExecMode

The public surface, as aliases so every value is the upstream pgx value itself and satisfies upstream interfaces. The vendored backend defines the same names against its own copy; keeping the two sets identical is what makes code written against this package portable across compilers.

type QueryTracer

type QueryTracer = pgx.QueryTracer

The public surface, as aliases so every value is the upstream pgx value itself and satisfies upstream interfaces. The vendored backend defines the same names against its own copy; keeping the two sets identical is what makes code written against this package portable across compilers.

type QueuedQuery

type QueuedQuery = pgx.QueuedQuery

The public surface, as aliases so every value is the upstream pgx value itself and satisfies upstream interfaces. The vendored backend defines the same names against its own copy; keeping the two sets identical is what makes code written against this package portable across compilers.

type Row

type Row = pgx.Row

The public surface, as aliases so every value is the upstream pgx value itself and satisfies upstream interfaces. The vendored backend defines the same names against its own copy; keeping the two sets identical is what makes code written against this package portable across compilers.

type RowScanner

type RowScanner = pgx.RowScanner

The public surface, as aliases so every value is the upstream pgx value itself and satisfies upstream interfaces. The vendored backend defines the same names against its own copy; keeping the two sets identical is what makes code written against this package portable across compilers.

type RowToFunc

type RowToFunc[T any] = pgx.RowToFunc[T]

The row-collection helpers. Generic functions can be neither aliased nor bound to a variable, so unlike the types above they are one-line forwards.

type Rows

type Rows = pgx.Rows

The public surface, as aliases so every value is the upstream pgx value itself and satisfies upstream interfaces. The vendored backend defines the same names against its own copy; keeping the two sets identical is what makes code written against this package portable across compilers.

type StrictNamedArgs

type StrictNamedArgs = pgx.StrictNamedArgs

The public surface, as aliases so every value is the upstream pgx value itself and satisfies upstream interfaces. The vendored backend defines the same names against its own copy; keeping the two sets identical is what makes code written against this package portable across compilers.

type Tx

type Tx = pgx.Tx

The public surface, as aliases so every value is the upstream pgx value itself and satisfies upstream interfaces. The vendored backend defines the same names against its own copy; keeping the two sets identical is what makes code written against this package portable across compilers.

type TxAccessMode

type TxAccessMode = pgx.TxAccessMode

The public surface, as aliases so every value is the upstream pgx value itself and satisfies upstream interfaces. The vendored backend defines the same names against its own copy; keeping the two sets identical is what makes code written against this package portable across compilers.

type TxDeferrableMode

type TxDeferrableMode = pgx.TxDeferrableMode

The public surface, as aliases so every value is the upstream pgx value itself and satisfies upstream interfaces. The vendored backend defines the same names against its own copy; keeping the two sets identical is what makes code written against this package portable across compilers.

type TxIsoLevel

type TxIsoLevel = pgx.TxIsoLevel

The public surface, as aliases so every value is the upstream pgx value itself and satisfies upstream interfaces. The vendored backend defines the same names against its own copy; keeping the two sets identical is what makes code written against this package portable across compilers.

type TxOptions

type TxOptions = pgx.TxOptions

The public surface, as aliases so every value is the upstream pgx value itself and satisfies upstream interfaces. The vendored backend defines the same names against its own copy; keeping the two sets identical is what makes code written against this package portable across compilers.

Directories

Path Synopsis
Package pgxpool provides the pgx-native connection pool under both TinyGo and standard Go.
Package pgxpool provides the pgx-native connection pool under both TinyGo and standard Go.
Package stdlib adapts database/pgx to database/sql, mirroring upstream pgx's stdlib package, and works under both TinyGo and standard Go.
Package stdlib adapts database/pgx to database/sql, mirroring upstream pgx's stdlib package, and works under both TinyGo and standard Go.

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
y or Y : Canonical URL