The withdrawal arm of the transaction search, as a view.
Assembled inline, the 12-arm transaction UNION serialises to ~124KB. RDS
Proxy refuses to parse a statement over 16KB and reacts by pinning the client
session to its database connection for the remainder of that session,
permanently costing the proxy a multiplexable connection. Behind a view the
runtime statement is ~90 bytes.
The caller-supplied filters live in
transaction-services/queries/withdrawal.ts as predicates on this view's own
projected columns, because a view takes no parameters. They are plain
contract-column comparisons emitted by the shared
transactionScalarConditions, so what matters here is what each filtered
column projects:
customer_id — t.customer_id on the main-debit, fee-debit and
return-credit sub-arms, fee_customer.external_id on the fee-credit
sub-arm.
signature — t.debit_signature on the main-debit and fee-debit sub-arms
(a fee debit has no receipt of its own, so it carries the parent
withdrawal's), t.fee_sweep_signature on the fee-credit sub-arm,
t.return_signature on the return-credit sub-arm.
bank_id — the coalesce() over the withdrawal's own and its bank
transaction's bank.
Changing what those three project silently changes the filters. The column
list must also stay identical to the sibling arms, or the UNION breaks.
securityInvoker is required, not cosmetic — every underlying table has RLS
enabled, and without it the view would run with the owner's row visibility
and silently bypass the querying role's policies.
The withdrawal arm of the transaction search, as a view.
Assembled inline, the 12-arm transaction UNION serialises to ~124KB. RDS Proxy refuses to parse a statement over 16KB and reacts by pinning the client session to its database connection for the remainder of that session, permanently costing the proxy a multiplexable connection. Behind a view the runtime statement is ~90 bytes.
The caller-supplied filters live in
transaction-services/queries/withdrawal.tsas predicates on this view's own projected columns, because a view takes no parameters. They are plain contract-column comparisons emitted by the sharedtransactionScalarConditions, so what matters here is what each filtered column projects:customer_id—t.customer_idon the main-debit, fee-debit and return-credit sub-arms,fee_customer.external_idon the fee-credit sub-arm.signature—t.debit_signatureon the main-debit and fee-debit sub-arms (a fee debit has no receipt of its own, so it carries the parent withdrawal's),t.fee_sweep_signatureon the fee-credit sub-arm,t.return_signatureon the return-credit sub-arm.bank_id— the coalesce() over the withdrawal's own and its bank transaction's bank.Changing what those three project silently changes the filters. The column list must also stay identical to the sibling arms, or the UNION breaks.
securityInvokeris required, not cosmetic — every underlying table has RLS enabled, and without it the view would run with the owner's row visibility and silently bypass the querying role's policies.