Skip to content

fix(oracle): restrict upsert update to the conflicting row - #18417

Draft
wikirik-agent wants to merge 1 commit into
mainfrom
wikirik-agent/oracle-upsert-where
Draft

wikirik-agent wants to merge 1 commit into
mainfrom
wikirik-agent/oracle-upsert-where

Conversation

@wikirik-agent

@wikirik-agent wikirik-agent commented Sep 17, 2026

Copy link
Copy Markdown
Contributor

Pull Request Checklist

  • Have you added new tests to prevent regressions?
  • If a documentation update is necessary, have you opened a PR to the documentation repository?
  • Did you update the typescript typings accordingly (if applicable)?
  • Does the description below contain a link to an existing issue (Closes #[issue]) or a description of the issue you are solving?
  • Does the name of your PR follow our conventions?

Description of Changes

When Model.upsert() is called without a primary key value, core passes an empty where to the dialect (Model.upsert uses instance.where(false, true) ?? {}). The Oracle query interface only built its own condition from the upsert keys when the primary key in where was null, which no longer happens. The empty where reached upsertQuery, which generated an UPDATE without a WHERE clause. Every row in the table was overwritten, and because SQL%ROWCOUNT > 0, the new row was never inserted:

const User = sequelize.define('User', { name: { type: DataTypes.STRING, unique: true }, city: DataTypes.STRING });
await User.upsert({ name: 'january', city: 'Amsterdam' });
await User.upsert({ name: 'july', city: 'Brussels' }); // overwrote the 'january' row

An existing unit test expected exactly that unrestricted UPDATE. Other dialects are not affected.

This PR:

  • builds the Oracle upsert condition from the selected upsert key (a unique key present in the update values, otherwise the primary key) when core provides no where, as long as every key has a value;
  • generates a plain insert when no key can identify a row, instead of an unrestricted UPDATE. This matches postgres and sqlite, where ON CONFLICT ("id") always inserts when the id is generated.

Tests

  • Integration (model/upsert.test.js, all dialects that support upserts): upserting by a unique column only updates the matching row. It fails on Oracle before this change and passes on postgres, mysql, mariadb, mssql, sqlite3, db2 and oracle after it.
  • Unit: the expected upsert SQL per dialect when no primary key is given, and the updated Oracle expectation for literal binds.

Follow-ups found while working on this are stacked on top: #18419 makes Oracle's upsert return the row like the other dialects, and #18420 adds conflictFields support.

List of Breaking Changes

None.

🤖 Generated with Claude Code

@coderabbitai

coderabbitai Bot commented Sep 17, 2026

Copy link
Copy Markdown
Contributor

Important

Draft PR not reviewed

Draft PRs are not automatically reviewed by default.

  • Trigger a manual review

To automatically review draft PRs, update your CodeRabbit configuration:

reviews:
  auto_review:
    drafts: true

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant