feat: add parameter style - #17560
Conversation
56ebb3d to
daf6304
Compare
There was a problem hiding this comment.
Actionable comments posted: 1
🧹 Nitpick comments (2)
packages/core/src/utils/sql.ts (1)
551-563: Seed the generator counter when reusing a populated bind map.If the caller hands in a bind object that already contains
sequelize_…entries (e.g. when augmenting an existing map), restarting the counter from zero will overwrite previously collected values. Please initialize the counter from the existing maximum (or assert the map is empty) before returning the closure.export function createBindParamGenerator( bind: Record<string, unknown>, ): (value: unknown) => string { - let i = 0; + let i = Object.keys(bind).reduce((max, key) => { + if (!key.startsWith('sequelize_')) { + return max; + } + + const parsed = Number.parseInt(key.slice('sequelize_'.length), 10); + + return Number.isNaN(parsed) ? max : Math.max(max, parsed); + }, 0); return (value: unknown): string => { const bindName = `sequelize_${++i}`;packages/db2/src/query-generator.js (1)
368-407: Respectsuper.updateQuery’s parameter-style decision before rebuilding the LIMIT variantHere we recompute the style from
options(defaulting toBIND). Ifsuper.updateQueryalready had to fall back to replacements (it returns{ query }without abindobject, e.g. whensearchPath/ prependSearchPath forces multi-statement execution), this branch reintroduces bind parameters and ends up returning abindbag again. That regresses the very scenariosuperjust handled.Derive the effective
parameterStylefrom the response ofsuper.updateQuerybefore deciding whether to allocatebind/bindParam:- let bind; - let bindParam; - const parameterStyle = options?.parameterStyle ?? ParameterStyle.BIND; + let bind; + let bindParam; + let parameterStyle = + options?.parameterStyle ?? + (sql.bind == null ? ParameterStyle.REPLACEMENT : ParameterStyle.BIND); + + if (sql.bind == null && parameterStyle === ParameterStyle.BIND) { + parameterStyle = ParameterStyle.REPLACEMENT; + }This keeps the LIMIT rewrite in lock-step with the base implementation and avoids resurrecting binds in contexts that already required inlined replacements.
📜 Review details
Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro
📒 Files selected for processing (28)
packages/core/src/abstract-dialect/query-generator-typescript.ts(3 hunks)packages/core/src/abstract-dialect/query-generator.d.ts(4 hunks)packages/core/src/abstract-dialect/query-generator.js(7 hunks)packages/core/src/abstract-dialect/query-generator.types.ts(2 hunks)packages/core/src/abstract-dialect/query-interface-internal.ts(1 hunks)packages/core/src/abstract-dialect/query-interface-typescript.ts(1 hunks)packages/core/src/abstract-dialect/query-interface.d.ts(1 hunks)packages/core/src/abstract-dialect/query-interface.js(1 hunks)packages/core/src/abstract-dialect/query.d.ts(1 hunks)packages/core/src/abstract-dialect/query.js(1 hunks)packages/core/src/abstract-dialect/where-sql-builder.ts(1 hunks)packages/core/src/enums.ts(1 hunks)packages/core/src/index-hints.ts(0 hunks)packages/core/src/index.d.ts(1 hunks)packages/core/src/index.mjs(2 hunks)packages/core/src/model.d.ts(1 hunks)packages/core/src/model.js(1 hunks)packages/core/src/query-types.ts(0 hunks)packages/core/src/sequelize.d.ts(1 hunks)packages/core/src/sequelize.js(2 hunks)packages/core/src/table-hints.ts(0 hunks)packages/core/src/utils/sql.ts(1 hunks)packages/core/test/support.ts(3 hunks)packages/core/test/unit/query-generator/insert-query.test.ts(3 hunks)packages/core/test/unit/query-generator/update-query.test.ts(3 hunks)packages/db2/src/query-generator.js(4 hunks)packages/ibmi/src/query-generator.js(0 hunks)packages/sqlite3/src/query-generator.js(4 hunks)
💤 Files with no reviewable changes (4)
- packages/core/src/index-hints.ts
- packages/core/src/query-types.ts
- packages/ibmi/src/query-generator.js
- packages/core/src/table-hints.ts
🧰 Additional context used
📓 Path-based instructions (5)
packages/**/src/**/*.js
📄 CodeRabbit inference engine (.github/copilot-instructions.md)
Write all new implementations in TypeScript; avoid creating new .js files in src
Files:
packages/core/src/abstract-dialect/query.jspackages/core/src/abstract-dialect/query-generator.jspackages/core/src/sequelize.jspackages/core/src/abstract-dialect/query-interface.jspackages/sqlite3/src/query-generator.jspackages/db2/src/query-generator.jspackages/core/src/model.js
packages/**/src/**/query-generator.{js,ts}
📄 CodeRabbit inference engine (.github/copilot-instructions.md)
When modifying query generation, update both the base query generator and all dialect-specific implementations
Files:
packages/core/src/abstract-dialect/query-generator.jspackages/sqlite3/src/query-generator.jspackages/db2/src/query-generator.js
packages/**/test/**/*.test.ts
📄 CodeRabbit inference engine (.github/copilot-instructions.md)
Name unit tests with the .test.ts suffix
Files:
packages/core/test/unit/query-generator/insert-query.test.tspackages/core/test/unit/query-generator/update-query.test.ts
packages/**/test/**/*.test.{js,ts}
📄 CodeRabbit inference engine (.github/copilot-instructions.md)
packages/**/test/**/*.test.{js,ts}: Use Support.getTestDialectTeaser() for dialect-specific test descriptions
Use beforeEach/afterEach to sync with { force: true } and close Sequelize instances in tests
In tests, skip unsupported behavior with dialect.supports.featureName checks
Files:
packages/core/test/unit/query-generator/insert-query.test.tspackages/core/test/unit/query-generator/update-query.test.ts
packages/*/src/query-generator.{js,ts}
📄 CodeRabbit inference engine (.github/copilot-instructions.md)
Implement dialect feature SQL in query-generator.ts (preferred) or legacy query-generator.js
Files:
packages/sqlite3/src/query-generator.jspackages/db2/src/query-generator.js
🧠 Learnings (3)
📚 Learning: 2025-09-29T19:49:24.715Z
Learnt from: CR
PR: sequelize/sequelize#0
File: .github/copilot-instructions.md:0-0
Timestamp: 2025-09-29T19:49:24.715Z
Learning: Applies to packages/*/src/query-interface.{js,ts} : Add schema operations for new features in query-interface.ts (preferred) or legacy query-interface.js
Applied to files:
packages/core/src/abstract-dialect/query-interface-internal.tspackages/core/src/abstract-dialect/query.jspackages/core/src/abstract-dialect/query-interface.js
📚 Learning: 2025-09-29T19:49:24.715Z
Learnt from: CR
PR: sequelize/sequelize#0
File: .github/copilot-instructions.md:0-0
Timestamp: 2025-09-29T19:49:24.715Z
Learning: Applies to packages/**/src/**/query-generator.{js,ts} : When modifying query generation, update both the base query generator and all dialect-specific implementations
Applied to files:
packages/core/src/abstract-dialect/query-interface-internal.tspackages/core/src/abstract-dialect/query.jspackages/core/src/abstract-dialect/query-generator.jspackages/core/src/abstract-dialect/query-interface.jspackages/core/src/abstract-dialect/query.d.tspackages/core/src/abstract-dialect/query-generator.d.ts
📚 Learning: 2025-09-29T19:49:24.715Z
Learnt from: CR
PR: sequelize/sequelize#0
File: .github/copilot-instructions.md:0-0
Timestamp: 2025-09-29T19:49:24.715Z
Learning: Applies to packages/*/src/query-generator.{js,ts} : Implement dialect feature SQL in query-generator.ts (preferred) or legacy query-generator.js
Applied to files:
packages/core/src/abstract-dialect/query.jspackages/core/src/abstract-dialect/query-generator.jspackages/core/test/support.tspackages/core/src/abstract-dialect/query-generator.d.ts
🧬 Code graph analysis (12)
packages/core/src/utils/sql.ts (1)
packages/core/src/abstract-dialect/where-sql-builder.ts (2)
value(751-765)value(767-781)
packages/core/src/abstract-dialect/where-sql-builder.ts (1)
packages/core/src/abstract-dialect/query-generator-typescript.ts (1)
options(192-194)
packages/core/src/abstract-dialect/query-generator.js (2)
packages/core/src/index.mjs (2)
ParameterStyle(95-95)ParameterStyle(95-95)packages/core/src/utils/sql.ts (1)
createBindParamGenerator(551-563)
packages/core/test/support.ts (1)
packages/core/src/abstract-dialect/query-generator.types.ts (1)
BoundQuery(15-18)
packages/core/src/sequelize.js (1)
packages/core/src/index.mjs (4)
Sequelize(4-4)Sequelize(4-4)ParameterStyle(95-95)ParameterStyle(95-95)
packages/core/src/abstract-dialect/query-generator-typescript.ts (3)
packages/core/src/abstract-dialect/data-types.ts (1)
BindParamOptions(65-67)packages/core/src/index.mjs (2)
ParameterStyle(95-95)ParameterStyle(95-95)packages/core/src/sequelize.d.ts (1)
BindOrReplacements(113-113)
packages/core/test/unit/query-generator/insert-query.test.ts (1)
packages/core/src/index.mjs (4)
literal(11-11)literal(11-11)ParameterStyle(95-95)ParameterStyle(95-95)
packages/sqlite3/src/query-generator.js (3)
packages/core/src/abstract-dialect/query-generator-typescript.ts (1)
options(192-194)packages/core/src/index.mjs (2)
ParameterStyle(95-95)ParameterStyle(95-95)packages/core/src/utils/sql.ts (1)
createBindParamGenerator(551-563)
packages/core/src/abstract-dialect/query-generator.d.ts (3)
packages/core/src/model.d.ts (1)
UpdateOptions(1285-1342)packages/core/src/abstract-dialect/query-generator-typescript.ts (1)
ParameterOptions(156-165)packages/core/src/abstract-dialect/query-generator.types.ts (1)
BoundQuery(15-18)
packages/core/src/enums.ts (1)
packages/core/src/index.mjs (8)
IndexHints(90-90)IndexHints(90-90)ParameterStyle(95-95)ParameterStyle(95-95)QueryTypes(87-87)QueryTypes(87-87)TableHints(89-89)TableHints(89-89)
packages/core/test/unit/query-generator/update-query.test.ts (1)
packages/core/src/index.mjs (4)
literal(11-11)literal(11-11)ParameterStyle(95-95)ParameterStyle(95-95)
packages/db2/src/query-generator.js (3)
packages/core/src/abstract-dialect/query-generator-typescript.ts (1)
options(192-194)packages/core/src/index.mjs (2)
ParameterStyle(95-95)ParameterStyle(95-95)packages/core/src/utils/sql.ts (1)
createBindParamGenerator(551-563)
🪛 Biome (2.1.2)
packages/core/src/abstract-dialect/query.js
[error] 3-4: Illegal use of an import declaration outside of a module
not allowed inside scripts
(parse)
[error] 4-5: Illegal use of an import declaration outside of a module
not allowed inside scripts
(parse)
packages/core/src/abstract-dialect/query-generator.js
[error] 18-19: Illegal use of an import declaration outside of a module
not allowed inside scripts
(parse)
[error] 19-20: Illegal use of an import declaration outside of a module
not allowed inside scripts
(parse)
[error] 27-28: Illegal use of an import declaration outside of a module
not allowed inside scripts
(parse)
[error] 28-29: Illegal use of an import declaration outside of a module
not allowed inside scripts
(parse)
packages/core/src/sequelize.js
[error] 19-20: Illegal use of an import declaration outside of a module
not allowed inside scripts
(parse)
[error] 20-21: Illegal use of an import declaration outside of a module
not allowed inside scripts
(parse)
packages/core/src/abstract-dialect/query-interface.js
[error] 10-11: Illegal use of an import declaration outside of a module
not allowed inside scripts
(parse)
[error] 11-12: Illegal use of an import declaration outside of a module
not allowed inside scripts
(parse)
packages/sqlite3/src/query-generator.js
[error] 2-3: Illegal use of an import declaration outside of a module
not allowed inside scripts
(parse)
[error] 3-7: Illegal use of an import declaration outside of a module
not allowed inside scripts
(parse)
[error] 11-12: Illegal use of an import declaration outside of a module
not allowed inside scripts
(parse)
[error] 12-13: Illegal use of an import declaration outside of a module
not allowed inside scripts
(parse)
packages/db2/src/query-generator.js
[error] 2-3: Illegal use of an import declaration outside of a module
not allowed inside scripts
(parse)
[error] 3-7: Illegal use of an import declaration outside of a module
not allowed inside scripts
(parse)
[error] 15-16: Illegal use of an import declaration outside of a module
not allowed inside scripts
(parse)
[error] 16-17: Illegal use of an import declaration outside of a module
not allowed inside scripts
(parse)
packages/core/src/model.js
[error] 40-41: Illegal use of an import declaration outside of a module
not allowed inside scripts
(parse)
[error] 41-42: Illegal use of an import declaration outside of a module
not allowed inside scripts
(parse)
⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (2)
- GitHub Check: Upload install and build artifact (Node 18)
- GitHub Check: Upload install and build artifact (Node 20)
🔇 Additional comments (14)
packages/core/src/abstract-dialect/query.d.ts (1)
1-1: LGTM! Import path updated correctly.The import source for
QueryTypeshas been correctly updated to use the centralized enums module.packages/core/src/abstract-dialect/query-generator.types.ts (2)
2-2: LGTM! Import path updated correctly.The import source for
TableHintshas been correctly updated to use the centralized enums module.
15-18: LGTM! New BoundQuery interface is well-defined.The
BoundQueryinterface provides a clean contract for representing SQL queries with optional bind parameters, supporting the new parameter-style binding mechanism.packages/core/src/abstract-dialect/query.js (1)
4-4: LGTM! Import correctly updated to ES module.The import has been correctly updated from CommonJS
requireto ES moduleimportand now sourcesQueryTypesfrom the centralized enums module. The static analysis errors about "imports outside modules" are false positives since this file uses ES modules.packages/core/src/enums.ts (1)
1-82: LGTM! Well-structured enum consolidation.The centralized enums module successfully consolidates
IndexHints,ParameterStyle,QueryTypes, andTableHintsinto a single location. All enums are:
- Properly documented with JSDoc comments
- Consistently structured with string values
- Clearly named and organized
This improves maintainability by providing a single source of truth for these core enums.
packages/core/src/abstract-dialect/query-generator-typescript.ts (2)
8-9: LGTM! Imports updated correctly.The imports have been correctly updated to source
ParameterStyle,IndexHints, andTableHintsfrom the centralized enums module.
133-165: LGTM! Improved parameter options design.The refactor successfully replaces the
Bindableinterface with a cleaner separation of concerns:
ParameterOptionsprovidesparameterStyleandreplacementsfor parameter binding configurationFormatWhereOptionsnow extends bothPartial<BindParamOptions>andParameterOptions- Added
modelproperty to aid type resolutionThis aligns with the PR's goal of replacing
bindParamwith the more flexibleparameterStyleAPI.packages/core/src/abstract-dialect/where-sql-builder.ts (1)
410-412: Verify the safety of mutating the options object.The code now mutates the
optionsobject in place by deleting thebindParamproperty, rather than creating a new object without it. While this achieves the same functional result for the IS operation, it could have side effects if the caller expects the original options object to remain unchanged.Please confirm that this mutation is intentional and that callers of this method do not rely on the options object remaining immutable.
If immutability is preferred, consider reverting to the previous pattern:
- // "IS" operator does not accept bind parameters, only literals - if (options.bindParam) { - delete options.bindParam; - } + // "IS" operator does not accept bind parameters, only literals + const optionsWithoutBind = options.bindParam + ? { ...options, bindParam: undefined } + : options; - return this.formatBinaryOperation(left, undefined, operator, right, undefined, options); + return this.formatBinaryOperation(left, undefined, operator, right, undefined, optionsWithoutBind);packages/core/src/abstract-dialect/query-interface-internal.ts (1)
2-2: LGTM! Import path updated correctly.The import source for
QueryTypeshas been correctly updated to use the centralized enums module.packages/core/src/abstract-dialect/query-interface.js (1)
11-11: LGTM! Import path updated correctly.The import source for
QueryTypeshas been correctly updated to use the centralized enums module. The static analysis errors about "imports outside modules" are false positives since this file uses ES modules.packages/core/src/index.d.ts (1)
49-49: Re-export looks good.
Consolidating the enum exports keeps the public surface consistent with the implementation move.packages/core/src/model.js (1)
41-41: Import swap is fine.
The module already centralizes enums in./enums.js, so pointingModelthere keeps everything consistent.packages/core/src/model.d.ts (1)
24-24: Type import matches runtime change.
PullingIndexHintsfrom./enums.jsaligns the typings with the new enum module.packages/core/src/index.mjs (1)
86-96: New export wired correctly.
Re-exportingParameterStylekeeps the top-level API in sync with the enum move.
WikiRik
left a comment
There was a problem hiding this comment.
Apologies for not reviewing this sooner, this looks great! I'll check in a bit if there's already a PR for the website repo to document the removal of bindParam (and replacement with parameterStyle)
…itions Op.is/Op.isNot (used for IS NULL/IS TRUE/IS FALSE) cannot use a bind parameter for its right-hand side, so the WhereSqlBuilder strips bindParam before formatting it. Since 1f4bdee (feat: add parameter style, sequelize#17560) it did this by deleting the property from the *shared* options object instead of a local copy, which permanently disabled bind parameters for every WHERE condition evaluated after an Op.is comparison in the same clause -- not just that one. Those conditions fall back to literal escaping, which breaks for e.g. a JSON ->> (text) comparison against a plain number: Postgres has no text = integer operator. Surfaced via sequelize-core-papandreou release testing against peakon/api's notification service; bisected to 1f4bdee by comparing against alpha.44. Releases sequelize-{core,postgres}-papandreou@7.0.0-alpha.48-patch2

Pull Request Checklist
Description of Changes
This PR implements the
ParameterStylechanges in #17131 which are required for #16988 and #17063List of Breaking Changes
The
bindParamoption have been replaced withparameterStylewhich defaults toParameterStyle.BIND.Summary by CodeRabbit
New Features
Refactor
Tests