Skip to content

fix(cleanup): pass array values as scalar binds, incompatible with fetch_types false - #6035

Merged
TheodoreSpeaks merged 1 commit into
stagingfrom
fix/prune-workspace-ids-in-list
Jul 29, 2026
Merged

fix(cleanup): pass array values as scalar binds, incompatible with fetch_types false#6035
TheodoreSpeaks merged 1 commit into
stagingfrom
fix/prune-workspace-ids-in-list

Conversation

@TheodoreSpeaks

Copy link
Copy Markdown
Collaborator

Summary

  • fix(cleanup): bind array params as arrays, not expanded value lists #6010 is deployed (v20260728.21) and the prune queries still fail with 22P02 Array value must start with "{". My fix there used sql.param(arr), which binds the array as a single parameter — and that is incompatible with the shared client config
  • packages/db/db.ts sets fetch_types: false, which skips the pg_catalog.pg_type roundtrip. That roundtrip is what builds postgres.js's array serializers, so an array parameter can no longer be encoded and Postgres rejects it. Scalar params are unaffected
  • Reproduced exactly: with fetch_types: true both forms work; with fetch_types: false, sql.param(arr) fails and an IN list of scalars succeeds
  • Switched the 3 workspaceIds sites to workspace_id IN ${workspaceIds} (scalar binds only) and added an explicit empty guard to each prune helper, since IN () is a syntax error
  • Switched the webhook-polling key removal to ARRAY[$1, $2]::text[] built from scalar binds — the jsonb - operator needs a real array operand, so it can't use IN

The db.ts docstring says "writes never reach the array serializer because Drizzle serializes arrays before binding". That holds for drizzle-typed columns, but not for a raw sql template binding an array — which is exactly this path.

Type of Change

  • Bug fix

Testing

  • prune-metadata-sql.test.ts now renders the real prune statements and asserts an IN list plus no array parameter at all; covers single and multiple ids, and still rejects the = IN and ANY((...)) forms
  • Rendered the real statements from the shipped code: all 3 emit workspace_id IN ($1) with 0 array params
  • EXPLAINed all 3 real statements against staging through the cleanup bouncer with fetch_types: false — the exact deployed combination that fails today: 3 planned OK, 0 failed
  • 115 tests across payloads + webhooks/polling pass; tsc --noEmit clean; lint and the full audit suite pass

Checklist

  • Code follows project style guidelines
  • Self-reviewed my changes
  • Tests added/updated and passing
  • No new warnings introduced
  • I confirm that I have read and agree to the terms outlined in the Contributor License Agreement (CLA)

@vercel

vercel Bot commented Jul 29, 2026

Copy link
Copy Markdown

The latest updates on your projects. Learn more about Vercel for GitHub.

1 Skipped Deployment
Project Deployment Actions Updated (UTC)
docs Skipped Skipped Jul 29, 2026 12:41am

Request Review

@cursor

cursor Bot commented Jul 29, 2026

Copy link
Copy Markdown

PR Summary

Medium Risk
Touches cleanup DELETE paths and atomic webhook JSON merges; wrong SQL binding would break pruning or corrupt provider config, but changes are narrowly scoped to parameter encoding with added regression tests.

Overview
Fixes 22P02 failures on large-value metadata prune jobs and webhook config updates when the DB client runs with fetch_types: false, which prevents postgres.js from serializing array bind parameters.

The three prune DELETE helpers now filter with workspace_id IN … using only scalar binds (replacing ANY($n::text[]) / sql.param array forms), and each helper returns early when workspaceIds is empty so IN () never runs. Webhook provider_config key removal builds ARRAY[$1, …]::text[] via sql.join on per-key scalar binds instead of binding the whole removedKeys array.

prune-metadata-sql.test.ts now asserts rendered SQL uses an IN list, rejects broken ANY((…)) / = IN shapes, and that no parameter is a JS array; webhook polling tests expect scalar 'cleared' in interpolated values and mock sql.join.

Reviewed by Cursor Bugbot for commit 47e9621. Bugbot is set up for automated code reviews on this repo. Configure here.

@greptile-apps

greptile-apps Bot commented Jul 29, 2026

Copy link
Copy Markdown
Contributor

Greptile Summary

Fixes prune/webhook SQL that still failed under fetch_types: false by binding only scalars.

  • Three large-value prune helpers use workspace_id IN ${workspaceIds} (scalar params) plus empty-list guards instead of ANY(sql.param(...)::text[]).
  • Webhook provider-config key removal builds ARRAY[$n, ...]::text[] via sql.join of scalar binds for jsonb -.
  • Prune SQL tests assert IN ($…) shape and that no param is an array; polling tests expect scalar removed keys.

Confidence Score: 5/5

Safe to merge; the binding fix matches the deployed client constraint and is covered by render-level tests for the prune path.

Scalar IN lists and ARRAY[scalar…] construction avoid the 22P02 array-parameter path under fetch_types: false; empty IN is guarded; webhook pattern aligns with production sql.join ARRAY usage.

Important Files Changed

Filename Overview
apps/sim/lib/execution/payloads/large-value-metadata.ts Empty guards plus IN-list scalar binds avoid postgres.js array serialization when fetch_types is false.
apps/sim/lib/execution/payloads/prune-metadata-sql.test.ts Dialect render tests require workspace_id IN ($n…) and forbid array params and bad ANY/IN forms.
apps/sim/lib/webhooks/polling/utils.ts jsonb key removal uses ARRAY of scalar binds via sql.join, matching existing table dispatcher pattern.
apps/sim/lib/webhooks/polling/utils.test.ts Mock updated for sql.join; asserts scalar removed key value rather than a whole array param.

Reviews (1): Last reviewed commit: "fix(cleanup): pass array values as scala..." | Re-trigger Greptile

@TheodoreSpeaks
TheodoreSpeaks merged commit b57cd58 into staging Jul 29, 2026
20 checks passed
@TheodoreSpeaks
TheodoreSpeaks deleted the fix/prune-workspace-ids-in-list branch July 29, 2026 02:11
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.

1 participant