[#190]: Add upsert support via onConflict argument
## What
Implements upsert support via `onConflict` argument on insert mutations.
Closes #190
## Why
This enables upsert operations (INSERT ... ON CONFLICT DO UPDATE) through the GraphQL API, which is a common requirement for applications that need idempotent writes.
## Changes
- **SQL Context**: Load index names from `pg_class` to identify constraints
- **SQL Types**: Add `on_conflict_indexes()` and `has_upsert_support()` methods to Table
- **GraphQL Types**:
- New `{Table}OnConflict` input type with `constraint`, `updateColumns`, and `filter` fields
- New `{Table}Constraint` enum (unique index names)
- New `{Table}UpdateColumn` enum (updatable column names)
- Conditionally expose `onConflict` arg only on tables with valid constraints
- **Builder**: Parse `onConflict` argument and map GraphQL column names back to Column objects
- **Transpile**: Generate `ON CONFLICT ON CONSTRAINT ... DO UPDATE SET ... WHERE ...`
## Example
```graphql
mutation {
insertIntoAccountCollection(
objects: [{ id: 1, email: "new@example.com", name: "Updated" }]
onConflict: {
constraint: account_pkey
updateColumns: [email, name]
filter: { status: { eq: "active" } }
}
) {
affectedCount
records { id email name }
}
}
```
## Notes
- Tables with serial/generated primary keys will not expose `onConflict` (constraint columns must be insertable)
- Empty `updateColumns` results in `DO NOTHING`
- Based on #503 but reimplemented on current master without unrelated changes
## Tests
Added tests in `test/sql/mutation_insert_on_conflict.sql`
合并状态:未合并 1 条评论