feat(core): add Firebird dialect support to Sequelize#18154
feat(core): add Firebird dialect support to Sequelize#18154Juank2001 wants to merge 3 commits intosequelize:mainfrom
Conversation
|
Note Reviews pausedIt looks like this branch is under active development. To avoid overwhelming you with review comments due to an influx of new commits, CodeRabbit has automatically paused this review. You can configure this behavior by changing the Use the following commands to manage reviews:
Use the checkboxes below for quick actions:
📝 WalkthroughWalkthroughAdds a new Firebird dialect package and registers it in core: adds Changes
Sequence Diagram(s)sequenceDiagram
participant App as Application
participant Seq as Sequelize Core
participant Dial as FirebirdDialect
participant ConnMgr as FirebirdConnectionManager
participant FB as node-firebird
participant Query as FirebirdQuery
App->>Seq: new Sequelize({ dialect: "firebird", ... })
Seq->>Dial: instantiate dialect
Dial->>ConnMgr: initialize connection manager
App->>Seq: query("SELECT ...")
Seq->>Dial: create Query instance
Query->>ConnMgr: acquire connection
ConnMgr->>FB: attach(options, callback)
FB-->>ConnMgr: connection
ConnMgr-->>Query: connection ready
Query->>FB: execute(sql, params, callback)
FB-->>Query: rows / error
Query->>Query: normalize rows, map errors
Query->>Seq: resolve Promise(result)
Seq-->>App: return results
Estimated code review effort🎯 4 (Complex) | ⏱️ ~75 minutes Possibly related PRs
Suggested reviewers
Poem
🚥 Pre-merge checks | ✅ 2 | ❌ 1❌ Failed checks (1 warning)
✅ Passed checks (2 passed)
✏️ Tip: You can configure your own custom pre-merge checks in the settings. ✨ Finishing Touches🧪 Generate unit tests (beta)
📝 Coding Plan for PR comments
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. Comment |
There was a problem hiding this comment.
Actionable comments posted: 9
Caution
Some comments are outside the diff and can’t be posted inline due to platform limitations.
⚠️ Outside diff range comments (1)
packages/core/src/sequelize-typescript.ts (1)
199-212:⚠️ Potential issue | 🟠 MajorAdd 'firebird' case to
importDialectfunction.The
importDialectfunction inpackages/core/src/sequelize.internals.tslacks a case for'firebird'. Users passingdialect: 'firebird'as a string will trigger the default error, which also does not mention 'firebird' in the list of supported dialects. Add the corresponding case handler and update the error message.🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed. In `@packages/core/src/sequelize-typescript.ts` around lines 199 - 212, The SUPPORTED_DIALECTS list includes 'firebird' but the importDialect function in packages/core/src/sequelize.internals.ts lacks a case for 'firebird', causing the default error to be thrown (and the error string also omits 'firebird'); update importDialect to add a case for 'firebird' that imports/returns the appropriate Firebird dialect implementation (mirror the pattern used for other dialects in importDialect) and update the default error message to include 'firebird' so the supported-dialects list and import behavior are consistent with SUPPORTED_DIALECTS.
🧹 Nitpick comments (9)
packages/firebird/src/query.ts (2)
14-14: Unused declaration:connectionManagerproperty.This property is declared but never used. Line 21 uses
this.connectioninstead. Either this declaration is unnecessary or there's a property name mismatch.♻️ Proposed fix - remove unused declaration
export class FirebirdQuery extends AbstractQuery { - declare connectionManager: FirebirdConnection;🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed. In `@packages/firebird/src/query.ts` at line 14, The class has an unused property declaration connectionManager while the code uses this.connection; remove the unused connectionManager declaration or rename it to connection to match usage (update any references to the property accordingly), ensuring the class property name (connection) aligns with places like methods referencing this.connection in the Query class.
157-182: Consider hoisting error class imports to module level.Using
require()inside the method body incurs repeated module resolution overhead on each error. These imports could be moved to the top of the file for better performance and clearer dependencies.♻️ Proposed refactor
import { AbstractQuery } from '@sequelize/core'; +import { + DatabaseError, + ForeignKeyConstraintError, + UniqueConstraintError, + ValidationError, + ValidationErrorItem, +} from '@sequelize/core'; import { logger } from '@sequelize/core/_non-semver-use-at-your-own-risk_/utils/logger.js';Then replace the
require()calls with direct usage of the imported classes.🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed. In `@packages/firebird/src/query.ts` around lines 157 - 182, Hoist the runtime imports for Sequelize error classes out of the method and into the module scope to avoid repeated require() calls: add a single top-level destructuring assignment like const { UniqueConstraintError, ForeignKeyConstraintError, ValidationError, ValidationErrorItem, DatabaseError } = require('@sequelize/core'); (or equivalent ES import) at the top of the file, then replace the inline require(...) usages inside the function that reference UniqueConstraintError, ForeignKeyConstraintError, ValidationError, ValidationErrorItem, and DatabaseError with the now-top-level identifiers so the function returns new UniqueConstraintError(...), new ForeignKeyConstraintError(...), new ValidationError(...), and new DatabaseError(...) without performing require() on each execution.packages/firebird/src/query-interface.ts (1)
3-9: Placeholder class noted.The class extends
AbstractQueryInterfacebut doesn't implement any Firebird-specific methods. The doc comment mentions "auto-increment via SEQUENCE + BEFORE INSERT TRIGGER" support, but the actual DDL operations aren't implemented yet.As per coding guidelines, schema operations for new features should be added in query-interface.ts. Consider tracking this as a follow-up task to implement the promised auto-increment DDL functionality.
Would you like me to open an issue to track implementing the Firebird-specific DDL operations (SEQUENCE/TRIGGER creation for auto-increment)?
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed. In `@packages/firebird/src/query-interface.ts` around lines 3 - 9, FirebirdQueryInterface currently only extends AbstractQueryInterface but lacks the Firebird-specific DDL operations promised in the docstring; add implementations to query-interface.ts that provide auto-increment support via SEQUENCE + BEFORE INSERT TRIGGER: implement methods on the FirebirdQueryInterface class such as createAutoIncrement (or createSequence and createTrigger), dropAutoIncrement (or dropSequence/dropTrigger), and any helpers to generate the proper SQL and execute it via the existing query runner; ensure method names are exported on FirebirdQueryInterface and integrate with existing AbstractQueryInterface patterns so callers can create/drop sequences and triggers for auto-increment columns.packages/firebird/readme.md (1)
63-79: Add language specifier to fenced code block.The package structure code block should have a language specifier for proper rendering and linting compliance.
📝 Proposed fix
-``` +```text packages/firebird/ ├── package.json🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed. In `@packages/firebird/readme.md` around lines 63 - 79, The fenced package-structure block in README.md is missing a language specifier; update the opening fence for the snippet that lists the packages/firebird tree from ``` to ```text (or another appropriate language like ```bash) so the block becomes a labeled code fence, leaving the closing ``` intact; this change targets the README.md file's package structure code block.packages/core/src/sequelize-typescript.ts (1)
203-206: Pre-existing duplicate entries inSUPPORTED_DIALECTS.Note:
'mariadb'and'mssql'appear twice in the array. This is a pre-existing issue unrelated to this PR, but may be worth addressing in a follow-up.🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed. In `@packages/core/src/sequelize-typescript.ts` around lines 203 - 206, The SUPPORTED_DIALECTS array contains duplicate entries ('mariadb' and 'mssql')—remove the duplicates so each dialect appears only once; locate the SUPPORTED_DIALECTS constant in sequelize-typescript.ts and update the array to hold unique strings (e.g., use a deduplicated list or construct it via Array.from(new Set(...))) to ensure no repeated dialect names.packages/firebird/src/connection-manager.ts (1)
199-233: Consider static imports for error classes.The error classes (
ConnectionRefusedError,AccessDeniedError, etc.) are dynamically required within#translateError. Using static imports at the top of the file would improve bundler compatibility and code clarity.Use static imports for error classes
-import type { AbstractConnection, ConnectionOptions } from '@sequelize/core'; -import { AbstractConnectionManager, ConnectionError } from '@sequelize/core'; +import type { AbstractConnection, ConnectionOptions } from '@sequelize/core'; +import { + AbstractConnectionManager, + AccessDeniedError, + ConnectionError, + ConnectionRefusedError, + HostNotFoundError, + HostNotReachableError, + InvalidConnectionError, +} from '@sequelize/core'; // ... later in `#translateError` ... `#translateError`(err: Error & { gdscode?: number }): ConnectionError { const msg = err.message ?? ''; if (/connection refused/i.test(msg)) { - const { ConnectionRefusedError } = require('@sequelize/core'); return new ConnectionRefusedError(err); } if (/access denied/i.test(msg) || err.gdscode === 335_544_472) { - const { AccessDeniedError } = require('@sequelize/core'); return new AccessDeniedError(err); } // ... similar for other error types }🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed. In `@packages/firebird/src/connection-manager.ts` around lines 199 - 233, Move the dynamic require calls inside `#translateError` to static imports at the top of the module: import { ConnectionRefusedError, AccessDeniedError, HostNotFoundError, HostNotReachableError, InvalidConnectionError, ConnectionError } from '@sequelize/core'; then update `#translateError` to reference these imported classes directly (remove require(...) calls) so the function uses the statically imported ConnectionRefusedError, AccessDeniedError, HostNotFoundError, HostNotReachableError, InvalidConnectionError and ConnectionError symbols.packages/firebird/src/query-generator.internal.ts (1)
6-8: Consider documenting why technical schema names is empty.Firebird doesn't support schemas in the same way other databases do. A brief comment explaining this would help maintainers understand the empty array isn't an oversight.
Add explanatory comment
getTechnicalSchemaNames(): readonly string[] { + // Firebird does not support schemas; there are no technical schema names to exclude return []; }🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed. In `@packages/firebird/src/query-generator.internal.ts` around lines 6 - 8, The getTechnicalSchemaNames() method currently returns an empty array but lacks explanation; add a short comment above the getTechnicalSchemaNames() function stating that Firebird does not implement named schemas like other DBs and therefore there are no technical schema names to return, so returning [] is intentional (reference the getTechnicalSchemaNames function to locate the spot).packages/firebird/src/_internal/data-types-overrides.ts (2)
170-174: Shadowing the globalJSONidentifier.The class name
JSONshadows the globalJSONobject, which can cause confusion and potential issues if the globalJSONis needed within this module. This is flagged by the static analysis tool.Consider renaming to
FirebirdJSONorJSON_TYPEto avoid shadowing, though since this is a data-type override module following the Sequelize pattern, the shadowing may be intentional for consistency with other dialects.🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed. In `@packages/firebird/src/_internal/data-types-overrides.ts` around lines 170 - 174, The class named JSON shadows the global JSON identifier; rename the export class JSON (and any references) to a non-conflicting identifier like FirebirdJSON or JSON_TYPE, update its extends clause (currently BaseTypes.JSON) and any places that import or instantiate this type so they reference the new name, and keep the toSql() implementation unchanged to return 'BLOB SUB_TYPE TEXT'.
113-116: Method signature diverges from base class.The
escapemethod adds an optional_optionsparameter that doesn't exist in the baseBOOLEAN.escape(value: boolean | unknown): stringsignature (seepackages/core/src/abstract-dialect/data-types.ts:1349-1351). While this works due to TypeScript's structural typing, it's inconsistent with the base class contract.Align with base class signature
- escape(value: boolean | unknown, _options?: any): string { + escape(value: boolean | unknown): string { return value ? 'TRUE' : 'FALSE'; }🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed. In `@packages/firebird/src/_internal/data-types-overrides.ts` around lines 113 - 116, The BOOLEAN.escape method signature diverges from the base class by including an extra optional parameter; update the method signature in the BOOLEAN class from escape(value: boolean | unknown, _options?: any): string to match the base class signature escape(value: boolean | unknown): string, and remove the unused _options parameter from the implementation so the override exactly matches the base contract.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.
Inline comments:
In `@packages/firebird/package.json`:
- Around line 42-44: The package.json lists an invalid dependency
"node-firebird@^2.0.2"; update it to a valid published version (e.g.,
"node-firebird@^1.1.9") or replace it with the correct package name if a
different library was intended; edit the dependency entry in packages/firebird's
package.json (the "node-firebird" dependency line) and run npm install / yarn
install to verify resolution and update package-lock.json or yarn.lock
accordingly.
In `@packages/firebird/src/_internal/data-types-overrides.ts`:
- Around line 128-136: The stringify implementation assumes sanitize(value)
returns a native Date; instead detect and normalize dayjs/Moment returns
(sanitize from the DATE base can yield Date | dayjs.Dayjs | Moment) before
calling Date methods: in stringify(AcceptedDate) call this.sanitize(value), if
the result is a Date use it, otherwise if it has a toDate() method
(dayjs/Moment) call that to obtain a Date, then use getFullYear()/getMonth()
etc. to build the Firebird 'YYYY-MM-DD HH:MM:SS.mmm' string; ensure you
reference the existing sanitize() and stringify() methods and AcceptedDate type
when making the change.
In `@packages/firebird/src/connection-manager.ts`:
- Around line 74-79: The JSDoc for the password property says "@default
'masterkey'" but the code default in the implementation is an empty string; pick
one and make them consistent: either update the JSDoc comment on the password?:
string declaration to "@default ''" to reflect the current behavior, or change
the implementation where the default is assigned (the code that initializes the
password default) to use 'masterkey' instead of '' so it matches the JSDoc;
ensure you update the JSDoc text and the default-assignment site together
(referencing the password property and the function/constructor that sets its
default).
In `@packages/firebird/src/dialect.ts`:
- Around line 112-127: The constructor in the Firebird dialect sets
identifierDelimiter to an empty string which disables identifier quoting and
contradicts Firebird behavior; update the constructor (in the Firebird dialect
class where constructor(sequelize: Sequelize, options: FirebirdDialectOptions)
is defined) to set identifierDelimiter to a double-quote character (") so the
dialect and the FirebirdQueryGenerator/FirebirdQueryInterface behavior align and
support delimited identifiers and reserved-word quoting.
In `@packages/firebird/src/query-generator.ts`:
- Around line 145-152: The PK join is matching RDB$INDEX_SEGMENTS by field name
only (alias iseg) which pulls segments from any table with the same column name;
change the join order to first LEFT JOIN RDB$RELATION_CONSTRAINTS rc ON
rc.RDB$RELATION_NAME = rf.RDB$RELATION_NAME AND rc.RDB$CONSTRAINT_TYPE =
'PRIMARY KEY' and then LEFT JOIN RDB$INDEX_SEGMENTS iseg ON iseg.RDB$INDEX_NAME
= rc.RDB$INDEX_NAME AND iseg.RDB$FIELD_NAME = rf.RDB$FIELD_NAME so the segment
match is scoped to the relation's primary-key index (use the aliases rf, rc,
iseg shown in the diff).
- Line 58: The metadata queries currently upper-case quoted identifiers causing
failures for mixed/lowercase names; update the predicates in tableExistsQuery,
showIndexesQuery, and describeTableQuery to stop calling .toUpperCase() on
table.tableName (and any similar uses for index or column names), i.e., use
this.escape(table.tableName) (or the original identifier variable without
.toUpperCase()) so the TRIM(RDB$RELATION_NAME) and related comparisons match
preserved-case catalog entries.
In `@packages/firebird/src/query.ts`:
- Around line 136-147: The `#normaliseRow` function is incorrectly adding Model
internals by setting out.dataValues and out._previousDataValues; remove those
two assignments so the function only lowercases keys and converts Buffers to
UTF-8 strings, returning a plain object, and ensure any code calling
`#normaliseRow` relies on Sequelize's hydration (or uses the existing
handleSelectQuery) to create Model instances rather than expecting these
injected properties.
- Around line 54-70: The current DML handling in the block using
isInsertQuery(), isUpdateQuery(), isDeleteQuery() returns hardcoded/incorrect
counts; wrap INSERT/UPDATE/DELETE executions in an EXECUTE BLOCK that captures
ROW_COUNT and returns it (and keep the INSERT RETURNING row when available) so
counts reflect actual affected rows. Update the logic in the function containing
handleInsertQuery() to: for inserts, execute a wrapped EXECUTE BLOCK that
performs the INSERT (producing RETURNING row if needed) and returns ROW_COUNT
alongside the returned row so you can return [insertedRow, rowCount]; for
updates and deletes replace the current rows.length return by executing the DML
inside an EXECUTE BLOCK that returns ROW_COUNT and return that count (or [rows,
rowCount] if your API expects rows plus count). Ensure you reuse/extend
handleInsertQuery(), and adjust callers to accept the new rowCount value instead
of the hardcoded 1 or rows.length.
---
Outside diff comments:
In `@packages/core/src/sequelize-typescript.ts`:
- Around line 199-212: The SUPPORTED_DIALECTS list includes 'firebird' but the
importDialect function in packages/core/src/sequelize.internals.ts lacks a case
for 'firebird', causing the default error to be thrown (and the error string
also omits 'firebird'); update importDialect to add a case for 'firebird' that
imports/returns the appropriate Firebird dialect implementation (mirror the
pattern used for other dialects in importDialect) and update the default error
message to include 'firebird' so the supported-dialects list and import behavior
are consistent with SUPPORTED_DIALECTS.
---
Nitpick comments:
In `@packages/core/src/sequelize-typescript.ts`:
- Around line 203-206: The SUPPORTED_DIALECTS array contains duplicate entries
('mariadb' and 'mssql')—remove the duplicates so each dialect appears only once;
locate the SUPPORTED_DIALECTS constant in sequelize-typescript.ts and update the
array to hold unique strings (e.g., use a deduplicated list or construct it via
Array.from(new Set(...))) to ensure no repeated dialect names.
In `@packages/firebird/readme.md`:
- Around line 63-79: The fenced package-structure block in README.md is missing
a language specifier; update the opening fence for the snippet that lists the
packages/firebird tree from ``` to ```text (or another appropriate language like
```bash) so the block becomes a labeled code fence, leaving the closing ```
intact; this change targets the README.md file's package structure code block.
In `@packages/firebird/src/_internal/data-types-overrides.ts`:
- Around line 170-174: The class named JSON shadows the global JSON identifier;
rename the export class JSON (and any references) to a non-conflicting
identifier like FirebirdJSON or JSON_TYPE, update its extends clause (currently
BaseTypes.JSON) and any places that import or instantiate this type so they
reference the new name, and keep the toSql() implementation unchanged to return
'BLOB SUB_TYPE TEXT'.
- Around line 113-116: The BOOLEAN.escape method signature diverges from the
base class by including an extra optional parameter; update the method signature
in the BOOLEAN class from escape(value: boolean | unknown, _options?: any):
string to match the base class signature escape(value: boolean | unknown):
string, and remove the unused _options parameter from the implementation so the
override exactly matches the base contract.
In `@packages/firebird/src/connection-manager.ts`:
- Around line 199-233: Move the dynamic require calls inside `#translateError` to
static imports at the top of the module: import { ConnectionRefusedError,
AccessDeniedError, HostNotFoundError, HostNotReachableError,
InvalidConnectionError, ConnectionError } from '@sequelize/core'; then update
`#translateError` to reference these imported classes directly (remove
require(...) calls) so the function uses the statically imported
ConnectionRefusedError, AccessDeniedError, HostNotFoundError,
HostNotReachableError, InvalidConnectionError and ConnectionError symbols.
In `@packages/firebird/src/query-generator.internal.ts`:
- Around line 6-8: The getTechnicalSchemaNames() method currently returns an
empty array but lacks explanation; add a short comment above the
getTechnicalSchemaNames() function stating that Firebird does not implement
named schemas like other DBs and therefore there are no technical schema names
to return, so returning [] is intentional (reference the getTechnicalSchemaNames
function to locate the spot).
In `@packages/firebird/src/query-interface.ts`:
- Around line 3-9: FirebirdQueryInterface currently only extends
AbstractQueryInterface but lacks the Firebird-specific DDL operations promised
in the docstring; add implementations to query-interface.ts that provide
auto-increment support via SEQUENCE + BEFORE INSERT TRIGGER: implement methods
on the FirebirdQueryInterface class such as createAutoIncrement (or
createSequence and createTrigger), dropAutoIncrement (or
dropSequence/dropTrigger), and any helpers to generate the proper SQL and
execute it via the existing query runner; ensure method names are exported on
FirebirdQueryInterface and integrate with existing AbstractQueryInterface
patterns so callers can create/drop sequences and triggers for auto-increment
columns.
In `@packages/firebird/src/query.ts`:
- Line 14: The class has an unused property declaration connectionManager while
the code uses this.connection; remove the unused connectionManager declaration
or rename it to connection to match usage (update any references to the property
accordingly), ensuring the class property name (connection) aligns with places
like methods referencing this.connection in the Query class.
- Around line 157-182: Hoist the runtime imports for Sequelize error classes out
of the method and into the module scope to avoid repeated require() calls: add a
single top-level destructuring assignment like const { UniqueConstraintError,
ForeignKeyConstraintError, ValidationError, ValidationErrorItem, DatabaseError }
= require('@sequelize/core'); (or equivalent ES import) at the top of the file,
then replace the inline require(...) usages inside the function that reference
UniqueConstraintError, ForeignKeyConstraintError, ValidationError,
ValidationErrorItem, and DatabaseError with the now-top-level identifiers so the
function returns new UniqueConstraintError(...), new
ForeignKeyConstraintError(...), new ValidationError(...), and new
DatabaseError(...) without performing require() on each execution.
ℹ️ Review info
⚙️ Run configuration
Configuration used: defaults
Review profile: CHILL
Plan: Pro
Run ID: b402ffcb-fcd3-4e4d-9c70-6c7a35257db0
⛔ Files ignored due to path filters (1)
yarn.lockis excluded by!**/yarn.lock,!**/*.lock
📒 Files selected for processing (17)
packages/core/src/sequelize-typescript.tspackages/core/src/sequelize.jspackages/core/src/utils/dialect.tspackages/firebird/.eslintrc.jspackages/firebird/package.jsonpackages/firebird/readme.mdpackages/firebird/src/_internal/data-types-overrides.tspackages/firebird/src/connection-manager.tspackages/firebird/src/dialect.tspackages/firebird/src/index.tspackages/firebird/src/query-generator.internal.tspackages/firebird/src/query-generator.tspackages/firebird/src/query-interface.tspackages/firebird/src/query-interface.types.tspackages/firebird/src/query.tspackages/firebird/tsconfig.jsonpackages/firebird/typedoc.json
| constructor(sequelize: Sequelize, options: FirebirdDialectOptions) { | ||
| super({ | ||
| identifierDelimiter: '', | ||
| options, | ||
| dataTypeOverrides: DataTypes, | ||
| sequelize, | ||
| minimumDatabaseVersion: '3.0.0', | ||
| dataTypesDocumentationUrl: | ||
| 'https://firebirdsql.org/refdocs/langrefupd25-datatypes.html', | ||
| name: 'firebird' as any, | ||
| }); | ||
|
|
||
| this.connectionManager = new FirebirdConnectionManager(this); | ||
| this.queryGenerator = new FirebirdQueryGenerator(this); | ||
| this.queryInterface = new FirebirdQueryInterface(this); | ||
| } |
There was a problem hiding this comment.
🧩 Analysis chain
🌐 Web query:
Does Firebird SQL support double-quoted identifiers for reserved words?
💡 Result:
Yes. Firebird supports delimited identifiers enclosed in double quotes, and a delimited identifier can be a reserved word (e.g., "USER", "DATE"). This applies in SQL Dialect 3 (the normal/default dialect); delimited identifiers are case-sensitive and stored “as-is”. [1]
Example
create table "USER" ("DATE" date);
select "DATE" from "USER";[1]
🏁 Script executed:
cat -n packages/firebird/src/dialect.ts | head -150Repository: sequelize/sequelize
Length of output: 5571
🏁 Script executed:
cat -n packages/firebird/src/query-generator.ts | head -100Repository: sequelize/sequelize
Length of output: 4357
🏁 Script executed:
cat -n packages/firebird/src/query-generator.internal.ts | head -50Repository: sequelize/sequelize
Length of output: 1319
🏁 Script executed:
rg -A 5 "quoteIdentifier" packages/firebird/src/Repository: sequelize/sequelize
Length of output: 1766
🏁 Script executed:
find packages/firebird -name "*.test.*" -o -name "*.spec.*" | head -10Repository: sequelize/sequelize
Length of output: 45
🏁 Script executed:
fd -t f "*.test\." packages/firebird/Repository: sequelize/sequelize
Length of output: 350
🏁 Script executed:
fd --glob "*.test.*" packages/firebird/Repository: sequelize/sequelize
Length of output: 45
🏁 Script executed:
rg "identifierDelimiter" packages/firebird/Repository: sequelize/sequelize
Length of output: 126
🏁 Script executed:
rg "identifierDelimiter" -B 2 -A 2 packages/ | grep -A 5 -B 5 "firebird\|Firebird"Repository: sequelize/sequelize
Length of output: 1056
🏁 Script executed:
rg "Double-quoted identifiers" -B 3 -A 3 packages/firebird/Repository: sequelize/sequelize
Length of output: 599
identifierDelimiter: '' contradicts documented Firebird behavior and disables identifier quoting.
The query generator explicitly documents "Double-quoted identifiers" as a key Firebird SQL difference, yet the dialect is configured with an empty identifierDelimiter, which disables all identifier quoting. This creates a contradiction since Firebird supports delimited identifiers in double quotes, particularly for:
- Reserved words used as identifiers (e.g.,
"USER","DATE") - Case-sensitive identifier storage
- Special characters in identifiers
The configuration should use identifierDelimiter: '"' to align with Firebird's documented capabilities and the query generator's stated behavior. Other dialects in the codebase (e.g., DB2) use double quotes correctly.
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.
In `@packages/firebird/src/dialect.ts` around lines 112 - 127, The constructor in
the Firebird dialect sets identifierDelimiter to an empty string which disables
identifier quoting and contradicts Firebird behavior; update the constructor (in
the Firebird dialect class where constructor(sequelize: Sequelize, options:
FirebirdDialectOptions) is defined) to set identifierDelimiter to a double-quote
character (") so the dialect and the
FirebirdQueryGenerator/FirebirdQueryInterface behavior align and support
delimited identifiers and reserved-word quoting.
| ' CASE f.RDB$FIELD_TYPE', | ||
| " WHEN 7 THEN 'SMALLINT'", | ||
| " WHEN 8 THEN 'INTEGER'", | ||
| " WHEN 10 THEN 'FLOAT'", | ||
| " WHEN 12 THEN 'DATE'", | ||
| " WHEN 13 THEN 'TIME'", | ||
| " WHEN 14 THEN 'CHAR'", | ||
| " WHEN 16 THEN 'BIGINT'", | ||
| " WHEN 23 THEN 'BOOLEAN'", | ||
| " WHEN 27 THEN 'DOUBLE PRECISION'", | ||
| " WHEN 35 THEN 'TIMESTAMP'", | ||
| " WHEN 37 THEN 'VARCHAR'", | ||
| " WHEN 261 THEN 'BLOB'", | ||
| " ELSE 'UNKNOWN'", | ||
| ' END AS "Type",', | ||
| " IIF(rf.RDB$NULL_FLAG = 1, 'NO', 'YES') AS \"Null\",", | ||
| ' rf.RDB$DEFAULT_SOURCE AS "Default",', |
There was a problem hiding this comment.
🧩 Analysis chain
🌐 Web query:
In Firebird metadata, which columns from RDB$FIELDS / RDB$RELATION_FIELDS are needed to distinguish VARCHAR length and NUMERIC/DECIMAL precision+scale/subtype beyond the base RDB$FIELD_TYPE code?
💡 Result:
To fully distinguish VARCHAR length and NUMERIC/DECIMAL precision/scale/subtype beyond the base RDB$FIELD_TYPE, you need these metadata columns (typically by joining RDB$RELATION_FIELDS.RDB$FIELD_SOURCE to RDB$FIELDS.RDB$FIELD_NAME) [2]:
VARCHAR / CHAR
RDB$FIELDS.RDB$CHARACTER_LENGTH— declared length in characters (what you usually want forCHAR/VARCHAR) [1]RDB$FIELDS.RDB$FIELD_LENGTH— max length in bytes (depends on character set; not reliable as “VARCHAR(n)” by itself) [1]RDB$FIELDS.RDB$CHARACTER_SET_ID(and optionally collation) — needed to interpret byte-length vs character-length correctly [1]
NUMERIC / DECIMAL (fixed-point)
(Stored using an integer RDB$FIELD_TYPE, so you must look at these too.)
RDB$FIELDS.RDB$FIELD_SUB_TYPE— distinguishesNUMERICvsDECIMALfor integer storage types (1= NUMERIC,2= DECIMAL) [2]RDB$FIELDS.RDB$FIELD_PRECISION— total digits (precision) [1]RDB$FIELDS.RDB$FIELD_SCALE— scale (negative value = digits after decimal point) [1]
Linking column (table/view column → domain/field definition):
RDB$RELATION_FIELDS.RDB$FIELD_SOURCE→RDB$FIELDS.RDB$FIELD_NAME[2]
Sources: Firebird system tables reference for RDB$FIELDS and RDB$RELATION_FIELDS [1][2], plus note that RDB$FIELD_LENGTH is byte length and you need RDB$CHARACTER_LENGTH for CHAR/VARCHAR [3].
[1] https://fb5doc.tetrasys.fi/The_Firebird_5.0_Language_Reference/fblangref50-appx04-systables
[2] https://firebirdsql.org/file/documentation/chunk/en/refdocs/fblangref40/fblangref-appx04-fields.html
[3] https://stackoverflow.com/questions/51190573/firebird-list-domains-and-data-types
🏁 Script executed:
# Check the structure of packages to understand the dialect organization
git ls-files "packages/*/src/query-generator.ts" "packages/*/src/query-generator.js" | head -20Repository: sequelize/sequelize
Length of output: 454
🏁 Script executed:
# Read the Firebird query-generator.ts around lines 128-144
head -150 packages/firebird/src/query-generator.ts | tail -30Repository: sequelize/sequelize
Length of output: 1289
🏁 Script executed:
# Check if there's a base query-generator that should also be updated
find packages -type f -name "query-generator.ts" -o -name "query-generator.js" | sortRepository: sequelize/sequelize
Length of output: 508
🏁 Script executed:
# Read the full describeTableQuery method to see all selected columns
sed -n '123,150p' packages/firebird/src/query-generator.tsRepository: sequelize/sequelize
Length of output: 1223
🏁 Script executed:
# Check the base query-generator describeTableQuery method
grep -A 50 "describeTableQuery" packages/core/src/abstract-dialect/query-generator.js | head -70Repository: sequelize/sequelize
Length of output: 45
🏁 Script executed:
# Look for any existing use of RDB$CHARACTER_LENGTH, RDB$FIELD_PRECISION, RDB$FIELD_SCALE in Firebird
rg "RDB\$CHARACTER_LENGTH|RDB\$FIELD_PRECISION|RDB\$FIELD_SCALE|RDB\$FIELD_SUB_TYPE" packages/firebird/Repository: sequelize/sequelize
Length of output: 45
🏁 Script executed:
# Check what the full describeTableQuery looks like in Firebird - need to see if it continues
sed -n '120,160p' packages/firebird/src/query-generator.tsRepository: sequelize/sequelize
Length of output: 1766
🏁 Script executed:
# Check if there are other Firebird-specific implementations that handle type projection better
rg "describeTableQuery" packages/firebird/Repository: sequelize/sequelize
Length of output: 168
🏁 Script executed:
# Verify the base implementation for reference
rg -A 40 "describeTableQuery" packages/core/src/abstract-dialect/query-generator.js | head -50Repository: sequelize/sequelize
Length of output: 45
🏁 Script executed:
# Check how other dialects (MySQL, PostgreSQL) handle type projection in describeTableQuery
rg -A 30 "describeTableQuery" packages/mysql/src/query-generator.js | head -40Repository: sequelize/sequelize
Length of output: 45
🏁 Script executed:
# Also check PostgreSQL for comparison
rg -A 30 "describeTableQuery" packages/postgres/src/query-generator.js | head -40Repository: sequelize/sequelize
Length of output: 45
🏁 Script executed:
# Search more broadly for describeTableQuery across all dialects
grep -r "describeTableQuery" packages/*/src/query-generator.* | head -20Repository: sequelize/sequelize
Length of output: 168
🏁 Script executed:
# Check if there's any code that processes the Type result from describeTableQuery
rg "describeTableQuery" packages/core/src/ -A 5 | head -30Repository: sequelize/sequelize
Length of output: 1251
🏁 Script executed:
# Look for any type resolution logic in Firebird package
rg -i "varchar|numeric|decimal|precision|scale" packages/firebird/src/ --type tsRepository: sequelize/sequelize
Length of output: 1372
🏁 Script executed:
# Check how the result of describeTableQuery is used/parsed
rg "describeTableQuery" packages/core/src/abstract-dialect/ -B 2 -A 10 | head -40Repository: sequelize/sequelize
Length of output: 2624
🏁 Script executed:
# Look at the DECIMAL and VARCHAR implementations in Firebird to understand what precision/scale should be captured
cat packages/firebird/src/_internal/data-types-overrides.ts | head -100Repository: sequelize/sequelize
Length of output: 2425
🏁 Script executed:
# Check if there's any logic that expects full type strings from describeTableQuery
rg "Type.*VARCHAR|Type.*DECIMAL|Type.*NUMERIC" packages/ -iRepository: sequelize/sequelize
Length of output: 13398
🏁 Script executed:
# Check if describeTableQuery results are used to reconstruct attributes
rg "describeTableQuery|DESCRIBE" packages/core/src/abstract-dialect/query-interface-typescript.ts -B 5 -A 15Repository: sequelize/sequelize
Length of output: 1224
🏁 Script executed:
# Look for any logic that might parse the Type column back into DataType objects
rg "parseTypeString|parseType|Type.*varchar|Type.*decimal" packages/ -i --type ts --type js | grep -i firebirdRepository: sequelize/sequelize
Length of output: 245
🏁 Script executed:
# Verify if there are tests for describeTable in Firebird
find packages/firebird -name "*.test.*" -o -name "*.spec.*" | xargs grep -l "describeTable" 2>/dev/nullRepository: sequelize/sequelize
Length of output: 47
🏁 Script executed:
# Check if there are any integration tests for describeTable
find packages -name "*.test.ts" -o -name "*.test.js" | xargs grep -l "describeTable" | head -5Repository: sequelize/sequelize
Length of output: 357
🏁 Script executed:
# Look at one of these tests to understand what describeTable output is expected to contain
rg -A 30 "describeTable" packages/core/test/integration/query-interface/describeTable.test.js | head -50Repository: sequelize/sequelize
Length of output: 1913
🏁 Script executed:
# Confirm the data-types file shows DECIMAL and STRING support precision/scale/length
cat packages/firebird/src/_internal/data-types-overrides.ts | grep -A 10 "class DECIMAL\|class STRING\|class CHAR"Repository: sequelize/sequelize
Length of output: 980
describeTable loses type fidelity by omitting length and precision metadata.
The CASE statement uses only RDB$FIELD_TYPE, so VARCHAR(32) and VARCHAR(255) both return "VARCHAR", and NUMERIC/DECIMAL columns collapse to their base storage type (INTEGER, BIGINT). This makes schema introspection and diffs unreliable.
Include RDB$CHARACTER_LENGTH for string types, RDB$FIELD_SUB_TYPE, RDB$FIELD_PRECISION, and RDB$FIELD_SCALE for numeric types to reconstruct the full type signature.
| " IIF(rc.RDB$CONSTRAINT_TYPE = 'PRIMARY KEY', 'PRI', '') AS \"Key\"", | ||
| 'FROM RDB$RELATION_FIELDS rf', | ||
| 'JOIN RDB$FIELDS f ON f.RDB$FIELD_NAME = rf.RDB$FIELD_SOURCE', | ||
| 'LEFT JOIN RDB$INDEX_SEGMENTS iseg ON iseg.RDB$FIELD_NAME = rf.RDB$FIELD_NAME', | ||
| 'LEFT JOIN RDB$RELATION_CONSTRAINTS rc', | ||
| ' ON rc.RDB$INDEX_NAME = iseg.RDB$INDEX_NAME', | ||
| ' AND rc.RDB$RELATION_NAME = rf.RDB$RELATION_NAME', | ||
| " AND rc.RDB$CONSTRAINT_TYPE = 'PRIMARY KEY'", |
There was a problem hiding this comment.
The PK lookup joins every same-named column in the database.
RDB$INDEX_SEGMENTS is joined on RDB$FIELD_NAME alone, so a common column like id will match index segments from unrelated tables. That can duplicate rows and make "Key" unstable. Join the table’s primary-key constraint first, then match its segments back to the current field.
🔧 Suggested fix
- " IIF(rc.RDB$CONSTRAINT_TYPE = 'PRIMARY KEY', 'PRI', '') AS \"Key\"",
+ " IIF(iseg.RDB$FIELD_NAME IS NOT NULL, 'PRI', '') AS \"Key\"",
...
- 'LEFT JOIN RDB$INDEX_SEGMENTS iseg ON iseg.RDB$FIELD_NAME = rf.RDB$FIELD_NAME',
- 'LEFT JOIN RDB$RELATION_CONSTRAINTS rc',
- ' ON rc.RDB$INDEX_NAME = iseg.RDB$INDEX_NAME',
- ' AND rc.RDB$RELATION_NAME = rf.RDB$RELATION_NAME',
- " AND rc.RDB$CONSTRAINT_TYPE = 'PRIMARY KEY'",
+ 'LEFT JOIN RDB$RELATION_CONSTRAINTS rc',
+ ' ON rc.RDB$RELATION_NAME = rf.RDB$RELATION_NAME',
+ " AND rc.RDB$CONSTRAINT_TYPE = 'PRIMARY KEY'",
+ 'LEFT JOIN RDB$INDEX_SEGMENTS iseg',
+ ' ON iseg.RDB$INDEX_NAME = rc.RDB$INDEX_NAME',
+ ' AND iseg.RDB$FIELD_NAME = rf.RDB$FIELD_NAME',🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.
In `@packages/firebird/src/query-generator.ts` around lines 145 - 152, The PK join
is matching RDB$INDEX_SEGMENTS by field name only (alias iseg) which pulls
segments from any table with the same column name; change the join order to
first LEFT JOIN RDB$RELATION_CONSTRAINTS rc ON rc.RDB$RELATION_NAME =
rf.RDB$RELATION_NAME AND rc.RDB$CONSTRAINT_TYPE = 'PRIMARY KEY' and then LEFT
JOIN RDB$INDEX_SEGMENTS iseg ON iseg.RDB$INDEX_NAME = rc.RDB$INDEX_NAME AND
iseg.RDB$FIELD_NAME = rf.RDB$FIELD_NAME so the segment match is scoped to the
relation's primary-key index (use the aliases rf, rc, iseg shown in the diff).
| if (this.isInsertQuery()) { | ||
| if (rows.length > 0) { | ||
| this.handleInsertQuery(rows[0]); | ||
|
|
||
| return [rows[0], 1]; | ||
| } | ||
|
|
||
| return [undefined, 1]; | ||
| } | ||
|
|
||
| if (this.isUpdateQuery()) { | ||
| return [rows, rows.length]; | ||
| } | ||
|
|
||
| if (this.isDeleteQuery()) { | ||
| return rows.length; | ||
| } |
There was a problem hiding this comment.
🧩 Analysis chain
🌐 Web query:
node-firebird npm how to get affected rows count
💡 Result:
node-firebird doesn’t reliably expose an “affected rows” number in the JS callback result (it mainly returns row data arrays), so the common approach is to ask Firebird itself for the count. (npmjs.com)
Recommended: wrap the DML in EXECUTE BLOCK and return ROW_COUNT
Firebird provides ROW_COUNT, which is the number of rows affected by the most recent DML statement in that block. (firebirdsql.org)
const sql = `
EXECUTE BLOCK (P_ID INTEGER = ?) RETURNS (AFFECTED INTEGER) AS
BEGIN
UPDATE MY_TABLE SET COL = 1 WHERE ID = :P_ID;
AFFECTED = ROW_COUNT;
SUSPEND;
END
`;
db.query(sql, [id], (err, rows) => {
if (err) throw err;
const affected = rows[0].AFFECTED; // number of updated rows
});Alternative: UPDATE ... RETURNING ... and count returned rows
Firebird supports UPDATE ... RETURNING to return values from the affected rows; you can count the rows returned (best only if you expect small row counts). (firebirdsql.org)
Citations:
- 1: https://www.npmjs.com/package/node-firebird?utm_source=openai
- 2: https://firebirdsql.org/file/documentation/chunk/en/refdocs/fblangref50/fblangref50-contextvars-row-count.html?utm_source=openai
- 3: https://firebirdsql.org/file/documentation/chunk/en/refdocs/fblangref40/fblangref40-dml-update.html?utm_source=openai
🏁 Script executed:
wc -l packages/firebird/src/query.tsRepository: sequelize/sequelize
Length of output: 97
🏁 Script executed:
cat -n packages/firebird/src/query.ts | sed -n '40,90p'Repository: sequelize/sequelize
Length of output: 1685
🏁 Script executed:
# Look for the handleInsertQuery implementation
rg -n "handleInsertQuery" packages/firebird/src/query.ts -A 20Repository: sequelize/sequelize
Length of output: 495
🏁 Script executed:
# Check the broader context of this file
head -n 100 packages/firebird/src/query.tsRepository: sequelize/sequelize
Length of output: 2748
🏁 Script executed:
# Find AbstractQuery class
fd -t f "abstract" packages/core/src | grep -i queryRepository: sequelize/sequelize
Length of output: 45
🏁 Script executed:
# Look for INSERT/UPDATE/DELETE SQL generation
rg -n "isInsertQuery|isUpdateQuery|isDeleteQuery" packages/firebird/src/ -A 2 -B 2Repository: sequelize/sequelize
Length of output: 855
🏁 Script executed:
# Check what SQL is being generated for inserts
rg -n "INSERT INTO" packages/firebird/src/Repository: sequelize/sequelize
Length of output: 45
🏁 Script executed:
# Look at how bulk inserts might be handled
rg -n "bulk" packages/firebird/src/ -iRepository: sequelize/sequelize
Length of output: 45
🏁 Script executed:
# Find the AbstractQuery class location
find packages -name "*.ts" -type f | xargs grep -l "class AbstractQuery"Repository: sequelize/sequelize
Length of output: 474
🏁 Script executed:
# Check what's in the core packages
ls -la packages/core/src/Repository: sequelize/sequelize
Length of output: 2665
🏁 Script executed:
# Look for how other dialects handle this
fd -t f "query.ts" packages/*/src/Repository: sequelize/sequelize
Length of output: 137
🏁 Script executed:
# Check the git history or comments in the firebird query to understand design
head -n 50 packages/firebird/src/query.tsRepository: sequelize/sequelize
Length of output: 1551
🏁 Script executed:
# Look at AbstractQuery implementation
head -n 200 packages/core/src/abstract-dialect/query.tsRepository: sequelize/sequelize
Length of output: 7317
🏁 Script executed:
# Search for how other dialects handle INSERT/UPDATE/DELETE responses
for file in packages/*/src/query.ts; do
if [ -f "$file" ]; then
echo "=== $file ==="
grep -A 10 "isInsertQuery()" "$file" 2>/dev/null || true
fi
doneRepository: sequelize/sequelize
Length of output: 310
🏁 Script executed:
# Look for test files that might show expected behavior
find packages/firebird -name "*.test.*" -o -name "*.spec.*"Repository: sequelize/sequelize
Length of output: 45
🏁 Script executed:
# Check if RETURNING is used anywhere in firebird dialect
rg -n "RETURNING" packages/firebird/Repository: sequelize/sequelize
Length of output: 142
🏁 Script executed:
# Check the INSERT handling - look for RETURNING usage
rg -n "INSERT" packages/firebird/src/ -A 3 -B 3Repository: sequelize/sequelize
Length of output: 2414
🏁 Script executed:
# Look at dialect.ts to understand the RETURNING limitation better
cat -n packages/firebird/src/dialect.ts | sed -n '40,80p'Repository: sequelize/sequelize
Length of output: 1401
🏁 Script executed:
# Check what the query generator produces for UPDATE/DELETE
rg -n "UPDATE|DELETE" packages/firebird/src/query-generator.ts -A 2 -B 2Repository: sequelize/sequelize
Length of output: 443
🏁 Script executed:
# Look for test expectations or integration tests
find packages/firebird -type f \( -name "*.test.*" -o -name "*.spec.*" \) -exec ls -la {} \;Repository: sequelize/sequelize
Length of output: 45
🏁 Script executed:
# Check if RETURNING is used in INSERT queries
rg -n "RETURNING" packages/firebird/src/query-generator.ts -B 5 -A 5Repository: sequelize/sequelize
Length of output: 45
🏁 Script executed:
# Look for INSERT query generation
rg -n "insertQuery" packages/firebird/src/ -B 3 -A 10Repository: sequelize/sequelize
Length of output: 45
🏁 Script executed:
# Check how parent class handles INSERT RETURNING
rg -n "RETURNING" packages/core/src/abstract-dialect/query-generator.ts -B 3 -A 3 | head -60Repository: sequelize/sequelize
Length of output: 156
🏁 Script executed:
# Understand the actual impact: check if bulk insert is even possible
rg -n "bulkInsert" packages/firebird/src/ -B 2 -A 5Repository: sequelize/sequelize
Length of output: 45
🏁 Script executed:
# List files in abstract-dialect
ls -la packages/core/src/abstract-dialect/Repository: sequelize/sequelize
Length of output: 1572
🏁 Script executed:
# Search for RETURNING in all TypeScript files
rg -t ts "RETURNING" packages/ | head -30Repository: sequelize/sequelize
Length of output: 4532
🏁 Script executed:
# Check how INSERT queries are generated in Firebird
fd -t f "query-generator" packages/firebird/Repository: sequelize/sequelize
Length of output: 153
🏁 Script executed:
# Look for return value handling in INSERT
rg -n "handleInsertQuery\|insertQuery" packages/firebird/src/query.ts -B 5 -A 10Repository: sequelize/sequelize
Length of output: 45
🏁 Script executed:
# Look at the Firebird query-generator files
cat packages/firebird/src/query-generator.ts | head -100Repository: sequelize/sequelize
Length of output: 3657
🏁 Script executed:
# Check if Firebird query generator has custom INSERT handling
rg -n "insertQuery\|INSERT" packages/firebird/src/query-generator.ts -B 2 -A 5Repository: sequelize/sequelize
Length of output: 45
🏁 Script executed:
# Look at Firebird query generator internal
cat packages/firebird/src/query-generator.internal.tsRepository: sequelize/sequelize
Length of output: 1137
🏁 Script executed:
# Check what returnValues means in the dialect
rg -n "returnValues" packages/core/src/abstract-dialect/ -B 2 -A 2Repository: sequelize/sequelize
Length of output: 7442
🏁 Script executed:
# Check if bulk insert is actually a feature being used
rg -n "bulk" packages/firebird/src/ -i -B 2 -A 2Repository: sequelize/sequelize
Length of output: 45
🏁 Script executed:
# Look at how INSERT queries are actually constructed
rg -n "INSERT INTO" packages/core/src/abstract-dialect/ -B 2 -A 5 | head -50Repository: sequelize/sequelize
Length of output: 45
🏁 Script executed:
# Check if the query.ts response handler receives RETURNING results for UPDATE/DELETE
rg -n "UPDATE.*RETURNING\|DELETE.*RETURNING" packages/firebird/src/ -iRepository: sequelize/sequelize
Length of output: 45
🏁 Script executed:
# Understand: does Firebird return affected rows somehow without RETURNING?
rg -n "node-firebird" packages/firebird/ -B 2 -A 2Repository: sequelize/sequelize
Length of output: 4259
🏁 Script executed:
# Check if there are any tests or integration tests that show expected behavior
find packages/firebird -type f -name "*.test.*" -o -name "*.spec.*" 2>/dev/nullRepository: sequelize/sequelize
Length of output: 45
🏁 Script executed:
# Check if maybe affected rows are passed in some other way
rg -n "affected|count" packages/firebird/src/query.ts -iRepository: sequelize/sequelize
Length of output: 45
🏁 Script executed:
# Look at the actual result structure from node-firebird
rg -n "conn.query\|result" packages/firebird/src/query.ts -B 3 -A 3Repository: sequelize/sequelize
Length of output: 45
🏁 Script executed:
# Check if there's documentation or comments about the known limitation
cat packages/firebird/readme.mdRepository: sequelize/sequelize
Length of output: 3225
Affected row counts are inaccurate due to Firebird driver limitations.
The current implementation has two issues:
- Insert queries: Returns hardcoded
1regardless of actual rows inserted, preventing bulk inserts from reporting correct counts. - Update/delete queries: Returns
rows.lengthwhich is always0because Firebird doesn't support theRETURNINGclause forUPDATEandDELETEstatements—only forINSERT.
Firebird provides ROW_COUNT within EXECUTE BLOCK to retrieve actual affected row counts. Consider refactoring DML queries to wrap them in EXECUTE BLOCK and use ROW_COUNT (as documented in Firebird's row count context variable) to return accurate counts for all DML operations.
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.
In `@packages/firebird/src/query.ts` around lines 54 - 70, The current DML
handling in the block using isInsertQuery(), isUpdateQuery(), isDeleteQuery()
returns hardcoded/incorrect counts; wrap INSERT/UPDATE/DELETE executions in an
EXECUTE BLOCK that captures ROW_COUNT and returns it (and keep the INSERT
RETURNING row when available) so counts reflect actual affected rows. Update the
logic in the function containing handleInsertQuery() to: for inserts, execute a
wrapped EXECUTE BLOCK that performs the INSERT (producing RETURNING row if
needed) and returns ROW_COUNT alongside the returned row so you can return
[insertedRow, rowCount]; for updates and deletes replace the current rows.length
return by executing the DML inside an EXECUTE BLOCK that returns ROW_COUNT and
return that count (or [rows, rowCount] if your API expects rows plus count).
Ensure you reuse/extend handleInsertQuery(), and adjust callers to accept the
new rowCount value instead of the hardcoded 1 or rows.length.
| #normaliseRow(row: Record<string, unknown>): Record<string, unknown> { | ||
| const out: Record<string, unknown> = {}; | ||
|
|
||
| for (const [k, v] of Object.entries(row)) { | ||
| out[k.toLowerCase()] = v instanceof Buffer ? v.toString('utf8') : v; | ||
| } | ||
|
|
||
| out.dataValues = out; | ||
| out._previousDataValues = {}; | ||
|
|
||
| return out; | ||
| } |
There was a problem hiding this comment.
Avoid injecting dataValues and _previousDataValues in row normalization.
These properties (dataValues, _previousDataValues) are Model instance internals that should be managed by Sequelize's model hydration layer, not raw query results. Adding them here may cause issues with:
- Raw queries expecting plain objects
handleSelectQuerywhich builds Model instances separately- Double-wrapping when model instances are created
🐛 Proposed fix - remove artificial dataValues injection
`#normaliseRow`(row: Record<string, unknown>): Record<string, unknown> {
const out: Record<string, unknown> = {};
for (const [k, v] of Object.entries(row)) {
out[k.toLowerCase()] = v instanceof Buffer ? v.toString('utf8') : v;
}
- out.dataValues = out;
- out._previousDataValues = {};
-
return out;
}🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.
In `@packages/firebird/src/query.ts` around lines 136 - 147, The `#normaliseRow`
function is incorrectly adding Model internals by setting out.dataValues and
out._previousDataValues; remove those two assignments so the function only
lowercases keys and converts Buffers to UTF-8 strings, returning a plain object,
and ensure any code calling `#normaliseRow` relies on Sequelize's hydration (or
uses the existing handleSelectQuery) to create Model instances rather than
expecting these injected properties.
There was a problem hiding this comment.
Actionable comments posted: 1
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.
Inline comments:
In @.github/workflows/pr-title.yml:
- Line 44: Update the misspelled scope string "firebase" to "firebird" in the PR
title validation workflow; locate the literal "firebase" token in the pr-title
workflow (the scope list or regex entry) and replace it with "firebird" so
Firebird dialect PRs validate correctly.
ℹ️ Review info
⚙️ Run configuration
Configuration used: defaults
Review profile: CHILL
Plan: Pro
Run ID: a56a25ce-c841-4671-bb88-db84c7d23f27
⛔ Files ignored due to path filters (1)
yarn.lockis excluded by!**/yarn.lock,!**/*.lock
📒 Files selected for processing (1)
.github/workflows/pr-title.yml
| sqlite3 | ||
| utils | ||
| validator.js | ||
| firebase |
There was a problem hiding this comment.
Typo: firebase should be firebird.
The PR adds Firebird dialect support, but the scope is misspelled as "firebase" (Google's mobile platform) instead of "firebird" (the SQL database). This will cause PR title validation to fail for future Firebird-related PRs.
🐛 Proposed fix
- firebase
+ firebird📝 Committable suggestion
‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.
| firebase | |
| firebird |
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.
In @.github/workflows/pr-title.yml at line 44, Update the misspelled scope
string "firebase" to "firebird" in the PR title validation workflow; locate the
literal "firebase" token in the pr-title workflow (the scope list or regex
entry) and replace it with "firebird" so Firebird dialect PRs validate
correctly.
- Introduced Firebird dialect with connection manager, query generator, and query interface. - Implemented Firebird-specific data types and overrides for Sequelize. - Added support for Firebird's SQL syntax differences, including handling of LIMIT/OFFSET, auto-increment via sequences, and BLOB handling. - Created necessary configuration files and TypeScript definitions for the Firebird package. - Updated GitHub workflow to include Firebase in the PR title check.
There was a problem hiding this comment.
Actionable comments posted: 7
Caution
Some comments are outside the diff and can’t be posted inline due to platform limitations.
⚠️ Outside diff range comments (1)
packages/core/src/sequelize-typescript.ts (1)
199-212:⚠️ Potential issue | 🔴 CriticalAdd the Firebird import mapping too.
SUPPORTED_DIALECTSnow accepts'firebird', butpackages/core/src/sequelize.internals.tsstill has nocase 'firebird'inimportDialect().new Sequelize({ dialect: 'firebird', ... })will throw at runtime instead of loading@sequelize/firebird.Suggested fix in `packages/core/src/sequelize.internals.ts`
case 'oracle': // eslint-disable-next-line import/no-extraneous-dependencies -- legacy function, will be removed. User needs to install the dependency themselves return require('@sequelize/oracle').OracleDialect; + case 'firebird': + // eslint-disable-next-line import/no-extraneous-dependencies -- legacy function, will be removed. User needs to install the dependency themselves + return require('@sequelize/firebird').FirebirdDialect; default: throw new Error( - `The dialect ${dialect} is not natively supported. Native dialects: mariadb, mssql, mysql, postgres, sqlite3, ibmi, db2, oracle and snowflake.`, + `The dialect ${dialect} is not natively supported. Native dialects: mariadb, mssql, mysql, postgres, sqlite3, ibmi, db2, oracle, snowflake and firebird.`, );🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed. In `@packages/core/src/sequelize-typescript.ts` around lines 199 - 212, SUPPORTED_DIALECTS now includes 'firebird' but importDialect() in sequelize.internals.ts lacks a case for it; add a 'firebird' branch in the importDialect function to return the module name '@sequelize/firebird' (same pattern used for other dialects like 'postgres'/'mysql'), and ensure the import mapping follows the existing switch/case or mapping structure so new Sequelize({ dialect: 'firebird', ... }) loads the `@sequelize/firebird` package at runtime without throwing.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.
Inline comments:
In `@packages/firebird/readme.md`:
- Line 67: Update the documented filename casing to match the actual file:
change the listed entry `README.md` to `readme.md` in the package tree shown in
packages/firebird/readme.md so the displayed structure matches the real filename
on case-sensitive filesystems; locate the package tree string (the line
containing "├── README.md") and replace it with "├── readme.md".
- Around line 63-79: The README's fenced package-tree block is unlabeled and
triggers MD040; edit the README's package-tree code fence (the block containing
the packages/firebird/ tree) to add a language identifier (e.g. ```text)
immediately after the opening backticks so the block becomes a labeled code
fence like ```text.
In `@packages/firebird/src/dialect.ts`:
- Around line 53-55: The dialect currently sets supports.returnValues =
'returning' which wrongly signals RETURNING support for INSERT/UPDATE/DELETE;
change the Firebird dialect to only advertise INSERT RETURNING (e.g., set
supports.returnValues to 'insert' or false) and/or add explicit overrides in the
Firebird query generator: implement updateQuery() and deleteQuery() in the
Firebird query generator to prevent appending RETURNING clauses (or strip them)
so only INSERT uses RETURNING; update references in dialect.ts
(supports.returnValues) and the Firebird query generator methods
updateQuery()/deleteQuery() accordingly.
- Around line 95-98: The truncate dialect metadata currently only sets
restartIdentity; add an explicit declaration that cascade is unsupported by
setting truncate.cascade to false (or marking it unsupported) so calls that pass
{ cascade: true } are rejected instead of silently falling back in
packages/firebird/src/query-generator.ts; update the truncate object in
dialect.ts (the truncate property) to include cascade: false and ensure any
validation or type hinting reflects this change.
In `@packages/firebird/src/query-interface.ts`:
- Around line 1-9: The FirebirdQueryInterface subclass is empty so
Firebird-specific DDL helpers (createSequenceQuery,
createAutoIncrementTriggerQuery) are never invoked; override createTable and
addColumn on the FirebirdQueryInterface class to detect autoIncrement columns
and call the helpers (createSequenceQuery and createAutoIncrementTriggerQuery)
after delegating to the parent via super.createTable / super.addColumn, ensuring
you preserve returned results and only run the sequence/trigger creation for
columns with autoIncrement metadata; add any necessary ordering (create sequence
before trigger) and error handling consistent with the project patterns.
In `@packages/firebird/src/query.ts`:
- Around line 16-18: getInsertIdField() currently returns the hardcoded string
'id' which fails for tables whose generated key uses a different column name;
change getInsertIdField() (in packages/firebird/src/query.ts) to derive the
actual generated-key column name instead of hardcoding it — e.g. read and return
the generated key name captured from the insert response/driver metadata (the
value stored when executing the INSERT with RETURNING or from the insert result
object like generatedKeys/insertIdName) or fall back to the model's primaryKey
property if available; update any code that calls getInsertIdField() to ensure
the real generated-column name produced by the insert is stored and returned.
- Around line 139-141: The loop that lower-cases keys and converts Buffer values
currently turns all Buffers into UTF-8 strings (for const [k, v] of
Object.entries(row) { out[k.toLowerCase()] = v instanceof Buffer ?
v.toString('utf8') : v; }), which corrupts binary BLOB/OCTETS; change this to
only call v.toString('utf8') when the read option for text BLOBs (e.g.
blobAsText) is set, otherwise leave Buffer values intact—update the
row-processing block that writes into out (and any surrounding function that
receives the blobAsText flag) to check the blobAsText flag before converting
Buffers to strings.
---
Outside diff comments:
In `@packages/core/src/sequelize-typescript.ts`:
- Around line 199-212: SUPPORTED_DIALECTS now includes 'firebird' but
importDialect() in sequelize.internals.ts lacks a case for it; add a 'firebird'
branch in the importDialect function to return the module name
'@sequelize/firebird' (same pattern used for other dialects like
'postgres'/'mysql'), and ensure the import mapping follows the existing
switch/case or mapping structure so new Sequelize({ dialect: 'firebird', ... })
loads the `@sequelize/firebird` package at runtime without throwing.
ℹ️ Review info
⚙️ Run configuration
Configuration used: defaults
Review profile: CHILL
Plan: Pro
Run ID: f65e48ad-811f-49e0-af9e-9e6be7c5506d
⛔ Files ignored due to path filters (1)
yarn.lockis excluded by!**/yarn.lock,!**/*.lock
📒 Files selected for processing (18)
.github/workflows/pr-title.ymlpackages/core/src/sequelize-typescript.tspackages/core/src/sequelize.jspackages/core/src/utils/dialect.tspackages/firebird/.eslintrc.jspackages/firebird/package.jsonpackages/firebird/readme.mdpackages/firebird/src/_internal/data-types-overrides.tspackages/firebird/src/connection-manager.tspackages/firebird/src/dialect.tspackages/firebird/src/index.tspackages/firebird/src/query-generator.internal.tspackages/firebird/src/query-generator.tspackages/firebird/src/query-interface.tspackages/firebird/src/query-interface.types.tspackages/firebird/src/query.tspackages/firebird/tsconfig.jsonpackages/firebird/typedoc.json
✅ Files skipped from review due to trivial changes (1)
- packages/firebird/src/index.ts
🚧 Files skipped from review as they are similar to previous changes (8)
- .github/workflows/pr-title.yml
- packages/firebird/.eslintrc.js
- packages/firebird/tsconfig.json
- packages/firebird/package.json
- packages/firebird/typedoc.json
- packages/firebird/src/query-interface.types.ts
- packages/core/src/utils/dialect.ts
- packages/core/src/sequelize.js
| ``` | ||
| packages/firebird/ | ||
| ├── package.json | ||
| ├── tsconfig.json | ||
| ├── README.md | ||
| └── src/ | ||
| ├── index.ts ← barrel export | ||
| ├── index.mjs ← ESM re-export | ||
| ├── dialect.ts ← FirebirdDialect class | ||
| ├── connection-manager.ts ← connect / disconnect via node-firebird | ||
| ├── query-generator.ts ← SQL builder (FIRST/SKIP, sequences…) | ||
| ├── query-interface.ts ← DDL: createTable, describeTable, etc. | ||
| ├── query-interface.types.ts ← Public types | ||
| ├── query.ts ← Query executor + result mapping | ||
| └── _internal/ | ||
| └── data-types-overrides.ts ← Firebird type mappings | ||
| ``` |
There was a problem hiding this comment.
Add a language to the fenced package-tree block.
This block is currently unlabeled, so it trips MD040 and will keep Markdown lint noisy.
Suggested fix
-```
+```text
packages/firebird/
├── package.json
├── tsconfig.json
├── README.md
└── src/
├── index.ts ← barrel export
├── index.mjs ← ESM re-export
├── dialect.ts ← FirebirdDialect class
├── connection-manager.ts ← connect / disconnect via node-firebird
├── query-generator.ts ← SQL builder (FIRST/SKIP, sequences…)
├── query-interface.ts ← DDL: createTable, describeTable, etc.
├── query-interface.types.ts ← Public types
├── query.ts ← Query executor + result mapping
└── _internal/
└── data-types-overrides.ts ← Firebird type mappings</details>
<!-- suggestion_start -->
<details>
<summary>📝 Committable suggestion</summary>
> ‼️ **IMPORTANT**
> Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.
```suggestion
🧰 Tools
🪛 markdownlint-cli2 (0.21.0)
[warning] 63-63: Fenced code blocks should have a language specified
(MD040, fenced-code-language)
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.
In `@packages/firebird/readme.md` around lines 63 - 79, The README's fenced
package-tree block is unlabeled and triggers MD040; edit the README's
package-tree code fence (the block containing the packages/firebird/ tree) to
add a language identifier (e.g. ```text) immediately after the opening backticks
so the block becomes a labeled code fence like ```text.
| packages/firebird/ | ||
| ├── package.json | ||
| ├── tsconfig.json | ||
| ├── README.md |
There was a problem hiding this comment.
Match the documented filename casing to the actual file.
Line 67 lists README.md, but this file is packages/firebird/readme.md. That mismatch makes the package structure inaccurate on case-sensitive filesystems.
Suggested fix
-├── README.md
+├── readme.md📝 Committable suggestion
‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.
| ├── README.md | |
| ├── readme.md |
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.
In `@packages/firebird/readme.md` at line 67, Update the documented filename
casing to match the actual file: change the listed entry `README.md` to
`readme.md` in the package tree shown in packages/firebird/readme.md so the
displayed structure matches the real filename on case-sensitive filesystems;
locate the package tree string (the line containing "├── README.md") and replace
it with "├── readme.md".
| // No native RETURNING except on INSERT | ||
| returnValues: 'returning', | ||
| inserts: { |
There was a problem hiding this comment.
🧩 Analysis chain
🏁 Script executed:
# First, check the exact context in the Firebird dialect file
head -70 packages/firebird/src/dialect.ts | tail -30Repository: sequelize/sequelize
Length of output: 885
🏁 Script executed:
# Search for how returnValues is used in query generators
rg -A 3 -B 3 'returnValues' --type ts packages/*/src/query-generator.ts | head -100Repository: sequelize/sequelize
Length of output: 45
🏁 Script executed:
# Check the Firebird query generator for RETURNING handling
rg -A 5 'RETURNING' packages/firebird/src/query-generator.tsRepository: sequelize/sequelize
Length of output: 45
🏁 Script executed:
# Look for the supports object definition pattern across dialects to understand the returnValues contract
rg -A 2 'supports.*returnValues' packages/*/src/dialect.tsRepository: sequelize/sequelize
Length of output: 45
🏁 Script executed:
# Search for AbstractDialect to find where returnValues is consumed
rg -A 10 'returnValues' packages/core/src/dialects/abstract/index.ts | head -50Repository: sequelize/sequelize
Length of output: 147
🏁 Script executed:
# Look for where RETURNING clauses are generated in update/delete
rg -B 5 -A 5 'updateQuery|deleteQuery' packages/core/src/dialects/abstract/ | grep -A 10 -B 10 -i 'returning' | head -80Repository: sequelize/sequelize
Length of output: 139
🏁 Script executed:
# Check if Firebird query-generator has special handling for update/destroy
cat packages/firebird/src/query-generator.ts | head -100Repository: sequelize/sequelize
Length of output: 3657
🏁 Script executed:
# Search for how other dialects set returnValues
rg 'returnValues:' packages/*/src/dialect.tsRepository: sequelize/sequelize
Length of output: 367
🏁 Script executed:
# Find the core package structure
find packages -name "abstract-dialect*" -o -name "query-generator*" | grep -v node_modules | head -20Repository: sequelize/sequelize
Length of output: 1192
🏁 Script executed:
# Search for returning method/function usage
rg 'returning' packages/firebird/src/query-generator.internal.ts -A 5 -B 5Repository: sequelize/sequelize
Length of output: 45
🏁 Script executed:
# Look at the AbstractQueryGenerator in core
rg -l 'class AbstractQueryGenerator' packages/ --type tsRepository: sequelize/sequelize
Length of output: 246
🏁 Script executed:
# Search for where returning clause is actually added to update/delete queries
rg 'UPDATE|DELETE' packages/firebird/src/query-generator.internal.ts -A 2 | head -50Repository: sequelize/sequelize
Length of output: 45
🏁 Script executed:
# Check if there's any specific returning handling in firebird
rg 'returning' packages/firebird/src/ -iRepository: sequelize/sequelize
Length of output: 203
🏁 Script executed:
# Look at the core query-generator implementation for how returnValues is used
grep -n 'returnValues\|returning' packages/core/src/abstract-dialect/query-generator.js | head -30Repository: sequelize/sequelize
Length of output: 1993
🏁 Script executed:
# Check if there's conditional logic around returning based on the supports flag
rg -B 5 -A 10 'supports.*returning|returnValues' packages/core/src/abstract-dialect/query-generator.js | head -100Repository: sequelize/sequelize
Length of output: 3324
🏁 Script executed:
# Search for UPDATE/DELETE query building in core
rg 'updateQuery|deleteQuery|UPDATE|DELETE' packages/core/src/abstract-dialect/query-generator.js -A 3 | grep -B 3 -A 3 'returning\|RETURNING' | head -60Repository: sequelize/sequelize
Length of output: 238
🏁 Script executed:
# Check query-generator-internal.ts for where returning is handled
cat packages/core/src/abstract-dialect/query-generator-internal.ts | head -150Repository: sequelize/sequelize
Length of output: 5850
🏁 Script executed:
# Verify that Firebird does NOT override updateQuery or deleteQuery
rg 'updateQuery|deleteQuery' packages/firebird/src/query-generator.tsRepository: sequelize/sequelize
Length of output: 45
🏁 Script executed:
# Verify that Firebird does NOT override updateQuery or deleteQuery in internal
rg 'updateQuery|deleteQuery' packages/firebird/src/query-generator.internal.tsRepository: sequelize/sequelize
Length of output: 45
🏁 Script executed:
# Check what the actual return value is for returnValues - is it a string or boolean?
cat packages/firebird/src/dialect.ts | sed -n '40,80p'Repository: sequelize/sequelize
Length of output: 1114
supports.returnValues is too broad for Firebird.
This flag controls RETURNING clause generation for INSERT, UPDATE, and DELETE operations. Setting it to 'returning' tells core generators that RETURNING is universally supported, but the adjacent comment explicitly states Firebird only supports it on INSERT. Without overrides for updateQuery() and deleteQuery() in the Firebird query generator, this will generate invalid SQL on returning UPDATE/DELETE operations.
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.
In `@packages/firebird/src/dialect.ts` around lines 53 - 55, The dialect currently
sets supports.returnValues = 'returning' which wrongly signals RETURNING support
for INSERT/UPDATE/DELETE; change the Firebird dialect to only advertise INSERT
RETURNING (e.g., set supports.returnValues to 'insert' or false) and/or add
explicit overrides in the Firebird query generator: implement updateQuery() and
deleteQuery() in the Firebird query generator to prevent appending RETURNING
clauses (or strip them) so only INSERT uses RETURNING; update references in
dialect.ts (supports.returnValues) and the Firebird query generator methods
updateQuery()/deleteQuery() accordingly.
| truncate: { | ||
| // Firebird has no TRUNCATE TABLE | ||
| restartIdentity: false, | ||
| }, |
There was a problem hiding this comment.
🧩 Analysis chain
🏁 Script executed:
cat -n packages/firebird/src/dialect.ts | head -120Repository: sequelize/sequelize
Length of output: 4498
🏁 Script executed:
fd query-generator packages/firebird/src --type fRepository: sequelize/sequelize
Length of output: 153
🏁 Script executed:
grep -n "cascade" packages/firebird/src/query-generator.tsRepository: sequelize/sequelize
Length of output: 45
🏁 Script executed:
# Check how other dialects handle truncate.cascade
grep -r "truncate.*cascade" packages/*/src/dialect.tsRepository: sequelize/sequelize
Length of output: 45
🏁 Script executed:
# Read query-generator implementation for truncate
grep -A 20 "truncate" packages/firebird/src/query-generator.ts | head -50Repository: sequelize/sequelize
Length of output: 909
🏁 Script executed:
# Check core dialect to understand truncate options
fd dialect.ts packages/core/src --type fRepository: sequelize/sequelize
Length of output: 143
🏁 Script executed:
# Check if cascade is defined as a feature in other dialects
grep -l "truncate" packages/*/src/dialect.tsRepository: sequelize/sequelize
Length of output: 160
🏁 Script executed:
# Check postgres dialect truncate support
sed -n '/truncate:/,/}/p' packages/postgres/src/dialect.ts | head -20Repository: sequelize/sequelize
Length of output: 135
🏁 Script executed:
# Check sqlite3 dialect truncate support
sed -n '/truncate:/,/}/p' packages/sqlite3/src/dialect.ts | head -20Repository: sequelize/sequelize
Length of output: 115
🏁 Script executed:
# Find TRUNCATE_TABLE_QUERY_SUPPORTABLE_OPTIONS definition
rg "TRUNCATE_TABLE_QUERY_SUPPORTABLE_OPTIONS" --type tsRepository: sequelize/sequelize
Length of output: 2231
🏁 Script executed:
# Get the exact definition of TRUNCATE_TABLE_QUERY_SUPPORTABLE_OPTIONS
grep -A 10 "export const TRUNCATE_TABLE_QUERY_SUPPORTABLE_OPTIONS" packages/core/src/abstract-dialect/query-generator-typescript.tsRepository: sequelize/sequelize
Length of output: 381
🏁 Script executed:
# Also check the TruncateTableQueryOptions type definition
rg "interface TruncateTableQueryOptions|type TruncateTableQueryOptions" -A 5 packages/core/srcRepository: sequelize/sequelize
Length of output: 596
🏁 Script executed:
# Check rejectInvalidOptions to understand how it validates
rg "function rejectInvalidOptions|export.*rejectInvalidOptions" -A 15 packages/core/srcRepository: sequelize/sequelize
Length of output: 1365
🏁 Script executed:
# Also verify behavior - check if other dialects declare cascade: false
grep -B 2 -A 4 "truncate:" packages/*/src/dialect.ts | grep -A 4 "cascade"Repository: sequelize/sequelize
Length of output: 417
Declare truncate.cascade as unsupported.
packages/firebird/src/query-generator.ts falls back to plain DELETE FROM for truncate operations. Explicitly declaring cascade: false ensures that passing { cascade: true } is rejected upfront, rather than being silently accepted and ignored.
Suggested fix
truncate: {
// Firebird has no TRUNCATE TABLE
+ cascade: false,
restartIdentity: false,
},🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.
In `@packages/firebird/src/dialect.ts` around lines 95 - 98, The truncate dialect
metadata currently only sets restartIdentity; add an explicit declaration that
cascade is unsupported by setting truncate.cascade to false (or marking it
unsupported) so calls that pass { cascade: true } are rejected instead of
silently falling back in packages/firebird/src/query-generator.ts; update the
truncate object in dialect.ts (the truncate property) to include cascade: false
and ensure any validation or type hinting reflects this change.
| import { AbstractQueryInterface } from '@sequelize/core'; | ||
|
|
||
| /** | ||
| * FirebirdQueryInterface | ||
| * | ||
| * Extends Sequelize's abstract QueryInterface with Firebird-specific DDL | ||
| * operations, most notably auto-increment via SEQUENCE + BEFORE INSERT TRIGGER. | ||
| */ | ||
| export class FirebirdQueryInterface extends AbstractQueryInterface {} |
There was a problem hiding this comment.
Wire the Firebird schema hooks into the query interface.
This subclass is empty, so the new createSequenceQuery / createAutoIncrementTriggerQuery helpers have no Firebird-specific DDL hook here. If autoIncrement is meant to be backed by a sequence + trigger, createTable/addColumn still need overrides that call them.
As per coding guidelines, packages/*/src/query-interface.{js,ts}: Add schema operations for new features in query-interface.ts (preferred) or legacy query-interface.js.
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.
In `@packages/firebird/src/query-interface.ts` around lines 1 - 9, The
FirebirdQueryInterface subclass is empty so Firebird-specific DDL helpers
(createSequenceQuery, createAutoIncrementTriggerQuery) are never invoked;
override createTable and addColumn on the FirebirdQueryInterface class to detect
autoIncrement columns and call the helpers (createSequenceQuery and
createAutoIncrementTriggerQuery) after delegating to the parent via
super.createTable / super.addColumn, ensuring you preserve returned results and
only run the sequence/trigger creation for columns with autoIncrement metadata;
add any necessary ordering (create sequence before trigger) and error handling
consistent with the project patterns.
| getInsertIdField(): string { | ||
| return 'id'; | ||
| } |
There was a problem hiding this comment.
Don't hardcode 'id' as the generated key name.
This only works for models whose auto-increment column is literally id. If Firebird returns user_id, invoice_no, or any other generated column name, the created instance won't get its primary key populated after insert.
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.
In `@packages/firebird/src/query.ts` around lines 16 - 18, getInsertIdField()
currently returns the hardcoded string 'id' which fails for tables whose
generated key uses a different column name; change getInsertIdField() (in
packages/firebird/src/query.ts) to derive the actual generated-key column name
instead of hardcoding it — e.g. read and return the generated key name captured
from the insert response/driver metadata (the value stored when executing the
INSERT with RETURNING or from the insert result object like
generatedKeys/insertIdName) or fall back to the model's primaryKey property if
available; update any code that calls getInsertIdField() to ensure the real
generated-column name produced by the insert is stored and returned.
| for (const [k, v] of Object.entries(row)) { | ||
| out[k.toLowerCase()] = v instanceof Buffer ? v.toString('utf8') : v; | ||
| } |
There was a problem hiding this comment.
Keep binary columns as Buffers.
blobAsText already covers text BLOBs. The remaining Buffer values are binary payloads (DataTypes.BLOB, OCTETS columns, etc.), and converting them to UTF-8 here will corrupt the result on read.
Suggested fix
- out[k.toLowerCase()] = v instanceof Buffer ? v.toString('utf8') : v;
+ out[k.toLowerCase()] = v;🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.
In `@packages/firebird/src/query.ts` around lines 139 - 141, The loop that
lower-cases keys and converts Buffer values currently turns all Buffers into
UTF-8 strings (for const [k, v] of Object.entries(row) { out[k.toLowerCase()] =
v instanceof Buffer ? v.toString('utf8') : v; }), which corrupts binary
BLOB/OCTETS; change this to only call v.toString('utf8') when the read option
for text BLOBs (e.g. blobAsText) is set, otherwise leave Buffer values
intact—update the row-processing block that writes into out (and any surrounding
function that receives the blobAsText flag) to check the blobAsText flag before
converting Buffers to strings.
There was a problem hiding this comment.
Actionable comments posted: 2
♻️ Duplicate comments (8)
packages/firebird/src/connection-manager.ts (1)
74-79:⚠️ Potential issue | 🟡 MinorAlign the documented password default with the actual one.
The JSDoc says the default password is
'masterkey', butconnect()falls back to''. Pick one so configuration docs and runtime behavior match.Also applies to: 149-150
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed. In `@packages/firebird/src/connection-manager.ts` around lines 74 - 79, The JSDoc for the password property currently documents a default of 'masterkey' but connect() actually falls back to an empty string; update the documentation to match runtime behavior by changing the JSDoc default to '' (empty string) for the password property and any other JSDoc occurrences (see the other docblock around the password/join lines referenced), or alternatively change the connect() fallback to 'masterkey' if you prefer that as the real default—ensure consistency between the password?: string JSDoc and the connect() implementation.packages/firebird/src/_internal/data-types-overrides.ts (1)
128-136:⚠️ Potential issue | 🟠 MajorOverride
toBindableValue(), notstringify().
AbstractDataType.escape()serializes DATE values throughtoBindableValue(), so this Firebird-specific formatter is bypassed and the base timestamp format still leaks through. Theas Datecast is also unsafe becausesanitize()can return DayJS/Moment objects.Possible fix
export class DATE extends BaseTypes.DATE { toSql(): string { // Firebird TIMESTAMP = date + time return 'TIMESTAMP'; } - stringify(value: AcceptedDate): string { - const d = this.sanitize(value) as Date; - // Firebird accepts: 'YYYY-MM-DD HH:MM:SS.mmm' - - return ( - `${d.getFullYear()}-${pad(d.getMonth() + 1)}-${pad(d.getDate())} ` + - `${pad(d.getHours())}:${pad(d.getMinutes())}:${pad(d.getSeconds())}.${pad(d.getMilliseconds(), 3)}` - ); + override toBindableValue(value: AcceptedDate): string { + return this._applyTimezone(value).format('YYYY-MM-DD HH:mm:ss.SSS'); } }#!/bin/bash rg -n "escape\\(|toBindableValue\\(|stringify\\(" \ packages/core/src/abstract-dialect/data-types.ts \ packages/firebird/src/_internal/data-types-overrides.ts -C2packages/firebird/src/dialect.ts (3)
53-55:⚠️ Potential issue | 🟠 Major
supports.returnValuesoverstates Firebird support.The adjacent comment says Firebird only supports
RETURNINGonINSERT, but'returning'advertises generic support and lets core generate invalidUPDATE ... RETURNING/DELETE ... RETURNINGSQL unless those paths are overridden.As per coding guidelines, "When adding a dialect feature, update packages/{dialect}/src/dialect.ts to declare feature support flags".
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed. In `@packages/firebird/src/dialect.ts` around lines 53 - 55, The supports.returnValues flag currently set to the generic 'returning' overstates Firebird's capability and allows core to emit UPDATE/DELETE ... RETURNING; change supports.returnValues so it only advertises RETURNING for INSERT (e.g., a structure indicating insert: 'returning' or otherwise disable update/delete returning) and ensure any related places (the inserts configuration and any update/delete code paths) are adjusted so core will not generate UPDATE ... RETURNING or DELETE ... RETURNING for the Firebird dialect.
112-115:⚠️ Potential issue | 🟠 MajorDon't disable identifier quoting for Firebird.
Firebird supports double-quoted identifiers. Using an empty delimiter turns quoting off completely, so reserved words and case-sensitive identifiers remain unsafe even though the core helper now avoids the regex crash.
As per coding guidelines, "When adding a dialect feature, update packages/{dialect}/src/dialect.ts to declare feature support flags".
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed. In `@packages/firebird/src/dialect.ts` around lines 112 - 115, The constructor in this Firebird dialect currently disables identifier quoting by setting identifierDelimiter: '', which is incorrect—change identifierDelimiter to '"' (double-quote) so Firebird double-quoted identifiers remain supported, and update the dialect feature flags in the same file (where Firebird dialect features are declared) to explicitly mark identifier quoting/case-sensitive identifier support per the coding guidelines; locate the constructor and the feature flags block (references: constructor(sequelize: Sequelize, options: FirebirdDialectOptions), identifierDelimiter) and adjust them accordingly.
95-98:⚠️ Potential issue | 🟠 MajorDeclare
truncate.cascadeas unsupported.The dialect metadata should reject
{ cascade: true }up front instead of silently accepting it while the query generator falls back toDELETE FROM.As per coding guidelines, "When adding a dialect feature, update packages/{dialect}/src/dialect.ts to declare feature support flags".
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed. In `@packages/firebird/src/dialect.ts` around lines 95 - 98, The truncate metadata for the Firebird dialect currently only sets restartIdentity and must explicitly mark cascade as unsupported; update the truncate object in packages/firebird/src/dialect.ts (the truncate metadata) to include cascade: false (or the dialect's unsupported flag) so the dialect rejects { cascade: true } up front instead of silently accepting it and letting the query generator fallback to DELETE FROM.packages/firebird/src/query.ts (3)
16-18:⚠️ Potential issue | 🟠 MajorDon't hardcode
'id'as the generated key name.This only works for models whose auto-increment column is literally
id. Inserts returninguser_id,invoice_no, or any other generated column will not hydrate the instance primary key correctly.🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed. In `@packages/firebird/src/query.ts` around lines 16 - 18, Replace the hardcoded return in getInsertIdField() so it reads the model/table metadata for the auto-generated primary key name instead of always returning 'id' — for example, return the configured primary key from this.model (e.g. this.model.primaryKey or this.model.getPrimaryKeyName() or this.model.meta.primaryKey) and only fall back to 'id' if no metadata exists; update getInsertIdField() to use that metadata path so inserts returning user_id, invoice_no, etc. hydrate correctly.
136-145:⚠️ Potential issue | 🟠 MajorKeep normalized rows plain and lossless.
This block currently forces every key to lowercase, ignores the
lowercase_keysconnection option, converts everyBufferto UTF-8, and injectsdataValues/_previousDataValuesinto raw results. That breaks case-sensitive aliases, corrupts binary BLOB/OCTETS data, and leaks model internals into rows that should stay plain.🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed. In `@packages/firebird/src/query.ts` around lines 136 - 145, The `#normaliseRow` function currently mutates raw rows by forcing all keys to lowercase, unconditionally converting Buffer values to UTF-8 strings, and injecting dataValues / _previousDataValues; update it to keep rows plain and lossless: respect the connection option lowercase_keys (only lower-case keys if that option is enabled), preserve Buffer/Uint8Array/BLOB types instead of converting them to strings, and remove the insertion of dataValues and _previousDataValues so the method returns an untouched record with only the normalized key transformation applied when enabled; locate the method named `#normaliseRow` to implement these changes.
53-69:⚠️ Potential issue | 🟠 MajorAffected-row counts are incorrect here.
Line 58/61 always reports insert count
1, and Lines 65/69 derive update/delete counts from returned rows even though those statements do not yield row sets in this dialect. That will break Sequelize'supdate,destroy, and bulk insert result contracts.🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed. In `@packages/firebird/src/query.ts` around lines 53 - 69, The `#handleResponse` currently returns a hardcoded insert count of 1 and derives update/delete counts from returned row arrays, which is incorrect for this dialect; change `#handleResponse` (and related call to handleInsertQuery) so that for inserts you return the inserted row(s) and the actual insert count (use rows.length, not 1), and for update/delete do NOT use rows.length but instead extract the affected-row count from the protocol/metadata (e.g. this.affectedRows or a new helper like getAffectedCountFromResponse()) and return [rowsOrUndefined, affectedCount]; update isInsertQuery/isUpdateQuery/isDeleteQuery branches to use those real counts and add a small helper on the class to normalize metadata -> affected count if needed (refer to `#handleResponse`, handleInsertQuery, isInsertQuery, isUpdateQuery, isDeleteQuery).
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.
Inline comments:
In `@packages/firebird/src/_internal/data-types-overrides.ts`:
- Line 170: The class currently declared as JSON shadows the global JSON and
triggers lint errors; rename the export to a non-conflicting identifier (e.g.,
JSONTYPE or JSONType) by changing the class declaration/export from JSON to
JSONTYPE and update any local references to this class within the overrides
collection so Object.values(overrides) and getDataTypeId() still find the
override via its base type (leave BaseTypes.JSON unchanged). Ensure the exported
symbol name is updated wherever this module's overrides are registered/consumed
so the dialect matching logic continues to work.
In `@packages/firebird/src/query.ts`:
- Line 14: The class currently narrows the wrong property: replace the incorrect
declaration of connectionManager with the parent property name by declaring the
connection field as the specific type; change the declaration to use
"connection: FirebirdConnection" (i.e., update the class to use declare
connection: FirebirdConnection) so AbstractQuery's connection is properly
narrowed to FirebirdConnection.
---
Duplicate comments:
In `@packages/firebird/src/connection-manager.ts`:
- Around line 74-79: The JSDoc for the password property currently documents a
default of 'masterkey' but connect() actually falls back to an empty string;
update the documentation to match runtime behavior by changing the JSDoc default
to '' (empty string) for the password property and any other JSDoc occurrences
(see the other docblock around the password/join lines referenced), or
alternatively change the connect() fallback to 'masterkey' if you prefer that as
the real default—ensure consistency between the password?: string JSDoc and the
connect() implementation.
In `@packages/firebird/src/dialect.ts`:
- Around line 53-55: The supports.returnValues flag currently set to the generic
'returning' overstates Firebird's capability and allows core to emit
UPDATE/DELETE ... RETURNING; change supports.returnValues so it only advertises
RETURNING for INSERT (e.g., a structure indicating insert: 'returning' or
otherwise disable update/delete returning) and ensure any related places (the
inserts configuration and any update/delete code paths) are adjusted so core
will not generate UPDATE ... RETURNING or DELETE ... RETURNING for the Firebird
dialect.
- Around line 112-115: The constructor in this Firebird dialect currently
disables identifier quoting by setting identifierDelimiter: '', which is
incorrect—change identifierDelimiter to '"' (double-quote) so Firebird
double-quoted identifiers remain supported, and update the dialect feature flags
in the same file (where Firebird dialect features are declared) to explicitly
mark identifier quoting/case-sensitive identifier support per the coding
guidelines; locate the constructor and the feature flags block (references:
constructor(sequelize: Sequelize, options: FirebirdDialectOptions),
identifierDelimiter) and adjust them accordingly.
- Around line 95-98: The truncate metadata for the Firebird dialect currently
only sets restartIdentity and must explicitly mark cascade as unsupported;
update the truncate object in packages/firebird/src/dialect.ts (the truncate
metadata) to include cascade: false (or the dialect's unsupported flag) so the
dialect rejects { cascade: true } up front instead of silently accepting it and
letting the query generator fallback to DELETE FROM.
In `@packages/firebird/src/query.ts`:
- Around line 16-18: Replace the hardcoded return in getInsertIdField() so it
reads the model/table metadata for the auto-generated primary key name instead
of always returning 'id' — for example, return the configured primary key from
this.model (e.g. this.model.primaryKey or this.model.getPrimaryKeyName() or
this.model.meta.primaryKey) and only fall back to 'id' if no metadata exists;
update getInsertIdField() to use that metadata path so inserts returning
user_id, invoice_no, etc. hydrate correctly.
- Around line 136-145: The `#normaliseRow` function currently mutates raw rows by
forcing all keys to lowercase, unconditionally converting Buffer values to UTF-8
strings, and injecting dataValues / _previousDataValues; update it to keep rows
plain and lossless: respect the connection option lowercase_keys (only
lower-case keys if that option is enabled), preserve Buffer/Uint8Array/BLOB
types instead of converting them to strings, and remove the insertion of
dataValues and _previousDataValues so the method returns an untouched record
with only the normalized key transformation applied when enabled; locate the
method named `#normaliseRow` to implement these changes.
- Around line 53-69: The `#handleResponse` currently returns a hardcoded insert
count of 1 and derives update/delete counts from returned row arrays, which is
incorrect for this dialect; change `#handleResponse` (and related call to
handleInsertQuery) so that for inserts you return the inserted row(s) and the
actual insert count (use rows.length, not 1), and for update/delete do NOT use
rows.length but instead extract the affected-row count from the
protocol/metadata (e.g. this.affectedRows or a new helper like
getAffectedCountFromResponse()) and return [rowsOrUndefined, affectedCount];
update isInsertQuery/isUpdateQuery/isDeleteQuery branches to use those real
counts and add a small helper on the class to normalize metadata -> affected
count if needed (refer to `#handleResponse`, handleInsertQuery, isInsertQuery,
isUpdateQuery, isDeleteQuery).
ℹ️ Review info
⚙️ Run configuration
Configuration used: defaults
Review profile: CHILL
Plan: Pro
Run ID: d162f3bf-cf30-45d0-94c5-038361dcb11c
📒 Files selected for processing (18)
.github/workflows/pr-title.ymlpackages/core/src/sequelize-typescript.tspackages/core/src/sequelize.jspackages/core/src/utils/dialect.tspackages/firebird/.eslintrc.jspackages/firebird/package.jsonpackages/firebird/readme.mdpackages/firebird/src/_internal/data-types-overrides.tspackages/firebird/src/connection-manager.tspackages/firebird/src/dialect.tspackages/firebird/src/index.tspackages/firebird/src/query-generator.internal.tspackages/firebird/src/query-generator.tspackages/firebird/src/query-interface.tspackages/firebird/src/query-interface.types.tspackages/firebird/src/query.tspackages/firebird/tsconfig.jsonpackages/firebird/typedoc.json
✅ Files skipped from review due to trivial changes (1)
- packages/firebird/readme.md
🚧 Files skipped from review as they are similar to previous changes (10)
- packages/firebird/.eslintrc.js
- packages/firebird/src/query-interface.types.ts
- packages/firebird/src/query-generator.internal.ts
- packages/firebird/package.json
- packages/firebird/src/query-interface.ts
- packages/firebird/typedoc.json
- packages/core/src/sequelize-typescript.ts
- packages/core/src/sequelize.js
- packages/firebird/src/query-generator.ts
- packages/firebird/tsconfig.json
|
|
||
| // ── JSON ────────────────────────────────────────────────────────────────────── | ||
|
|
||
| export class JSON extends BaseTypes.JSON { |
There was a problem hiding this comment.
🧩 Analysis chain
🏁 Script executed:
# Check if the file exists and view the relevant section
find packages/firebird -name "data-types-overrides.ts" -type fRepository: sequelize/sequelize
Length of output: 118
🏁 Script executed:
# If file exists, check its content around line 170
if [ -f "packages/firebird/src/_internal/data-types-overrides.ts" ]; then
wc -l "packages/firebird/src/_internal/data-types-overrides.ts"
fiRepository: sequelize/sequelize
Length of output: 122
🏁 Script executed:
# Also search for data-types-overrides in firebird package
find packages -path "*firebird*" -name "*data-types*" -type fRepository: sequelize/sequelize
Length of output: 118
🏁 Script executed:
# Read the file to see the JSON class definition and surrounding context
cat -n "packages/firebird/src/_internal/data-types-overrides.ts"Repository: sequelize/sequelize
Length of output: 5523
🏁 Script executed:
# Find the firebird dialect.ts file to understand how overrides are registered
find packages/firebird -name "dialect.ts" -type fRepository: sequelize/sequelize
Length of output: 95
🏁 Script executed:
# Search for how dataTypes overrides are used in firebird
rg "data-types-overrides" packages/firebird/src/ -A 3 -B 3Repository: sequelize/sequelize
Length of output: 796
🏁 Script executed:
# Search for any references to JSON class in the firebird dialect
rg "\.JSON" packages/firebird/src/ -A 2 -B 2Repository: sequelize/sequelize
Length of output: 558
🏁 Script executed:
# Read the firebird dialect.ts to understand how overrides are registered
cat -n "packages/firebird/src/dialect.ts" | head -100Repository: sequelize/sequelize
Length of output: 3795
🏁 Script executed:
# Search for Object.values in the dialect or how DataTypes is used
rg "Object.values|DataTypes" packages/firebird/src/dialect.ts -B 2 -A 2Repository: sequelize/sequelize
Length of output: 592
🏁 Script executed:
# Search for how dataTypeOverrides is used in AbstractDialect
rg "dataTypeOverrides" packages/core/src/_non-semver-use-at-your-own-risk_/abstract-dialect/ -B 2 -A 5Repository: sequelize/sequelize
Length of output: 172
🏁 Script executed:
# Also check the core dialect to see the pattern
cat -n packages/core/src/_non-semver-use-at-your-own-risk_/abstract-dialect/dialect.ts | head -150Repository: sequelize/sequelize
Length of output: 174
🏁 Script executed:
# Find the core package structure
find packages -name "abstract-dialect" -type dRepository: sequelize/sequelize
Length of output: 97
🏁 Script executed:
# Search for AbstractDialect class definition
rg "class AbstractDialect" packages/ -B 2 -A 10Repository: sequelize/sequelize
Length of output: 994
🏁 Script executed:
# Search for dataTypeOverrides in the dialect.ts file
rg "dataTypeOverrides" packages/core/src/abstract-dialect/dialect.ts -B 5 -A 10Repository: sequelize/sequelize
Length of output: 2840
🏁 Script executed:
# Also look for Object.values in the dialect implementation
rg "Object.values" packages/core/src/abstract-dialect/ -B 3 -A 3Repository: sequelize/sequelize
Length of output: 3103
🏁 Script executed:
# Search for getDataTypeId implementation to understand how it works
rg "getDataTypeId" packages/core/src/abstract-dialect/ -B 2 -A 5Repository: sequelize/sequelize
Length of output: 11343
🏁 Script executed:
# Check the BaseTypes.JSON to see what its dataTypeId would be
rg "class JSON extends" packages/core/src/abstract-dialect/data-types.ts -B 2 -A 10Repository: sequelize/sequelize
Length of output: 418
Rename this override to avoid the lint error.
Biome is correctly flagging JSON for shadowing the global JSON object. The dialect uses Object.values() to iterate through overrides and then calls getDataTypeId() to match them with their base types—the export name has no impact on this matching mechanism. Renaming to JSONTYPE or similar is safe.
Suggested fix
-export class JSON extends BaseTypes.JSON {
+export class JSONTYPE extends BaseTypes.JSON {
toSql(): string {
// Firebird has no native JSON type; store as BLOB SUB_TYPE TEXT.
return 'BLOB SUB_TYPE TEXT';
}
}📝 Committable suggestion
‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.
| export class JSON extends BaseTypes.JSON { | |
| export class JSONTYPE extends BaseTypes.JSON { | |
| toSql(): string { | |
| // Firebird has no native JSON type; store as BLOB SUB_TYPE TEXT. | |
| return 'BLOB SUB_TYPE TEXT'; | |
| } | |
| } |
🧰 Tools
🪛 Biome (2.4.6)
[error] 170-170: Do not shadow the global "JSON" property.
(lint/suspicious/noShadowRestrictedNames)
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.
In `@packages/firebird/src/_internal/data-types-overrides.ts` at line 170, The
class currently declared as JSON shadows the global JSON and triggers lint
errors; rename the export to a non-conflicting identifier (e.g., JSONTYPE or
JSONType) by changing the class declaration/export from JSON to JSONTYPE and
update any local references to this class within the overrides collection so
Object.values(overrides) and getDataTypeId() still find the override via its
base type (leave BaseTypes.JSON unchanged). Ensure the exported symbol name is
updated wherever this module's overrides are registered/consumed so the dialect
matching logic continues to work.
| * query interface and maps raw results to Sequelize's expected shapes. | ||
| */ | ||
| export class FirebirdQuery extends AbstractQuery { | ||
| declare connectionManager: FirebirdConnection; |
There was a problem hiding this comment.
🧩 Analysis chain
🏁 Script executed:
#!/bin/bash
rg -n "class AbstractQuery|connectionManager|connection:" \
packages/core/src/abstract-dialect/query.ts \
packages/firebird/src/query.ts -C2Repository: sequelize/sequelize
Length of output: 1320
connectionManager is the wrong field to narrow here.
The parent class AbstractQuery declares the property as connection: AbstractConnection, not connectionManager. To properly narrow its type to FirebirdConnection, use declare connection: FirebirdConnection.
Fix
export class FirebirdQuery extends AbstractQuery {
- declare connectionManager: FirebirdConnection;
+ declare connection: FirebirdConnection;📝 Committable suggestion
‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.
| declare connectionManager: FirebirdConnection; | |
| declare connection: FirebirdConnection; |
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.
In `@packages/firebird/src/query.ts` at line 14, The class currently narrows the
wrong property: replace the incorrect declaration of connectionManager with the
parent property name by declaring the connection field as the specific type;
change the declaration to use "connection: FirebirdConnection" (i.e., update the
class to use declare connection: FirebirdConnection) so AbstractQuery's
connection is properly narrowed to FirebirdConnection.
There was a problem hiding this comment.
Actionable comments posted: 1
🧹 Nitpick comments (3)
packages/firebird/src/connection-manager.ts (2)
199-233: Consider importing error classes at the top instead of dynamic requires.The repeated
require('@sequelize/core')calls inside#translateErrorare inefficient and deviate from the ES module import pattern used elsewhere in the file. SinceConnectionErroris already imported, the other error classes can be imported alongside it.Suggested refactor
-import { AbstractConnectionManager, ConnectionError } from '@sequelize/core'; +import { + AbstractConnectionManager, + ConnectionError, + ConnectionRefusedError, + AccessDeniedError, + HostNotFoundError, + HostNotReachableError, + InvalidConnectionError, +} from '@sequelize/core'; ... `#translateError`(err: Error & { gdscode?: number }): ConnectionError { const msg = err.message ?? ''; if (/connection refused/i.test(msg)) { - const { ConnectionRefusedError } = require('@sequelize/core'); return new ConnectionRefusedError(err); } if (/access denied/i.test(msg) || err.gdscode === 335_544_472) { - const { AccessDeniedError } = require('@sequelize/core'); return new AccessDeniedError(err); } // ... similar for other error types }🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed. In `@packages/firebird/src/connection-manager.ts` around lines 199 - 233, Replace the dynamic require calls inside the private method `#translateError` with static imports at the top of the module: import ConnectionRefusedError, AccessDeniedError, HostNotFoundError, HostNotReachableError, and InvalidConnectionError from '@sequelize/core' alongside the existing ConnectionError import, then update the `#translateError` function to instantiate those imported classes instead of calling require(...) so the method uses the statically imported symbols (ConnectionRefusedError, AccessDeniedError, HostNotFoundError, HostNotReachableError, InvalidConnectionError, ConnectionError).
175-177: Validation only checks the closed flag, not actual connection health.The
validate()method returnstrueif the connection hasn't been explicitly closed, but doesn't verify the connection is still alive (e.g., server-side timeout or network drop). Consider adding a lightweight ping or query if node-firebird supports it.🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed. In `@packages/firebird/src/connection-manager.ts` around lines 175 - 177, The validate() method currently only checks the CLOSED_SYMBOL flag; update validate(connection: FirebirdConnection) to perform a lightweight health check (e.g., call a ping method or run a trivial query like SELECT 1) in addition to checking CLOSED_SYMBOL, catch any errors/timeouts and return false on failure, and return true only when both the closed flag is false and the health check succeeds; ensure the implementation uses the existing CLOSED_SYMBOL and handles errors quickly (short timeout) to avoid blocking the pool.packages/firebird/src/_internal/data-types-overrides.ts (1)
114-116:escape()may produce incorrect output for non-boolean falsy values.The method coerces any falsy value (including
0,'',null,undefined) to'FALSE'. Consider explicit boolean type checking for stricter correctness.Suggested improvement
escape(value: boolean | unknown, _options?: any): string { - return value ? 'TRUE' : 'FALSE'; + return value === true ? 'TRUE' : 'FALSE'; }🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed. In `@packages/firebird/src/_internal/data-types-overrides.ts` around lines 114 - 116, The escape(value: boolean | unknown, _options?: any) method currently coerces any falsy value to 'FALSE'; change it to explicitly check boolean identity so only true yields 'TRUE' and only false yields 'FALSE' (e.g., if (value === true) return 'TRUE'; if (value === false) return 'FALSE';), and for non-boolean inputs either throw a TypeError or handle them explicitly (choose consistent behavior for non-boolean values) to avoid silently producing incorrect SQL.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.
Inline comments:
In `@packages/firebird/src/query-generator.ts`:
- Around line 110-115: The generated index name is being lowercased when built
from attributes, but Firebird stores unquoted identifiers as uppercase; update
the logic that sets indexName (in the block using indexNameOrAttributes and
extractTableDetails) to not lowercase the result—use the Firebird normalization
(uppercase) or omit the .toLowerCase() call so the derived indexName matches the
catalog name used by DROP INDEX. Ensure the change is applied where indexName is
constructed from indexNameOrAttributes so DROP/CREATE use the same normalized
identifier.
---
Nitpick comments:
In `@packages/firebird/src/_internal/data-types-overrides.ts`:
- Around line 114-116: The escape(value: boolean | unknown, _options?: any)
method currently coerces any falsy value to 'FALSE'; change it to explicitly
check boolean identity so only true yields 'TRUE' and only false yields 'FALSE'
(e.g., if (value === true) return 'TRUE'; if (value === false) return 'FALSE';),
and for non-boolean inputs either throw a TypeError or handle them explicitly
(choose consistent behavior for non-boolean values) to avoid silently producing
incorrect SQL.
In `@packages/firebird/src/connection-manager.ts`:
- Around line 199-233: Replace the dynamic require calls inside the private
method `#translateError` with static imports at the top of the module: import
ConnectionRefusedError, AccessDeniedError, HostNotFoundError,
HostNotReachableError, and InvalidConnectionError from '@sequelize/core'
alongside the existing ConnectionError import, then update the `#translateError`
function to instantiate those imported classes instead of calling require(...)
so the method uses the statically imported symbols (ConnectionRefusedError,
AccessDeniedError, HostNotFoundError, HostNotReachableError,
InvalidConnectionError, ConnectionError).
- Around line 175-177: The validate() method currently only checks the
CLOSED_SYMBOL flag; update validate(connection: FirebirdConnection) to perform a
lightweight health check (e.g., call a ping method or run a trivial query like
SELECT 1) in addition to checking CLOSED_SYMBOL, catch any errors/timeouts and
return false on failure, and return true only when both the closed flag is false
and the health check succeeds; ensure the implementation uses the existing
CLOSED_SYMBOL and handles errors quickly (short timeout) to avoid blocking the
pool.
ℹ️ Review info
⚙️ Run configuration
Configuration used: defaults
Review profile: CHILL
Plan: Pro
Run ID: 307fcf3d-693a-49d6-a5dc-7ab7c42dfbf1
⛔ Files ignored due to path filters (1)
yarn.lockis excluded by!**/yarn.lock,!**/*.lock
📒 Files selected for processing (5)
packages/firebird/src/_internal/data-types-overrides.tspackages/firebird/src/connection-manager.tspackages/firebird/src/dialect.tspackages/firebird/src/query-generator.tspackages/mysql/package.json
Description of Changes
Summary by CodeRabbit
New Features
Bug Fixes / Improvements
Documentation
Chores