fix(list-queries): correct WHERE param numbering for count_query in 6 list_* methods #85

Merged
YousifShkara merged 1 commit from fix/list-count-query-param-mismatch into main 2026-06-05 07:27:43 +02:00
Owner

When any filter is present on these endpoints, the count query fails with postgres 42P18 ('could not determine data type of parameter $N'):

  • GET /api/v1/tickets with any filter (q, status_id, priority_id, queue_id, company_id, assigned_to_id)
  • GET /api/v1/contacts/companies with q/company_type/status/account_manager_id
  • GET /api/v1/contacts/contacts with q/company_id/contact_type/status
  • GET /api/v1/billing/invoices with company_id/status/contract_id/q
  • GET /api/v1/billing/payments with invoice_id/company_id

Cause: data_query and count_query shared one where_clause string. The data query had $1=tenant + $2=limit + $3=offset, so the WHERE clause numbered filter placeholders starting at $4. The count query had only $1=tenant + filters, but the shared where_clause still said $4 for the first filter. count_builder bound the filters at positions $2, $3, ... while the SQL referenced $4+, leaving those positional slots unbound and postgres unable to infer their types.

Reproduces in staging on a company detail page where the SPA hits GET /api/v1/tickets?company_id=...&per_page=5&sort=-updated_at. The contact_id path returns 200 by accident because TicketFilter has no contact_id field (the query string param is ignored) so the WHERE stays trivial.

Fix: build two parallel condition lists, one for the data query starting at $4 and one for the count query starting at $2. Same shape as the list_users fix in PMS-4 (commit 4d995d4). All 6 list methods get the same surgical treatment in this PR.

Verified: cargo check --tests + cargo clippy --tests -- -Dwarnings + cargo fmt --all --check all clean. Pattern is identical to the list_users fix that lands with 10/10 test coverage in tests/auth.rs; CI will exercise the full workspace test suite on PR.

Discovered while debugging staging deployment for PMS-4 (see PR #83 + #84). Latent in 5 of the 6 methods until a non-trivial filter is supplied at runtime.

When any filter is present on these endpoints, the count query fails with postgres 42P18 ('could not determine data type of parameter $N'): - GET /api/v1/tickets with any filter (q, status_id, priority_id, queue_id, company_id, assigned_to_id) - GET /api/v1/contacts/companies with q/company_type/status/account_manager_id - GET /api/v1/contacts/contacts with q/company_id/contact_type/status - GET /api/v1/billing/invoices with company_id/status/contract_id/q - GET /api/v1/billing/payments with invoice_id/company_id Cause: data_query and count_query shared one where_clause string. The data query had \$1=tenant + \$2=limit + \$3=offset, so the WHERE clause numbered filter placeholders starting at \$4. The count query had only \$1=tenant + filters, but the shared where_clause still said \$4 for the first filter. count_builder bound the filters at positions \$2, \$3, ... while the SQL referenced \$4+, leaving those positional slots unbound and postgres unable to infer their types. Reproduces in staging on a company detail page where the SPA hits GET /api/v1/tickets?company_id=...&per_page=5&sort=-updated_at. The contact_id path returns 200 by accident because TicketFilter has no contact_id field (the query string param is ignored) so the WHERE stays trivial. Fix: build two parallel condition lists, one for the data query starting at \$4 and one for the count query starting at \$2. Same shape as the list_users fix in PMS-4 (commit 4d995d4). All 6 list methods get the same surgical treatment in this PR. Verified: cargo check --tests + cargo clippy --tests -- -Dwarnings + cargo fmt --all --check all clean. Pattern is identical to the list_users fix that lands with 10/10 test coverage in tests/auth.rs; CI will exercise the full workspace test suite on PR. Discovered while debugging staging deployment for PMS-4 (see PR #83 + #84). Latent in 5 of the 6 methods until a non-trivial filter is supplied at runtime.
fix(list-queries): correct WHERE param numbering for count_query in 6 list_* methods
All checks were successful
Create release / Create release from merged PR (pull_request) Has been skipped
Check / fmt + clippy + compile + tests (pull_request) Successful in 1m28s
Build OCI container / Build and push mokosh-api image (push) Successful in 3m16s
6acbb23d3b
When any filter is present on these endpoints, the count query fails with postgres 42P18 ('could not determine data type of parameter $N'):

- GET /api/v1/tickets with any filter (q, status_id, priority_id, queue_id, company_id, assigned_to_id)
- GET /api/v1/contacts/companies with q/company_type/status/account_manager_id
- GET /api/v1/contacts/contacts with q/company_id/contact_type/status
- GET /api/v1/billing/invoices with company_id/status/contract_id/q
- GET /api/v1/billing/payments with invoice_id/company_id

Cause: data_query and count_query shared one where_clause string. The data query had \$1=tenant + \$2=limit + \$3=offset, so the WHERE clause numbered filter placeholders starting at \$4. The count query had only \$1=tenant + filters, but the shared where_clause still said \$4 for the first filter. count_builder bound the filters at positions \$2, \$3, ... while the SQL referenced \$4+, leaving those positional slots unbound and postgres unable to infer their types.

Reproduces in staging on a company detail page where the SPA hits GET /api/v1/tickets?company_id=...&per_page=5&sort=-updated_at. The contact_id path returns 200 by accident because TicketFilter has no contact_id field (the query string param is ignored) so the WHERE stays trivial.

Fix: build two parallel condition lists, one for the data query starting at \$4 and one for the count query starting at \$2. Same shape as the list_users fix in PMS-4 (commit 4d995d4). All 6 list methods get the same surgical treatment in this PR.

Verified: cargo check --tests + cargo clippy --tests -- -Dwarnings + cargo fmt --all --check all clean. Pattern is identical to the list_users fix that lands with 10/10 test coverage in tests/auth.rs; CI will exercise the full workspace test suite on PR.

Discovered while debugging staging deployment for PMS-4 (see PR #83 + #84). Latent in 5 of the 6 methods until a non-trivial filter is supplied at runtime.
YousifShkara deleted branch fix/list-count-query-param-mismatch 2026-06-05 07:27:43 +02:00
Sign in to join this conversation.
No reviewers
No labels
No milestone
No project
No assignees
1 participant
Notifications
Due date
The due date is invalid or out of range. Please use the format "yyyy-mm-dd".

No due date set.

Dependencies

No dependencies set

Reference
psa-systems/mokosh-server!85
No description provided.