Improve InsertQuery with IGNORE and flexible ON CONFLICT#148
Improve InsertQuery with IGNORE and flexible ON CONFLICT#148cungminh2710 wants to merge 2 commits into
Conversation
- Implement MySQL `INSERT IGNORE` support via `.Ignore()`. - Map `OnConflict().DoNothing()` to `INSERT IGNORE` for MySQL. - Allow `OnConflict().DoNothing()` without targets for PostgreSQL and SQLite. - Support `schema.Expression` in `OnConflict` targets for functional indexes. - Ensure non-column expressions in conflict targets are wrapped in parentheses. - Add comprehensive tests for the new insertion behaviors. Co-authored-by: cungminh2710 <8063319+cungminh2710@users.noreply.github.com>
|
👋 Jules, reporting for duty! I'm here to lend a hand with this pull request. When you start a review, I'll add a 👀 emoji to each comment to let you know I've read it. I'll focus on feedback directed at me and will do my best to stay out of conversations between you and other bots or reviewers to keep the noise down. I'll push a commit with your requested changes shortly after. Please note there might be a delay between these steps, but rest assured I'm on the job! For more direct control, you can switch me to Reactive Mode. When this mode is on, I will only act on comments where you specifically mention me with New to Jules? Learn more at jules.google/docs. For security, I will only act on instructions from the user who triggered this task. |
Greptile SummaryThis PR expands insert conflict handling across dialects. The main changes are:
Confidence Score: 5/5This looks safe to merge from this follow-up review.
|
| Filename | Overview |
|---|---|
| pkg/rain/query_insert.go | Updates insert compilation for ignore mode, targetless conflict handling, and expression conflict targets. |
| pkg/rain/query_insert_test.go | Adds coverage for MySQL ignore inserts, targetless conflict handling, and functional conflict targets. |
Reviews (2): Last reviewed commit: "feat(rain): improve InsertQuery with IGN..." | Re-trigger Greptile
| if q.conflict.action == insertConflictActionDoNothing { | ||
| return nil |
There was a problem hiding this comment.
Scoped Conflicts Become Global Ignore
When a MySQL caller uses OnConflict(users.Email).Where(...).DoNothing() or OnConstraint(...).DoNothing(), this branch returns before rejecting the unsupported target fields and the compiler emits plain INSERT IGNORE. That drops the requested conflict scope and can silently ignore unrelated duplicate-key, NOT NULL, foreign-key, or data conversion errors instead of returning them.
Context Used: AGENTS.md (source)
Prompt To Fix With AI
This is a comment left during a code review.
Path: pkg/rain/query_insert.go
Line: 729-730
Comment:
**Scoped Conflicts Become Global Ignore**
When a MySQL caller uses `OnConflict(users.Email).Where(...).DoNothing()` or `OnConstraint(...).DoNothing()`, this branch returns before rejecting the unsupported target fields and the compiler emits plain `INSERT IGNORE`. That drops the requested conflict scope and can silently ignore unrelated duplicate-key, NOT NULL, foreign-key, or data conversion errors instead of returning them.
**Context Used:** AGENTS.md ([source](https://app.greptile.com/hyperlocalise/github/hyperlocalise/rain-orm/-/custom-context?memory=3b24bd19-4fb7-4328-8fc3-52795c121ec6))
How can I resolve this? If you propose a fix, please make it concise.| defer releaseCompileContext(ctx) | ||
|
|
||
| if q.dialect.Name() == "mysql" && q.conflict != nil && q.conflict.action == insertConflictActionDoNothing { | ||
| q.ignore = true |
There was a problem hiding this comment.
Compilation Persists Ignore State
ToSQL, Exec, and Prepare now mutate the builder by setting q.ignore when MySQL DoNothing is compiled. If the same InsertQuery is compiled once for DoNothing and then reused with a different conflict action, the stale flag still emits INSERT IGNORE, so a later DoUpdateSet query can compile as INSERT IGNORE ... ON DUPLICATE KEY UPDATE ... without the caller asking for ignore semantics.
Context Used: AGENTS.md (source)
Prompt To Fix With AI
This is a comment left during a code review.
Path: pkg/rain/query_insert.go
Line: 272
Comment:
**Compilation Persists Ignore State**
`ToSQL`, `Exec`, and `Prepare` now mutate the builder by setting `q.ignore` when MySQL `DoNothing` is compiled. If the same `InsertQuery` is compiled once for `DoNothing` and then reused with a different conflict action, the stale flag still emits `INSERT IGNORE`, so a later `DoUpdateSet` query can compile as `INSERT IGNORE ... ON DUPLICATE KEY UPDATE ...` without the caller asking for ignore semantics.
**Context Used:** AGENTS.md ([source](https://app.greptile.com/hyperlocalise/github/hyperlocalise/rain-orm/-/custom-context?memory=3b24bd19-4fb7-4328-8fc3-52795c121ec6))
How can I resolve this? If you propose a fix, please make it concise.| ctx.writeColumnName(col) | ||
| } else { | ||
| if err := ctx.writeExpression(target); err != nil { |
There was a problem hiding this comment.
Conflict Targets Accept Parameters
Non-column conflict targets are rendered with the general expression writer, which can add bind parameters for expressions such as schema.Raw("lower(email COLLATE ?)", locale), placeholders, values, comparisons, or subqueries. PostgreSQL and SQLite conflict targets must name columns or index expressions, so this can return SQL like ON CONFLICT (lower(email COLLATE $2)) with an extra argument that the database rejects instead of failing during query construction.
Context Used: AGENTS.md (source)
Prompt To Fix With AI
This is a comment left during a code review.
Path: pkg/rain/query_insert.go
Line: 790-792
Comment:
**Conflict Targets Accept Parameters**
Non-column conflict targets are rendered with the general expression writer, which can add bind parameters for expressions such as `schema.Raw("lower(email COLLATE ?)", locale)`, placeholders, values, comparisons, or subqueries. PostgreSQL and SQLite conflict targets must name columns or index expressions, so this can return SQL like `ON CONFLICT (lower(email COLLATE $2))` with an extra argument that the database rejects instead of failing during query construction.
**Context Used:** AGENTS.md ([source](https://app.greptile.com/hyperlocalise/github/hyperlocalise/rain-orm/-/custom-context?memory=3b24bd19-4fb7-4328-8fc3-52795c121ec6))
How can I resolve this? If you propose a fix, please make it concise.- Implement MySQL `INSERT IGNORE` support via `.Ignore()`. - Map `OnConflict().DoNothing()` to `INSERT IGNORE` for MySQL. - Allow `OnConflict().DoNothing()` without targets for PostgreSQL and SQLite. - Support `schema.Expression` in `OnConflict` targets for functional indexes. - Ensure non-column expressions in conflict targets are correctly rendered. - Add comprehensive tests for the new insertion behaviors. Co-authored-by: cungminh2710 <8063319+cungminh2710@users.noreply.github.com>
This change enhances Rain ORM's
InsertQueryto achieve better parity with Drizzle ORM.Key improvements:
INSERT IGNORE: Added an.Ignore()method and updated the compiler to emitINSERT IGNOREfor MySQL.ON CONFLICT DO NOTHING: Removed the requirement for at least one conflict target when the action isDO NOTHING, matching standard SQL behavior for these dialects.OnConflictto accept...schema.Expressioninstead of just columns. This allows targeting functional indexes (e.g.,OnConflict(schema.Raw("(lower(email))")))..OnConflict().DoNothing()on a MySQL dialect now automatically utilizesINSERT IGNORElogic, providing a consistent API across dialects.Verified with comprehensive unit tests for PostgreSQL and MySQL dialects.
PR created automatically by Jules for task 6210615493842366896 started by @cungminh2710