Feature Roadmap: Wire Protocol and Driver Comparison #72
Replies: 33 comments 2 replies
-
|
I opened an issue on Lori for item 1 (SSL/TSL Negotiation)... ponylang/lori#170 |
Beta Was this translation helpful? Give feedback.
-
|
"3. Named prepared statements" has a design discussion at #77 |
Beta Was this translation helpful? Give feedback.
-
|
Item 3 (named prepared statements) and item 8 (Close message) are now implemented — PR #78. Design discussion: #77. |
Beta Was this translation helpful? Give feedback.
-
|
Item 1 (SSL/TLS negotiation) has been implemented in #79 |
Beta Was this translation helpful? Give feedback.
-
|
Design plan for SCRAM-SHA-256 authentication (the second Tier 1 item): #83 |
Beta Was this translation helpful? Give feedback.
-
|
Number 32 "Pass session to ResultReceiver callbacks" added in #84 |
Beta Was this translation helpful? Give feedback.
-
|
Number 33 "Equality on Rows/Row/Field" added in #85 |
Beta Was this translation helpful? Give feedback.
-
|
Number 4 "Graceful termination" was implemented in #86 |
Beta Was this translation helpful? Give feedback.
-
|
Number 5 "BackendKeyData handling" was implemented in #87 |
Beta Was this translation helpful? Give feedback.
-
Beta Was this translation helpful? Give feedback.
-
|
Number 2 "SCRAM-SHA-256 authentication" was implemented in #94. Design discussion: #83. |
Beta Was this translation helpful? Give feedback.
-
|
Close message (statement closing) was added in PR #78 (named prepared statement support). Portal closing is not needed yet — nothing in the driver uses named portals or partial result fetching. Considering this done. |
Beta Was this translation helpful? Give feedback.
-
|
Transaction status tracking design: #102 |
Beta Was this translation helpful? Give feedback.
-
|
LISTEN/NOTIFY design: #103 |
Beta Was this translation helpful? Give feedback.
-
|
Design for COPY IN protocol posted: #104 |
Beta Was this translation helpful? Give feedback.
-
|
Item #11 — Expanded type conversions is resolved. After analysis in #118, only |
Beta Was this translation helpful? Give feedback.
-
|
ParameterStatus tracking (#7) is done — implemented in PR #120. |
Beta Was this translation helpful? Give feedback.
-
Beta Was this translation helpful? Give feedback.
-
|
Row streaming design: #123 |
Beta Was this translation helpful? Give feedback.
-
|
Items 9 (Flush message) and 15 (Portal-based cursors) are both covered by the row streaming design (#123). Flush is required for between-batch communication, and portal-based cursors are the protocol mechanism that streaming is built on. |
Beta Was this translation helpful? Give feedback.
-
Beta Was this translation helpful? Give feedback.
-
|
Binary types (#21) and Custom codecs (#19) implemented in #150 |
Beta Was this translation helpful? Give feedback.
-
|
1D array support number 22, implemented in #156. |
Beta Was this translation helpful? Give feedback.
-
|
Statement/query timeout implemented in #178 |
Beta Was this translation helpful? Give feedback.
-
|
Connection timeout implemented in #179 |
Beta Was this translation helpful? Give feedback.
-
|
Item 28 (multi-host connection with failover) is demonstrated as a user-space pattern in |
Beta Was this translation helpful? Give feedback.
-
|
Cleartext password support added in #181 |
Beta Was this translation helpful? Give feedback.
-
Remaining Items — Driver Support SurveyResearch across the 8 surveyed drivers (pgx, tokio-postgres, sqlx, asyncpg, psycopg3, PgJDBC, node-postgres, Postgrex) for the 5 items that haven't been implemented yet:
DetailsComposite types (#23): PgJDBC and node-postgres are the two that don't — PgJDBC returns raw strings in Enum types (#24): Universal support, but depth varies significantly. tokio-postgres, sqlx, and psycopg3 offer rich compile-time or registration-based mapping between language enums and PostgreSQL enums. pgx and asyncpg provide runtime registration. PgJDBC, node-postgres, and Postgrex treat enum values as strings at the driver level and leave structured mapping to the application or ORM. SCRAM-SHA-256-PLUS (#25): sqlx detects the mechanism but has it hardcoded off (rustls only recently added the necessary API). asyncpg deliberately chose not to implement it (noted in a source comment). Postgrex has no implementation at all. The 5 that support it all use Automatic type OID discovery (#29): pgx had this in v3 but deliberately removed it in v4 for performance — now provides semi-manual Large object API (#30): Only pgx (Go's |
Beta Was this translation helpful? Give feedback.
-
Beta Was this translation helpful? Give feedback.
-
|
Item 24 (Enum type support) implemented in #186. Design: #185. |
Beta Was this translation helpful? Give feedback.
Uh oh!
There was an error while loading. Please reload this page.
Uh oh!
There was an error while loading. Please reload this page.
-
Research comparing the ponylang/postgres driver against the PostgreSQL wire protocol (v3) and popular PostgreSQL drivers from other languages (pgx for Go, tokio-postgres/sqlx for Rust, asyncpg/psycopg3 for Python, PgJDBC for Java, node-postgres for Node.js, Postgrex for Elixir).
Currently Supported
Tier 1 — Protocol Gaps / Table Stakes
Every mature driver has these.
1.
SSL/TLS negotiationSSLRequest + TLS handshake. The
ssldependency is already present (used for MD5 hashing) but not used for connection encryption. Every surveyed driver supports this.2.
SCRAM-SHA-256 authenticationThe modern default since PostgreSQL 10. MD5 is deprecated. All 8 surveyed drivers support SCRAM. The protocol involves a multi-step SASL exchange (SASLInitialResponse, SASLContinue, SASLFinal).
3.
Named prepared statementsAlready on the roadmap as next priority. Current implementation uses unnamed only. Named statements persist across queries, enabling prepared statement caching for repeated queries (7/8 drivers support this).
4.
Graceful terminationSend Terminate (
X) message before closing TCP. Currently the connection is hard-closed without notifying the server.5.
BackendKeyData handlingThe server sends process ID + secret key during startup. Currently silently consumed. Needed for query cancellation.
6.
Query cancellationCancelRequest on a separate TCP connection using the BackendKeyData. Supported by 6/8 drivers. Important for long-running queries.
7.
ParameterStatus trackingServer sends key-value pairs during startup and on changes (server_version, integer_datetimes, standard_conforming_strings, etc.). Currently silently consumed. Some values affect type encoding behavior.
8.
Close messageNever sent currently. Needed for named prepared statement cleanup and explicit portal destruction.
9.
Flush messageForce server output without Sync. Useful for getting Parse/Bind responses before sending Execute.
10.
NoticeResponse handlingInformational messages from the server (same format as ErrorResponse). Currently silently consumed. Should be surfaced to the user via a callback.
11.
Expanded type conversionsCurrently 7 types. High-value additions based on real-world usage:
numeric(1700) — arbitrary precision, no native Pony type, return as Stringdate(1082) — ISO format Stringtimestamp(1114) /timestamptz(1184) — ISO format Stringuuid(2950) — Stringjson(114) /jsonb(3802) — Stringbytea(17) — Array[U8] valinterval(1186) — Stringvarchar(1043) /bpchar(1042) — String (already handled by default, but explicit OID mapping is cleaner)Tier 2 — Important Features
5-6 out of 8 mature drivers have these.
12.
COPY IN protocolBulk data loading via
COPY ... FROM STDIN. Supported by 7/8 drivers. Orders of magnitude faster than individual INSERTs for bulk loads. Requires CopyInResponse, CopyData, CopyDone/CopyFail message handling.13.
COPY OUT protocolBulk data export via
COPY ... TO STDOUT. Requires CopyOutResponse, CopyData, CopyDone message handling.14.
LISTEN/NOTIFYAsynchronous notification support. All 8 drivers support this. Requires handling NotificationResponse messages that can arrive between any other messages. Needs a notification callback on Session or a separate listener interface.
15.
Portal-based cursors (partial result fetching)Execute with
max_rows > 0, handle PortalSuspended, re-Execute to continue. Currently max_rows is hardcoded to 0. Essential for large result sets (6/8 drivers).16.
Describe for statementsCurrently only Describe for portals. Statement describe returns ParameterDescription (input param types), which is useful for validating parameter types before binding.
17.
Transaction status trackingReadyForQuery includes
I/T/Estatus. Currently used only to determine query readiness (idle vs not). Exposing transaction status to the user enables better transaction management.18.
Row streamingCurrently all rows are buffered in memory before delivery. A streaming API would let users process rows as they arrive without buffering the full result set. Supported by 7/8 drivers.
19.
Custom type codec registryLet users register their own OID-to-Pony-type converters without modifying the driver. 7/8 drivers support this.
20.
PipeliningSend multiple Parse/Bind/Execute/Sync sequences without waiting for responses. Currently queries are strictly serialized. 3/8 drivers support this, but it's the most performance-focused ones (pgx, tokio-postgres, psycopg3).
Tier 3 — Nice to Have / Longer Term
21.
Binary format for parameters and resultsCurrently text-only. Binary is more efficient for numeric types (no parse/format overhead). 6/8 drivers support binary.
22.
Array type supportPostgreSQL arrays mapped to Pony arrays. Supported by all 8 drivers surveyed.
23.
Composite/record type supportPostgreSQL composite types mapped to structured Pony types.
24.
Enum type supportUser-defined PostgreSQL enums.25. SCRAM-SHA-256-PLUS (channel binding)
Binds authentication to TLS session, prevents MITM.
26.
Connection timeoutTimeout on TCP connection establishment.
27.
Statement/query timeoutServer-side or client-side timeout for long queries.
28.
Multi-host connection with failoverConnect to first available host from a list. Demonstrated as a user-space pattern in
examples/failover/rather than built into the driver.29. Automatic type OID discovery
Query
pg_typecatalog to handle custom/extension types dynamically.30. Large object API
For storing/retrieving large binary data via server-side lo_* functions.
31.
Cleartext password authenticationSimple but sometimes needed (e.g., behind SSL proxies).
API Improvements (not protocol features)
32.
Pass session to ResultReceiver callbacksAlready noted as TODO. Would let receivers execute follow-up queries.
33.
Equality on Rows/Row/FieldAlready noted as TODO. Needed for testing and programmatic comparison.
34.
Docstrings on all public typesSeveral public types lack documentation.
Beta Was this translation helpful? Give feedback.
All reactions