server

package
v0.0.0-...-d79ae9c Latest Latest
Warning

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

Go to latest
Published: Jun 12, 2026 License: MIT Imports: 56 Imported by: 0

Documentation

Index

Constants

View Source
const (
	OidBool        int32 = 16
	OidBytea       int32 = 17
	OidChar        int32 = 18 // "char" - single-byte internal type
	OidName        int32 = 19 // name - 64-byte internal type for identifiers
	OidInt8        int32 = 20 // bigint
	OidInt2        int32 = 21 // smallint
	OidInt4        int32 = 23 // integer
	OidText        int32 = 25
	OidOid         int32 = 26
	OidFloat4      int32 = 700  // real
	OidFloat8      int32 = 701  // double precision
	OidBpchar      int32 = 1042 // blank-padded char
	OidVarchar     int32 = 1043
	OidDate        int32 = 1082
	OidTime        int32 = 1083
	OidTimestamp   int32 = 1114
	OidTimestamptz int32 = 1184
	OidInterval    int32 = 1186
	OidNumeric     int32 = 1700
	OidUUID        int32 = 2950
	OidTimetz      int32 = 1266
	OidJSON        int32 = 114
	OidJSONB       int32 = 3802

	// Array OIDs
	OidBoolArray        int32 = 1000
	OidInt2Array        int32 = 1005
	OidInt4Array        int32 = 1007
	OidTextArray        int32 = 1009
	OidVarcharArray     int32 = 1015
	OidInt8Array        int32 = 1016
	OidFloat4Array      int32 = 1021
	OidFloat8Array      int32 = 1022
	OidTimestampArray   int32 = 1115
	OidDateArray        int32 = 1182
	OidTimeArray        int32 = 1183
	OidTimestamptzArray int32 = 1185
	OidIntervalArray    int32 = 1187
	OidNumericArray     int32 = 1231
	OidTimetzArray      int32 = 1270
	OidUUIDArray        int32 = 2951
)

PostgreSQL type OIDs

View Source
const (
	ExitSuccess     = 0  // Clean disconnect
	ExitError       = 1  // Error (crash, protocol error)
	ExitAuthFailure = 10 // Authentication failure (triggers rate limit update)
)

Exit codes for child processes

View Source
const DefaultDuckLakeSpecVersion = ducklake.DefaultSpecVersion

DefaultDuckLakeSpecVersion is re-exported for callers that referenced the constant under the server package before the migration code moved.

View Source
const DefaultSessionInitTimeout = 10 * time.Second

DefaultSessionInitTimeout bounds startup metadata initialization and catalog probes.

View Source
const ProfilingOutputPath = "/tmp/duckgres-profiling.json"

ProfilingOutputPath is where DuckDB writes the per-query profile JSON. The duckdbservice worker reads this file after each query and forwards the contents to the control plane via gRPC trailer (see duckdbservice.sendProfilingMetadata) where EnrichSpanWithProfiling turns it into OTEL child spans.

Variables

View Source
var (
	NewRateLimiter              = auth.NewRateLimiter
	DefaultRateLimitConfig      = auth.DefaultRateLimitConfig
	BeginRateLimitedAuthAttempt = auth.BeginRateLimitedAuthAttempt
	RecordFailedAuthAttempt     = auth.RecordFailedAuthAttempt
	RecordSuccessfulAuthAttempt = auth.RecordSuccessfulAuthAttempt
	ValidateUserPassword        = auth.ValidateUserPassword
)
View Source
var (
	HasAttachedCatalog          = sessionmeta.HasAttachedCatalog
	InitSessionDatabaseMetadata = sessionmeta.InitSessionDatabaseMetadata
)

HasAttachedCatalog and InitSessionDatabaseMetadata moved to server/sessionmeta. Re-exports kept here for the dozen call sites in the control plane and elsewhere; new code should import server/sessionmeta directly.

View Source
var (
	CheckDuckLakeMigrationVersion   = ducklake.CheckMigrationVersion
	CheckAndBackupDuckLakeMigration = ducklake.CheckAndBackupMigration
	BackupDuckLakeMetadata          = ducklake.BackupMetadata
	DefaultDeltaCatalogPath         = ducklake.DefaultDeltaCatalogPath
)

Re-exports of the migration / backup / delta-path entry points so callers that referenced them under the server package continue to compile after the implementation moved to server/ducklake. New code should import server/ducklake directly.

View Source
var (
	IncrementOpenConnections = observe.IncrementOpenConnections
	DecrementOpenConnections = observe.DecrementOpenConnections
)

connectionsGauge, IncrementOpenConnections, DecrementOpenConnections moved to server/observe. The aliases below preserve the existing server.X spellings for the call sites in this package and the control plane.

View Source
var (
	IsEmptyQuery          = sqlcore.IsEmptyQuery
	OTELGRPCClientHandler = sqlcore.OTELGRPCClientHandler
)
View Source
var (
	SystemMemoryBytes   = sysinfo.SystemMemoryBytes
	ValidateMemoryLimit = sysinfo.ValidateMemoryLimit
	ParseMemoryBytes    = sysinfo.ParseMemoryBytes
)
View Source
var (
	NewACMEManager     = tlscert.NewACMEManager
	NewACMEDNSManager  = tlscert.NewACMEDNSManager
	EnsureCertificates = tlscert.EnsureCertificates
)
View Source
var GenerateSecretKey = wire.GenerateSecretKey

GenerateSecretKey re-exports wire.GenerateSecretKey so existing callers that imported it from server keep compiling. New code should use server/wire directly.

View Source
var RedactSecrets = wire.RedactSecrets

RedactSecrets is a re-export var for callers that imported it from this package. See server/wire/redact.go for the implementation.

View Source
var Tracer = observe.Tracer

Tracer re-exports observe.Tracer for callers that previously imported it from this package. The tracing helpers, profiling-output enrichment, and connection counters all live in server/observe; new code should import that package directly.

Functions

func ActivateDBConnection

func ActivateDBConnection(db *sql.DB, cfg Config, duckLakeSem chan struct{}, username string) error

ActivateDBConnection applies tenant-specific DuckLake runtime to an already initialized generic DuckDB connection used by a shared warm worker.

func ApplyProfilingSettings

func ApplyProfilingSettings(ctx context.Context, conn *sql.Conn)

ApplyProfilingSettings runs ProfilingSetupSQL against the given connection, writing profiles to ProfilingOutputPath. Use this for connections that bypass ConfigureMainDB — primarily fresh per-session connections in the cluster-mode worker, where eviction between sessions discards whatever settings ConfigureMainDB applied.

func AttachDeltaCatalog

func AttachDeltaCatalog(db *sql.DB, dlCfg DuckLakeConfig, sem chan struct{}) error

AttachDeltaCatalog attaches the configured Delta Lake catalog/table alongside DuckLake. It reuses the DuckLake S3 secret settings so Delta scans can access the same object store credentials.

Delta is enabled by default. When no path is derivable (e.g. a plain standalone DuckDB instance with no DuckLake object_store/data_path), this is a benign no-op: there's no Delta sibling to attach.

func AttachDuckLake

func AttachDuckLake(db *sql.DB, dlCfg DuckLakeConfig, sem chan struct{}, dataDir string) error

AttachDuckLake attaches a DuckLake catalog if configured (but does NOT set it as default). Call setDuckLakeDefault after creating per-connection views in memory.main. This is a standalone function so it can be reused by control plane workers. dataDir is used for writing migration backup files if a schema upgrade is needed.

func AttachIcebergCatalog

func AttachIcebergCatalog(db *sql.DB, ic IcebergConfig, sem chan struct{}, keyID, secret, sessionToken string) error

AttachIcebergCatalog attaches the per-tenant Iceberg catalog. Lakekeeper REST is the only backend; the AWS S3 Tables path was removed when S3 Tables stopped being a supported product. Idempotent if the catalog is already attached; fail-soft for the "fresh tenant, no namespaces yet" case so a worker activation isn't blocked.

func BootstrapBundledExtensions

func BootstrapBundledExtensions(dataDir string) error

BootstrapBundledExtensions eagerly seeds bundled extension binaries into the configured extension_directory cache once per data directory.

func BuildDuckDBCopyFromSQL

func BuildDuckDBCopyFromSQL(tableName, columnList, filePath string, opts *CopyFromOptions) string

BuildDuckDBCopyFromSQL generates a DuckDB COPY FROM statement

func CancelClientConn

func CancelClientConn(cc *clientConn)

CancelClientConn cancels the context of a clientConn.

func ConfigureDBConnection

func ConfigureDBConnection(db *sql.DB, cfg Config, duckLakeSem chan struct{}, username string, serverStartTime time.Time, serverVersion string) error

ConfigureDBConnection initializes an existing DuckDB connection with pg_catalog, information_schema, and DuckLake catalog attachment.

func ConfigureMainDB

func ConfigureMainDB(db *sql.DB, cfg Config, username string) error

ConfigureMainDB applies the per-instance DuckDB settings (threads, memory, temp dir, extensions, profiling) that the client-query DB needs. Shared between openBaseDB (single-DB path) and OpenDuckDBPair (shared-connector path) so the main DB is configured identically either way.

func CreateDBConnection

func CreateDBConnection(cfg Config, duckLakeSem chan struct{}, username string, serverStartTime time.Time, serverVersion string) (*sql.DB, error)

CreateDBConnection creates a DuckDB connection for a client session. Uses in-memory database as an anchor for DuckLake attachment (actual data lives in RDS/S3). This is a standalone function so it can be reused by both the server and control plane workers. serverStartTime is the time the top-level server process started (may differ from processStartTime in process isolation mode where each child has its own processStartTime). serverVersion is the version of the top-level server/control-plane process.

func CreatePassthroughDBConnection

func CreatePassthroughDBConnection(cfg Config, duckLakeSem chan struct{}, username string, serverStartTime time.Time, serverVersion string) (*sql.DB, error)

CreatePassthroughDBConnection creates a DuckDB connection without pg_catalog or information_schema initialization. DuckLake is still attached if configured so passthrough users can access the same data. This is used for passthrough users who send DuckDB-native SQL and don't need the PostgreSQL compatibility layer.

func DuckDBDSN

func DuckDBDSN(cfg Config, username string) (string, error)

DuckDBDSN returns the DSN openBaseDB / the duckdbservice pair builder use for cfg/username. Exported so duckdbservice (which holds the duckdb-go-v2 import) can build a *duckdb.Connector against the same DSN that openBaseDB would have passed to sql.Open.

func InitMinimalServer

func InitMinimalServer(s *Server, cfg Config, queryCancelCh <-chan struct{})

InitMinimalServer initializes a Server struct with minimal fields for use in control plane worker sessions.

func LegacySecretDirectory

func LegacySecretDirectory(cfg Config) string

LegacySecretDirectory returns DuckDB's pre-pinning default persistent-secret location for a worker whose HOME is its DataDir (<DataDir>/.duckdb/stored_secrets). This is where secrets accumulated before SecretDirectory pinning existed, and the only reason it's a named helper is so the recycle wipe and this derivation stay colocated and can't drift apart. Returns "" when DataDir is unset.

func LoadExtensions

func LoadExtensions(db *sql.DB, extensions []string) error

LoadExtensions installs and loads DuckDB extensions. This is a standalone function so it can be reused by control plane workers. Extension strings can include a source, e.g. "cache_httpfs FROM community". INSTALL uses the full string; LOAD uses just the extension name.

NOTE: Extension names come from trusted server config, not user input.

func NewClientConn

func NewClientConn(s *Server, conn net.Conn, reader *bufio.Reader, writer *bufio.Writer,
	username, orgID, database, applicationName string, executor QueryExecutor, pid, secretKey int32, workerID int, workerPod string) *clientConn

NewClientConn creates a clientConn with pre-initialized fields for use by the control plane worker. The returned value is opaque (*clientConn) but can be used with SendInitialParams and RunMessageLoop.

func ParseStartupOptions

func ParseStartupOptions(options string) map[string]string

ParseStartupOptions parses the Postgres startup-message `options` parameter, which carries `-c name=value` GUC settings (also accepted: `-cname=value` and `--name=value`), e.g. `-c search_path=iceberg.public`. libpq's `options` connection keyword, the PGOPTIONS env var, and pgjdbc's `currentSchema` all arrive here. Values may contain backslash-escaped spaces. Returns a map of setting name -> value (later settings win on duplicate names).

func ProcessVersion

func ProcessVersion() string

ProcessVersion returns the version string for this process.

func ProfilingSetupSQL

func ProfilingSetupSQL(outputPath string) []string

ProfilingSetupSQL returns the SQL statements that configure DuckDB profiling so the output is written to outputPath. These are session-scoped — DuckDB rejects `SET GLOBAL` for each one — so any caller that hands out fresh connections (e.g. after evictConnFromPool) must re-run them per connection.

func ReadMessage

func ReadMessage(r io.Reader) (byte, []byte, error)

func ReadStartupMessage

func ReadStartupMessage(r io.Reader) (map[string]string, error)

func RecoverAbortedTransaction

func RecoverAbortedTransaction[T any](
	err error,
	canRollback bool,
	rollback func() error,
	retry func() (T, error),
) (T, error, bool)

RecoverAbortedTransaction rolls back and retries once when a DuckLake-backed connection is stuck in "Current transaction is aborted" state. This is only safe when the caller owns the transaction lifecycle (autocommit / no active user transaction). Callers should pass canRollback=false for explicit user transactions so the original error is surfaced unchanged.

func RefreshIcebergSecret

func RefreshIcebergSecret(db *sql.DB, ic IcebergConfig, sem chan struct{}, keyID, secretKey, sessionToken string) error

RefreshIcebergSecret replaces the DuckDB iceberg-extension S3 secret (iceberg_sigv4) with updated credentials. Used when a hot-idle worker is reclaimed and the STS credentials minted by the control plane have rotated. Without this, iceberg queries on a long-lived worker would start 403'ing after the first STS rotation (~1h) while DuckLake stays fresh.

Unlike AttachIcebergCatalog this does NOT short-circuit when the iceberg catalog is already attached — the whole point is to overwrite the existing secret in place. ATTACH state on the catalog itself is unaffected; DuckDB resolves the secret at request time, so the new credentials take effect for the next iceberg query without an explicit reattach.

Same auth model as AttachIcebergCatalog: explicit credentials are the only supported path. A refresh with missing credentials is a config bug (the activator failed to populate fresh STS credentials in the payload) and surfaces as an explicit error rather than a silent fallback to credential_chain.

func RefreshS3Secret

func RefreshS3Secret(db *sql.DB, dlCfg DuckLakeConfig, duckLakeSem chan struct{}) error

RefreshS3Secret replaces the DuckDB S3 secret with updated credentials. Used when a hot-idle worker is reclaimed and STS credentials have rotated. Respects the configured S3 provider (config, aws_sdk, credential_chain).

func RegisterDuckDBAppender

func RegisterDuckDBAppender(f DuckDBAppendFunc)

RegisterDuckDBAppender wires a real DuckDB Appender implementation into the COPY codepath. duckdbservice's init() calls this; binaries that don't link duckdbservice get the unavailable fallback below.

func RegisterValueNormalizer

func RegisterValueNormalizer(n ValueNormalizer)

RegisterValueNormalizer adds a hook consulted by normalizeDriverValue before the binary encoders dispatch on the value's type. Intended for use from init() in importers that own driver-specific value types — duckdbservice registers a normalizer that converts duckdb.Interval and duckdb.Decimal to their arrowmap equivalents.

func RunChildMode

func RunChildMode()

RunChildMode is the entry point for child worker processes. It reconstructs the TCP connection from FD 3, completes TLS handshake, authenticates the user, creates a DuckDB connection, and runs the message loop.

Configuration is read from stdin as JSON (more secure than env vars for passwords).

Exit codes:

  • 0: Success (clean disconnect)
  • 1: Error (crash, protocol error)
  • 10: Authentication failure

func RunMessageLoop

func RunMessageLoop(cc *clientConn) error

RunMessageLoop runs the main message loop for a client connection. It cancels the connection context when the loop exits, ensuring in-flight query contexts (and any gRPC calls derived from them) are cancelled promptly.

func RunShell

func RunShell(cfg Config)

RunShell starts an interactive SQL shell with a fully initialized DuckDB connection. It uses the same CreateDBConnection path as the PostgreSQL server, so extensions, DuckLake, and pg_catalog views are all available.

func S3ProviderForConfig

func S3ProviderForConfig(dlCfg DuckLakeConfig) string

S3ProviderForConfig returns the effective S3 provider for the given DuckLake config.

func SanitizeSearchPath

func SanitizeSearchPath(s string) (string, bool)

SanitizeSearchPath validates a client-supplied search_path so it can be safely embedded in `SET search_path = '<value>'`. Returns (trimmed, true) when the value is a plausible, injection-safe search_path; ("", false) otherwise (callers should then fall back to the default search_path).

func SecretDirectory

func SecretDirectory(cfg Config) string

SecretDirectory returns the directory DuckDB should use for persistent secrets for this instance, or "" to leave DuckDB's default in place.

DuckDB defaults persistent secrets to $HOME/.duckdb/stored_secrets, independent of the database file. On a worker that means a CREATE PERSISTENT SECRET lands in whatever $HOME the process happens to have and survives across restarts on any non-ephemeral disk — long after the in-memory secret of the same name (recreated each activation) gets re-added, which is exactly what produces DuckDB's "secret occurs in multiple storage backends" ambiguity errors. Pinning it under DataDir makes the location deterministic and, crucially, wipeable on worker recycle (see duckdbservice.Warmup).

func SendInitialParams

func SendInitialParams(cc *clientConn)

SendInitialParams sends the initial parameter status messages and backend key data.

func SetCatalogUseRewrite

func SetCatalogUseRewrite(cc *clientConn, enabled bool)

SetCatalogUseRewrite records whether this session should expand a bare `USE ducklake`/`USE iceberg` into its reliable two-part target. This is not masking — the catalog names are real; it only works around DuckDB's bare-catalog `USE` resolution.

func SetConnectionIcebergConfig

func SetConnectionIcebergConfig(cc *clientConn, cfg IcebergConfig)

SetConnectionIcebergConfig records the per-tenant Iceberg config for control-plane proxy connections. The proxy server's global config is not tenant-specific, so query-time metadata loading must use this override.

func SetConnectionPhysicalCatalog

func SetConnectionPhysicalCatalog(cc *clientConn, catalog string)

SetConnectionPhysicalCatalog records the resolved DuckDB catalog for control-plane proxy connections. The PostgreSQL-visible database remains on clientConn.database; this value is used only for execution/transpiler policy.

func SetPassthrough

func SetPassthrough(cc *clientConn, enabled bool)

SetPassthrough flips this session into passthrough mode (bypasses the SQL transpiler + pg_catalog). The control plane resolves the per-org flag from the config store after auth and calls this before the message loop starts. Single-tenant mode keeps using server.Config.PassthroughUsers and never calls this.

func SetProcessVersion

func SetProcessVersion(v string)

SetProcessVersion sets the version string for this process. Called from main().

func SetProgressFn

func SetProgressFn(s *Server, fn func(pid int32) (pct float64, rows, totalRows uint64, stalled bool))

SetProgressFn sets the progress lookup function on a Server. Used by the control plane to provide cached query progress from worker health checks.

func SetQueryLogger

func SetQueryLogger(s *Server, ql *QueryLogger)

SetQueryLogger sets the query logger on a Server. Used by the control plane to attach a query logger to the minimal server after creation.

func SetUserSecretManager

func SetUserSecretManager(s *Server, mgr UserSecretManager)

SetUserSecretManager installs the per-user persistent secret manager on a Server. Used by the multitenant control plane after the config store is up. Must be called before the server starts accepting connections.

func StartCredentialRefresh

func StartCredentialRefresh(execer sqlExecer, dlCfg DuckLakeConfig, isTxActive ...func() bool) func()

StartCredentialRefresh starts a background goroutine that periodically refreshes S3 credentials for long-lived DuckDB connections using the credential_chain provider. This prevents credential expiration when running on EC2 with IAM instance roles, STS assume-role, or other temporary credential sources.

The execer parameter accepts either *sql.DB (standalone mode) or *sql.Conn (worker mode where the pool's only connection is pinned by the session).

The optional isTxActive callback reports whether the caller currently has an active user transaction on this connection. When provided and returning false, aborted transaction errors are auto-recovered by issuing ROLLBACK and retrying once. When omitted (or returning true), automatic rollback is skipped to avoid rolling back caller-owned transactions.

Note: ExecContext serializes behind any running query (pool contention for *sql.DB, internal mutex for *sql.Conn). This means credentials are refreshed between queries, not during them. A query that runs longer than the credential TTL (~6h for instance roles) could still fail if DuckDB makes S3 requests with stale cached credentials.

Returns a stop function that cancels the refresh goroutine. The caller must call the stop function when the connection is closed to prevent goroutine leaks. If credential refresh is not needed (static credentials, no S3, etc.), returns a no-op.

func WriteAuthCleartextPassword

func WriteAuthCleartextPassword(w io.Writer) error

func WriteAuthOK

func WriteAuthOK(w io.Writer) error

func WriteBackendKeyData

func WriteBackendKeyData(w io.Writer, pid, secretKey int32) error

func WriteErrorResponse

func WriteErrorResponse(w io.Writer, severity, code, message string) error

func WriteParameterStatus

func WriteParameterStatus(w io.Writer, name, value string) error

func WriteReadyForQuery

func WriteReadyForQuery(w io.Writer, txStatus byte) error

Types

type ACMEDNSManager

type ACMEDNSManager = tlscert.ACMEDNSManager

type ACMEManager

type ACMEManager = tlscert.ACMEManager

type BackendKey

type BackendKey = wire.BackendKey

BackendKey moved to server/wire. Alias kept for back-compat with the dozens of references to server.BackendKey across this package and the control plane.

type ChildConfig

type ChildConfig struct {
	// Connection info (RemoteAddr is known at spawn time; Username/Database are read after TLS)
	RemoteAddr string `json:"remote_addr"`

	// Server config
	DataDir     string   `json:"data_dir"`
	Extensions  []string `json:"extensions"`
	IdleTimeout int64    `json:"idle_timeout"` // nanoseconds

	// TLS config
	TLSCertFile string `json:"tls_cert_file"`
	TLSKeyFile  string `json:"tls_key_file"`

	// DuckLake config
	DuckLake DuckLakeConfig `json:"ducklake"`

	// Authentication - map of username -> password
	// Child will look up after reading username from startup message
	Users map[string]string `json:"users"`

	// Backend key (pre-generated by parent for cancel request routing)
	// BackendPid is set to child's actual PID after fork
	BackendSecretKey int32 `json:"backend_secret_key"`

	// ServerStartTime is the parent server's start time (Unix nanoseconds).
	// Used to distinguish server uptime from child process uptime.
	ServerStartTime int64 `json:"server_start_time"`

	// ServerVersion is the parent server's version string.
	// Used to distinguish control_plane_version() from worker_version().
	ServerVersion string `json:"server_version,omitempty"`
}

ChildConfig contains all configuration needed by a child worker process. It is passed from parent to child via the DUCKGRES_CHILD_CONFIG env var as JSON.

type ChildProcess

type ChildProcess struct {
	PID        int
	Cmd        *exec.Cmd
	Username   string
	RemoteAddr string
	BackendKey BackendKey
	StartTime  time.Time
	// contains filtered or unexported fields
}

ChildProcess represents a spawned child worker process

type ChildTracker

type ChildTracker struct {
	// contains filtered or unexported fields
}

ChildTracker manages spawned child worker processes

func NewChildTracker

func NewChildTracker() *ChildTracker

NewChildTracker creates a new child tracker

func (*ChildTracker) Add

func (ct *ChildTracker) Add(child *ChildProcess)

Add registers a new child process

func (*ChildTracker) Count

func (ct *ChildTracker) Count() int

Count returns the number of active child processes

func (*ChildTracker) FindByBackendKey

func (ct *ChildTracker) FindByBackendKey(key BackendKey) *ChildProcess

FindByBackendKey finds a child process by its backend key (for cancel requests)

func (*ChildTracker) Get

func (ct *ChildTracker) Get(pid int) *ChildProcess

Get returns a child process by PID

func (*ChildTracker) Remove

func (ct *ChildTracker) Remove(pid int) *ChildProcess

Remove unregisters a child process by PID

func (*ChildTracker) SignalAll

func (ct *ChildTracker) SignalAll(sig syscall.Signal)

SignalAll sends a signal to all child processes

func (*ChildTracker) WaitAll

func (ct *ChildTracker) WaitAll() <-chan struct{}

WaitAll returns a channel that is closed when all children have exited. Caller should call this after SignalAll to wait for graceful shutdown.

NOTE: This method creates a new goroutine each time it's called. It captures a snapshot of current children at call time - children added after the call won't be waited on. For typical shutdown scenarios, call this once after SignalAll.

type ColumnTyper

type ColumnTyper = sqlcore.ColumnTyper

The SQL/result interfaces moved to server/sqlcore so the Flight client and other duckdb-free callers can implement them without importing server. The aliases below preserve the old server.X spellings for the dozens of references inside this package and elsewhere.

type Config

type Config struct {
	Host string
	Port int
	// FlightPort enables Arrow Flight SQL ingress on the control plane.
	// 0 disables Flight ingress.
	FlightPort int

	// FlightSessionIdleTTL controls how long an idle Flight auth session is kept
	// before being reaped.
	FlightSessionIdleTTL time.Duration

	// FlightSessionReapInterval controls how frequently idle Flight auth sessions
	// are scanned and reaped.
	FlightSessionReapInterval time.Duration

	// FlightHandleIdleTTL controls stale prepared/query handle cleanup inside a
	// Flight auth session.
	FlightHandleIdleTTL time.Duration

	// FlightSessionTokenTTL controls the absolute lifetime of issued
	// x-duckgres-session tokens. Expired tokens are rejected and require
	// a fresh bootstrap request.
	FlightSessionTokenTTL time.Duration
	DataDir               string
	Users                 map[string]string // username -> password

	// TLS configuration (required unless ACME is configured)
	TLSCertFile string // Path to TLS certificate file
	TLSKeyFile  string // Path to TLS private key file

	// ACME/Let's Encrypt configuration (alternative to static TLS cert/key)
	ACMEDomain   string // Domain for ACME certificate (e.g., "decisive-mongoose-wine.us.duckgres.com")
	ACMEEmail    string // Contact email for Let's Encrypt notifications
	ACMECacheDir string // Directory for cached certificates (default: "./certs/acme")

	// ACME DNS-01 challenge configuration (for private/internal interfaces)
	// When ACMEDNSProvider is set, DNS-01 challenges are used instead of HTTP-01.
	// This allows certificate issuance for hosts without public port 80 access.
	ACMEDNSProvider string // DNS provider for ACME DNS-01 challenges (currently only "route53")
	ACMEDNSZoneID   string // Route53 hosted zone ID for DNS-01 challenges

	// Rate limiting configuration
	RateLimit RateLimitConfig

	// Extensions to load on database initialization
	Extensions []string

	// DuckLake configuration
	DuckLake DuckLakeConfig

	// Iceberg catalog (AWS S3 Tables) configuration. Per-tenant in
	// multitenant mode (sourced from the configstore via shared_worker_activator);
	// optional opt-in for standalone instances via --iceberg-* flags.
	Iceberg IcebergConfig

	// AlwaysDuckLake forces the SQL transpiler into DuckLake mode for every
	// session even when the global DuckLake.MetadataStore is empty. The
	// multitenant control plane sets this because metadata stores are
	// per-org (loaded from configstore), so the global field stays empty
	// even though every worker is DuckLake-backed.
	AlwaysDuckLake bool

	// Graceful shutdown timeout (default: 30s)
	ShutdownTimeout time.Duration

	// IdleTimeout is the maximum time a connection can be idle before being closed.
	// This prevents accumulation of zombie connections from clients that disconnect
	// uncleanly. Default: 24 hours. Set to a negative value (e.g., -1) to disable.
	IdleTimeout time.Duration

	// SessionInitTimeout bounds startup metadata initialization and catalog probes.
	// Default: 10 seconds.
	SessionInitTimeout time.Duration

	// FilePersistence stores DuckDB data in <DataDir>/<username>.duckdb instead of :memory:.
	// DuckDB memory-maps the file and serves queries from RAM, so performance is similar
	// to in-memory mode while data persists across connections and restarts.
	FilePersistence bool

	// ProcessIsolation enables spawning each client connection in a separate OS process.
	// This prevents DuckDB C++ crashes from taking down the entire server.
	// When enabled, rate limiting and cancel requests are handled by the parent process,
	// while TLS, authentication, and query execution happen in child processes.
	ProcessIsolation bool

	// PinSecretDirectory pins DuckDB's persistent-secret directory under DataDir
	// (<DataDir>/secrets) instead of DuckDB's $HOME default. Set for worker
	// processes (see duckdbservice.OpenDuckDBPair): it makes the persisted-secret
	// location deterministic and wipeable on recycle, and — by redirecting away
	// from the $HOME default — stops stale secrets in the old location from being
	// loaded and colliding with the in-memory secrets re-created at activation.
	// Left false for standalone, so upgrading doesn't relocate an existing
	// standalone user's persistent secrets.
	//
	// Note: we deliberately do NOT also set allow_persistent_secrets=false.
	// Disabling persistent secrets unregisters DuckDB's local_file secret
	// storage backend, which the DuckLake ATTACH path depends on ("Unknown
	// secret storage found: 'local_file'") — so the directory pinning plus the
	// recycle wipe is how workers stay clean.
	PinSecretDirectory bool

	// UserSecrets persists per-user CREATE PERSISTENT SECRET statements
	// across sessions and worker pods. Set by the multitenant control plane
	// (remote backend, config-store-backed); nil everywhere else, in which
	// case secret DDL passes through to DuckDB untouched.
	UserSecrets UserSecretManager

	// MemoryLimit is the DuckDB memory_limit per session (e.g., "4GB").
	// If empty, auto-detected from system memory.
	MemoryLimit string

	// Threads is the DuckDB threads per session.
	// If zero, defaults to runtime.NumCPU().
	Threads int

	// MemoryBudget is the total memory available for all DuckDB sessions (e.g., "24GB").
	// Used in control-plane mode for dynamic per-session memory allocation.
	// If empty, defaults to 75% of system RAM.
	MemoryBudget string

	// MemoryRebalance enables dynamic per-connection memory reallocation in control-plane mode.
	// When enabled, the memory budget is redistributed across all active sessions on every
	// connect/disconnect. When disabled (default), each session gets a static allocation
	// of budget/max_workers at creation time.
	MemoryRebalance bool

	// PassthroughUsers are users that bypass the SQL transpiler and pg_catalog initialization.
	// Queries from these users go directly to DuckDB without any PostgreSQL compatibility layer.
	PassthroughUsers map[string]bool

	// QueryLog configures the DuckLake query log (system.query_log table).
	QueryLog QueryLogConfig
}

type CopyFromOptions

type CopyFromOptions struct {
	TableName  string
	ColumnList string // Empty string or "(col1, col2, ...)"
	Delimiter  string
	HasHeader  bool
	NullString string
	Quote      string // Quote character (default " for CSV)
	Escape     string // Escape character (default same as Quote)
	IsBinary   bool   // True if FORMAT binary
}

CopyFromOptions contains parsed options from a COPY FROM STDIN command

func ParseCopyFromOptions

func ParseCopyFromOptions(query string) (*CopyFromOptions, error)

ParseCopyFromOptions extracts options from a COPY FROM STDIN command

type CopyToOptions

type CopyToOptions struct {
	Source    string // Table name or (SELECT query)
	Delimiter string
	HasHeader bool
	IsQuery   bool // True if Source is a query in parentheses
}

CopyToOptions contains parsed options from a COPY TO STDOUT command

func ParseCopyToOptions

func ParseCopyToOptions(query string) (*CopyToOptions, error)

ParseCopyToOptions extracts options from a COPY TO STDOUT command

type DuckDBAppendFunc

type DuckDBAppendFunc func(rawConn sqlcore.RawConn, parts []string, rows [][]any) (int, error)

DuckDBAppendFunc bulk-inserts rows into a DuckDB table using the duckdb-go Appender API. The implementation calls rawConn.Raw to extract the underlying driver.Conn and then drives duckdb.NewAppender* against it.

The signature lives in the server package (rather than in duckdbservice) because the COPY codepath in clientConn dispatches through it; the duckdbservice package registers the actual implementation at init time via RegisterDuckDBAppender, which keeps server/conn_copy.go itself free of any duckdb-go imports.

parts is the result of splitQualifiedName(tableName) — a 1, 2, or 3 element slice of catalog/schema/table parts (preserving the precise args the original switch passed to NewAppender* / NewAppenderFromConn).

type DuckLakeCheckpointer

type DuckLakeCheckpointer struct {
	// contains filtered or unexported fields
}

DuckLakeCheckpointer runs DuckLake CHECKPOINT on a schedule. CHECKPOINT performs full catalog maintenance: expires snapshots, merges adjacent files, rewrites data files, and cleans up orphaned files.

func NewDuckLakeCheckpointer

func NewDuckLakeCheckpointer(cfg Config) (*DuckLakeCheckpointer, error)

NewDuckLakeCheckpointer opens a dedicated DuckDB connection, attaches DuckLake, and starts a background goroutine that runs CHECKPOINT on the configured interval.

func (*DuckLakeCheckpointer) Stop

func (c *DuckLakeCheckpointer) Stop()

Stop shuts down the checkpoint scheduler, waits for any in-progress checkpoint to finish, and closes the database connection.

type DuckLakeConfig

type DuckLakeConfig = ducklake.Config

DuckLakeConfig is an alias for ducklake.Config retained so the dozens of references to server.DuckLakeConfig across this package and others continue to compile after the migration code moved to server/ducklake. New code should import server/ducklake and use ducklake.Config directly.

type ExecResult

type ExecResult = sqlcore.ExecResult

The SQL/result interfaces moved to server/sqlcore so the Flight client and other duckdb-free callers can implement them without importing server. The aliases below preserve the old server.X spellings for the dozens of references inside this package and elsewhere.

type IcebergConfig

type IcebergConfig = iceberg.Config

IcebergConfig is an alias for iceberg.Config so callers that already import "github.com/posthog/duckgres/server" can reach it as server.IcebergConfig without a second import.

type LocalExecutor

type LocalExecutor struct {
	// contains filtered or unexported fields
}

LocalExecutor wraps *sql.DB to implement QueryExecutor for local DuckDB access.

func NewLocalExecutor

func NewLocalExecutor(db *sql.DB) *LocalExecutor

NewLocalExecutor creates a new LocalExecutor wrapping the given *sql.DB.

func (*LocalExecutor) Close

func (e *LocalExecutor) Close() error

func (*LocalExecutor) ConnContext

func (e *LocalExecutor) ConnContext(ctx context.Context) (RawConn, error)

func (*LocalExecutor) DB

func (e *LocalExecutor) DB() *sql.DB

DB returns the underlying *sql.DB (for credential refresh and other direct access).

func (*LocalExecutor) Exec

func (e *LocalExecutor) Exec(query string, args ...any) (ExecResult, error)

func (*LocalExecutor) ExecContext

func (e *LocalExecutor) ExecContext(ctx context.Context, query string, args ...any) (ExecResult, error)

func (*LocalExecutor) LastProfilingOutput

func (e *LocalExecutor) LastProfilingOutput() string

func (*LocalExecutor) PingContext

func (e *LocalExecutor) PingContext(ctx context.Context) error

func (*LocalExecutor) Query

func (e *LocalExecutor) Query(query string, args ...any) (RowSet, error)

func (*LocalExecutor) QueryContext

func (e *LocalExecutor) QueryContext(ctx context.Context, query string, args ...any) (RowSet, error)

type LocalRowSet

type LocalRowSet struct {
	// contains filtered or unexported fields
}

LocalRowSet wraps *sql.Rows to implement RowSet.

func (*LocalRowSet) Close

func (r *LocalRowSet) Close() error

func (*LocalRowSet) ColumnTypes

func (r *LocalRowSet) ColumnTypes() ([]ColumnTyper, error)

func (*LocalRowSet) Columns

func (r *LocalRowSet) Columns() ([]string, error)

func (*LocalRowSet) Err

func (r *LocalRowSet) Err() error

func (*LocalRowSet) Next

func (r *LocalRowSet) Next() bool

func (*LocalRowSet) Scan

func (r *LocalRowSet) Scan(dest ...any) error

type PinnedExecutor

type PinnedExecutor struct {
	// contains filtered or unexported fields
}

PinnedExecutor wraps a pinned *sql.Conn from a shared *sql.DB pool to implement QueryExecutor for file-persistence mode.

func NewPinnedExecutor

func NewPinnedExecutor(conn *sql.Conn, db *sql.DB) *PinnedExecutor

func (*PinnedExecutor) Close

func (e *PinnedExecutor) Close() error

Close returns the pinned connection to the pool; it does not close the underlying DB.

func (*PinnedExecutor) ConnContext

func (e *PinnedExecutor) ConnContext(ctx context.Context) (RawConn, error)

func (*PinnedExecutor) DB

func (e *PinnedExecutor) DB() *sql.DB

DB returns the underlying *sql.DB (for credential refresh and other direct access).

func (*PinnedExecutor) Exec

func (e *PinnedExecutor) Exec(query string, args ...any) (ExecResult, error)

func (*PinnedExecutor) ExecContext

func (e *PinnedExecutor) ExecContext(ctx context.Context, query string, args ...any) (ExecResult, error)

func (*PinnedExecutor) LastProfilingOutput

func (e *PinnedExecutor) LastProfilingOutput() string

func (*PinnedExecutor) PingContext

func (e *PinnedExecutor) PingContext(ctx context.Context) error

func (*PinnedExecutor) Query

func (e *PinnedExecutor) Query(query string, args ...any) (RowSet, error)

func (*PinnedExecutor) QueryContext

func (e *PinnedExecutor) QueryContext(ctx context.Context, query string, args ...any) (RowSet, error)

type QueryExecutor

type QueryExecutor = sqlcore.QueryExecutor

The SQL/result interfaces moved to server/sqlcore so the Flight client and other duckdb-free callers can implement them without importing server. The aliases below preserve the old server.X spellings for the dozens of references inside this package and elsewhere.

type QueryLogConfig

type QueryLogConfig struct {
	Enabled              bool
	FlushInterval        time.Duration
	BatchSize            int
	CompactInterval      time.Duration
	DataInliningRowLimit int
}

QueryLogConfig configures the query log feature.

type QueryLogEntry

type QueryLogEntry struct {
	EventTime       time.Time
	QueryDurationMs int64
	Type            string // "QueryFinish" or "ExceptionWhileProcessing"
	Query           string
	TranspiledQuery *string // nil if unchanged
	QueryKind       string  // "Select","Insert","Update","Delete","DDL","Utility","Copy","Cursor"
	NormalizedHash  int64
	ResultRows      int64
	WrittenRows     int64
	ExceptionCode   string
	Exception       string
	UserName        string
	OrgID           string
	CurrentDatabase string
	ClientAddress   string
	ClientPort      int
	ApplicationName string
	PID             int32
	WorkerID        int
	IsTranspiled    bool
	Protocol        string // "simple" or "extended"
	TraceID         string // OTEL trace ID (empty when tracing is off)
	SpanID          string // OTEL span ID (empty when tracing is off)
	// PostgresScanMs is the thread-time spent in postgres_scan operators
	// during this query — DuckLake metadata DB roundtrips. Zero when DuckDB
	// returned no profiling output (cancelled / errored before exec /
	// profiling disabled). Lets us answer "which query shape pounds the
	// metadata DB?" against `system.query_log` without re-parsing profiling.
	PostgresScanMs int64
}

QueryLogEntry represents a single entry in the query log.

type QueryLogger

type QueryLogger struct {
	// contains filtered or unexported fields
}

QueryLogger batches query log entries and writes them to a DuckLake table.

func NewQueryLogger

func NewQueryLogger(cfg Config) (*QueryLogger, error)

NewQueryLogger opens a dedicated :memory: DuckDB, attaches DuckLake, creates the system.query_log table, and starts the background flush goroutine.

func (*QueryLogger) Log

func (ql *QueryLogger) Log(entry QueryLogEntry)

Log sends an entry to the query log. Non-blocking; drops if channel is full.

func (*QueryLogger) Stop

func (ql *QueryLogger) Stop()

Stop drains remaining entries and shuts down the flush goroutine.

type RateLimitConfig

type RateLimitConfig = auth.RateLimitConfig

type RateLimiter

type RateLimiter = auth.RateLimiter

type RawConn

type RawConn = sqlcore.RawConn

The SQL/result interfaces moved to server/sqlcore so the Flight client and other duckdb-free callers can implement them without importing server. The aliases below preserve the old server.X spellings for the dozens of references inside this package and elsewhere.

type RowSet

type RowSet = sqlcore.RowSet

The SQL/result interfaces moved to server/sqlcore so the Flight client and other duckdb-free callers can implement them without importing server. The aliases below preserve the old server.X spellings for the dozens of references inside this package and elsewhere.

type Server

type Server struct {
	// contains filtered or unexported fields
}

func New

func New(cfg Config) (*Server, error)

func (*Server) ActiveConnections

func (s *Server) ActiveConnections() int64

ActiveConnections returns the number of active connections

func (*Server) CancelQuery

func (s *Server) CancelQuery(key BackendKey) bool

CancelQuery cancels a running query by its backend key. Returns true if a query was found and cancelled, false otherwise.

func (*Server) CancelQueryBySignal

func (s *Server) CancelQueryBySignal(key BackendKey) bool

CancelQueryBySignal sends SIGUSR1 to a child process to cancel its current query. Returns true if the signal was sent successfully.

func (*Server) Close

func (s *Server) Close() error

func (*Server) ListenAndServe

func (s *Server) ListenAndServe() error

func (*Server) QueryLogger

func (s *Server) QueryLogger() *QueryLogger

QueryLogger returns the server's query logger (may be nil).

func (*Server) RegisterQuery

func (s *Server) RegisterQuery(key BackendKey, cancel context.CancelFunc)

RegisterQuery registers a cancel function for a backend key. This allows the query to be cancelled via a cancel request from another connection.

func (*Server) Shutdown

func (s *Server) Shutdown(ctx context.Context) error

Shutdown performs a graceful shutdown with the given context

func (*Server) UnregisterQuery

func (s *Server) UnregisterQuery(key BackendKey)

UnregisterQuery removes the cancel function for a backend key. This should be called when a query completes (successfully or with error).

func (*Server) UserSecretManager

func (s *Server) UserSecretManager() UserSecretManager

UserSecretManager returns the installed per-user persistent secret manager (nil when the feature is not configured).

type TypeInfo

type TypeInfo struct {
	OID    int32
	Size   int16 // -1 for variable length
	Typmod int32 // -1 = no modifier; for NUMERIC: ((precision << 16) | scale) + 4
}

TypeInfo contains PostgreSQL type information

type UserSecretManager

type UserSecretManager interface {
	// Ready reports whether secrets can be persisted (e.g. the encryption
	// key is configured). A non-nil error is shown to the client.
	Ready() error
	// PutSecret stores one statement. With ifNotExists set, an already-stored
	// name is left untouched (mirroring DuckDB's IF NOT EXISTS no-op on the
	// live session); otherwise any prior statement with the same name is
	// replaced. Called only after the statement executed successfully on the
	// live session.
	PutSecret(ctx context.Context, orgID, username, secretName, statement string, ifNotExists bool) error
	// DeleteSecret removes one stored secret, reporting whether it existed.
	DeleteSecret(ctx context.Context, orgID, username, secretName string) (existed bool, err error)
}

UserSecretManager persists per-user CREATE PERSISTENT SECRET statements so they survive across sessions and worker pods. Implemented by the multitenant control plane (backed by the config store); nil in standalone and process-worker modes, where secret DDL passes through untouched.

type ValueNormalizer

type ValueNormalizer func(any) any

ValueNormalizer is a hook that converts driver-specific value types (e.g., duckdb.Interval, duckdb.Decimal) into the duckdb-free equivalents in arrowmap (IntervalValue, DecimalValue) so the binary-format encoders in types.go can handle them without importing the duckdb-go driver.

A normalizer must return the input unchanged when it doesn't recognize the type; the encode helpers fall back to AppendNull/return nil when the final value still isn't a recognized type.

type WorkerActivationPayload

type WorkerActivationPayload = wire.WorkerActivationPayload

WorkerActivationPayload moved to server/wire so the control plane can use it without importing the rest of server. The alias preserves the existing server.WorkerActivationPayload spelling for current call sites.

type WorkerControlMetadata

type WorkerControlMetadata = wire.WorkerControlMetadata

type WorkerCreateSessionPayload

type WorkerCreateSessionPayload = wire.WorkerCreateSessionPayload

type WorkerDestroySessionPayload

type WorkerDestroySessionPayload = wire.WorkerDestroySessionPayload

type WorkerHealthCheckPayload

type WorkerHealthCheckPayload = wire.WorkerHealthCheckPayload

type WorkerReleaseQueryHandlePayload

type WorkerReleaseQueryHandlePayload = wire.WorkerReleaseQueryHandlePayload

type WorkerWaitSessionIdlePayload

type WorkerWaitSessionIdlePayload = wire.WorkerWaitSessionIdlePayload

Directories

Path Synopsis
Package auth holds duckgres' connection rate-limiting and password validation policy.
Package auth holds duckgres' connection rate-limiting and password validation policy.
Package ducklake holds DuckLake configuration, the metadata-store version migration check, and the SQL fragments needed to ATTACH a DuckLake catalog.
Package ducklake holds DuckLake configuration, the metadata-store version migration check, and the SQL fragments needed to ATTACH a DuckLake catalog.
Package iceberg holds Iceberg catalog configuration and the SQL fragments needed to ATTACH the DuckDB Iceberg extension catalog.
Package iceberg holds Iceberg catalog configuration and the SQL fragments needed to ATTACH the DuckDB Iceberg extension catalog.
Package icebergmeta loads real Iceberg column metadata for information_schema.columns compatibility.
Package icebergmeta loads real Iceberg column metadata for information_schema.columns compatibility.
Package lakekeeperbroker is a tiny in-process HTTP server that bridges DuckDB's OAuth2 client_credentials expectations to a Kubernetes-projected ServiceAccount token.
Package lakekeeperbroker is a tiny in-process HTTP server that bridges DuckDB's OAuth2 client_credentials expectations to a Kubernetes-projected ServiceAccount token.
Package observe holds duckgres' OpenTelemetry tracing helpers, the connection-count gauge, and the per-query Prometheus metrics emitted from the trace path.
Package observe holds duckgres' OpenTelemetry tracing helpers, the connection-count gauge, and the per-query Prometheus metrics emitted from the trace path.
Package sessionmeta installs session-local catalog/metadata overrides on a duckgres connection (current_database, pg_database, information_schema views) so they reflect the catalog the session defaults to on the PG wire.
Package sessionmeta installs session-local catalog/metadata overrides on a duckgres connection (current_database, pg_database, information_schema views) so they reflect the catalog the session defaults to on the PG wire.
Package sqlcore holds the duckgres-internal SQL/result interfaces that span the wire-protocol/server layer and the Arrow Flight client.
Package sqlcore holds the duckgres-internal SQL/result interfaces that span the wire-protocol/server layer and the Arrow Flight client.
Package sysinfo holds duckgres' system-memory detection helpers and the memory-limit string parser shared between the server, the control plane, and config resolution.
Package sysinfo holds duckgres' system-memory detection helpers and the memory-limit string parser shared between the server, the control plane, and config resolution.
Package usersecrets implements the building blocks of the per-user persistent secret manager: classification of DuckDB secret DDL statements and authenticated encryption for storing them in the config store.
Package usersecrets implements the building blocks of the per-user persistent secret manager: classification of DuckDB secret DDL statements and authenticated encryption for storing them in the config store.
Package wire holds duckgres wire-level types and helpers shared between the PG protocol layer and the control plane / worker RPC paths.
Package wire holds duckgres wire-level types and helpers shared between the PG protocol layer and the control plane / worker RPC paths.

Jump to

Keyboard shortcuts

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