Skip to content

step.db_exec: add returning mode to capture rows from RETURNING clause#300

Merged
intel352 merged 11 commits intomainfrom
copilot/support-returning-clause-insert-update
Mar 12, 2026
Merged

step.db_exec: add returning mode to capture rows from RETURNING clause#300
intel352 merged 11 commits intomainfrom
copilot/support-returning-clause-insert-update

Conversation

Copy link
Contributor

Copilot AI commented Mar 11, 2026

step.db_exec called db.Exec() unconditionally, discarding rows from PostgreSQL RETURNING clauses. The only workaround was semantically incorrect use of step.db_query for write operations.

Changes

  • DBExecStep: Added returning bool and mode string fields
  • Factory: Reads returning and mode from config; validates mode is "list" or "single" when returning: true (defaults to "list"); invalid values rejected at build time
  • Execute(): When returning: true, uses db.Query() and processes rows identically to step.db_querymode: single{row, found}, mode: list{rows, count}; ignore_error continues to work in both modes
  • Tests: Single mode, list mode (multi-row UPDATE…RETURNING), and invalid-mode factory rejection
  • Docs: Updated step.db_exec table entry

Usage

- name: insert
  type: step.db_exec
  config:
    database: db
    query: >
      INSERT INTO items (id, name)
      VALUES (gen_random_uuid(), $1)
      RETURNING id, name, created_at
    params: ["{{.steps.parse.body.name}}"]
    returning: true
    mode: single   # output: {row: {...}, found: true}
Original prompt

This section details on the original issue you should resolve

<issue_title>step.db_exec: support RETURNING clause for insert/update operations</issue_title>
<issue_description>## Problem

step.db_exec is designed for INSERT/UPDATE/DELETE operations that don't return rows. However, PostgreSQL's RETURNING clause allows these operations to return the affected rows — which is essential for getting auto-generated values (IDs, timestamps, computed columns) without a separate SELECT query.

Currently, to get values back from an INSERT, you must either:

  1. Use step.db_query instead of step.db_exec (works but semantically misleading — queries imply reads)
  2. Perform the INSERT with step.db_exec then follow up with a separate step.db_query SELECT to fetch the generated values

Option 1 actually works today (we use it), but option 2 introduces race conditions and unnecessary round-trips.

Use Case

Common patterns that need RETURNING:

-- Get the auto-generated UUID and timestamps after insert
INSERT INTO follow_up_prompts (id, affiliate_id, name, ...)
VALUES (gen_random_uuid(), $1, $2, ...)
RETURNING id, created_at, updated_at;

-- Get the previous status after an update (for audit/state machine logic)
UPDATE orders SET status = 'shipped', updated_at = NOW()
WHERE id = $1
RETURNING id, status, updated_at;

-- Soft delete and return the deleted row
DELETE FROM sessions WHERE id = $1
RETURNING *;

Proposed Solution

Option A: step.db_exec gains a returning mode

- name: insert
  type: step.db_exec
  config:
    database: db
    query: >
      INSERT INTO items (id, name) VALUES (gen_random_uuid(), $1)
      RETURNING id, name, created_at
    params: ["{{.steps.parse.body.name}}"]
    returning: true    # switches from Exec() to Query(), returns rows
    mode: single       # like step.db_query — "single" returns {row, found}

When returning: true, the step internally uses Query() instead of Exec() and makes the returned rows available in the pipeline context, just like step.db_query.

Option B: Officially document step.db_query for writes

If the engine already supports using step.db_query for INSERT...RETURNING (which it does — we use it in production), document this as the intended pattern and ensure mode: single works correctly with write queries. The main concern is whether step.db_query applies any read-only optimizations or transaction isolation that would be wrong for write operations.

Current Workaround

We use step.db_query with mode: single for INSERT...RETURNING, which works but is semantically confusing — code reviewers expect db_query to be read-only. The step name implies a pure read operation.</issue_description>

Comments on the Issue (you are @copilot in this section)


✨ Let Copilot coding agent set things up for you — coding agent works faster and does higher quality work when set up for your repo.

…g option

Co-authored-by: intel352 <77607+intel352@users.noreply.github.com>
Copilot AI changed the title [WIP] Add support for RETURNING clause in step.db_exec step.db_exec: add returning mode to capture rows from RETURNING clause Mar 11, 2026
@intel352 intel352 marked this pull request as ready for review March 12, 2026 00:02
Copilot AI review requested due to automatic review settings March 12, 2026 00:02
Copy link
Contributor

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Adds an opt-in returning mode to step.db_exec so INSERT/UPDATE/DELETE statements that include a PostgreSQL-style RETURNING clause can return rows (avoiding the current workaround of using step.db_query for write operations).

Changes:

  • Extend DBExecStep + factory config parsing to support returning: true and mode: list|single (validated at build time).
  • Update DBExecStep.Execute() to use Query() and return rows/count or row/found outputs when returning is enabled.
  • Add tests for returning single/list behavior and invalid-mode rejection; update docs entry for step.db_exec.

Reviewed changes

Copilot reviewed 3 out of 3 changed files in this pull request and generated 4 comments.

File Description
module/pipeline_step_db_exec.go Adds returning + mode config and implements row-returning execution path via Query() with db_query-like outputs.
module/pipeline_step_db_exec_test.go Adds unit tests covering returning single/list modes and factory-time invalid mode validation.
DOCUMENTATION.md Documents step.db_exec support for returning: true with mode.

@intel352
Copy link
Contributor

@copilot apply changes based on the comments in this thread

Build failing, lint failing, tests failing, config validation failing

@github-actions
Copy link

github-actions bot commented Mar 12, 2026

⏱ Benchmark Results

No significant performance regressions detected.

benchstat comparison (baseline → PR)
## benchstat: baseline → PR
baseline-bench.txt:244: parsing iteration count: invalid syntax
baseline-bench.txt:312344: parsing iteration count: invalid syntax
baseline-bench.txt:639696: parsing iteration count: invalid syntax
baseline-bench.txt:934498: parsing iteration count: invalid syntax
baseline-bench.txt:1231892: parsing iteration count: invalid syntax
baseline-bench.txt:1537767: parsing iteration count: invalid syntax
benchmark-results.txt:244: parsing iteration count: invalid syntax
benchmark-results.txt:318629: parsing iteration count: invalid syntax
benchmark-results.txt:608985: parsing iteration count: invalid syntax
benchmark-results.txt:886855: parsing iteration count: invalid syntax
benchmark-results.txt:1189721: parsing iteration count: invalid syntax
benchmark-results.txt:1489650: parsing iteration count: invalid syntax
goos: linux
goarch: amd64
pkg: github.com/GoCodeAlone/workflow/dynamic
cpu: AMD EPYC 7763 64-Core Processor                
                            │ baseline-bench.txt │
                            │       sec/op       │
InterpreterCreation-4               7.651m ± 55%
ComponentLoad-4                     3.784m ±  3%
ComponentExecute-4                  2.066µ ±  1%
PoolContention/workers-1-4          1.135µ ±  3%
PoolContention/workers-2-4          1.148µ ±  1%
PoolContention/workers-4-4          1.148µ ±  1%
PoolContention/workers-8-4          1.141µ ±  2%
PoolContention/workers-16-4         1.134µ ±  2%
ComponentLifecycle-4                3.744m ±  3%
SourceValidation-4                  2.337µ ±  2%
RegistryConcurrent-4                770.2n ±  4%
LoaderLoadFromString-4              3.584m ±  1%
geomean                             19.37µ

                            │ baseline-bench.txt │
                            │        B/op        │
InterpreterCreation-4               1.944Mi ± 0%
ComponentLoad-4                     2.097Mi ± 0%
ComponentExecute-4                  1.203Ki ± 0%
PoolContention/workers-1-4          1.203Ki ± 0%
PoolContention/workers-2-4          1.203Ki ± 0%
PoolContention/workers-4-4          1.203Ki ± 0%
PoolContention/workers-8-4          1.203Ki ± 0%
PoolContention/workers-16-4         1.203Ki ± 0%
ComponentLifecycle-4                2.099Mi ± 0%
SourceValidation-4                  1.984Ki ± 0%
RegistryConcurrent-4                1.133Ki ± 0%
LoaderLoadFromString-4              2.099Mi ± 0%
geomean                             15.05Ki

                            │ baseline-bench.txt │
                            │     allocs/op      │
InterpreterCreation-4                15.09k ± 0%
ComponentLoad-4                      17.43k ± 0%
ComponentExecute-4                    25.00 ± 0%
PoolContention/workers-1-4            25.00 ± 0%
PoolContention/workers-2-4            25.00 ± 0%
PoolContention/workers-4-4            25.00 ± 0%
PoolContention/workers-8-4            25.00 ± 0%
PoolContention/workers-16-4           25.00 ± 0%
ComponentLifecycle-4                 17.48k ± 0%
SourceValidation-4                    32.00 ± 0%
RegistryConcurrent-4                  2.000 ± 0%
LoaderLoadFromString-4               17.47k ± 0%
geomean                               181.2

cpu: AMD EPYC 9V74 80-Core Processor                
                            │ benchmark-results.txt │
                            │        sec/op         │
InterpreterCreation-4                  5.962m ± 69%
ComponentLoad-4                        3.441m ±  1%
ComponentExecute-4                     1.949µ ±  0%
PoolContention/workers-1-4             1.047µ ±  5%
PoolContention/workers-2-4             1.047µ ±  1%
PoolContention/workers-4-4             1.044µ ±  1%
PoolContention/workers-8-4             1.052µ ±  1%
PoolContention/workers-16-4            1.056µ ±  2%
ComponentLifecycle-4                   3.449m ±  0%
SourceValidation-4                     2.133µ ±  1%
RegistryConcurrent-4                   834.0n ±  3%
LoaderLoadFromString-4                 3.505m ±  1%
geomean                                17.91µ

                            │ benchmark-results.txt │
                            │         B/op          │
InterpreterCreation-4                  1.944Mi ± 0%
ComponentLoad-4                        2.097Mi ± 0%
ComponentExecute-4                     1.203Ki ± 0%
PoolContention/workers-1-4             1.203Ki ± 0%
PoolContention/workers-2-4             1.203Ki ± 0%
PoolContention/workers-4-4             1.203Ki ± 0%
PoolContention/workers-8-4             1.203Ki ± 0%
PoolContention/workers-16-4            1.203Ki ± 0%
ComponentLifecycle-4                   2.099Mi ± 0%
SourceValidation-4                     1.984Ki ± 0%
RegistryConcurrent-4                   1.133Ki ± 0%
LoaderLoadFromString-4                 2.099Mi ± 0%
geomean                                15.05Ki

                            │ benchmark-results.txt │
                            │       allocs/op       │
InterpreterCreation-4                   15.09k ± 0%
ComponentLoad-4                         17.43k ± 0%
ComponentExecute-4                       25.00 ± 0%
PoolContention/workers-1-4               25.00 ± 0%
PoolContention/workers-2-4               25.00 ± 0%
PoolContention/workers-4-4               25.00 ± 0%
PoolContention/workers-8-4               25.00 ± 0%
PoolContention/workers-16-4              25.00 ± 0%
ComponentLifecycle-4                    17.48k ± 0%
SourceValidation-4                       32.00 ± 0%
RegistryConcurrent-4                     2.000 ± 0%
LoaderLoadFromString-4                  17.47k ± 0%
geomean                                  181.2

pkg: github.com/GoCodeAlone/workflow/middleware
cpu: AMD EPYC 7763 64-Core Processor                
                                  │ baseline-bench.txt │
                                  │       sec/op       │
CircuitBreakerDetection-4                  286.1n ± 4%
CircuitBreakerExecution_Success-4          22.54n ± 1%
CircuitBreakerExecution_Failure-4          65.33n ± 0%
geomean                                    74.96n

                                  │ baseline-bench.txt │
                                  │        B/op        │
CircuitBreakerDetection-4                 144.0 ± 0%
CircuitBreakerExecution_Success-4         0.000 ± 0%
CircuitBreakerExecution_Failure-4         0.000 ± 0%
geomean                                              ¹
¹ summaries must be >0 to compute geomean

                                  │ baseline-bench.txt │
                                  │     allocs/op      │
CircuitBreakerDetection-4                 1.000 ± 0%
CircuitBreakerExecution_Success-4         0.000 ± 0%
CircuitBreakerExecution_Failure-4         0.000 ± 0%
geomean                                              ¹
¹ summaries must be >0 to compute geomean

cpu: AMD EPYC 9V74 80-Core Processor                
                                  │ benchmark-results.txt │
                                  │        sec/op         │
CircuitBreakerDetection-4                     299.0n ± 9%
CircuitBreakerExecution_Success-4             22.69n ± 2%
CircuitBreakerExecution_Failure-4             70.42n ± 1%
geomean                                       78.17n

                                  │ benchmark-results.txt │
                                  │         B/op          │
CircuitBreakerDetection-4                    144.0 ± 0%
CircuitBreakerExecution_Success-4            0.000 ± 0%
CircuitBreakerExecution_Failure-4            0.000 ± 0%
geomean                                                 ¹
¹ summaries must be >0 to compute geomean

                                  │ benchmark-results.txt │
                                  │       allocs/op       │
CircuitBreakerDetection-4                    1.000 ± 0%
CircuitBreakerExecution_Success-4            0.000 ± 0%
CircuitBreakerExecution_Failure-4            0.000 ± 0%
geomean                                                 ¹
¹ summaries must be >0 to compute geomean

pkg: github.com/GoCodeAlone/workflow/module
cpu: AMD EPYC 7763 64-Core Processor                
                                 │ baseline-bench.txt │
                                 │       sec/op       │
JQTransform_Simple-4                     906.3n ± 30%
JQTransform_ObjectConstruction-4         1.473µ ±  1%
JQTransform_ArraySelect-4                3.411µ ±  1%
JQTransform_Complex-4                    39.12µ ±  1%
JQTransform_Throughput-4                 1.817µ ±  1%
SSEPublishDelivery-4                     66.45n ±  1%
geomean                                  1.668µ

                                 │ baseline-bench.txt │
                                 │        B/op        │
JQTransform_Simple-4                   1.273Ki ± 0%
JQTransform_ObjectConstruction-4       1.773Ki ± 0%
JQTransform_ArraySelect-4              2.625Ki ± 0%
JQTransform_Complex-4                  16.22Ki ± 0%
JQTransform_Throughput-4               1.984Ki ± 0%
SSEPublishDelivery-4                     0.000 ± 0%
geomean                                             ¹
¹ summaries must be >0 to compute geomean

                                 │ baseline-bench.txt │
                                 │     allocs/op      │
JQTransform_Simple-4                     10.00 ± 0%
JQTransform_ObjectConstruction-4         15.00 ± 0%
JQTransform_ArraySelect-4                30.00 ± 0%
JQTransform_Complex-4                    324.0 ± 0%
JQTransform_Throughput-4                 17.00 ± 0%
SSEPublishDelivery-4                     0.000 ± 0%
geomean                                             ¹
¹ summaries must be >0 to compute geomean

cpu: AMD EPYC 9V74 80-Core Processor                
                                 │ benchmark-results.txt │
                                 │        sec/op         │
JQTransform_Simple-4                        833.2n ± 32%
JQTransform_ObjectConstruction-4            1.409µ ±  1%
JQTransform_ArraySelect-4                   3.363µ ±  1%
JQTransform_Complex-4                       40.33µ ±  2%
JQTransform_Throughput-4                    1.732µ ±  1%
SSEPublishDelivery-4                        57.23n ±  1%
geomean                                     1.584µ

                                 │ benchmark-results.txt │
                                 │         B/op          │
JQTransform_Simple-4                      1.273Ki ± 0%
JQTransform_ObjectConstruction-4          1.773Ki ± 0%
JQTransform_ArraySelect-4                 2.625Ki ± 0%
JQTransform_Complex-4                     16.22Ki ± 0%
JQTransform_Throughput-4                  1.984Ki ± 0%
SSEPublishDelivery-4                        0.000 ± 0%
geomean                                                ¹
¹ summaries must be >0 to compute geomean

                                 │ benchmark-results.txt │
                                 │       allocs/op       │
JQTransform_Simple-4                        10.00 ± 0%
JQTransform_ObjectConstruction-4            15.00 ± 0%
JQTransform_ArraySelect-4                   30.00 ± 0%
JQTransform_Complex-4                       324.0 ± 0%
JQTransform_Throughput-4                    17.00 ± 0%
SSEPublishDelivery-4                        0.000 ± 0%
geomean                                                ¹
¹ summaries must be >0 to compute geomean

pkg: github.com/GoCodeAlone/workflow/schema
cpu: AMD EPYC 7763 64-Core Processor                
                                    │ baseline-bench.txt │
                                    │       sec/op       │
SchemaValidation_Simple-4                    1.113µ ± 3%
SchemaValidation_AllFields-4                 1.695µ ± 1%
SchemaValidation_FormatValidation-4          1.614µ ± 2%
SchemaValidation_ManySchemas-4               1.811µ ± 4%
geomean                                      1.532µ

                                    │ baseline-bench.txt │
                                    │        B/op        │
SchemaValidation_Simple-4                   0.000 ± 0%
SchemaValidation_AllFields-4                0.000 ± 0%
SchemaValidation_FormatValidation-4         0.000 ± 0%
SchemaValidation_ManySchemas-4              0.000 ± 0%
geomean                                                ¹
¹ summaries must be >0 to compute geomean

                                    │ baseline-bench.txt │
                                    │     allocs/op      │
SchemaValidation_Simple-4                   0.000 ± 0%
SchemaValidation_AllFields-4                0.000 ± 0%
SchemaValidation_FormatValidation-4         0.000 ± 0%
SchemaValidation_ManySchemas-4              0.000 ± 0%
geomean                                                ¹
¹ summaries must be >0 to compute geomean

cpu: AMD EPYC 9V74 80-Core Processor                
                                    │ benchmark-results.txt │
                                    │        sec/op         │
SchemaValidation_Simple-4                       1.079µ ± 5%
SchemaValidation_AllFields-4                    1.628µ ± 3%
SchemaValidation_FormatValidation-4             1.579µ ± 2%
SchemaValidation_ManySchemas-4                  1.583µ ± 1%
geomean                                         1.447µ

                                    │ benchmark-results.txt │
                                    │         B/op          │
SchemaValidation_Simple-4                      0.000 ± 0%
SchemaValidation_AllFields-4                   0.000 ± 0%
SchemaValidation_FormatValidation-4            0.000 ± 0%
SchemaValidation_ManySchemas-4                 0.000 ± 0%
geomean                                                   ¹
¹ summaries must be >0 to compute geomean

                                    │ benchmark-results.txt │
                                    │       allocs/op       │
SchemaValidation_Simple-4                      0.000 ± 0%
SchemaValidation_AllFields-4                   0.000 ± 0%
SchemaValidation_FormatValidation-4            0.000 ± 0%
SchemaValidation_ManySchemas-4                 0.000 ± 0%
geomean                                                   ¹
¹ summaries must be >0 to compute geomean

pkg: github.com/GoCodeAlone/workflow/store
cpu: AMD EPYC 7763 64-Core Processor                
                                   │ baseline-bench.txt │
                                   │       sec/op       │
EventStoreAppend_InMemory-4                1.242µ ± 26%
EventStoreAppend_SQLite-4                  1.864m ±  5%
GetTimeline_InMemory/events-10-4           14.71µ ±  3%
GetTimeline_InMemory/events-50-4           72.25µ ± 14%
GetTimeline_InMemory/events-100-4          128.2µ ±  2%
GetTimeline_InMemory/events-500-4          652.5µ ±  1%
GetTimeline_InMemory/events-1000-4         1.346m ±  3%
GetTimeline_SQLite/events-10-4             113.5µ ±  2%
GetTimeline_SQLite/events-50-4             257.0µ ±  2%
GetTimeline_SQLite/events-100-4            439.2µ ±  1%
GetTimeline_SQLite/events-500-4            1.854m ±  2%
GetTimeline_SQLite/events-1000-4           3.717m ±  3%
geomean                                    232.1µ

                                   │ baseline-bench.txt │
                                   │        B/op        │
EventStoreAppend_InMemory-4                  756.5 ± 9%
EventStoreAppend_SQLite-4                  1.984Ki ± 2%
GetTimeline_InMemory/events-10-4           7.953Ki ± 0%
GetTimeline_InMemory/events-50-4           46.62Ki ± 0%
GetTimeline_InMemory/events-100-4          94.48Ki ± 0%
GetTimeline_InMemory/events-500-4          472.8Ki ± 0%
GetTimeline_InMemory/events-1000-4         944.3Ki ± 0%
GetTimeline_SQLite/events-10-4             16.74Ki ± 0%
GetTimeline_SQLite/events-50-4             87.14Ki ± 0%
GetTimeline_SQLite/events-100-4            175.4Ki ± 0%
GetTimeline_SQLite/events-500-4            846.1Ki ± 0%
GetTimeline_SQLite/events-1000-4           1.639Mi ± 0%
geomean                                    67.10Ki

                                   │ baseline-bench.txt │
                                   │     allocs/op      │
EventStoreAppend_InMemory-4                  7.000 ± 0%
EventStoreAppend_SQLite-4                    53.00 ± 0%
GetTimeline_InMemory/events-10-4             125.0 ± 0%
GetTimeline_InMemory/events-50-4             653.0 ± 0%
GetTimeline_InMemory/events-100-4           1.306k ± 0%
GetTimeline_InMemory/events-500-4           6.514k ± 0%
GetTimeline_InMemory/events-1000-4          13.02k ± 0%
GetTimeline_SQLite/events-10-4               382.0 ± 0%
GetTimeline_SQLite/events-50-4              1.852k ± 0%
GetTimeline_SQLite/events-100-4             3.681k ± 0%
GetTimeline_SQLite/events-500-4             18.54k ± 0%
GetTimeline_SQLite/events-1000-4            37.29k ± 0%
geomean                                     1.162k

cpu: AMD EPYC 9V74 80-Core Processor                
                                   │ benchmark-results.txt │
                                   │        sec/op         │
EventStoreAppend_InMemory-4                   1.230µ ± 22%
EventStoreAppend_SQLite-4                     1.101m ±  3%
GetTimeline_InMemory/events-10-4              12.66µ ±  3%
GetTimeline_InMemory/events-50-4              56.23µ ± 24%
GetTimeline_InMemory/events-100-4             112.8µ ±  1%
GetTimeline_InMemory/events-500-4             574.9µ ±  1%
GetTimeline_InMemory/events-1000-4            1.167m ±  1%
GetTimeline_SQLite/events-10-4                97.80µ ±  1%
GetTimeline_SQLite/events-50-4                236.7µ ±  1%
GetTimeline_SQLite/events-100-4               394.0µ ±  2%
GetTimeline_SQLite/events-500-4               1.693m ±  0%
GetTimeline_SQLite/events-1000-4              3.277m ±  0%
geomean                                       198.3µ

                                   │ benchmark-results.txt │
                                   │         B/op          │
EventStoreAppend_InMemory-4                     775.5 ± 7%
EventStoreAppend_SQLite-4                     1.983Ki ± 2%
GetTimeline_InMemory/events-10-4              7.953Ki ± 0%
GetTimeline_InMemory/events-50-4              46.62Ki ± 0%
GetTimeline_InMemory/events-100-4             94.48Ki ± 0%
GetTimeline_InMemory/events-500-4             472.8Ki ± 0%
GetTimeline_InMemory/events-1000-4            944.3Ki ± 0%
GetTimeline_SQLite/events-10-4                16.74Ki ± 0%
GetTimeline_SQLite/events-50-4                87.14Ki ± 0%
GetTimeline_SQLite/events-100-4               175.4Ki ± 0%
GetTimeline_SQLite/events-500-4               846.1Ki ± 0%
GetTimeline_SQLite/events-1000-4              1.639Mi ± 0%
geomean                                       67.24Ki

                                   │ benchmark-results.txt │
                                   │       allocs/op       │
EventStoreAppend_InMemory-4                     7.000 ± 0%
EventStoreAppend_SQLite-4                       53.00 ± 0%
GetTimeline_InMemory/events-10-4                125.0 ± 0%
GetTimeline_InMemory/events-50-4                653.0 ± 0%
GetTimeline_InMemory/events-100-4              1.306k ± 0%
GetTimeline_InMemory/events-500-4              6.514k ± 0%
GetTimeline_InMemory/events-1000-4             13.02k ± 0%
GetTimeline_SQLite/events-10-4                  382.0 ± 0%
GetTimeline_SQLite/events-50-4                 1.852k ± 0%
GetTimeline_SQLite/events-100-4                3.681k ± 0%
GetTimeline_SQLite/events-500-4                18.54k ± 0%
GetTimeline_SQLite/events-1000-4               37.29k ± 0%
geomean                                        1.162k

Benchmarks run with go test -bench=. -benchmem -count=6.
Regressions ≥ 20% are flagged. Results compared via benchstat.

…ix error message and docs markdown

Co-authored-by: intel352 <77607+intel352@users.noreply.github.com>
Copy link
Contributor Author

Copilot AI commented Mar 12, 2026

@copilot apply changes based on the comments in this thread

Build failing, lint failing, tests fai...

Addressed all review feedback in commit 6226635:

  • QueryContext/ExecContext: Both the returning path and the standard exec path now propagate context cancellations/timeouts.
  • Shared helper: Extracted scanSQLRows + formatQueryOutput into pipeline_step_db_helpers.go; both db_exec and db_query now use them, eliminating the duplication.
  • Error message: "exec failed""query failed" in the returning path.
  • Docs markdown: Fixed mode: single\|listmode: single or mode: list.
  • go mod tidy: Ran to resolve the build/validate CI failures.

@intel352
Copy link
Contributor

@copilot Look at the changes that happened in main, vs our branch, and intelligently resolve the conflict while preserving intent of both sets of changes.

…NBytesOrString into scanSQLRows helper

Co-authored-by: intel352 <77607+intel352@users.noreply.github.com>
Copy link
Contributor Author

Copilot AI commented Mar 12, 2026

@copilot Look at the changes that happened in main, vs our branch, and intelligently resolve the conflict while preserving intent of both sets of changes.

Merged in commit 02181b4. There was a single conflict in module/pipeline_step_db_query.go:

  • Main (006b368) updated the inline scan loop to use parseJSONBytesOrString(b) for proper PostgreSQL json/jsonb handling.
  • Our branch replaced that inline loop with the shared scanSQLRows() helper + QueryContext.

Resolution: kept our shared-helper + QueryContext approach and updated scanSQLRows() in pipeline_step_db_helpers.go to call parseJSONBytesOrString(b) instead of string(b) — so both db_query and db_exec's RETURNING path now benefit from the json/jsonb fix. All other changes from main (cors, partitioned db lifecycle hooks, auth.m2m trusted keys, step.json_parse) merged cleanly.

@intel352
Copy link
Contributor

@copilot Address the build, lint, test, config validation failures

…tion in pipeline_step_db_query.go

Co-authored-by: intel352 <77607+intel352@users.noreply.github.com>
Copy link
Contributor Author

Copilot AI commented Mar 12, 2026

@copilot Address the build, lint, test, config validation failures

Fixed in commit c492869. The previous conflict resolution left 49 lines of main's inline scan loop (lines 181–229) in pipeline_step_db_query.go after our scanSQLRows() call, causing redeclaration errors and a type mismatch on the return. Removed the dead code — build, lint, tests, and wfctl validate all pass clean now.

@intel352
Copy link
Contributor

@copilot Address the incoming conflict. The documentation section that is conflicted added a new column to it's table and the docs have been reordered. accept the incoming format and make sure any additions you're introducing are intelligently reflected.

…in format, add returning clause to step.db_exec entry

Co-authored-by: intel352 <77607+intel352@users.noreply.github.com>
Copy link
Contributor Author

Copilot AI commented Mar 12, 2026

@copilot Address the incoming conflict. The documentation section that is conflicted added a new column to it's table and the docs have been reordered. accept the incoming format and...

Resolved in commit a8770f2. Accepted main's format (3-column table with Plugin column) for the Pipeline Steps section, and updated the step.db_exec entry to include the returning clause documentation in the new format:

| `step.db_exec` | Executes parameterized SQL INSERT/UPDATE/DELETE against a named database. Supports `returning: true` with `mode: single` or `mode: list` to capture rows from a `RETURNING` clause | pipelinesteps |

All the additional steps and sections added in main (CI/CD, Platform, etc.) are preserved.

@intel352 intel352 merged commit 53ec135 into main Mar 12, 2026
11 checks passed
@intel352 intel352 deleted the copilot/support-returning-clause-insert-update branch March 12, 2026 10:54
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.

step.db_exec: support RETURNING clause for insert/update operations

3 participants