diff --git a/.gitignore b/.gitignore index d27a490..8ad8884 100644 --- a/.gitignore +++ b/.gitignore @@ -32,3 +32,5 @@ htmldocs/ htmdocs/ *.out +audit/ +.audit/ diff --git a/async_postgres.nim b/async_postgres.nim index 6e8bf4c..4c27fd6 100644 --- a/async_postgres.nim +++ b/async_postgres.nim @@ -134,6 +134,134 @@ import pg_pool_cluster, pg_largeobject, pg_advisory_lock, pg_sql, pg_replication, ] -export - async_backend, pg_protocol, pg_auth, pg_types, pg_connection, pg_client, pg_pool, - pg_pool_cluster, pg_largeobject, pg_advisory_lock, pg_sql, pg_replication +# `pg_types`/`pg_connection`/`pg_client` whitelist themselves; the other +# modules expose only their public API surface. +export pg_types, pg_connection, pg_client +export pg_pool_cluster, pg_largeobject, pg_advisory_lock, pg_sql, pg_replication +export pg_auth + +# `pg_pool` — public pool API (internal gauges/helpers stay in the module). +export pg_pool.PoolConfig +export pg_pool.PoolMetrics +export pg_pool.PooledConnHandle +export pg_pool.PgPool +export pg_pool.initPoolConfig +export pg_pool.idleCount +export pg_pool.activeCount +export pg_pool.size +export pg_pool.isClosed +export pg_pool.metrics +export pg_pool.resetSession +export pg_pool.newPool +export pg_pool.release +export pg_pool.resetSessionAndRelease +export pg_pool.acquire +export pg_pool.runAndRelease +export pg_pool.withConnection +export pg_pool.exec +export pg_pool.query +export pg_pool.queryEach +export pg_pool.queryRow +export pg_pool.queryRowOpt +export pg_pool.queryValue +export pg_pool.queryValueOpt +export pg_pool.queryValueOrDefault +export pg_pool.queryExists +export pg_pool.queryColumn +export pg_pool.simpleQuery +export pg_pool.simpleExec +export pg_pool.execInTransaction +export pg_pool.queryInTransaction +export pg_pool.notify +export pg_pool.withTransaction +export pg_pool.withTransactionRetry +export pg_pool.withTransactionDeadline +export pg_pool.withTransactionRetryDeadline +export pg_pool.withPipeline +export pg_pool.close + +# `async_backend` is exported wholesale; it also re-exports the selected +# backend (asyncdispatch / chronos), supplying `async`, `waitFor`, etc. +export async_backend + +# `pg_protocol` — the wire protocol codec and entry points. The inbound +# decoders and leaf encoders stay internal; the send-buffer helpers are +# re-exported because the `addParseDirect`/`addBindDirect` macros and advanced +# call sites resolve them in the caller's scope. +export pg_protocol.FrontendMessageKind +export pg_protocol.BackendMessageKind +export pg_protocol.DescribeKind +export pg_protocol.TransactionStatus +export pg_protocol.FieldDescription +export pg_protocol.CopyFormat +export pg_protocol.BackendMessage +export pg_protocol.ParseState +export pg_protocol.ParseResult +export pg_protocol.RowData +export pg_protocol.Row +export pg_protocol.syncMsg +export pg_protocol.flushMsg +export pg_protocol.copyDoneMsg +export pg_protocol.BinarySafeOids +export pg_protocol.maxInt32Len +export pg_protocol.DefaultMaxBackendMessageLen +export pg_protocol.MaxNegotiateProtocolOptions +export pg_protocol.MaxErrorOrNoticeFields +export pg_protocol.MaxSaslMechanisms +export pg_protocol.initRow +export pg_protocol.data +export pg_protocol.rowIdx +export pg_protocol.isBinarySafeOid +export pg_protocol.addInt16 +export pg_protocol.addInt32 +export pg_protocol.addCount16 +export pg_protocol.addLen32 +export pg_protocol.addCString +export pg_protocol.patchMsgLen +export pg_protocol.encodeStartup +export pg_protocol.encodeSSLRequest +export pg_protocol.encodePassword +export pg_protocol.encodeSASLInitialResponse +export pg_protocol.encodeSASLResponse +export pg_protocol.encodeQuery +export pg_protocol.addParse +export pg_protocol.addBind +export pg_protocol.addBindRaw +export pg_protocol.addDescribe +export pg_protocol.addExecute +export pg_protocol.addClose +export pg_protocol.addSync +export pg_protocol.addFlush +export pg_protocol.addCopyDone +export pg_protocol.encodeParse +export pg_protocol.encodeBind +export pg_protocol.encodeDescribe +export pg_protocol.encodeExecute +export pg_protocol.encodeClose +export pg_protocol.encodeSync +export pg_protocol.encodeFlush +export pg_protocol.encodeTerminate +export pg_protocol.encodeCancelRequest +export pg_protocol.encodeCopyData +export pg_protocol.encodeCopyDone +export pg_protocol.encodeCopyFail +export pg_protocol.newRowData +export pg_protocol.reuseRowData +export pg_protocol.clone +export pg_protocol.buildResultFormats +export pg_protocol.parseDataRowInto +export pg_protocol.parseBackendMessage +export pg_protocol.formatError +export pg_protocol.addCopyBinaryHeader +export pg_protocol.addCopyBinaryTrailer +export pg_protocol.addCopyTupleStart +export pg_protocol.addCopyFieldNull +export pg_protocol.addCopyFieldInt16 +export pg_protocol.addCopyFieldInt32 +export pg_protocol.addCopyFieldInt64 +export pg_protocol.addCopyFieldFloat64 +export pg_protocol.addCopyFieldFloat32 +export pg_protocol.addCopyFieldBool +export pg_protocol.addCopyFieldText +export pg_protocol.addCopyFieldString +export pg_protocol.encodeStandbyStatusUpdate diff --git a/async_postgres/pg_advisory_lock.nim b/async_postgres/pg_advisory_lock.nim index b03a445..6708138 100644 --- a/async_postgres/pg_advisory_lock.nim +++ b/async_postgres/pg_advisory_lock.nim @@ -79,6 +79,7 @@ import std/[macros, importutils] import async_backend, pg_protocol, pg_types, pg_connection, pg_client +import pg_connection/types privateAccess(PgConnection) diff --git a/async_postgres/pg_client.nim b/async_postgres/pg_client.nim index e2fb62e..dc1a58f 100644 --- a/async_postgres/pg_client.nim +++ b/async_postgres/pg_client.nim @@ -77,6 +77,68 @@ export core.RetryOptions export core.isRetryableTxError export core.backoffDelayMs -export - exec, query, prepared, copy, transaction, transaction_helpers, pipeline, cursor, - direct +# `exec` — exec / notify entry points (the `*Impl` helpers stay internal). +export exec.exec +export exec.notify + +# `query` — query entry points and result accessors (`*Impl` stay internal). +export query.query +export query.queryEach +export query.queryRow +export query.queryRowOpt +export query.queryValue +export query.queryValueOpt +export query.queryValueOrDefault +export query.queryExists +export query.queryColumn + +# `prepared` — prepared statements. +export prepared.PreparedStatement +export prepared.columnIndex +export prepared.prepare +export prepared.execute +export prepared.close + +# `copy` — COPY IN / COPY OUT entry points (`*Impl` stay internal). +export copy.copyIn +export copy.copyInStream +export copy.copyOut +export copy.copyOutStream + +# `transaction` — transaction/savepoint scoping macros. `rollbackGrace` is +# re-exported because pg_pool's deadline macros resolve it via `bindSym`. +export transaction.withTransaction +export transaction.withTransactionRetry +export transaction.withSavepoint +export transaction.withTransactionDeadline +export transaction.withTransactionRetryDeadline +export transaction.withSavepointDeadline +export transaction.rollbackGrace + +# `transaction_helpers` — the two in-transaction convenience helpers. +export transaction_helpers.execInTransaction +export transaction_helpers.queryInTransaction + +# `pipeline` — batching. +export pipeline.Pipeline +export pipeline.PipelineResult +export pipeline.PipelineResultKind +export pipeline.IsolatedPipelineResults +export pipeline.newPipeline +export pipeline.reset +export pipeline.addExec +export pipeline.addQuery +export pipeline.execute +export pipeline.executeIsolated + +# `cursor` — result cursors. +export cursor.Cursor +export cursor.columnIndex +export cursor.fetchNext +export cursor.close +export cursor.withCursor +export cursor.openCursor + +# `direct` — zero-allocation macros. +export direct.queryDirect +export direct.execDirect diff --git a/async_postgres/pg_client/copy.nim b/async_postgres/pg_client/copy.nim index efd31c8..6ecef94 100644 --- a/async_postgres/pg_client/copy.nim +++ b/async_postgres/pg_client/copy.nim @@ -4,6 +4,7 @@ import std/[options] import ../[async_backend, pg_protocol, pg_connection, pg_types] +import ../pg_connection/[types, buffer_io, simple_query] import ./core proc pollCopyInError( @@ -88,7 +89,7 @@ proc abortCopyWatch(conn: PgConnection, watch: RecvWatch) = watch.cancel() conn.state = csClosed -proc copyInRawImpl*( +proc copyInRawImpl( conn: PgConnection, sql: string, data: seq[byte] ): Future[string] {.async.} = conn.checkReady() @@ -263,7 +264,7 @@ proc copyIn*( offset += chunk.len copyIn(conn, sql, combined, timeout) -proc copyInStreamImpl*( +proc copyInStreamImpl( conn: PgConnection, sql: string, callback: CopyInCallback ): Future[CopyInInfo] {.async.} = conn.checkReady() @@ -496,7 +497,7 @@ proc copyInStream*( ) return info -proc copyOutImpl*(conn: PgConnection, sql: string): Future[CopyResult] {.async.} = +proc copyOutImpl(conn: PgConnection, sql: string): Future[CopyResult] {.async.} = conn.checkReady() let msg = encodeQuery(sql) conn.state = csBusy @@ -569,7 +570,7 @@ proc copyOut*( awaitOrInvalidate(conn, cr, copyOutImpl(conn, sql), timeout, "COPY OUT timed out") return cr -proc copyOutStreamImpl*( +proc copyOutStreamImpl( conn: PgConnection, sql: string, callback: CopyOutCallback ): Future[CopyOutInfo] {.async.} = conn.checkReady() diff --git a/async_postgres/pg_client/core.nim b/async_postgres/pg_client/core.nim index 5bfaeae..6e105c6 100644 --- a/async_postgres/pg_client/core.nim +++ b/async_postgres/pg_client/core.nim @@ -8,6 +8,8 @@ import std/[options, tables, math, random] import ../[async_backend, pg_protocol, pg_connection, pg_types] +import ../pg_connection/[types, buffer_io, cache, simple_query] +import ../pg_types/encoding type IsolationLevel* = enum diff --git a/async_postgres/pg_client/cursor.nim b/async_postgres/pg_client/cursor.nim index 9370a20..dd8483b 100644 --- a/async_postgres/pg_client/cursor.nim +++ b/async_postgres/pg_client/cursor.nim @@ -4,6 +4,7 @@ import std/[options] import ../[async_backend, pg_protocol, pg_connection, pg_types] +import ../pg_connection/[types, buffer_io, cache, simple_query, lifecycle] import ./core type Cursor* = ref object diff --git a/async_postgres/pg_client/direct.nim b/async_postgres/pg_client/direct.nim index 1958bd9..a3f7313 100644 --- a/async_postgres/pg_client/direct.nim +++ b/async_postgres/pg_client/direct.nim @@ -4,6 +4,8 @@ import std/[algorithm, macros, options, sets, tables] import ../[async_backend, pg_protocol, pg_connection, pg_types] +import ../pg_connection/[types, buffer_io, cache, simple_query] +import ../pg_types/encoding import ./core proc queryDirectRunImpl*( diff --git a/async_postgres/pg_client/exec.nim b/async_postgres/pg_client/exec.nim index fe0809c..1b17614 100644 --- a/async_postgres/pg_client/exec.nim +++ b/async_postgres/pg_client/exec.nim @@ -4,6 +4,8 @@ import std/[options, tables] import ../[async_backend, pg_protocol, pg_connection, pg_types] +import ../pg_connection/[types, buffer_io, cache, simple_query] +import ../pg_types/encoding import ./core proc execImpl*( diff --git a/async_postgres/pg_client/pipeline.nim b/async_postgres/pg_client/pipeline.nim index d463d73..1b72ca3 100644 --- a/async_postgres/pg_client/pipeline.nim +++ b/async_postgres/pg_client/pipeline.nim @@ -5,6 +5,8 @@ import std/[options, tables] import ../[async_backend, pg_protocol, pg_connection, pg_types] +import ../pg_connection/[types, buffer_io, cache, simple_query] +import ../pg_types/encoding import core type diff --git a/async_postgres/pg_client/prepared.nim b/async_postgres/pg_client/prepared.nim index a4a0d05..66040f1 100644 --- a/async_postgres/pg_client/prepared.nim +++ b/async_postgres/pg_client/prepared.nim @@ -3,6 +3,8 @@ import std/[options] import ../[async_backend, pg_protocol, pg_connection, pg_types] +import ../pg_connection/[types, buffer_io, cache, simple_query] +import ../pg_types/encoding import ./core type PreparedStatement* = object diff --git a/async_postgres/pg_client/query.nim b/async_postgres/pg_client/query.nim index 71651d3..da87666 100644 --- a/async_postgres/pg_client/query.nim +++ b/async_postgres/pg_client/query.nim @@ -5,6 +5,8 @@ import std/[options, tables] import ../[async_backend, pg_protocol, pg_connection, pg_types] +import ../pg_connection/[types, buffer_io, cache, simple_query] +import ../pg_types/encoding import ./core proc queryImpl*( diff --git a/async_postgres/pg_client/transaction.nim b/async_postgres/pg_client/transaction.nim index 1b397ef..2c4a45a 100644 --- a/async_postgres/pg_client/transaction.nim +++ b/async_postgres/pg_client/transaction.nim @@ -4,9 +4,10 @@ import std/[macros, options] import ../[async_backend, pg_protocol, pg_connection] +import ../pg_connection/[types, simple_query] import ./core -proc hasReturnStmt*(n: NimNode): bool = +proc hasReturnStmt(n: NimNode): bool = ## Check whether an AST contains a `return` statement (excluding nested ## proc/func/method/iterator definitions where `return` is valid). if n.kind == nnkReturnStmt: @@ -25,7 +26,7 @@ proc escapeLabelName(n: NimNode): string = ## Plain name of a `break`/`continue`/`block` label (`nnkIdent` or `nnkSym`). n.strVal -proc hasLoopEscapeStmt*(n: NimNode): bool = +proc hasLoopEscapeStmt(n: NimNode): bool = ## True if a `break`/`continue` in `n` would escape to a loop or `block:` ## outside the body, skipping the trailing COMMIT / RELEASE. Statements ## captured by a body-local loop/`block` are accepted. @@ -189,7 +190,7 @@ proc buildRollbackCleanup*(connSym, rollbackTimeout: NimNode): NimNode = newException(PgError, `cleanupDefectSym`.msg, `cleanupDefectSym`), ) -proc buildSavepointRollbackCleanup*( +proc buildSavepointRollbackCleanup( connSym, spNameSym, rollbackTimeout: NimNode ): NimNode = ## Build the shared `onCleanupSkipped`-wired ROLLBACK TO SAVEPOINT cleanup used @@ -237,7 +238,7 @@ proc buildSavepointRollbackCleanup*( newException(PgError, `cleanupDefectSym`.msg, `cleanupDefectSym`), ) -proc buildDeadlineAwaitAndTimeout*( +proc buildDeadlineAwaitAndTimeout( connSym, bodyFnSym, totalDurSym: NimNode, reason: string, catchableCleanup: NimNode ): NimNode = ## Build the single-attempt deadline-bounded await + timeout handler shared diff --git a/async_postgres/pg_client/transaction_helpers.nim b/async_postgres/pg_client/transaction_helpers.nim index 0064560..ff16d82 100644 --- a/async_postgres/pg_client/transaction_helpers.nim +++ b/async_postgres/pg_client/transaction_helpers.nim @@ -5,6 +5,7 @@ import std/[options] import ../[async_backend, pg_protocol, pg_connection, pg_types] +import ../pg_connection/[types, buffer_io, simple_query] import ./core proc queryInTransactionImpl( diff --git a/async_postgres/pg_connection.nim b/async_postgres/pg_connection.nim index 8b481fd..f92e1bf 100644 --- a/async_postgres/pg_connection.nim +++ b/async_postgres/pg_connection.nim @@ -37,18 +37,115 @@ ## `to_regtype` (extension types like ## `hstore`, `citext`, etc.). ## -## Every public symbol previously defined in this file is re-exported from -## here, so existing `import async_postgres/pg_connection` (or the -## bundled `import pkg/async_postgres`) call sites keep working without -## changes. Test files that previously used `import pg_connection -## {.all.}` to reach private helpers must now import the specific -## submodule directly, e.g. -## `import pg_connection/buffer_io {.all.}`. +## Only the public API listed below is re-exported. Anything not listed stays +## in its defining submodule (e.g. `pg_connection/buffer_io`) and must be +## imported from there directly, not through `import pg_connection`. import pg_errors import - pg_connection/ - [types, dsn, buffer_io, ssl, cache, simple_query, lifecycle, notify, type_lookup] + pg_connection/[types, dsn, buffer_io, simple_query, lifecycle, notify, type_lookup] export pg_errors -export types, dsn, buffer_io, ssl, cache, simple_query, lifecycle, notify, type_lookup + +# `types` — public types, the tracer hook data types and the tracing helpers. +export types.PgConnState +export types.SslMode +export types.SslNegotiation +export types.ChannelBindingMode +export types.AuthMethod +export types.TargetSessionAttrs +export types.LoadBalanceHosts +export types.HostEntry +export types.ConnConfig +export types.PgTracer +export types.Notification +export types.NotifyCallback +export types.Notice +export types.NoticeCallback +export types.CachedStmt +export types.dialAddr +export types.displayHost +export types.QueryResult +export types.CopyResult +export types.CopyOutInfo +export types.CopyInInfo +export types.CopyOutCallback +export types.CopyInCallback +export types.PgPoolOwner +export types.PgConnection +export types.RowCallback +export types.ClientCertPairingErrorMsg +export types.TraceContext +export types.TraceCopyDirection +export types.TraceConnectStartData +export types.TraceConnectEndData +export types.TraceQueryStartData +export types.TraceQueryEndData +export types.TracePrepareStartData +export types.TracePrepareEndData +export types.TracePipelineStartData +export types.TracePipelineEndData +export types.TraceCopyStartData +export types.TraceCopyEndData +export types.TracePoolAcquireStartData +export types.TracePoolAcquireEndData +export types.TracePoolReleaseStartData +export types.TracePoolReleaseEndData +export types.TracePoolDoubleReleaseData +export types.TracePoolCloseErrorData +export types.TraceTransportCloseErrorData +export types.TransportCloseStage +export types.CleanupKind +export types.CleanupSkipReason +export types.TraceCleanupSkippedData +export types.TraceLeakedSessionLocksData +export types.TraceInsecureAuthData +export types.TraceDeprecatedAuthData +export types.TraceAdvisoryUnlockFailedData +export types.withConnTracing +export types.withTracing + +# `dsn` — the documented DSN entry points. +export dsn.initConnConfig +export dsn.parseDsn + +# `buffer_io` — public connection I/O and keepalive surface. +export buffer_io.isUnixSocket +export buffer_io.unixSocketPath +export buffer_io.getHosts +export buffer_io.makeCopyOutCallback +export buffer_io.makeCopyInCallback +export buffer_io.socketHasFin +export buffer_io.socketHasPendingData +export buffer_io.isConnected + +# `simple_query` — the simple-query protocol and query-result helpers. +export simple_query.len +export simple_query.columnIndex +export simple_query.rows +export simple_query.items +export simple_query.quoteIdentifier +export simple_query.cancel +export simple_query.cancelNoWait +export simple_query.invalidateOnTimeout +export simple_query.simpleExec +export simple_query.simpleQuery +export simple_query.ping +export simple_query.checkSessionAttrs + +# `lifecycle` — connect / close and host ordering. +export lifecycle.close +export lifecycle.orderedHosts +export lifecycle.connect +export lifecycle.connectToHost + +# `notify` — LISTEN / NOTIFY pump and waiters. +export notify.onNotify +export notify.onListenError +export notify.listen +export notify.unlisten +export notify.waitNotification + +# `type_lookup` — extension type OID resolution. +export type_lookup.TypeOidInfo +export type_lookup.lookupTypeOids diff --git a/async_postgres/pg_connection/buffer_io.nim b/async_postgres/pg_connection/buffer_io.nim index 6401288..395c1e8 100644 --- a/async_postgres/pg_connection/buffer_io.nim +++ b/async_postgres/pg_connection/buffer_io.nim @@ -9,8 +9,10 @@ ## - Host helpers (`isUnixSocket`, `unixSocketPath`, `getHosts`) ## - `makeCopyOutCallback` / `makeCopyInCallback` cross-backend templates ## -## Re-exported through `pg_connection.nim`; depends only on `types.nim` and -## the protocol/error/backend abstraction modules. +## The host helpers and `makeCopy*` templates are re-exported through +## `pg_connection.nim`; the transport buffering machinery stays here for +## sibling modules and tests. Depends only on `types.nim` and the +## protocol/error/backend abstraction modules. import std/[deques, options, tables] when defined(posix): @@ -26,8 +28,8 @@ elif hasAsyncDispatch: when defined(posix): # POSIX socket option constants (used by liveness probes and TCP keepalive) - var TCP_NODELAY* {.importc, header: "".}: cint - var MSG_DONTWAIT* {.importc, header: "".}: cint + var TCP_NODELAY {.importc, header: "".}: cint + var MSG_DONTWAIT {.importc, header: "".}: cint type RecvWatch* = ref object diff --git a/async_postgres/pg_connection/cache.nim b/async_postgres/pg_connection/cache.nim index 2545e0d..8f19b09 100644 --- a/async_postgres/pg_connection/cache.nim +++ b/async_postgres/pg_connection/cache.nim @@ -6,7 +6,8 @@ ## adding via `addStmtCache`, and use `pendingStmtCloses` to bundle Close ## messages with the next operation's Sync. ## -## Re-exported through `pg_connection.nim`. +## Internal: not re-exported through `pg_connection.nim`; import this module +## directly. import std/[tables, lists] diff --git a/async_postgres/pg_connection/dsn.nim b/async_postgres/pg_connection/dsn.nim index 2af20fe..aac4c18 100644 --- a/async_postgres/pg_connection/dsn.nim +++ b/async_postgres/pg_connection/dsn.nim @@ -4,8 +4,9 @@ ## - keyword=value: ``host=localhost port=5432 dbname=test`` ## - URI: ``postgresql://user:pass@host:port/db?param=value`` ## -## Re-exported through `pg_connection.nim`; depends only on `types.nim` -## (in particular, does not touch `PgConnection`). +## Only `initConnConfig` / `parseDsn` are re-exported through `pg_connection.nim`; +## the intermediate parsers stay here. Depends only on `types.nim` (does not +## touch `PgConnection`). import std/strutils when defined(posix): diff --git a/async_postgres/pg_connection/lifecycle.nim b/async_postgres/pg_connection/lifecycle.nim index cd68f74..6b2fdb7 100644 --- a/async_postgres/pg_connection/lifecycle.nim +++ b/async_postgres/pg_connection/lifecycle.nim @@ -30,7 +30,7 @@ when hasAsyncDispatch: # Authentication policy helpers -proc enforceAuthAllowed*( +proc enforceAuthAllowed( authMethod: AuthMethod, allowed: set[AuthMethod], offered: string = "" ) {.raises: [PgConnectionError].} = if allowed.len > 0 and authMethod notin allowed: diff --git a/async_postgres/pg_connection/simple_query.nim b/async_postgres/pg_connection/simple_query.nim index ffe06e3..d353c3d 100644 --- a/async_postgres/pg_connection/simple_query.nim +++ b/async_postgres/pg_connection/simple_query.nim @@ -99,7 +99,7 @@ proc quoteIdentifier*(s: string): string = # Simple Query Protocol entry points -proc simpleQueryImpl*( +proc simpleQueryImpl( conn: PgConnection, sql: string ): Future[seq[QueryResult]] {.async.} = conn.checkReady() @@ -128,7 +128,7 @@ proc simpleQueryImpl*( return results -proc simpleExecImpl*(conn: PgConnection, sql: string): Future[string] {.async.} = +proc simpleExecImpl(conn: PgConnection, sql: string): Future[string] {.async.} = conn.checkReady() let msg = encodeQuery(sql) conn.state = csBusy diff --git a/async_postgres/pg_connection/ssl.nim b/async_postgres/pg_connection/ssl.nim index bb121ed..d588c01 100644 --- a/async_postgres/pg_connection/ssl.nim +++ b/async_postgres/pg_connection/ssl.nim @@ -13,7 +13,8 @@ ## trust anchors written to a temp file and `SSL_get_peer_certificate` used ## for channel binding. ## -## Re-exported through `pg_connection.nim`. +## Internal: not re-exported through `pg_connection.nim`; import this module +## directly. import std/[net, strutils] import ../[async_backend, pg_errors, pg_protocol, pg_types] diff --git a/async_postgres/pg_connection/types.nim b/async_postgres/pg_connection/types.nim index 2641bf9..d10f4b6 100644 --- a/async_postgres/pg_connection/types.nim +++ b/async_postgres/pg_connection/types.nim @@ -37,8 +37,8 @@ else: var listenReconnectStopWaitMs* = 10_000 ## Max wait (ms) for a listen pump stuck in a blocking `connect()`; it is - ## orphaned on timeout. Unexported so users cannot set it to 0 and disable - ## orphan safety — siblings and tests reach it via `import types {.all.}`. + ## orphaned on timeout. Not re-exported through `pg_connection`, so call + ## sites cannot set it to 0 via the aggregate import and disable orphan safety. type PgConnState* = enum diff --git a/async_postgres/pg_largeobject.nim b/async_postgres/pg_largeobject.nim index 63b3623..21dc354 100644 --- a/async_postgres/pg_largeobject.nim +++ b/async_postgres/pg_largeobject.nim @@ -21,6 +21,7 @@ import std/[strutils, options] import async_backend, pg_types, pg_protocol, pg_connection, pg_client +import pg_connection/types const INV_READ* = 0x00040000'i32 diff --git a/async_postgres/pg_pool.nim b/async_postgres/pg_pool.nim index 0720561..4453102 100644 --- a/async_postgres/pg_pool.nim +++ b/async_postgres/pg_pool.nim @@ -1,6 +1,8 @@ import std/[deques, macros, options, importutils] import async_backend, pg_protocol, pg_connection, pg_types, pg_client +import pg_connection/[types, buffer_io, cache, simple_query, lifecycle] +import pg_client/[transaction, pipeline] privateAccess(PgConnection) diff --git a/async_postgres/pg_pool_cluster.nim b/async_postgres/pg_pool_cluster.nim index 5803e2a..1ff3cfa 100644 --- a/async_postgres/pg_pool_cluster.nim +++ b/async_postgres/pg_pool_cluster.nim @@ -1,6 +1,8 @@ import std/macros import async_backend, pg_protocol, pg_connection, pg_types, pg_pool, pg_client +import pg_connection/types +import pg_client/transaction type ReplicaFallback* = enum diff --git a/async_postgres/pg_replication.nim b/async_postgres/pg_replication.nim index d276761..151c004 100644 --- a/async_postgres/pg_replication.nim +++ b/async_postgres/pg_replication.nim @@ -18,6 +18,8 @@ import std/[strutils, tables, times, options] import async_backend, pg_protocol, pg_connection, pg_types +import pg_connection/[types, dsn, buffer_io, simple_query, lifecycle] +import pg_types/encoding type Lsn* = distinct uint64 diff --git a/async_postgres/pg_sql.nim b/async_postgres/pg_sql.nim index 4c5066b..947463c 100644 --- a/async_postgres/pg_sql.nim +++ b/async_postgres/pg_sql.nim @@ -29,6 +29,7 @@ import std/macros import async_backend, pg_types, pg_connection, pg_client, pg_pool +import pg_connection/[types, simple_query] type SqlQuery* = object ## A parameterised SQL query with its bound parameters. diff --git a/async_postgres/pg_types.nim b/async_postgres/pg_types.nim index af26161..45ad244 100644 --- a/async_postgres/pg_types.nim +++ b/async_postgres/pg_types.nim @@ -3,7 +3,61 @@ import std/[json, macros, options, times] import pg_protocol import pg_types/[core, array, encoding, decoding, accessors, user_types, ranges] -export core, array, encoding, decoding, accessors, user_types, ranges +# `core` — the stable type-conversion API; exported wholesale. +export core +# `array` (PgArray + shape validation) and `user_types` (enum/composite/domain +# macros) likewise expose only public API. +export array +export user_types + +# `encoding` — typed-parameter encode/decode surface. The registry, bounds +# guards and raw binary helpers stay in the module; `paramOidOf` and the +# `addParseDirect`/`addBindDirect` writers are re-exported because the direct +# macros resolve them in the caller's scope. +export encoding.toPgParamInline +export encoding.toPgParam +export encoding.toPgDateParam +export encoding.toPgTimestampTzParam +export encoding.encodeHstoreText +export encoding.encodeBinaryArray +export encoding.pgParams +export encoding.toPgBinaryParam +export encoding.toPgBinaryDateParam +export encoding.toPgBinaryTimestampTzParam +export encoding.toPgTimestampArrayParam +export encoding.toPgTimestampTzArrayParam +export encoding.toPgDateArrayParam +export encoding.toPgMoneyArrayParam +export encoding.toPgMoneyArrayNDParam +export encoding.toPgByteaArrayParam +export encoding.coerceBinaryParam +export encoding.addParseDirect +export encoding.addBindDirect +export encoding.paramOidOf +export encoding.writeParamFormat +export encoding.writeParamValue +export encoding.writeParamOid + +# `decoding` — public text parsers; the raw binary decoders stay internal. +export decoding.fromPgText +export decoding.parseTimestampText +export decoding.parseDateText +export decoding.parseTimeText +export decoding.parseTimeTzText +export decoding.parseHstoreText +export decoding.parseIntervalText +export decoding.parseInetText +export decoding.parsePointText +export decoding.parsePointsText +export decoding.parseTextArray + +# `accessors` — typed row accessors and query-result helpers; its internals +# were privatised in the module itself. +export accessors + +# `ranges` — range/multirange construction and typed parameters; the raw +# binary decoders were privatised in the module itself. +export ranges # Name-based accessors bound here so both accessors.nim (non-range getters) # and ranges.nim (Range/Multirange getters) are visible when `nameAccessor` diff --git a/async_postgres/pg_types/accessors.nim b/async_postgres/pg_types/accessors.nim index 385cf1f..e367515 100644 --- a/async_postgres/pg_types/accessors.nim +++ b/async_postgres/pg_types/accessors.nim @@ -16,7 +16,7 @@ proc cellInfo*(row: Row, col: int): tuple[off: int, len: int] {.inline.} = result.off = int(row.data.cellIndex[idx]) result.len = int(row.data.cellIndex[idx + 1]) -template bufView*(row: Row, off, clen: int): openArray[char] = +template bufView(row: Row, off, clen: int): openArray[char] = ## Zero-copy char view into row.data.buf for parseutils. ## clen <= 0 skips `addr buf[off]`: a trailing empty cell has off == buf.len, ## which would otherwise raise an uncatchable IndexDefect. @@ -57,7 +57,7 @@ converter toRow*(cells: seq[Option[seq[byte]]]): Row = rd.buf.add(data) initRow(rd, 0) -proc parseAffectedRowsRaw*(tag: openArray[char]): int64 = +proc parseAffectedRowsRaw(tag: openArray[char]): int64 = ## Extract row count from the raw bytes of a command tag (e.g. ## "UPDATE 3" -> 3, "INSERT 0 1" -> 1). Unlike `parseAffectedRows(string)` ## this performs zero heap allocation — useful for pipelines that process @@ -83,7 +83,7 @@ proc parseAffectedRowsRaw*(tag: openArray[char]): int64 = return 0 parsed -proc parseAffectedRows*(tag: string): int64 = +proc parseAffectedRows(tag: string): int64 = ## Extract row count from command tag (e.g. "UPDATE 3" -> 3, "INSERT 0 1" -> 1). parseAffectedRowsRaw(tag.toOpenArray(0, tag.high)) @@ -120,7 +120,7 @@ proc isBinaryCol*(row: Row, col: int): bool {.inline.} = # bounds check, so a negative col would reach `colFormats[col]` here. col >= 0 and row.data.colFormats.len > col and row.data.colFormats[col] == 1'i16 -proc colTypeOid*(row: Row, col: int): int32 {.inline.} = +proc colTypeOid(row: Row, col: int): int32 {.inline.} = ## Get the type OID for a column, or 0 if not available. if col >= 0 and row.data.colTypeOids.len > col: row.data.colTypeOids[col] @@ -368,10 +368,10 @@ proc getMoney*(row: Row, col: int, scale: int = 2): PgMoney = # Binary decoders for types whose scalar accessors reuse the same body as the # array-element decoders below. Defined here (above the scalars) so both call # sites route through a single implementation. The rest of the -# `decodePgArrayElement*` overload set — plus text-only helpers — lives in the +# `decodePgArrayElement` overload set — plus text-only helpers — lives in the # registry section further down. -proc decodePgArrayElement*(_: typedesc[PgUuid], buf: openArray[byte]): PgUuid = +proc decodePgArrayElement(_: typedesc[PgUuid], buf: openArray[byte]): PgUuid = if buf.len != 16: raise newException(PgTypeError, "uuid: bad length " & $buf.len) const hexChars = "0123456789abcdef" @@ -387,14 +387,14 @@ proc decodePgArrayElement*(_: typedesc[PgUuid], buf: openArray[byte]): PgUuid = pos += 2 PgUuid(s) -proc decodePgArrayElement*(_: typedesc[PgInterval], buf: openArray[byte]): PgInterval = +proc decodePgArrayElement(_: typedesc[PgInterval], buf: openArray[byte]): PgInterval = if buf.len != 16: raise newException(PgTypeError, "interval: bad length " & $buf.len) result.microseconds = fromBE64(buf.toOpenArray(0, 7)) result.days = fromBE32(buf.toOpenArray(8, 11)) result.months = fromBE32(buf.toOpenArray(12, 15)) -proc decodePgArrayElement*(_: typedesc[PgMacAddr], buf: openArray[byte]): PgMacAddr = +proc decodePgArrayElement(_: typedesc[PgMacAddr], buf: openArray[byte]): PgMacAddr = if buf.len != 6: raise newException(PgTypeError, "macaddr: bad length " & $buf.len) var parts = newSeq[string](6) @@ -402,7 +402,7 @@ proc decodePgArrayElement*(_: typedesc[PgMacAddr], buf: openArray[byte]): PgMacA parts[j] = toHex(buf[j], 2).toLowerAscii() PgMacAddr(parts.join(":")) -proc decodePgArrayElement*(_: typedesc[PgMacAddr8], buf: openArray[byte]): PgMacAddr8 = +proc decodePgArrayElement(_: typedesc[PgMacAddr8], buf: openArray[byte]): PgMacAddr8 = if buf.len != 8: raise newException(PgTypeError, "macaddr8: bad length " & $buf.len) var parts = newSeq[string](8) @@ -410,7 +410,7 @@ proc decodePgArrayElement*(_: typedesc[PgMacAddr8], buf: openArray[byte]): PgMac parts[j] = toHex(buf[j], 2).toLowerAscii() PgMacAddr8(parts.join(":")) -proc decodeJsonArrayElem*(buf: openArray[byte], elemOid: int32): JsonNode = +proc decodeJsonArrayElem(buf: openArray[byte], elemOid: int32): JsonNode = # Strip the leading jsonb version byte only when elemOid says jsonb. let jsonStr = if elemOid == OidJsonb and buf.len > 0 and buf[0] == 1: @@ -932,48 +932,48 @@ optAccessor(getCircle, getCircleOpt, PgCircle) # Shared array element decoder registry — 1-D and N-D accessors route here. -proc decodePgArrayElement*(_: typedesc[int16], buf: openArray[byte]): int16 = +proc decodePgArrayElement(_: typedesc[int16], buf: openArray[byte]): int16 = if buf.len != 2: raise newException(PgTypeError, "int2 array element: bad length " & $buf.len) fromBE16(buf) -proc decodePgArrayElement*(_: typedesc[int32], buf: openArray[byte]): int32 = +proc decodePgArrayElement(_: typedesc[int32], buf: openArray[byte]): int32 = if buf.len != 4: raise newException(PgTypeError, "int4 array element: bad length " & $buf.len) fromBE32(buf) -proc decodePgArrayElement*(_: typedesc[int64], buf: openArray[byte]): int64 = +proc decodePgArrayElement(_: typedesc[int64], buf: openArray[byte]): int64 = if buf.len != 8: raise newException(PgTypeError, "int8 array element: bad length " & $buf.len) fromBE64(buf) -proc decodePgArrayElement*(_: typedesc[float32], buf: openArray[byte]): float32 = +proc decodePgArrayElement(_: typedesc[float32], buf: openArray[byte]): float32 = if buf.len != 4: raise newException(PgTypeError, "float4 array element: bad length " & $buf.len) decodeFloat32BE(buf) -proc decodePgArrayElement*(_: typedesc[float64], buf: openArray[byte]): float64 = +proc decodePgArrayElement(_: typedesc[float64], buf: openArray[byte]): float64 = if buf.len != 8: raise newException(PgTypeError, "float8 array element: bad length " & $buf.len) decodeFloat64BE(buf) -proc decodePgArrayElement*(_: typedesc[bool], buf: openArray[byte]): bool = +proc decodePgArrayElement(_: typedesc[bool], buf: openArray[byte]): bool = if buf.len != 1: raise newException(PgTypeError, "bool array element: bad length " & $buf.len) buf[0] != 0'u8 -proc decodePgArrayElement*(_: typedesc[string], buf: openArray[byte]): string = +proc decodePgArrayElement(_: typedesc[string], buf: openArray[byte]): string = readString(buf, 0, buf.len) -proc decodePgArrayElement*(_: typedesc[seq[byte]], buf: openArray[byte]): seq[byte] = +proc decodePgArrayElement(_: typedesc[seq[byte]], buf: openArray[byte]): seq[byte] = readBytes(buf, 0, buf.len) -proc decodePgArrayElement*(_: typedesc[PgNumeric], buf: openArray[byte]): PgNumeric = +proc decodePgArrayElement(_: typedesc[PgNumeric], buf: openArray[byte]): PgNumeric = decodeNumericBinary(buf) # No PgMoney overload: binary money lacks scale; callers must supply it. -proc decodePgArrayElement*(_: typedesc[PgBit], buf: openArray[byte]): PgBit = +proc decodePgArrayElement(_: typedesc[PgBit], buf: openArray[byte]): PgBit = if buf.len < 4: raise newException(PgTypeError, "bit array element too short") let nbits = fromBE32(buf.toOpenArray(0, 3)) @@ -995,53 +995,51 @@ proc decodePgArrayElement*(_: typedesc[PgBit], buf: openArray[byte]): PgBit = data[j] = buf[4 + j] PgBit(nbits: nbits, data: data) -proc decodePgArrayElement*(_: typedesc[PgTime], buf: openArray[byte]): PgTime = +proc decodePgArrayElement(_: typedesc[PgTime], buf: openArray[byte]): PgTime = if buf.len != 8: raise newException(PgTypeError, "time array element: bad length " & $buf.len) decodeBinaryTime(buf) -proc decodePgArrayElement*(_: typedesc[PgTimeTz], buf: openArray[byte]): PgTimeTz = +proc decodePgArrayElement(_: typedesc[PgTimeTz], buf: openArray[byte]): PgTimeTz = if buf.len != 12: raise newException(PgTypeError, "timetz array element: bad length " & $buf.len) decodeBinaryTimeTz(buf) -proc decodePgArrayElement*[T: PgInet | PgCidr]( - _: typedesc[T], buf: openArray[byte] -): T = +proc decodePgArrayElement[T: PgInet | PgCidr](_: typedesc[T], buf: openArray[byte]): T = let (ip, mask) = decodeInetBinary(buf) T(address: ip, mask: mask) -proc decodePgArrayElement*[T: PgXml | PgTsVector | PgTsQuery]( +proc decodePgArrayElement[T: PgXml | PgTsVector | PgTsQuery]( _: typedesc[T], buf: openArray[byte] ): T = T(readString(buf, 0, buf.len)) -proc decodePgArrayElement*(_: typedesc[PgHstore], buf: openArray[byte]): PgHstore = +proc decodePgArrayElement(_: typedesc[PgHstore], buf: openArray[byte]): PgHstore = decodeHstoreBinary(buf) -proc decodePgArrayElement*(_: typedesc[PgPoint], buf: openArray[byte]): PgPoint = +proc decodePgArrayElement(_: typedesc[PgPoint], buf: openArray[byte]): PgPoint = if buf.len != 16: raise newException(PgTypeError, "point array element: bad length " & $buf.len) decodePointBinary(buf, 0) -proc decodePgArrayElement*(_: typedesc[PgLine], buf: openArray[byte]): PgLine = +proc decodePgArrayElement(_: typedesc[PgLine], buf: openArray[byte]): PgLine = if buf.len != 24: raise newException(PgTypeError, "line array element: bad length " & $buf.len) result.a = decodeFloat64BE(buf, 0) result.b = decodeFloat64BE(buf, 8) result.c = decodeFloat64BE(buf, 16) -proc decodePgArrayElement*(_: typedesc[PgLseg], buf: openArray[byte]): PgLseg = +proc decodePgArrayElement(_: typedesc[PgLseg], buf: openArray[byte]): PgLseg = if buf.len != 32: raise newException(PgTypeError, "lseg array element: bad length " & $buf.len) PgLseg(p1: decodePointBinary(buf, 0), p2: decodePointBinary(buf, 16)) -proc decodePgArrayElement*(_: typedesc[PgBox], buf: openArray[byte]): PgBox = +proc decodePgArrayElement(_: typedesc[PgBox], buf: openArray[byte]): PgBox = if buf.len != 32: raise newException(PgTypeError, "box array element: bad length " & $buf.len) PgBox(high: decodePointBinary(buf, 0), low: decodePointBinary(buf, 16)) -proc decodePgArrayElement*(_: typedesc[PgPath], buf: openArray[byte]): PgPath = +proc decodePgArrayElement(_: typedesc[PgPath], buf: openArray[byte]): PgPath = if buf.len < 5: raise newException(PgTypeError, "path array element too short: " & $buf.len) result.closed = buf[0] != 0 @@ -1055,7 +1053,7 @@ proc decodePgArrayElement*(_: typedesc[PgPath], buf: openArray[byte]): PgPath = for j in 0 ..< npts: result.points[j] = decodePointBinary(buf, 5 + j * 16) -proc decodePgArrayElement*(_: typedesc[PgPolygon], buf: openArray[byte]): PgPolygon = +proc decodePgArrayElement(_: typedesc[PgPolygon], buf: openArray[byte]): PgPolygon = if buf.len < 4: raise newException(PgTypeError, "polygon array element too short: " & $buf.len) let npts = fromBE32(buf.toOpenArray(0, 3)) @@ -1068,7 +1066,7 @@ proc decodePgArrayElement*(_: typedesc[PgPolygon], buf: openArray[byte]): PgPoly for j in 0 ..< npts: result.points[j] = decodePointBinary(buf, 4 + j * 16) -proc decodePgArrayElement*(_: typedesc[PgCircle], buf: openArray[byte]): PgCircle = +proc decodePgArrayElement(_: typedesc[PgCircle], buf: openArray[byte]): PgCircle = if buf.len != 24: raise newException(PgTypeError, "circle array element: bad length " & $buf.len) result.center = decodePointBinary(buf, 0) @@ -1077,16 +1075,14 @@ proc decodePgArrayElement*(_: typedesc[PgCircle], buf: openArray[byte]): PgCircl # Named helpers where typedesc dispatch can't distinguish: DateTime is shared # by timestamp/timestamptz/date; JsonNode needs runtime elemOid. -proc decodeTimestampArrayElem*( - buf: openArray[byte], typeName: static string -): DateTime = +proc decodeTimestampArrayElem(buf: openArray[byte], typeName: static string): DateTime = if buf.len != 8: raise newException( PgTypeError, "Invalid binary " & typeName & " element length: " & $buf.len ) decodeBinaryTimestamp(buf) -proc decodeDateArrayElem*(buf: openArray[byte]): DateTime = +proc decodeDateArrayElem(buf: openArray[byte]): DateTime = if buf.len != 4: raise newException(PgTypeError, "Invalid binary date element length: " & $buf.len) decodeBinaryDate(buf) diff --git a/async_postgres/pg_types/ranges.nim b/async_postgres/pg_types/ranges.nim index a0d341e..578f8fc 100644 --- a/async_postgres/pg_types/ranges.nim +++ b/async_postgres/pg_types/ranges.nim @@ -18,7 +18,7 @@ type upperData: seq[byte], ] - RangeBinaryRaw* = + RangeBinaryRaw = tuple[ isEmpty: bool, hasLower: bool, @@ -31,7 +31,7 @@ type upperLen: int, ] -proc decodeRangeBinaryRaw*(data: openArray[byte]): RangeBinaryRaw = +proc decodeRangeBinaryRaw(data: openArray[byte]): RangeBinaryRaw = if data.len < 1: raise newException(PgTypeError, "Binary range too short") let flags = data[0] @@ -65,7 +65,7 @@ proc decodeRangeBinaryRaw*(data: openArray[byte]): RangeBinaryRaw = result.upperOff = pos result.upperLen = bLen -proc decodeInt4RangeBinary*(data: openArray[byte]): PgRange[int32] = +proc decodeInt4RangeBinary(data: openArray[byte]): PgRange[int32] = let raw = decodeRangeBinaryRaw(data) if raw.isEmpty: return PgRange[int32](isEmpty: true) @@ -90,7 +90,7 @@ proc decodeInt4RangeBinary*(data: openArray[byte]): PgRange[int32] = inclusive: raw.upperInc, ) -proc decodeInt8RangeBinary*(data: openArray[byte]): PgRange[int64] = +proc decodeInt8RangeBinary(data: openArray[byte]): PgRange[int64] = let raw = decodeRangeBinaryRaw(data) if raw.isEmpty: return PgRange[int64](isEmpty: true) @@ -115,7 +115,7 @@ proc decodeInt8RangeBinary*(data: openArray[byte]): PgRange[int64] = inclusive: raw.upperInc, ) -proc decodeNumRangeBinary*(data: openArray[byte]): PgRange[PgNumeric] = +proc decodeNumRangeBinary(data: openArray[byte]): PgRange[PgNumeric] = let raw = decodeRangeBinaryRaw(data) if raw.isEmpty: return PgRange[PgNumeric](isEmpty: true) @@ -136,7 +136,7 @@ proc decodeNumRangeBinary*(data: openArray[byte]): PgRange[PgNumeric] = inclusive: raw.upperInc, ) -proc decodeTsRangeBinary*(data: openArray[byte]): PgRange[DateTime] = +proc decodeTsRangeBinary(data: openArray[byte]): PgRange[DateTime] = let raw = decodeRangeBinaryRaw(data) if raw.isEmpty: return PgRange[DateTime](isEmpty: true) @@ -161,7 +161,7 @@ proc decodeTsRangeBinary*(data: openArray[byte]): PgRange[DateTime] = inclusive: raw.upperInc, ) -proc decodeDateRangeBinary*(data: openArray[byte]): PgRange[DateTime] = +proc decodeDateRangeBinary(data: openArray[byte]): PgRange[DateTime] = let raw = decodeRangeBinaryRaw(data) if raw.isEmpty: return PgRange[DateTime](isEmpty: true) @@ -186,7 +186,7 @@ proc decodeDateRangeBinary*(data: openArray[byte]): PgRange[DateTime] = inclusive: raw.upperInc, ) -proc decodeMultirangeBinaryRaw*( +proc decodeMultirangeBinaryRaw( data: openArray[byte] ): seq[tuple[off: RelOff, len: int]] = ## Decode the framing of a binary multirange into ``(off, len)`` pairs for diff --git a/tests/all_tests.nim b/tests/all_tests.nim index ec0f075..efa42c5 100644 --- a/tests/all_tests.nim +++ b/tests/all_tests.nim @@ -1,13 +1,13 @@ {.push warning[UnusedImport]: off.} import - test_abandonment_e2e, test_advisory_lock, test_async_backend, test_auth, - test_cancel_e2e, test_copy_race, test_dsn, test_e2e_arrays, test_e2e_connection, - test_e2e_convenience, test_e2e_copy, test_e2e_cursor, test_e2e_listen, test_e2e_misc, - test_e2e_pool, test_e2e_query, test_e2e_transaction, test_e2e_types, - test_fill_recvbuf, test_keepalive, test_largeobject, test_listen_reconnect, - test_network_failure, test_physical_replication, test_pool, test_protocol, - test_protocol_fuzz, test_replication, test_replication_keepalive, test_rowdata, - test_saslprep, test_session_attrs, test_sql, test_ssl, test_tls_error_paths, - test_tracing, test_transaction_cancel, test_tx_cleanup_defect, test_types, - test_pool_cluster + test_abandonment_e2e, test_advisory_lock, test_aggregate, test_async_backend, + test_auth, test_cancel_e2e, test_copy_race, test_dsn, test_e2e_arrays, + test_e2e_connection, test_e2e_convenience, test_e2e_copy, test_e2e_cursor, + test_e2e_listen, test_e2e_misc, test_e2e_pool, test_e2e_query, test_e2e_transaction, + test_e2e_types, test_fill_recvbuf, test_keepalive, test_largeobject, + test_listen_reconnect, test_network_failure, test_physical_replication, test_pool, + test_protocol, test_protocol_fuzz, test_replication, test_replication_keepalive, + test_rowdata, test_saslprep, test_session_attrs, test_sql, test_ssl, + test_tls_error_paths, test_tracing, test_transaction_cancel, test_tx_cleanup_defect, + test_types, test_pool_cluster {.pop.} diff --git a/tests/test_aggregate.nim b/tests/test_aggregate.nim new file mode 100644 index 0000000..73178d0 --- /dev/null +++ b/tests/test_aggregate.nim @@ -0,0 +1,737 @@ +import std/[unittest, macros] + +import ../async_postgres + +# Compile-time probe: the aggregate `import ../async_postgres` must re-export +# the documented public API surface. Every symbol individually re-exported by +# `async_postgres.nim` / `pg_connection.nim` / `pg_client.nim` / `pg_types.nim` +# is probed here, plus a representative subset of the modules that are still +# re-exported wholesale (`pg_pool_cluster` / `pg_largeobject` / +# `pg_advisory_lock` / `pg_sql` / `pg_replication` / `pg_auth` / `async_backend` +# and the `pg_types` submodules `core` / `array` / `user_types` / `accessors` / +# `ranges`). A forgotten whitelist entry fails the build instead of surfacing +# downstream. The wholesale-module subset is not exhaustive: a symbol dropped +# from a wholesale module outside this list stays undetected — extend the +# probes when narrowing those modules. +# +# The existence check is scoped to the aggregate module +# (`async_postgres.`) rather than the bare `declared(name)`. A bare name +# also resolves to std/system symbols (`close`, `items`, `len`, `reset`, ...), +# so it would stay green even if the aggregate stopped re-exporting them. +# Qualified lookup only sees the aggregate's own exported surface, so these +# std-collision names are guarded just like everything else. +# +# The check is name visibility only: a whitelist entry re-exports every +# overload of a symbol at once, so dropping a *single* overload inside a +# submodule (rather than the whole name) is not caught by this probe. The same +# caveat applies to the `nameAccessor`-generated getter families below: an +# index-based overload under the same name keeps the probe green even if the +# name-based overload is removed. The probes still catch a family row that +# disappears entirely (macro table edit or module narrowing). +template apiExists(name: untyped) = + when not declared(async_postgres.`name`): + {.error: "aggregate import does not expose `" & astToStr(name) & "`".} + +# -- connection types +apiExists(PgConnection) +apiExists(ConnConfig) +apiExists(SslMode) +apiExists(SslNegotiation) +apiExists(ChannelBindingMode) +apiExists(AuthMethod) +apiExists(TargetSessionAttrs) +apiExists(LoadBalanceHosts) +apiExists(HostEntry) +apiExists(PgConnState) +apiExists(PgTracer) +apiExists(Notification) +apiExists(Notice) +apiExists(CachedStmt) +apiExists(QueryResult) +apiExists(CopyResult) +apiExists(CopyOutInfo) +apiExists(CopyInInfo) +apiExists(CopyOutCallback) +apiExists(CopyInCallback) +apiExists(PgPoolOwner) +apiExists(RowCallback) +apiExists(ClientCertPairingErrorMsg) +apiExists(TypeOidInfo) + +# -- protocol types +apiExists(FrontendMessageKind) +apiExists(BackendMessageKind) +apiExists(DescribeKind) +apiExists(TransactionStatus) +apiExists(FieldDescription) +apiExists(CopyFormat) +apiExists(BackendMessage) +apiExists(ParseState) +apiExists(ParseResult) +apiExists(RowData) +apiExists(Row) + +# -- pool API +apiExists(PgPool) +apiExists(PoolConfig) +apiExists(PoolMetrics) +apiExists(PooledConnHandle) + +# -- client API +apiExists(PreparedStatement) +apiExists(Pipeline) +apiExists(PipelineResult) +apiExists(PipelineResultKind) +apiExists(IsolatedPipelineResults) +apiExists(Cursor) +apiExists(IsolationLevel) +apiExists(AccessMode) +apiExists(DeferrableMode) +apiExists(TransactionOptions) +apiExists(RetryOptions) + +# -- wrapper / feature modules +apiExists(SqlQuery) +apiExists(Lsn) +apiExists(ReplicationCallback) +apiExists(ReplicaFallback) + +# -- pg_types values +apiExists(PgParam) +apiExists(PgParamInline) +apiExists(PgUuid) +apiExists(PgInterval) +apiExists(PgMoney) +apiExists(PgNumeric) +apiExists(PgInet) +apiExists(PgCidr) +apiExists(PgMacAddr) +apiExists(PgMacAddr8) +apiExists(PgHstore) +apiExists(PgPoint) +apiExists(PgPath) +apiExists(PgPolygon) +apiExists(PgBox) +apiExists(PgCircle) +apiExists(PgLseg) +apiExists(PgLine) +apiExists(PgBit) +apiExists(PgTime) +apiExists(PgTimeTz) +apiExists(PgXml) +apiExists(PgTsVector) +apiExists(PgTsQuery) +apiExists(PgRange) +apiExists(PgArray) + +# -- connection entry points +apiExists(connect) +apiExists(simpleQuery) +apiExists(simpleExec) +apiExists(ping) +apiExists(cancel) +apiExists(cancelNoWait) +apiExists(invalidateOnTimeout) +apiExists(checkSessionAttrs) +apiExists(orderedHosts) +apiExists(connectToHost) +apiExists(isConnected) +apiExists(getHosts) +apiExists(isUnixSocket) +apiExists(unixSocketPath) +apiExists(socketHasFin) +apiExists(socketHasPendingData) + +# -- listen / notify +apiExists(listen) +apiExists(unlisten) +apiExists(onNotify) +apiExists(onListenError) +apiExists(waitNotification) + +# -- query / exec +apiExists(query) +apiExists(exec) +apiExists(queryEach) +apiExists(queryRow) +apiExists(queryRowOpt) +apiExists(queryValue) +apiExists(queryValueOpt) +apiExists(queryValueOrDefault) +apiExists(queryExists) +apiExists(queryColumn) +apiExists(notify) +apiExists(execInTransaction) +apiExists(queryInTransaction) +apiExists(buildBeginSql) +apiExists(isRetryableTxError) +apiExists(backoffDelayMs) + +# -- prepared statements / cursors +apiExists(prepare) +apiExists(execute) +apiExists(columnIndex) +apiExists(fetchNext) +apiExists(openCursor) + +# -- COPY +apiExists(copyIn) +apiExists(copyOut) +apiExists(copyInStream) +apiExists(copyOutStream) + +# -- pool operations +apiExists(newPool) +apiExists(acquire) +apiExists(release) +apiExists(runAndRelease) +apiExists(resetSession) +apiExists(resetSessionAndRelease) +apiExists(idleCount) +apiExists(activeCount) +apiExists(size) +apiExists(isClosed) +apiExists(metrics) +apiExists(initPoolConfig) +apiExists(close) + +# -- DSN +apiExists(initConnConfig) +apiExists(parseDsn) + +# -- pipeline +apiExists(newPipeline) +apiExists(addExec) +apiExists(addQuery) +apiExists(executeIsolated) +apiExists(reset) + +# -- type conversion and accessors +apiExists(toPgParam) +apiExists(toPgParamInline) +apiExists(toPgBinaryParam) +apiExists(pgParams) +apiExists(fromPgText) +apiExists(parseTimestampText) +apiExists(parseDateText) +apiExists(parseTimeText) +apiExists(parseTimeTzText) +apiExists(parseHstoreText) +apiExists(parseIntervalText) +apiExists(parseInetText) +apiExists(parsePointText) +apiExists(parsePointsText) +apiExists(parseTextArray) +apiExists(getStr) +apiExists(getInt) +apiExists(getBool) +apiExists(getBytes) +apiExists(getJson) +apiExists(getUuid) +apiExists(getNumeric) +apiExists(getMoney) +apiExists(getTimestamp) +apiExists(getDate) +apiExists(getTime) +apiExists(getInterval) +apiExists(getInet) +apiExists(getCidr) +apiExists(getHstore) +apiExists(getPoint) +apiExists(getBox) +apiExists(getCircle) +apiExists(isNull) + +# -- range helpers +apiExists(emptyRange) +apiExists(rangeOf) +apiExists(rangeFrom) +apiExists(rangeTo) +apiExists(unboundedRange) +apiExists(parseRangeText) + +# -- query-result helpers +apiExists(quoteIdentifier) +apiExists(dialAddr) +apiExists(displayHost) +apiExists(lookupTypeOids) + +# -- macros / templates that must stay reachable in user scope +apiExists(withTransaction) +apiExists(withTransactionRetry) +apiExists(withSavepoint) +apiExists(withTransactionDeadline) +apiExists(withTransactionRetryDeadline) +apiExists(withSavepointDeadline) +apiExists(withConnection) +apiExists(withPipeline) +apiExists(withCursor) +apiExists(queryDirect) +apiExists(execDirect) +apiExists(sql) +apiExists(withAdvisoryLock) +apiExists(withAdvisoryLockShared) +apiExists(withLargeObject) +apiExists(makeCopyInCallback) +apiExists(makeCopyOutCallback) +apiExists(withTracing) +apiExists(withConnTracing) + +# -- protocol send-buffer writers (pg_protocol) +apiExists(addInt16) +apiExists(addInt32) +apiExists(addLen32) +apiExists(addCount16) +apiExists(addCString) +apiExists(addParse) +apiExists(addBind) +apiExists(addBindRaw) +apiExists(addDescribe) +apiExists(addExecute) +apiExists(addClose) +apiExists(addSync) +apiExists(addFlush) +apiExists(addCopyDone) +apiExists(addCopyBinaryHeader) +apiExists(addCopyBinaryTrailer) +apiExists(addCopyTupleStart) +apiExists(addCopyFieldNull) +apiExists(addCopyFieldInt16) +apiExists(addCopyFieldInt32) +apiExists(addCopyFieldInt64) +apiExists(addCopyFieldFloat32) +apiExists(addCopyFieldFloat64) +apiExists(addCopyFieldBool) +apiExists(addCopyFieldText) +apiExists(addCopyFieldString) +apiExists(patchMsgLen) +apiExists(syncMsg) +apiExists(flushMsg) +apiExists(copyDoneMsg) + +# -- protocol message encoders / parse helpers (pg_protocol) +apiExists(encodeStartup) +apiExists(encodeSSLRequest) +apiExists(encodePassword) +apiExists(encodeSASLInitialResponse) +apiExists(encodeSASLResponse) +apiExists(encodeQuery) +apiExists(encodeParse) +apiExists(encodeBind) +apiExists(encodeDescribe) +apiExists(encodeExecute) +apiExists(encodeClose) +apiExists(encodeSync) +apiExists(encodeFlush) +apiExists(encodeTerminate) +apiExists(encodeCancelRequest) +apiExists(encodeCopyData) +apiExists(encodeCopyDone) +apiExists(encodeCopyFail) +apiExists(encodeStandbyStatusUpdate) +apiExists(buildResultFormats) +apiExists(parseDataRowInto) +apiExists(parseBackendMessage) +apiExists(formatError) +apiExists(isBinarySafeOid) +apiExists(BinarySafeOids) +apiExists(maxInt32Len) +apiExists(DefaultMaxBackendMessageLen) +apiExists(MaxNegotiateProtocolOptions) +apiExists(MaxErrorOrNoticeFields) +apiExists(MaxSaslMechanisms) + +# -- row / QueryResult helpers (pg_protocol, simple_query) +apiExists(initRow) +apiExists(rowIdx) +apiExists(data) +apiExists(clone) +apiExists(newRowData) +apiExists(reuseRowData) +apiExists(rows) +apiExists(items) +apiExists(len) + +# -- encoding binary-param helpers (pg_types/encoding) +apiExists(toPgDateParam) +apiExists(toPgTimestampTzParam) +apiExists(toPgBinaryDateParam) +apiExists(toPgBinaryTimestampTzParam) +apiExists(toPgTimestampArrayParam) +apiExists(toPgTimestampTzArrayParam) +apiExists(toPgDateArrayParam) +apiExists(toPgMoneyArrayParam) +apiExists(toPgMoneyArrayNDParam) +apiExists(toPgByteaArrayParam) +apiExists(encodeBinaryArray) +apiExists(encodeHstoreText) +apiExists(coerceBinaryParam) +apiExists(paramOidOf) +apiExists(addParseDirect) +apiExists(addBindDirect) +apiExists(writeParamFormat) +apiExists(writeParamValue) +apiExists(writeParamOid) + +# -- trace hook data types (pg_connection/types) +apiExists(TraceContext) +apiExists(TraceCopyDirection) +apiExists(TraceConnectStartData) +apiExists(TraceConnectEndData) +apiExists(TraceQueryStartData) +apiExists(TraceQueryEndData) +apiExists(TracePrepareStartData) +apiExists(TracePrepareEndData) +apiExists(TracePipelineStartData) +apiExists(TracePipelineEndData) +apiExists(TraceCopyStartData) +apiExists(TraceCopyEndData) +apiExists(TracePoolAcquireStartData) +apiExists(TracePoolAcquireEndData) +apiExists(TracePoolReleaseStartData) +apiExists(TracePoolReleaseEndData) +apiExists(TracePoolDoubleReleaseData) +apiExists(TracePoolCloseErrorData) +apiExists(TraceTransportCloseErrorData) +apiExists(TraceCleanupSkippedData) +apiExists(TraceLeakedSessionLocksData) +apiExists(TraceInsecureAuthData) +apiExists(TraceDeprecatedAuthData) +apiExists(TraceAdvisoryUnlockFailedData) +apiExists(CleanupKind) +apiExists(CleanupSkipReason) +apiExists(TransportCloseStage) +apiExists(NoticeCallback) +apiExists(NotifyCallback) + +# -- symbol bound into user scope by the transaction macros (pg_client/transaction) +apiExists(rollbackGrace) + +# -- large object API (pg_largeobject, wholesale export) +apiExists(loCreate) +apiExists(loOpen) +apiExists(loClose) +apiExists(loRead) +apiExists(loReadAll) +apiExists(loReadAllDeadline) +apiExists(loWrite) +apiExists(loWriteAll) +apiExists(loWriteAllDeadline) +apiExists(loSeek) +apiExists(loTell) +apiExists(loSize) +apiExists(loSizeDeadline) +apiExists(loTruncate) +apiExists(loUnlink) +apiExists(loImport) +apiExists(loExport) +apiExists(loReadStream) +apiExists(loReadStreamDeadline) +apiExists(loWriteStream) +apiExists(loWriteStreamDeadline) +apiExists(makeLoReadCallback) +apiExists(makeLoWriteCallback) +apiExists(INV_READ) +apiExists(INV_WRITE) +apiExists(INV_READWRITE) + +# -- advisory lock API (pg_advisory_lock, wholesale export) +apiExists(advisoryLock) +apiExists(advisoryLockShared) +apiExists(advisoryLockXact) +apiExists(advisoryLockXactShared) +apiExists(advisoryTryLock) +apiExists(advisoryTryLockShared) +apiExists(advisoryTryLockXact) +apiExists(advisoryTryLockXactShared) +apiExists(advisoryUnlock) +apiExists(advisoryUnlockShared) +apiExists(advisoryUnlockAll) +apiExists(withAdvisoryLockXact) +apiExists(withAdvisoryLockXactShared) + +# -- replication API (pg_replication, wholesale export) +apiExists(connectReplication) +apiExists(startReplication) +apiExists(startPhysicalReplication) +apiExists(stopReplication) +apiExists(createReplicationSlot) +apiExists(dropReplicationSlot) +apiExists(readReplicationSlot) +apiExists(identifySystem) +apiExists(timelineHistory) +apiExists(currentPgTimestamp) +apiExists(decodePgOutput) +apiExists(parsePgOutputMessage) +apiExists(parseReplicationMessage) +apiExists(sendCopyData) +apiExists(sendStandbyStatus) +apiExists(parseLsn) +apiExists(toInt64) +apiExists(toUInt64) +apiExists(confirmedFlushLsn) +apiExists(confirmFlushed) +apiExists(receivedEndLsn) +apiExists(hasOldTuple) +apiExists(makeReplicationCallback) + +# -- pool-cluster API (pg_pool_cluster, wholesale export) +apiExists(newPoolCluster) +apiExists(primaryPool) +apiExists(replicaPool) +apiExists(withReadConnection) +apiExists(withWriteConnection) +apiExists(readConnection) +apiExists(writeConnection) +apiExists(fallbackTimeout) +apiExists(onReadFallback) + +# -- auth helpers (pg_auth, wholesale export) +apiExists(md5AuthHash) +apiExists(scramClientFirstMessage) +apiExists(scramClientFinalMessage) +apiExists(scramVerifyServerFinal) +apiExists(scramEscapeUsername) +apiExists(computeTlsServerEndpoint) +apiExists(ScramState) +apiExists(DefaultMaxScramIterations) + +# -- backend switches and helpers (async_backend, wholesale export) +apiExists(hasChronos) +apiExists(hasAsyncDispatch) +apiExists(hasTls) +apiExists(remainingDeadlineDuration) + +# -- query-builder helper (pg_sql, wholesale export) +apiExists(sqlParams) + +# -- range / multirange parameters and text parse (pg_types/ranges, wholesale export) +apiExists(toMultirange) +apiExists(toPgRangeParam) +apiExists(toPgMultirangeParam) +apiExists(toPgDateRangeParam) +apiExists(toPgDateMultirangeParam) +apiExists(toPgDateRangeArrayParam) +apiExists(toPgDateMultirangeArrayParam) +apiExists(toPgTsMultirangeArrayParam) +apiExists(toPgTsTzRangeParam) +apiExists(toPgTsTzMultirangeParam) +apiExists(toPgTsTzRangeArrayParam) +apiExists(toPgTsTzMultirangeArrayParam) +apiExists(toPgBinaryDateRangeParam) +apiExists(toPgBinaryDateMultirangeParam) +apiExists(toPgBinaryDateRangeArrayParam) +apiExists(toPgBinaryDateMultirangeArrayParam) +apiExists(toPgBinaryTsTzRangeParam) +apiExists(toPgBinaryTsTzMultirangeParam) +apiExists(toPgBinaryTsTzRangeArrayParam) +apiExists(toPgBinaryTsTzMultirangeArrayParam) +apiExists(parseMultirangeText) + +# -- user-defined type macros / getters (pg_types/user_types, wholesale export) +apiExists(pgEnum) +apiExists(pgComposite) +apiExists(pgDomain) +apiExists(getEnum) +apiExists(getEnumOpt) +apiExists(getEnumArray) +apiExists(getEnumArrayOpt) +apiExists(getEnumArrayElemOpt) +apiExists(getComposite) +apiExists(getCompositeOpt) +apiExists(getDomain) +apiExists(getDomainOpt) +apiExists(parseCompositeText) +apiExists(encodeCompositeText) +apiExists(encodeEnumTextArray) +apiExists(encodeBinaryComposite) + +# -- name-based row accessors / range&multirange getters generated by `nameAccessor*` +# -- (pg_types.nim): a removed family row here fails the build. +# -- See the header comment for the index-overload caveat. +apiExists(getBit) +apiExists(getBitArray) +apiExists(getBitArrayOpt) +apiExists(getBitOpt) +apiExists(getBoolArray) +apiExists(getBoolArrayElemOpt) +apiExists(getBoolArrayElemOptOpt) +apiExists(getBoolArrayOpt) +apiExists(getBoolOpt) +apiExists(getBoxArray) +apiExists(getBoxArrayOpt) +apiExists(getBoxOpt) +apiExists(getBytesArray) +apiExists(getBytesArrayOpt) +apiExists(getBytesOpt) +apiExists(getCidrArray) +apiExists(getCidrArrayOpt) +apiExists(getCidrOpt) +apiExists(getCircleArray) +apiExists(getCircleArrayOpt) +apiExists(getCircleOpt) +apiExists(getDateArray) +apiExists(getDateArrayOpt) +apiExists(getDateMultirange) +apiExists(getDateMultirangeArray) +apiExists(getDateMultirangeArrayOpt) +apiExists(getDateMultirangeOpt) +apiExists(getDateOpt) +apiExists(getDateRange) +apiExists(getDateRangeArray) +apiExists(getDateRangeArrayOpt) +apiExists(getDateRangeOpt) +apiExists(getFloat) +apiExists(getFloat32) +apiExists(getFloat32Array) +apiExists(getFloat32ArrayElemOpt) +apiExists(getFloat32ArrayElemOptOpt) +apiExists(getFloat32ArrayOpt) +apiExists(getFloat32Opt) +apiExists(getFloatArray) +apiExists(getFloatArrayElemOpt) +apiExists(getFloatArrayElemOptOpt) +apiExists(getFloatArrayOpt) +apiExists(getFloatOpt) +apiExists(getHstoreArray) +apiExists(getHstoreArrayOpt) +apiExists(getHstoreOpt) +apiExists(getInetArray) +apiExists(getInetArrayOpt) +apiExists(getInetOpt) +apiExists(getInt16) +apiExists(getInt16Array) +apiExists(getInt16ArrayElemOpt) +apiExists(getInt16ArrayElemOptOpt) +apiExists(getInt16ArrayOpt) +apiExists(getInt16Opt) +apiExists(getInt4Multirange) +apiExists(getInt4MultirangeArray) +apiExists(getInt4MultirangeArrayOpt) +apiExists(getInt4MultirangeOpt) +apiExists(getInt4Range) +apiExists(getInt4RangeArray) +apiExists(getInt4RangeArrayOpt) +apiExists(getInt4RangeOpt) +apiExists(getInt64) +apiExists(getInt64Array) +apiExists(getInt64ArrayElemOpt) +apiExists(getInt64ArrayElemOptOpt) +apiExists(getInt64ArrayOpt) +apiExists(getInt64Opt) +apiExists(getInt8Multirange) +apiExists(getInt8MultirangeArray) +apiExists(getInt8MultirangeArrayOpt) +apiExists(getInt8MultirangeOpt) +apiExists(getInt8Range) +apiExists(getInt8RangeArray) +apiExists(getInt8RangeArrayOpt) +apiExists(getInt8RangeOpt) +apiExists(getIntArray) +apiExists(getIntArrayElemOpt) +apiExists(getIntArrayElemOptOpt) +apiExists(getIntArrayOpt) +apiExists(getIntOpt) +apiExists(getIntervalArray) +apiExists(getIntervalArrayOpt) +apiExists(getIntervalOpt) +apiExists(getJsonArray) +apiExists(getJsonArrayOpt) +apiExists(getJsonOpt) +apiExists(getLine) +apiExists(getLineArray) +apiExists(getLineArrayOpt) +apiExists(getLineOpt) +apiExists(getLseg) +apiExists(getLsegArray) +apiExists(getLsegArrayOpt) +apiExists(getLsegOpt) +apiExists(getMacAddr) +apiExists(getMacAddr8) +apiExists(getMacAddr8Array) +apiExists(getMacAddr8ArrayOpt) +apiExists(getMacAddr8Opt) +apiExists(getMacAddrArray) +apiExists(getMacAddrArrayOpt) +apiExists(getMacAddrOpt) +apiExists(getMoneyArray) +apiExists(getMoneyArrayND) +apiExists(getMoneyArrayNDOpt) +apiExists(getMoneyArrayOpt) +apiExists(getMoneyOpt) +apiExists(getNumMultirange) +apiExists(getNumMultirangeArray) +apiExists(getNumMultirangeArrayOpt) +apiExists(getNumMultirangeOpt) +apiExists(getNumRange) +apiExists(getNumRangeArray) +apiExists(getNumRangeArrayOpt) +apiExists(getNumRangeOpt) +apiExists(getNumericArray) +apiExists(getNumericArrayOpt) +apiExists(getNumericOpt) +apiExists(getPath) +apiExists(getPathArray) +apiExists(getPathArrayOpt) +apiExists(getPathOpt) +apiExists(getPointArray) +apiExists(getPointArrayOpt) +apiExists(getPointOpt) +apiExists(getPolygon) +apiExists(getPolygonArray) +apiExists(getPolygonArrayOpt) +apiExists(getPolygonOpt) +apiExists(getStrArray) +apiExists(getStrArrayElemOpt) +apiExists(getStrArrayElemOptOpt) +apiExists(getStrArrayOpt) +apiExists(getStrOpt) +apiExists(getTimeArray) +apiExists(getTimeArrayOpt) +apiExists(getTimeOpt) +apiExists(getTimeTz) +apiExists(getTimeTzArray) +apiExists(getTimeTzArrayOpt) +apiExists(getTimeTzOpt) +apiExists(getTimestampArray) +apiExists(getTimestampArrayOpt) +apiExists(getTimestampOpt) +apiExists(getTimestampTz) +apiExists(getTimestampTzArray) +apiExists(getTimestampTzArrayOpt) +apiExists(getTimestampTzOpt) +apiExists(getTsMultirange) +apiExists(getTsMultirangeArray) +apiExists(getTsMultirangeArrayOpt) +apiExists(getTsMultirangeOpt) +apiExists(getTsQuery) +apiExists(getTsQueryArray) +apiExists(getTsQueryArrayOpt) +apiExists(getTsQueryOpt) +apiExists(getTsRange) +apiExists(getTsRangeArray) +apiExists(getTsRangeArrayOpt) +apiExists(getTsRangeOpt) +apiExists(getTsTzMultirange) +apiExists(getTsTzMultirangeArray) +apiExists(getTsTzMultirangeArrayOpt) +apiExists(getTsTzMultirangeOpt) +apiExists(getTsTzRange) +apiExists(getTsTzRangeArray) +apiExists(getTsTzRangeArrayOpt) +apiExists(getTsTzRangeOpt) +apiExists(getTsVector) +apiExists(getTsVectorArray) +apiExists(getTsVectorArrayOpt) +apiExists(getTsVectorOpt) +apiExists(getUuidArray) +apiExists(getUuidArrayOpt) +apiExists(getUuidOpt) +apiExists(getXml) +apiExists(getXmlArray) +apiExists(getXmlArrayOpt) +apiExists(getXmlOpt) + +suite "aggregate re-export": + test "public API surface resolves through `import pkg/async_postgres`": + check true diff --git a/tests/test_dsn.nim b/tests/test_dsn.nim index db3bb0d..5d5ad62 100644 --- a/tests/test_dsn.nim +++ b/tests/test_dsn.nim @@ -3,6 +3,7 @@ when defined(posix): import std/posix import ../async_postgres/[async_backend, pg_connection] +import ../async_postgres/pg_connection/dsn const dummyPem = "-----BEGIN CERTIFICATE-----\ndummy\n-----END CERTIFICATE-----\n" diff --git a/tests/test_e2e_convenience.nim b/tests/test_e2e_convenience.nim index 136b411..7fac947 100644 --- a/tests/test_e2e_convenience.nim +++ b/tests/test_e2e_convenience.nim @@ -4,6 +4,7 @@ import ../async_postgres/ [async_backend, pg_protocol, pg_types, pg_client, pg_pool, pg_connection] import ../async_postgres/pg_client/core +import ../async_postgres/pg_connection/cache when hasAsyncDispatch: import std/strutils diff --git a/tests/test_e2e_listen.nim b/tests/test_e2e_listen.nim index ddf717d..dafed53 100644 --- a/tests/test_e2e_listen.nim +++ b/tests/test_e2e_listen.nim @@ -2,6 +2,10 @@ import std/[unittest, options, strutils, math, deques, importutils, net] import ../async_postgres/[async_backend, pg_protocol, pg_types, pg_client, pg_connection] +import ../async_postgres/pg_connection/buffer_io +import + ../async_postgres/pg_connection/ + [types, dsn, buffer_io, ssl, cache, simple_query, lifecycle, notify, type_lookup] when hasChronos: import std/sets diff --git a/tests/test_e2e_misc.nim b/tests/test_e2e_misc.nim index b0a7e0c..126dc01 100644 --- a/tests/test_e2e_misc.nim +++ b/tests/test_e2e_misc.nim @@ -3,6 +3,7 @@ import std/[unittest, options, tables, math, importutils, net] import ../async_postgres/ [async_backend, pg_protocol, pg_types, pg_replication, pg_client, pg_connection] +import ../async_postgres/pg_connection/[simple_query, lifecycle, notify] import e2e_common diff --git a/tests/test_e2e_transaction.nim b/tests/test_e2e_transaction.nim index 108a36d..fe2fce8 100644 --- a/tests/test_e2e_transaction.nim +++ b/tests/test_e2e_transaction.nim @@ -6,6 +6,9 @@ import pg_connection, ] +import ../async_postgres/pg_client/transaction {.all.} +import ../async_postgres/pg_connection/[simple_query, lifecycle, notify, buffer_io] + import e2e_common privateAccess(PgConnection) diff --git a/tests/test_fill_recvbuf.nim b/tests/test_fill_recvbuf.nim index 621da84..158cedb 100644 --- a/tests/test_fill_recvbuf.nim +++ b/tests/test_fill_recvbuf.nim @@ -22,6 +22,9 @@ import std/[unittest] import ../async_postgres/async_backend import ../async_postgres/pg_connection {.all.} +import ../async_postgres/pg_connection/buffer_io +import ../async_postgres/pg_connection/simple_query +import ../async_postgres/pg_connection/types import ./mock_pg_server diff --git a/tests/test_keepalive.nim b/tests/test_keepalive.nim index c91b57d..4e36847 100644 --- a/tests/test_keepalive.nim +++ b/tests/test_keepalive.nim @@ -1,6 +1,8 @@ import std/[unittest, posix] import ../async_postgres/pg_connection {.all.} +import ../async_postgres/pg_connection/buffer_io +import ../async_postgres/pg_connection/types {.all.} suite "configureKeepalive": proc getIntSockOpt(fd: SocketHandle, level: cint, optname: cint): cint = diff --git a/tests/test_largeobject.nim b/tests/test_largeobject.nim index 8470864..ac37e90 100644 --- a/tests/test_largeobject.nim +++ b/tests/test_largeobject.nim @@ -2,6 +2,7 @@ import std/[unittest, importutils] import ../async_postgres/[async_backend, pg_client, pg_largeobject] import ../async_postgres/pg_connection {.all.} +import ../async_postgres/pg_connection/buffer_io privateAccess(PgConnection) diff --git a/tests/test_listen_reconnect.nim b/tests/test_listen_reconnect.nim index 2e5fbf6..4764abc 100644 --- a/tests/test_listen_reconnect.nim +++ b/tests/test_listen_reconnect.nim @@ -24,6 +24,8 @@ import std/[monotimes, unittest, sets, strutils] import ../async_postgres/async_backend import ../async_postgres/pg_connection {.all.} +import ../async_postgres/pg_connection/buffer_io +import ../async_postgres/pg_connection/[simple_query, notify] import ../async_postgres/pg_connection/types {.all.} import ./mock_pg_server diff --git a/tests/test_network_failure.nim b/tests/test_network_failure.nim index a48cae1..d1cade6 100644 --- a/tests/test_network_failure.nim +++ b/tests/test_network_failure.nim @@ -13,6 +13,7 @@ import pkg/nimcrypto/pbkdf2 import ../async_postgres/[async_backend, pg_protocol] import ../async_postgres/pg_connection {.all.} +import ../async_postgres/pg_connection/buffer_io import ./mock_pg_server diff --git a/tests/test_pool.nim b/tests/test_pool.nim index f13a9dd..ae55099 100644 --- a/tests/test_pool.nim +++ b/tests/test_pool.nim @@ -5,6 +5,9 @@ when hasChronos: import pkg/chronos/streams/asyncstream import ../async_postgres/[pg_protocol, pg_types, pg_connection] +import ../async_postgres/pg_connection/buffer_io +import ../async_postgres/pg_connection/simple_query +import ../async_postgres/pg_connection/cache import ../async_postgres/pg_pool {.all.} import mock_pg_server diff --git a/tests/test_protocol.nim b/tests/test_protocol.nim index f2225f2..09082f9 100644 --- a/tests/test_protocol.nim +++ b/tests/test_protocol.nim @@ -1,6 +1,8 @@ import std/[unittest, options, strutils, tables, importutils] import ../async_postgres/[async_backend, pg_bytes, pg_protocol, pg_connection] +import ../async_postgres/pg_connection/buffer_io +import ../async_postgres/pg_connection/types import ../async_postgres/pg_types/[core, encoding] privateAccess(PgConnection) diff --git a/tests/test_replication.nim b/tests/test_replication.nim index 3bc3db9..d0f7971 100644 --- a/tests/test_replication.nim +++ b/tests/test_replication.nim @@ -2,6 +2,7 @@ import std/[unittest, importutils, tables] import ../async_postgres/[async_backend, pg_errors, pg_protocol] import ../async_postgres/pg_connection {.all.} +import ../async_postgres/pg_connection/[buffer_io, simple_query, types] import ../async_postgres/pg_replication {.all.} privateAccess(PgConnection) diff --git a/tests/test_ssl.nim b/tests/test_ssl.nim index 34a3195..207573f 100644 --- a/tests/test_ssl.nim +++ b/tests/test_ssl.nim @@ -3,6 +3,7 @@ import std/[unittest, strutils, os] import ../async_postgres/[async_backend, pg_bytes, pg_protocol] import ../async_postgres/pg_connection {.all.} +import ../async_postgres/pg_connection/[ssl, lifecycle, types] when hasChronos: import ../async_postgres/pg_bearssl {.all.} diff --git a/tests/test_tracing.nim b/tests/test_tracing.nim index c0882b2..81e48f2 100644 --- a/tests/test_tracing.nim +++ b/tests/test_tracing.nim @@ -6,6 +6,8 @@ import ../async_postgres/[pg_client, pg_types, pg_protocol] import ../async_postgres/pg_pool {.all.} import ../async_postgres/pg_pool_cluster {.all.} import ../async_postgres/pg_connection {.all.} +import ../async_postgres/pg_connection/[buffer_io, simple_query, lifecycle] +import ../async_postgres/pg_connection/types const PgHost = "127.0.0.1" diff --git a/tests/test_types.nim b/tests/test_types.nim index 5a58206..6a98721 100644 --- a/tests/test_types.nim +++ b/tests/test_types.nim @@ -5,8 +5,13 @@ import import ../async_postgres/pg_protocol import ../async_postgres/pg_types {.all.} +import ../async_postgres/pg_types/encoding {.all.} +import ../async_postgres/pg_types/accessors {.all.} +import ../async_postgres/pg_types/decoding {.all.} +import ../async_postgres/pg_types/ranges {.all.} import ../async_postgres/pg_client import ../async_postgres/pg_client/core {.all.} +import ../async_postgres/pg_client/pipeline {.all.} type UsPostalCode = distinct string