Closes#47015
## What kind of change does this PR introduce?
Bug fix.
## What is the current behavior?
The queue message list paginates with `WHERE enqueued_at > <last>` and
`ORDER BY enqueued_at`. `enqueued_at` is not unique: pgmq defaults it to
`now()`, so every message sent in one `send_batch` shares a timestamp.
When a group of same-timestamp messages straddles a page boundary, the
strict cursor skips the rest of that group, so those messages never
appear in the grid even though they are still in the queue. With 40
messages from one batch, only 30 render.
## What is the new behavior?
Pagination uses a composite `(enqueued_at, msg_id)` keyset cursor and
orders by the same pair. `msg_id` is unique within each queue/archive
table and breaks the tie, so no rows are dropped between pages. After
the change, all 40 messages render. This mirrors the cron-runs query,
which already paginates on a unique key.
## Additional context
Added a test in
`apps/studio/data/database-queues/database-queue-messages-infinite-query.test.ts`
asserting next pages use the composite cursor and order by `enqueued_at,
msg_id`.
<!-- This is an auto-generated comment: release notes by coderabbit.ai
-->
## Summary by CodeRabbit
* **Bug Fixes**
* Improved database queue message pagination to reliably retrieve all
messages, including those with identical enqueued timestamps, preventing
potential message skipping during pagination.
* **Tests**
* Added test coverage for database queue message pagination behavior.
<!-- end of auto-generated comment: release notes by coderabbit.ai -->
Co-authored-by: Ali Waseem <waseema393@gmail.com>
## Context
Just some clean up as I was going through stuff
- `useExecuteSqlQuery` is deprecated and not used at all
- As such `execute-sql-query` is technically irrelevant, the more
relevant file is `execute-sql-mutation`
- Hence opting to consolidate `execute-sql-query` into
`execute-sql-mutation`
- Also removing `ExecuteSqlError` since its just re-exporting the
`ResponseError` type
There's a lot of file changes but its essentially just updating the
importing statements across the files
## Summary
- Converts ~27 `executeSql` call sites in `apps/studio/data/**` to build
SQL through `safeSql` / `ident` / `literal` / `keyword` /
`joinSqlFragments` instead of raw template-string interpolation.
- Tightens the `useDatabaseCronJobCreateMutation` and
`useDatabaseEventTriggerCreateMutation` `sql`/`query` parameter types
from `string` to `SafeSqlFragment` (callers already produce one).
- Updates `getDeleteEnumeratedTypeSQL` in `packages/pg-meta` to return
`SafeSqlFragment`.
- Fixes a bug noticed while testing where Queues integration does not
correctly handle queues with uppercase names.
## Pages to manually test
- Integrations > Cron Jobs
- Integrations > Queues
- Database > Triggers > Event Triggers
- Database > Indexes
- Reports > Query Performance
- Storage
<!-- This is an auto-generated comment: release notes by coderabbit.ai
-->
## Summary by CodeRabbit
## Release Notes
* **Bug Fixes**
* Queue lookups now correctly handle case-insensitive queue names.
* Queue table references are now properly managed and consistently
applied throughout the queue management interface.
* Improved queue name display normalization in the user interface.
* **Chores**
* Enhanced SQL query safety across the database layer through
parameterized query construction and safer templating approaches.
<!-- end of auto-generated comment: release notes by coderabbit.ai -->
## What
Escapes user-controlled string values before interpolating them into SQL
in `apps/studio/data/database-queues/`.
## Why
Several queue message queries were constructing SQL via direct string
interpolation without sanitization:
| File | Value | Risk |
|------|-------|------|
| `database-queue-messages-send-mutation.ts` | `payload` | **High** —
arbitrary user-provided JSON; a single quote breaks the query and a
crafted payload could execute arbitrary SQL |
| `database-queue-messages-infinite-query.ts` | `afterTimestamp` |
Medium — sourced from a previous DB result, but still unsafe to
interpolate |
| `database-queue-messages-delete-mutation.ts` | `messageId` | Low —
typed `number`, but truncated for safety |
| `database-queue-messages-archive-mutation.ts` | `messageId` | Low —
same as above |
## Fix
- Escape string literals with the standard PostgreSQL approach (doubling
single quotes `'` → `''`) before interpolation
- Wrap numeric `messageId` values with `Math.trunc()` to prevent
floating-point edge cases
- `queueName` was already validated via `isQueueNameValid` regex
(alphanumeric/underscore/hyphen only) — no change needed
Fixes#44375
## Test plan
- [x] Open Queue Messages panel in Studio
- [x] Send a message with a payload containing single quotes (e.g.
`{"key": "it's a value"}`) — verify it sends without error
- [x] Verify pagination still works correctly after fix
<!-- This is an auto-generated comment: release notes by coderabbit.ai
-->
## Summary by CodeRabbit
* **Bug Fixes**
* Improved safety of queue operations by ensuring message IDs, payloads,
timestamps, and queue names are handled securely to prevent injection
and formatting issues.
* Normalized numeric message fields (IDs/delays) for consistent
processing.
* Increased stability and correctness of archive, delete, query, and
send operations; no public APIs were changed.
<!-- end of auto-generated comment: release notes by coderabbit.ai -->
Co-authored-by: Claude Sonnet 4.6 <noreply@anthropic.com>
## I have read the
[CONTRIBUTING.md](https://github.com/supabase/supabase/blob/master/CONTRIBUTING.md)
file.
YES
## What kind of change does this PR introduce?
Bug fix
## What is the current behavior?
The `getNextPageParam` function in
`database-queue-messages-infinite-query.ts` uses `<=` instead of `>=`,
which means pagination never stops. Since the result length is always
less than or equal to the page size, `hasNextPage` is always `true`,
causing infinite API requests when viewing queue messages in Studio.
Resolves#44291
## What is the new behavior?
Uses `>=` to correctly detect when there are more pages, consistent with
every other infinite query in the codebase:
- `database-cron-jobs-infinite-query.ts` uses `>=`
- `users-infinite-query.ts` uses `>=`
- `database-cron-jobs-runs-infinite-query.ts` uses `< PAGE_SIZE` to
return `undefined` (equivalent logic)
## Additional context
One character change: `<=` to `>=` on line 112.
* Bump the deps, refactor deprecated code.
* Migrate keepPreviousData usage.
* Migrate all uses of InfiniteQuery.
* Fix refetchInterval in queries.
* Migrate all use of isLoading to isPending in mutations.
* Fix accessing location in claim-project.
* Fix a bug in duplicate query keys.
* Migrate all queries to use isPending.
* Revert "Fix accessing location in claim-project."
This reverts commit 2a07df64b5.
* Revert the rss.xml file to master.
* fix: input validation for queue name
* grammar
* fix: whitespacing issue
* Reuse the validation logic for queue name.
* Reuse the query name schema in the create queue sheet.
---------
Co-authored-by: Ivan Vasilov <vasilov.ivan@gmail.com>
* Add custom types for queries, mutations and infinite queries.
* Migrate all queries to use the new type.
* Migrate all infinite queries to useCustomInfiniteQueryOptions.
* Migrate all mutations to use useCustomMutationOptions.
* Add type to all imports in `types` folder.
* Migrate all uses of invalidateQueries to use object syntax.
* Migrate the remainder of useInfiniteQuery.
* Migrate all setQueriesData.
* Migrate all fetchQuery uses.
* Migrate some leftover functions from RQ.
* Fix issues found by Charis.
* Make the title prop on ProjectIntegrationLayout mandatory. Fix the title on some of the integration pages. Fix wrong layout on wrappers/new.
* Add code for the initial page.
* Make the FilterPopover more type-safe.
* Add a page to list message in a single queue.
* Add feature flag for queues.
* Handle the case where pgmq is not available on the database.
* Minor fixes.
* Some minor fixes.
* Fix the query when fetching only archived messages.
* Fix the filters when there's no choices selected.
* Add a comment for local dev.
* Add a max size to the queue name input.