postgres/postgres
libpq
libpq is the C client library for PostgreSQL — the official wire-protocol implementation. Almost every other PostgreSQL driver either wraps it via FFI or implements the same protocol independently. Source: src/interfaces/libpq/.
Source layout
src/interfaces/libpq/
├── exports.txt # symbols exported from the shared library
├── fe-auth.c # authentication: cleartext, MD5, SCRAM
├── fe-auth-oauth.c, fe-auth-oauth-curl.c # OAUTHBEARER + curl backend
├── fe-auth-sasl.c # SCRAM-SHA-256 implementation
├── fe-cancel.c # PQcancelCreate / PQcancelStart (async cancel API)
├── fe-connect.c # connection establishment, options parsing
├── fe-exec.c # query API (PQexec, PQsendQuery, PQgetResult, ...)
├── fe-gssapi-common.c, fe-secure-gssapi.c # GSSAPI/Kerberos
├── fe-lobj.c # large objects API
├── fe-misc.c # I/O helpers, message accumulation
├── fe-print.c # PQprint* (legacy, retained for compatibility)
├── fe-protocol3.c # protocol 3 message dispatch
├── fe-secure.c # SSL framework
├── fe-secure-openssl.c # OpenSSL backend
├── fe-trace.c # PQtrace
├── libpq-fe.h # public header
├── libpq-int.h # internal header
└── pqexpbuffer.c # buffer string managementPublic API summary
The header libpq-fe.h declares everything user code uses. Major functional groups:
Connection management
PGconn *PQconnectdb(const char *conninfo);
PGconn *PQconnectdbParams(const char * const *keywords, const char * const *values, int expand_dbname);
PGconn *PQconnectStart(const char *conninfo); /* nonblocking */
PostgresPollingStatusType PQconnectPoll(PGconn *conn);
ConnStatusType PQstatus(const PGconn *conn);
void PQfinish(PGconn *conn);
void PQreset(PGconn *conn);
/* Connection options */
const char *PQhost(const PGconn *conn);
const char *PQdb(const PGconn *conn);
int PQbackendPID(const PGconn *conn);
int PQsocket(const PGconn *conn);Connection strings accept either keyword=value form (host=db.example.com user=alice dbname=mydb) or URIs (postgres://alice@db.example.com/mydb?sslmode=require). The full option list is in the docs and in the PQconninfoOptions table inside fe-connect.c.
Synchronous query
PGresult *PQexec(PGconn *conn, const char *query);
PGresult *PQexecParams(PGconn *conn,
const char *command,
int nParams,
const Oid *paramTypes,
const char * const *paramValues,
const int *paramLengths,
const int *paramFormats,
int resultFormat);
PGresult *PQprepare(PGconn *conn, const char *stmtName, const char *query, int nParams, const Oid *paramTypes);
PGresult *PQexecPrepared(PGconn *conn, const char *stmtName, ...);
ExecStatusType PQresultStatus(const PGresult *res);
char *PQerrorMessage(const PGconn *conn);
char *PQresultErrorField(const PGresult *res, int fieldcode);
int PQntuples(const PGresult *res);
int PQnfields(const PGresult *res);
char *PQgetvalue(const PGresult *res, int row, int col);
void PQclear(PGresult *res);PQexec runs in simple query protocol — one round trip per ;-separated statement, results all returned at once. PQexecParams switches to extended query protocol with bind parameters; safer (no SQL injection) and supports binary parameters.
Asynchronous query
int PQsendQuery(PGconn *conn, const char *query);
int PQsendQueryParams(...);
int PQconsumeInput(PGconn *conn);
int PQisBusy(PGconn *conn);
PGresult *PQgetResult(PGconn *conn);
int PQflush(PGconn *conn);The async API is the basis of every non-blocking driver. The pattern:
PQsendQuery— buffers the query, returns immediately.- Caller monitors
PQsocketfor read/write readiness. PQconsumeInputwhen the socket is readable.- Loop calling
PQgetResultuntil it returnsNULL. Each call returns one result; multi-statement queries produce multiple results.
PQflush empties the send buffer when the socket becomes writable (on EAGAIN).
Single-row mode
PQsetSingleRowMode(conn);After PQsendQuery, PQgetResult returns one result per row (status PGRES_SINGLE_TUPLE), then a final PGRES_TUPLES_OK summary. Avoids accumulating large result sets in memory.
Pipeline mode
Pipeline mode (added in 14) lets a client issue many queries before reading any results, similar to HTTP pipelining:
PQenterPipelineMode(conn);
PQsendQueryParams(conn, "INSERT ...", ...);
PQsendQueryParams(conn, "INSERT ...", ...);
PQpipelineSync(conn);
/* drain results */
while ((res = PQgetResult(conn)) != NULL) { ... }
PQexitPipelineMode(conn);The server processes them serially but doesn't have to wait for the client between each. Significant latency reduction on round-trippy workloads.
COPY
/* Server → client */
PQputCopyData(conn, buf, len);
PQputCopyEnd(conn, errormsg);
/* Client → server */
PQgetCopyData(conn, &buf, async);COPY is a sub-protocol: after the server replies CopyOutResponse or CopyInResponse, the connection is in COPY mode and exchanges raw CopyData messages until terminated.
Notifications
LISTEN channel; (server-side) plus the client polling:
PQconsumeInput(conn);
PGnotify *n;
while ((n = PQnotifies(conn)) != NULL)
{
/* handle n->relname, n->extra, n->be_pid */
PQfreemem(n);
}Combined with PQsocket poll-readiness, this is how clients implement reactive features on top of NOTIFY.
Cancellation
PQcancelCreate (newer API) plus PQcancelStart / PQcancelPoll issue an out-of-band cancel request to the backend running on behalf of this connection. The legacy PQrequestCancel is still available but blocking.
Connection establishment
sequenceDiagram
participant Client as PQconnectdb
participant Net as TCP/Unix socket
participant SSL as SSL handshake
participant Auth as Auth handshake
participant Server
Client->>Net: connect()
Net-->>Client: socket open
opt sslmode != disable
Client->>Server: SSLRequest
Server-->>Client: 'S' or 'N'
alt 'S'
Client->>SSL: TLS handshake
SSL-->>Client: secure stream
end
end
Client->>Server: StartupMessage (proto=3, params)
Server-->>Client: AuthenticationXxx (challenge)
loop until AuthenticationOk
Client->>Auth: build response
Auth->>Server: PasswordMessage / SASL response
Server-->>Client: AuthenticationXxx
end
Server-->>Client: ParameterStatus*, BackendKeyData
Server-->>Client: ReadyForQueryThe state machine in fe-connect.c is driven by PQconnectPoll. When PQconnectdb is called synchronously, libpq spins on PQconnectPoll internally; when called via PQconnectStart, the application drives the loop.
Multiple host targets — host=a,b,c port=5432,5433,5432 — produce a list of candidates that libpq tries in order. target_session_attrs=read-write filters to a writable server.
SSL backends
fe-secure.c defines a tiny abstract interface:
struct PgSSL_Methods {
int (*open_client)(PGconn *);
int (*close)(PGconn *);
ssize_t (*read)(PGconn *, void *, size_t);
ssize_t (*write)(PGconn *, const void *, size_t);
/* ... */
};The OpenSSL backend (fe-secure-openssl.c) is the only one in tree. GSSAPI (fe-secure-gssapi.c) provides an analogous secure stream when the server uses gss encryption.
Authentication
fe-auth.c is the dispatcher. SCRAM-SHA-256 is implemented in fe-auth-sasl.c (the SASL exchange) plus fe-auth-scram.c. OAuth (SASL-OAUTHBEARER) is split into fe-auth-oauth.c (the SASL exchange) and fe-auth-oauth-curl.c (the device-code flow), with most of the actual flow loaded from libpq-oauth so the code is only linked when needed.
Threading
libpq is "thread-safe" in the sense that different connections from different threads work fine, but a single PGconn may be used by only one thread at a time. PQisthreadsafe() reports whether libpq was built with thread support — it almost always is.
Tracing
PQtrace(conn, FILE*) writes every protocol message in human-readable form to a file. Useful when chasing protocol-level bugs in a driver.
Tests
src/test/modules/libpq_pipeline/ carries a thorough pipeline-mode regression test. SSL, GSSAPI, SCRAM, and connection-string tests live in src/test/ssl/, src/test/kerberos/, and various TAP suites. The src/interfaces/libpq/test/ directory has a connection-string parser test.
Entry points for modification
- New connection option: register in
PQconninfoOptionsinfe-connect.c. Add documentation indoc/src/sgml/libpq.sgml. - New auth method: hook into
pg_fe_sendauthinfe-auth.c; corresponding backend support insrc/backend/libpq/auth.c. - New protocol message: a wide-blast change touching
fe-protocol3.c,fe-exec.c, the backendsrc/backend/tcop/postgres.c, and the protocol docs. Such patches are uncommon and require careful negotiation handling for older clients.
For other clients, see Interfaces.
Built by Factory AutoWiki from public repository content. It is a generated preview for codebase exploration, not source-maintained documentation.