ash-project / ash-project/ash_postgres
Find a cleaner solution for the return_skipped_upsert? logic introduced in #626
- Dominant language
- Elixir
- Stars
- 189
- Forks
- 168
- Avg merge
- 13h 1m
- Merged PRs (30d)
- 22
Description
### Code of Conduct
- [x] I agree to follow this project's Code of Conduct
### AI Policy
- [x] I agree to follow this project's AI Policy, or I agree that AI was not used while creating this issue.
### Is your feature request related to a problem? Please describe.
https://github.com/ash-project/ash_postgres/pull/626 adds support for returning skipped records from bulk_upserts. but we need to do an extra query and some data wrangling to achieve it.
### Describe the solution you'd like
I tried doing it as part of the upsert statement by adding the upsert_condition logic to the update statement and add a marker to the return values to check if one of the inserts was actually skipped because of the condition logic.
1. CASE WHEN in DO UPDATE SET was successfully implemented - the conditional logic works, SQL generates correctly
2. The goal was to add the condition to RETURNING like:
RETURNING id, price, (price != EXCLUDED.price) AS met_upsert_condition
3. PostgreSQL supports this - expressions in RETURNING are valid SQL
4. But Ecto doesn't expose a way to do it:
- The :returning option flows through quote_names() which calls quote_name/1 on each item
- quote_name/1 only has function clauses for atoms and strings - it quotes them as identifiers
- If {:unsafe_fragment, "..."} is passed (like :conflict_target supports), it crashes with FunctionClauseError because there's no matching clause
- If a plain string like "(condition) AS met" is passed, it gets quoted as "(condition) AS met" which is an invalid identifier
### Describe alternatives you've considered
_No response_
### Additional context
_No response_
Contributor guide
Assessment
This issue has not been assessed yet.