Skip to content

Add pipeline mode support for PostgreSQL 14+ (RFC)#182

Open
jjn1056 wants to merge 19 commits into
bucardo:masterfrom
jjn1056:pipeline-mode
Open

Add pipeline mode support for PostgreSQL 14+ (RFC)#182
jjn1056 wants to merge 19 commits into
bucardo:masterfrom
jjn1056:pipeline-mode

Conversation

@jjn1056
Copy link
Copy Markdown

@jjn1056 jjn1056 commented Mar 30, 2026

Working reference implementation of the pipeline mode API proposed in #181. See the issue for API rationale, open questions, and design alternatives.

Summary

  • 10 new $dbh methods wrapping libpq's pipeline API
  • Both ? and $1/$2 placeholder syntax supported via C-level converter
  • Compile-time gating (#if PGLIBVERSION >= 140000) — builds cleanly against older libpq, methods croak if called
  • COPY operations guarded against in pipeline mode
  • 109 tests covering lifecycle, queries, errors, prepared statements, flush, placeholder edge cases
  • Full author test suite passes (4,757 tests, AUTHOR_TESTING=1 RELEASE_TESTING=1)

This is an RFC to get a stake in the ground and start a conversation. The pipeline mode TODO item has been in the project for a while, and the public API here is a proposal. The code works and is well-tested, but we'd like maintainer input on the API design and approach before considering it final. See #181 for the full discussion.

Test plan

  • Enter/exit lifecycle and idempotency
  • Pipeline sync with result collection
  • INSERT/SELECT pipelines with data verification
  • Error handling: FATAL_ERROR -> PIPELINE_ABORTED -> recovery
  • Prepared statements in pipeline (PREPARE + EXECUTE)
  • Flush request without sync point
  • COPY guards (putcopydata/putcopyend/getcopydata croak)
  • Zero-row SELECT, NULL params, aborted status, consecutive syncs
  • ? placeholder conversion: basic, multiple, inside quotes/comments/dollar-quoting
  • $1 passthrough when already present
  • Large pipeline (100 queries)
  • Full author test suite with AUTHOR_TESTING=1 RELEASE_TESTING=1

🤖 Generated with Claude Code

jjn1056 and others added 16 commits March 29, 2026 20:12
Add DBDPG_HAS_PIPELINE compile-time define for PostgreSQL 14+,
trace macros for pipeline libpq functions, pipeline tracking field
in imp_dbh_st, and function declarations for all pipeline methods.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Create t/11pipeline.t with PG14+ version detection. Implement
pg_pipeline_status wrapping PQpipelineStatus — returns 0 (off),
1 (on), or 2 (aborted).

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Wrap PQenterPipelineMode and PQexitPipelineMode as $dbh methods.
Both are idempotent, croak if compiled without PG14+ support.
Tests cover enter, exit, idempotency, and post-pipeline query sanity.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
pg_pipeline_sync wraps PQpipelineSync — sends a sync point that
delimits an implicit transaction boundary.

pg_getresult wraps PQgetResult — returns a hashref with status,
error, ntuples, nfields, cmdtuples, and rows (for SELECT results),
or undef when no more results are available. This enables manual
pipeline result collection.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Wrap PQsendQueryParams for pipeline query submission with $1/$2
parameter syntax. Tests cover INSERT pipeline with data verification,
SELECT with row data extraction, and PIPELINE_ABORTED error flow
with recovery after sync point.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
…g_flush

pg_send_prepare wraps PQsendPrepare for pipelining PREPARE commands.
pg_send_query_prepared wraps PQsendQueryPrepared for executing prepared
statements in pipeline mode. pg_send_flush_request wraps PQsendFlushRequest
to retrieve results without a sync point. pg_flush wraps PQflush for
manual output buffer management.

Tests cover prepared statement pipeline (PREPARE + 2 EXECUTEs), and
flush request to retrieve results without a sync point.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Reject pg_putcopydata/pg_putcopyend in pipeline mode with clear croak.
Test exit_pipeline_mode failure with unconsumed results. Add multiple
pipeline sync cycles without exiting. Test 100-INSERT large pipeline
with result draining. Add dbd_pg_test_pipeline to cleanup list.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Document all pipeline methods in Pg.pm POD with examples and return
values. Fix spellcheck (nfields, ntuples, PQpipelineStatus), add
missing TRACE macros in pg_db_getresult, update MANIFEST and
README.dev for t/11pipeline.t.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Initialize imp_dbh->pipeline = 0 in dbd_db_login6 alongside other
fields. Remove unused D_imp_dbh from pg_getresult XS binding. Move
variable declarations inside #ifdef DBDPG_HAS_PIPELINE in send
functions to avoid unused variable warnings on PG < 14 builds.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Add standalone pg_flush POD section. Add pipeline mode to Changes
for v3.21.0. Document blocking mode deadlock risk for large pipelines.
Add pg_getcopydata pipeline guard matching putcopydata/putcopyend.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Test SELECT returning zero rows (no rows key in result), NULL/undef
parameter values, pg_pipeline_status == 2 during aborted state,
pg_flush return value, pg_send_query_params without params argument,
and two consecutive pipeline syncs without draining between them.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Use single-line entry format that the Changes file parser in
t/00_release.t can handle. Keep entry under current version.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Add Perl-side ? to $N conversion in pg_send_query_params so that
DBI-standard ? placeholders work alongside libpq-native $1/$2 syntax.
This enables compatibility with SQL generators like DBIx::Class that
produce ? placeholders exclusively.

The conversion is a simple regex that detects ? when no $N placeholders
are present. The XS functions are renamed to _pg_send_query_params and
_pg_send_query_prepared with Perl wrappers handling the conversion.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Add pg_convert_placeholders() static function in dbdimp.c that
converts DBI ? placeholders to libpq $N style while properly
skipping single-quoted strings, double-quoted identifiers,
dollar-quoted strings, and SQL comments. Follows the same skip
patterns as pg_st_split_statement for correctness.

Remove the Perl-side regex wrapper and revert XS function names
back to pg_send_query_params/pg_send_query_prepared.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Test that ? inside single-quoted strings, double-quoted identifiers,
dollar-quoted strings, line comments, and block comments is NOT
converted. Test multiple ? sequence ($1,$2,$3) and $1-present bypass.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Pass SV *dbh to pg_convert_placeholders so TRACE_PQPARAMETERSTATUS
works correctly. Rename seg_start to segment_start to avoid spellcheck
hit on 'seg'. Add edge case tests for ? inside quoted strings,
comments, dollar-quoting, multiple ? sequencing, and $1 bypass.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Comment thread Changes Outdated
Comment thread Pg.pm
jjn1056 and others added 3 commits April 9, 2026 15:58
The 3.20.0 version has already been released, so the pipeline mode
entry doesn't belong there. The entry will be added under the next
version when a release is prepared.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Explain that pg_getresult returns undef as a delimiter between each
query's results, and that callers must consume each separator. This
addresses reviewer feedback that the undef calls seemed unclear.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants