Skip to content

feat(sqlite): add support for jsonb column type in SQLite#11933

Merged
gioboa merged 2 commits intotypeorm:masterfrom
Cprakhar:feat/jsonb-sqlite
Mar 15, 2026
Merged

feat(sqlite): add support for jsonb column type in SQLite#11933
gioboa merged 2 commits intotypeorm:masterfrom
Cprakhar:feat/jsonb-sqlite

Conversation

@Cprakhar
Copy link
Contributor

@Cprakhar Cprakhar commented Jan 20, 2026

Description of Change

This pull request (PR) introduces support for the jsonb datatype in SQLite.

Example:

@Entity()
export class Record {
  @PrimaryGeneratedColumn()
  id: number

  @Column("jsonb")
  data: any

  @Column({
    type: "jsonb",
    default: { foo: "bar" }
  })
  defaultData: any
}
-- Create
CREATE TABLE "record" ("id" integer PRIMARY KEY AUTOINCREMENT NOT NULL, "data" jsonb, "defaultData" jsonb DEFAULT (jsonb('{"foo":"bar"}')))

-- Insert
INSERT INTO "record"("id", "data", "defaultData") VALUES (NULL, jsonb(?), jsonb('{"hello":"world","foo":"bar"}')) -- PARAMETERS: ["{\"key\":\"value\",\"nested\":{\"num\":42}}"]

-- Select
SELECT "Record"."id" AS "Record_id", json("Record"."data") AS "Record_data", json("Record"."defaultData") AS "Record_defaultData" FROM "record" "Record" WHERE (("Record"."id" = 1)) LIMIT 1

Closes #11930

Changes Made

  • Implemented logic to handle jsonb in both the preparePersistentValue and prepareHydratedValue methods to ensure proper persistence and retrieval of the value.
  • Included jsonb in the supported data types for the AbstractSqliteDriver.
  • Added a private method to compare default values in order to detect any changes for migrations.
  • Updated docs for sqlite driver to include both json and jsonb in the Column Types section

Pull-Request Checklist

  • Code is up-to-date with the master branch
  • This pull request links relevant issues as Fixes #11930
  • There are new or updated tests validating the change (tests/**.test.ts)
  • Documentation has been updated to reflect this change (docs/docs/**.md)

@qodo-free-for-open-source-projects

User description

Description of Change

This pull request (PR) introduces support for the jsonb datatype in SQLite.

Closes #11930

Changes Made

  • Implemented logic to handle jsonb in both the preparePersistentValue and prepareHydratedValue methods to ensure proper persistence and retrieval of the value.
  • Included jsonb in the supported data types for the AbstractSqliteDriver.
  • Added a private method to compare default values in order to detect any changes for migrations.
  • Updated docs for sqlite driver to include both json and jsonb in the Column Types section

Pull-Request Checklist

  • Code is up-to-date with the master branch
  • This pull request links relevant issues as Fixes #11930
  • There are new or updated tests validating the change (tests/**.test.ts)
  • Documentation has been updated to reflect this change (docs/docs/**.md)

PR Type

Enhancement


Description

  • Add jsonb column type support to SQLite driver

  • Implement semantic comparison for JSON/JSONB default values

  • Handle object type defaults in normalizeDefault method

  • Extend JSONB tests to cover SQLite and related drivers


Diagram Walkthrough

flowchart LR
  A["SQLite Driver"] -->|"Add jsonb type"| B["Supported Types"]
  C["Column Metadata"] -->|"Persist/Hydrate"| D["preparePersistentValue<br/>prepareHydratedValue"]
  E["Default Values"] -->|"Semantic Compare"| F["compareDefaults Method"]
  F -->|"JSON/JSONB"| G["Deep Compare"]
  F -->|"Other Types"| H["Normalize Compare"]
  I["Tests"] -->|"Extend Coverage"| J["SQLite + Variants"]
Loading

File Walkthrough

Relevant files
Enhancement
AbstractSqliteDriver.ts
Add jsonb support and semantic default comparison               

src/driver/sqlite-abstract/AbstractSqliteDriver.ts

  • Added jsonb to supported column types list
  • Updated preparePersistentValue to handle jsonb type conversion
  • Updated prepareHydratedValue to handle jsonb type conversion
  • Implemented compareDefaults private method for semantic JSON/JSONB
    comparison
  • Enhanced normalizeDefault to handle object types and moved null checks
  • Updated findChangedColumns to use new compareDefaults method
+41/-5   
Documentation
ColumnTypes.ts
Update jsonb type documentation                                                   

src/driver/types/ColumnTypes.ts

  • Updated jsonb type documentation to include SQLite support
+1/-1     
sqlite.md
Document json and jsonb column types                                         

docs/docs/drivers/sqlite.md

  • Added json and jsonb to supported column types documentation
+1/-1     
Tests
Post.ts
Add jsonb property to test entity                                               

test/functional/database-schema/column-types/sqlite/entity/Post.ts

  • Added jsonb column property to Post entity
+3/-0     
column-types-sqlite.test.ts
Add jsonb column type tests                                                           

test/functional/database-schema/column-types/sqlite/column-types-sqlite.test.ts

  • Added jsonb field assignment in test data setup
  • Added jsonb field validation in loaded data assertions
  • Added jsonb type verification in schema inspection
+3/-0     
basic-jsonb.test.ts
Extend jsonb tests to SQLite drivers                                         

test/functional/json/basic-jsonb/basic-jsonb.test.ts

  • Extended enabled drivers to include SQLite variants
  • Added conditional logic for SQLite to handle column default
    alterations
  • Used query runner for SQLite default changes instead of direct SQL
+48/-7   
jsonb-defaults.test.ts
Enable jsonb defaults tests for SQLite                                     

test/functional/json/jsonb-defaults/jsonb-defaults.test.ts

  • Extended enabled drivers to include SQLite and variants
+6/-1     

@qodo-free-for-open-source-projects
Copy link

qodo-free-for-open-source-projects bot commented Jan 20, 2026

PR Code Suggestions ✨

Latest suggestions up to 1a2d2b4

CategorySuggestion                                                                                                                                    Impact
Possible issue
Resolve columns by property name

In createInsertExpression, when looking up a column for orUpdate, fall back to
searching by property name (findColumnWithPropertyName) if the lookup by
database name (findColumnWithDatabaseName) fails.

src/query-builder/InsertQueryBuilder.ts [635-649]

 const col =
     this.expressionMap.mainAlias?.metadata.findColumnWithDatabaseName(
+        column,
+    ) ??
+    this.expressionMap.mainAlias?.metadata.findColumnWithPropertyName(
         column,
     )
 if (col) {
     expression = (
         this.connection.driver as
             | AbstractSqliteDriver
             | ReactNativeDriver
-    ).wrapWithJsonFunction(
-        expression,
-        col,
-        true,
-    )
+    ).wrapWithJsonFunction(expression, col, true)
 }
  • Apply / Chat
Suggestion importance[1-10]: 8

__

Why: The suggestion correctly points out that orUpdate uses property names, and the current implementation only checks for database names, which could cause jsonb columns to be handled incorrectly.

Medium
Fail safe on JSON parse errors

In defaultEqual, if JSON.parse fails with a SyntaxError, return false instead of
swallowing the error to ensure schema differences are detected.

src/driver/postgres/PostgresDriver.ts [1241-1257]

 if (typeof jsonString === "string") {
     try {
         const tableColumnDefault = JSON.parse(jsonString)
         return OrmUtils.deepCompare(
             columnMetadata.default,
             tableColumnDefault,
         )
     } catch (err) {
-        if (!(err instanceof SyntaxError)) {
-            throw new TypeORMError(
-                `Failed to compare default values of ${columnMetadata.propertyName} column`,
-            )
+        if (err instanceof SyntaxError) {
+            return false
         }
+        throw new TypeORMError(
+            `Failed to compare default values of ${columnMetadata.propertyName} column`,
+        )
     }
 } else {
     return OrmUtils.deepCompare(columnMetadata.default, jsonString)
 }
  • Apply / Chat
Suggestion importance[1-10]: 7

__

Why: The suggestion correctly identifies that swallowing a SyntaxError can lead to incorrect schema diffing, and returning false is a safer default to ensure schema synchronization is triggered.

Medium
  • Update

Previous suggestions

✅ Suggestions up to commit 32b2688
CategorySuggestion                                                                                                                                    Impact
Possible issue
Prevent unsupported jsonb() calls

Add a capability check for jsonb support in the SQLite driver and fall back to
json() if the feature is unavailable to prevent runtime errors during
persistence.

src/driver/sqlite-abstract/AbstractSqliteDriver.ts [1037-1046]

 wrapWithJsonFunction(
     value: string,
     column: ColumnMetadata,
     jsonb: boolean = false,
 ): string {
-    if (column.type === "jsonb") {
-        return jsonb ? `jsonb(${value})` : `json(${value})`
+    if (column.type !== "jsonb") return value
+
+    // Avoid generating `jsonb(...)` on engines that don't support it (SQLite < 3.45)
+    if (!(this as any).isJsonbSupported) {
+        return `json(${value})`
     }
-    return value
+
+    return jsonb ? `jsonb(${value})` : `json(${value})`
 }
Suggestion importance[1-10]: 7

__

Why: The suggestion correctly identifies that jsonb() calls are generated unconditionally, which will cause runtime errors on older SQLite versions, and proposes a robust capability check to prevent this.

Medium
Make JSONB defaults backward-safe

Add a capability check for jsonb support before generating jsonb() in default
column values to ensure schema compatibility with older SQLite versions.

src/driver/sqlite-abstract/AbstractSqliteDriver.ts [699-705]

 if (typeof defaultValue === "object") {
     const jsonString = JSON.stringify(defaultValue).replace(/'/g, "''")
+
     if (columnMetadata.type === "jsonb") {
+        if (!(this as any).isJsonbSupported) {
+            return `'${jsonString}'`
+        }
         return `jsonb('${jsonString}')`
     }
+
     return `'${jsonString}'`
 }
Suggestion importance[1-10]: 7

__

Why: The suggestion correctly identifies that generating jsonb() in default values will cause schema synchronization to fail on older SQLite versions and proposes a robust capability check.

Medium
General
Robustly parse JSON defaults
Suggestion Impact:Updated the SQLite JSON/JSONB default comparison logic to trim whitespace, unwrap optional surrounding parentheses, and detect json/jsonb function-wrapped string defaults via regex before JSON.parse, improving flexibility and reducing incorrect schema change detection (with added SyntaxError handling).

code diff:

+            let tableDefault = tableColumn.default
+            if (typeof tableDefault === "string") {
+                tableDefault = tableDefault.trim()
+                if (
+                    tableDefault.startsWith("(") &&
+                    tableDefault.endsWith(")")
+                ) {
+                    tableDefault = tableDefault.slice(1, -1)
+                }
+
+                const fnWrapped = tableDefault.match(
+                    /^(jsonb|json)\s*\(\s*'((?:''|[^'])*)'\s*\)\s*$/i,
+                )
+                if (fnWrapped) tableDefault = fnWrapped[2]
+                else if (
+                    tableDefault.startsWith("'") &&
+                    tableDefault.endsWith("'")
+                ) {
+                    tableDefault = tableDefault.slice(1, -1)
+                }
+            }
+
+            if (typeof tableDefault === "string") {
+                try {
+                    const tableDefaultObj = JSON.parse(
+                        tableDefault.replace(/''/g, "'"),
+                    )
+                    return OrmUtils.deepCompare(
+                        columnMetadata.default,
+                        tableDefaultObj,
+                    )
+                } catch (err) {
+                    if (!(err instanceof SyntaxError)) {
+                        throw new TypeORMError(
+                            `Failed to compare default values of ${columnMetadata.propertyName} column`,
                         )
                     }
-
-                    if (
-                        tableDefault.toLowerCase().startsWith("jsonb('") &&
-                        tableDefault.endsWith("')")
-                    ) {
-                        tableDefault = tableDefault.substring(
-                            7,
-                            tableDefault.length - 2,
-                        )
-                    } else if (
-                        tableDefault.startsWith("'") &&
-                        tableDefault.endsWith("'")
-                    ) {
-                        tableDefault = tableDefault.substring(
-                            1,
-                            tableDefault.length - 1,
-                        )
-                    }
-                }
-
-                const tableDefaultObj =
-                    typeof tableDefault === "string"
-                        ? JSON.parse(tableDefault.replace(/''/g, "'"))
-                        : tableDefault
+                }
+            } else {
                 return OrmUtils.deepCompare(
                     columnMetadata.default,
-                    tableDefaultObj,
-                )
-            } catch (err) {
-                return (
-                    this.normalizeDefault(columnMetadata) ===
-                    tableColumn.default
+                    tableDefault,
                 )
             }

Improve the parsing of JSON/JSONB default values to be more flexible with
whitespace and function wrappers like json() or jsonb(), preventing incorrect
schema change detection.

src/driver/sqlite-abstract/AbstractSqliteDriver.ts [832-882]

 if (
     ["json", "jsonb"].includes(columnMetadata.type as string) &&
     !["function", "undefined"].includes(typeof columnMetadata.default)
 ) {
     try {
         let tableDefault = tableColumn.default
+
         if (typeof tableDefault === "string") {
-            if (
-                tableDefault.startsWith("(") &&
-                tableDefault.endsWith(")")
-            ) {
-                tableDefault = tableDefault.substring(
-                    1,
-                    tableDefault.length - 1,
-                )
+            tableDefault = tableDefault.trim()
+
+            if (tableDefault.startsWith("(") && tableDefault.endsWith(")")) {
+                tableDefault = tableDefault.slice(1, -1).trim()
             }
 
-            if (
-                tableDefault.toLowerCase().startsWith("jsonb('") &&
-                tableDefault.endsWith("')")
-            ) {
-                tableDefault = tableDefault.substring(
-                    7,
-                    tableDefault.length - 2,
-                )
-            } else if (
-                tableDefault.startsWith("'") &&
-                tableDefault.endsWith("'")
-            ) {
-                tableDefault = tableDefault.substring(
-                    1,
-                    tableDefault.length - 1,
-                )
+            const fnWrapped = tableDefault.match(
+                /^(jsonb|json)\s*\(\s*'(.*)'\s*\)\s*$/i,
+            )
+            if (fnWrapped) {
+                tableDefault = fnWrapped[2]
+            } else if (tableDefault.startsWith("'") && tableDefault.endsWith("'")) {
+                tableDefault = tableDefault.slice(1, -1)
             }
         }
 
         const tableDefaultObj =
             typeof tableDefault === "string"
                 ? JSON.parse(tableDefault.replace(/''/g, "'"))
                 : tableDefault
-        return OrmUtils.deepCompare(
-            columnMetadata.default,
-            tableDefaultObj,
-        )
+
+        return OrmUtils.deepCompare(columnMetadata.default, tableDefaultObj)
     } catch (err) {
         return (
-            this.normalizeDefault(columnMetadata) ===
-            tableColumn.default
+            this.normalizeDefault(columnMetadata) === tableColumn.default
         )
     }
 }
Suggestion importance[1-10]: 6

__

Why: The suggestion correctly points out that the current parsing of JSON default values is too strict and could lead to unnecessary migrations, proposing a more robust regex-based approach.

Low
✅ Suggestions up to commit 1f110b4
CategorySuggestion                                                                                                                                    Impact
Possible issue
Escape single quotes in JSON defaults
Suggestion Impact:Updated normalizeDefault to stringify JSON defaults, escape single quotes via .replace(/'/g, "''"), and use jsonb('...') wrapping for jsonb columns instead of returning the raw quoted JSON string.

code diff:

@@ -680,7 +697,11 @@
         }
 
         if (typeof defaultValue === "object") {
-            return `'${JSON.stringify(defaultValue)}'`
+            const jsonString = JSON.stringify(defaultValue).replace(/'/g, "''")
+            if (columnMetadata.type === "jsonb") {
+                return `jsonb('${jsonString}')`
+            }
+            return `'${jsonString}'`
         }

In normalizeDefault, escape single quotes in the stringified JSON default value
to prevent SQL syntax errors.

src/driver/sqlite-abstract/AbstractSqliteDriver.ts [682-687]

 if (typeof defaultValue === "object") {
+    const jsonString = JSON.stringify(defaultValue).replace(/'/g, "''")
     if (columnMetadata.type === "jsonb") {
-        return `jsonb('${JSON.stringify(defaultValue)}')`
+        return `jsonb('${jsonString}')`
     }
-    return `'${JSON.stringify(defaultValue)}'`
+    return `'${jsonString}'`
 }
Suggestion importance[1-10]: 8

__

Why: The suggestion correctly identifies a bug where single quotes within a JSON default value would lead to SQL syntax errors, and it provides the correct fix by escaping them.

Medium
✅ Suggestions up to commit 039c900
CategorySuggestion                                                                                                                                    Impact
Possible issue
Escape single quotes in JSON defaults
Suggestion Impact:Updated normalizeDefault to stringify JSON defaults, escape single quotes via .replace(/'/g, "''"), and use jsonb('...') wrapping for jsonb columns instead of returning the raw quoted JSON string.

code diff:

@@ -680,7 +697,11 @@
         }
 
         if (typeof defaultValue === "object") {
-            return `'${JSON.stringify(defaultValue)}'`
+            const jsonString = JSON.stringify(defaultValue).replace(/'/g, "''")
+            if (columnMetadata.type === "jsonb") {
+                return `jsonb('${jsonString}')`
+            }
+            return `'${jsonString}'`
         }

Escape single quotes in default JSON object values to prevent SQL syntax errors.

src/driver/sqlite-abstract/AbstractSqliteDriver.ts [682-687]

 if (typeof defaultValue === "object") {
+    const jsonString = JSON.stringify(defaultValue).replace(/'/g, "''")
     if (columnMetadata.type === "jsonb") {
-        return `jsonb('${JSON.stringify(defaultValue)}')`
+        return `jsonb('${jsonString}')`
     }
-    return `'${JSON.stringify(defaultValue)}'`
+    return `'${jsonString}'`
 }
Suggestion importance[1-10]: 7

__

Why: The suggestion correctly identifies that an unescaped single quote in a default JSON value will cause a SQL syntax error, and the proposed fix is accurate for SQLite.

Medium
Unescape quotes before JSON parsing
Suggestion Impact:Updated PostgresDriver default comparison for json/jsonb to unescape doubled single-quotes (replace /''/g with "'") before JSON.parse, preventing parse failures on escaped defaults; also wrapped parsing in try/catch with fallback comparison and adjusted default normalization escaping.

code diff:

@@ -1193,29 +1211,45 @@
     /**
      * Compares "default" value of the column.
      * Postgres sorts json values before it is saved, so in that case a deep comparison has to be performed to see if has changed.
+     * @param columnMetadata
+     * @param tableColumn
      */
     private defaultEqual(
         columnMetadata: ColumnMetadata,
         tableColumn: TableColumn,
     ): boolean {
+        // defaults are equal if both are undefined or null
+        if (
+            (columnMetadata.default === null ||
+                columnMetadata.default === undefined) &&
+            (tableColumn.default === null || tableColumn.default === undefined)
+        )
+            return true
+
         if (
             ["json", "jsonb"].includes(columnMetadata.type as string) &&
             !["function", "undefined"].includes(typeof columnMetadata.default)
         ) {
-            const tableColumnDefault =
-                typeof tableColumn.default === "string"
-                    ? JSON.parse(
-                          tableColumn.default.substring(
-                              1,
-                              tableColumn.default.length - 1,
-                          ),
-                      )
-                    : tableColumn.default
-
-            return OrmUtils.deepCompare(
-                columnMetadata.default,
-                tableColumnDefault,
-            )
+            try {
+                const tableColumnDefault =
+                    typeof tableColumn.default === "string"
+                        ? JSON.parse(
+                              tableColumn.default
+                                  .substring(1, tableColumn.default.length - 1)
+                                  .replace(/''/g, "'"),
+                          )
+                        : tableColumn.default
+
+                return OrmUtils.deepCompare(
+                    columnMetadata.default,
+                    tableColumnDefault,
+                )
+            } catch (err) {
+                const columnDefault = this.lowerDefaultValueIfNecessary(
+                    this.normalizeDefault(columnMetadata),
+                )
+                return columnDefault === tableColumn.default
+            }
         }

Unescape double single-quotes to single-quotes from the default value string
before parsing it as JSON.

src/driver/postgres/PostgresDriver.ts [1207-1232]

 if (
     ["json", "jsonb"].includes(columnMetadata.type as string) &&
     !["function", "undefined"].includes(typeof columnMetadata.default)
 ) {
     try {
         const tableColumnDefault =
             typeof tableColumn.default === "string"
                 ? JSON.parse(
-                      tableColumn.default.substring(
-                          1,
-                          tableColumn.default.length - 1,
-                      ),
+                      tableColumn.default
+                          .substring(1, tableColumn.default.length - 1)
+                          .replace(/''/g, "'"),
                   )
                 : tableColumn.default
 
         return OrmUtils.deepCompare(
             columnMetadata.default,
             tableColumnDefault,
         )
     } catch (err) {
         const columnDefault = this.lowerDefaultValueIfNecessary(
             this.normalizeDefault(columnMetadata),
         )
         return columnDefault === tableColumn.default
     }
 }
Suggestion importance[1-10]: 7

__

Why: The suggestion correctly identifies that escaped single quotes in a JSON default string from the database are not being handled, which would cause JSON.parse to fail.

Medium
✅ Suggestions up to commit 0d57335
CategorySuggestion                                                                                                                                    Impact
General
Validate string format before parsing
Suggestion Impact:The suggestion's core idea of validating string format before parsing was implemented in the commit. The commit added checks for single quotes (lines 67-73) before parsing JSON, similar to the suggestion's intent. However, the implementation is more comprehensive, also handling parentheses wrapping (lines 49-57) and jsonb function wrapping (lines 60-66), going beyond the original suggestion's scope.

code diff:

+            try {
+                let tableDefault = tableColumn.default
+                if (typeof tableDefault === "string") {
+                    if (
+                        tableDefault.startsWith("(") &&
+                        tableDefault.endsWith(")")
+                    ) {
+                        tableDefault = tableDefault.substring(
+                            1,
+                            tableDefault.length - 1,
+                        )
+                    }
+
+                    if (
+                        tableDefault.toLowerCase().startsWith("jsonb('") &&
+                        tableDefault.endsWith("')")
+                    ) {
+                        tableDefault = tableDefault
+                            .substring(7, tableDefault.length - 2)
+                            .replace(/''/g, "'")
+                    } else if (
+                        tableDefault.startsWith("'") &&
+                        tableDefault.endsWith("'")
+                    ) {
+                        tableDefault = tableDefault
+                            .substring(1, tableDefault.length - 1)
+                            .replace(/''/g, "'")
+                    }
+                }
+
+                const tableDefaultObj =
+                    typeof tableDefault === "string"
+                        ? JSON.parse(tableDefault)
+                        : tableDefault

Improve JSON default value parsing by first checking if the string is wrapped in
single quotes before attempting to remove them, making the logic more robust.

src/driver/sqlite-abstract/AbstractSqliteDriver.ts [802-826]

 if (
     ["json", "jsonb"].includes(columnMetadata.type as string) &&
     !["function", "undefined"].includes(typeof columnMetadata.default)
 ) {
     try {
-        const tableDefaultObj =
-            typeof tableColumn.default === "string"
-                ? JSON.parse(
-                      tableColumn.default.substring(
-                          1,
-                          tableColumn.default.length - 1,
-                      ),
-                  )
-                : tableColumn.default
+        let tableDefaultObj = tableColumn.default
+        if (typeof tableColumn.default === "string") {
+            const trimmed = tableColumn.default.trim()
+            if (trimmed.startsWith("'") && trimmed.endsWith("'") && trimmed.length > 1) {
+                tableDefaultObj = JSON.parse(trimmed.substring(1, trimmed.length - 1))
+            } else {
+                tableDefaultObj = JSON.parse(trimmed)
+            }
+        }
         return OrmUtils.deepCompare(
             columnMetadata.default,
             tableDefaultObj,
         )
     } catch (err) {
         return (
             this.normalizeDefault(columnMetadata) ===
             tableColumn.default
         )
     }
 }
Suggestion importance[1-10]: 6

__

Why: The suggestion correctly identifies that blindly using substring is fragile and proposes a more robust check for single quotes before parsing the JSON string, improving code resilience.

Low
Log errors in catch block
Suggestion Impact:The commit reworked the JSON default comparison logic to explicitly handle JSON.parse errors: SyntaxError is treated as an expected fallback case, while non-SyntaxError cases are surfaced by throwing a TypeORMError (instead of logging). This addresses the suggestion’s goal of differentiating expected vs unexpected failures, though it does not add logging.

code diff:

@@ -1193,29 +1211,50 @@
     /**
      * Compares "default" value of the column.
      * Postgres sorts json values before it is saved, so in that case a deep comparison has to be performed to see if has changed.
+     * @param columnMetadata
+     * @param tableColumn
      */
     private defaultEqual(
         columnMetadata: ColumnMetadata,
         tableColumn: TableColumn,
     ): boolean {
+        // defaults are equal if both are undefined or null
+        if (
+            (columnMetadata.default === null ||
+                columnMetadata.default === undefined) &&
+            (tableColumn.default === null || tableColumn.default === undefined)
+        )
+            return true
+
         if (
             ["json", "jsonb"].includes(columnMetadata.type as string) &&
             !["function", "undefined"].includes(typeof columnMetadata.default)
         ) {
-            const tableColumnDefault =
-                typeof tableColumn.default === "string"
-                    ? JSON.parse(
-                          tableColumn.default.substring(
-                              1,
-                              tableColumn.default.length - 1,
-                          ),
-                      )
-                    : tableColumn.default
-
-            return OrmUtils.deepCompare(
-                columnMetadata.default,
-                tableColumnDefault,
-            )
+            let jsonString = tableColumn.default
+            if (typeof jsonString === "string") {
+                jsonString = jsonString.trim()
+                if (jsonString.startsWith("'") && jsonString.endsWith("'")) {
+                    jsonString = jsonString.slice(1, -1).replace(/''/g, "'")
+                }
+            }
+
+            if (typeof jsonString === "string") {
+                try {
+                    const tableColumnDefault = JSON.parse(jsonString)
+                    return OrmUtils.deepCompare(
+                        columnMetadata.default,
+                        tableColumnDefault,
+                    )
+                } catch (err) {
+                    if (!(err instanceof SyntaxError)) {
+                        throw new TypeORMError(
+                            `Failed to compare default values of ${columnMetadata.propertyName} column`,
+                        )
+                    }
+                }
+            } else {
+                return OrmUtils.deepCompare(columnMetadata.default, jsonString)
+            }
         }

Add logging within the catch block to differentiate between expected JSON
parsing failures and other unexpected errors, which will aid in debugging.

src/driver/postgres/PostgresDriver.ts [1211-1231]

 try {
     const tableColumnDefault =
         typeof tableColumn.default === "string"
             ? JSON.parse(
                   tableColumn.default.substring(
                       1,
                       tableColumn.default.length - 1,
                   ),
               )
             : tableColumn.default
 
     return OrmUtils.deepCompare(
         columnMetadata.default,
         tableColumnDefault,
     )
 } catch (err) {
+    // Log parsing failure for debugging
+    if (err instanceof SyntaxError) {
+        // Expected: fall back to string comparison
+    } else {
+        console.warn('Unexpected error comparing JSON defaults:', err)
+    }
     const columnDefault = this.lowerDefaultValueIfNecessary(
         this.normalizeDefault(columnMetadata),
     )
     return columnDefault === tableColumn.default
 }
Suggestion importance[1-10]: 5

__

Why: The suggestion correctly points out that swallowing errors silently can hinder debugging, and proposes adding logging for unexpected errors, which is a good practice for maintainability.

Low
✅ Suggestions up to commit bf6bec7
CategorySuggestion                                                                                                                                    Impact
General
Fix method naming convention
Suggestion Impact:The suggestion was implemented. The method was renamed from 'compareDefaults' to 'defaultEqual' (line 5), and the method call was updated accordingly (line 63). While the original suggestion mentioned renaming from 'DefaultEqual', the actual implementation renamed from 'compareDefaults', but the end result matches the suggested name 'defaultEqual'.

code diff:

-    private compareDefaults(
+    private defaultEqual(
         columnMetadata: ColumnMetadata,
         tableColumn: TableColumn,
     ): boolean {
+        // defaults are equal if both are undefined or null
+        if (
+            (columnMetadata.default === null ||
+                columnMetadata.default === undefined) &&
+            (tableColumn.default === null || tableColumn.default === undefined)
+        )
+            return true
+
         if (
             ["json", "jsonb"].includes(columnMetadata.type as string) &&
-            !["function", "undefined"].includes(
-                typeof columnMetadata.default,
-            ) &&
-            columnMetadata.default !== null
+            !["function", "undefined"].includes(typeof columnMetadata.default)
         ) {
-            const tableDefaultObj =
-                typeof tableColumn.default === "string"
-                    ? JSON.parse(
-                          tableColumn.default.substring(
-                              1,
-                              tableColumn.default.length - 1,
-                          ),
-                      )
-                    : tableColumn.default
-            return OrmUtils.deepCompare(columnMetadata.default, tableDefaultObj)
+            try {
+                const tableDefaultObj =
+                    typeof tableColumn.default === "string"
+                        ? JSON.parse(
+                              tableColumn.default.substring(
+                                  1,
+                                  tableColumn.default.length - 1,
+                              ),
+                          )
+                        : tableColumn.default
+                return OrmUtils.deepCompare(
+                    columnMetadata.default,
+                    tableDefaultObj,
+                )
+            } catch (err) {
+                return (
+                    this.normalizeDefault(columnMetadata) ===
+                    tableColumn.default
+                )
+            }
         }
 
         return this.normalizeDefault(columnMetadata) === tableColumn.default
@@ -833,7 +848,7 @@
                 tableColumn.length !== columnMetadata.length ||
                 tableColumn.precision !== columnMetadata.precision ||
                 tableColumn.scale !== columnMetadata.scale ||
-                !this.compareDefaults(columnMetadata, tableColumn) ||

Rename the DefaultEqual method to defaultEqual to adhere to the camelCase naming
convention for methods.

src/driver/sqlite-abstract/AbstractSqliteDriver.ts [790-793]

-private DefaultEqual(
+private defaultEqual(
     columnMetadata: ColumnMetadata,
     tableColumn: TableColumn,
 ): boolean {
Suggestion importance[1-10]: 4

__

Why: The suggestion correctly identifies a naming convention violation (PascalCase instead of camelCase) for a newly added private method, which improves code consistency and maintainability.

Low
Update method call to match convention

Update the call to DefaultEqual to defaultEqual in findChangedColumns to match
the corrected method name.

src/driver/sqlite-abstract/AbstractSqliteDriver.ts [851]

-!this.DefaultEqual(columnMetadata, tableColumn) ||
+!this.defaultEqual(columnMetadata, tableColumn) ||
Suggestion importance[1-10]: 4

__

Why: This suggestion is a necessary follow-up to the first suggestion, correctly pointing out that the call site for the method must also be updated to prevent a breaking change.

Low
✅ Suggestions up to commit 336aa4d
CategorySuggestion                                                                                                                                    Impact
Possible issue
Add JSON parsing error handling
Suggestion Impact:The commit implemented the core suggestion by wrapping the JSON.parse operation in a try...catch block (lines 31-51). The error handling approach differs slightly - instead of returning a direct comparison in the catch block, it uses helper methods (lowerDefaultValueIfNecessary and normalizeDefault) for the fallback comparison, but the fundamental intent of adding error handling for JSON parsing was implemented.

code diff:

+            try {
+                const tableColumnDefault =
+                    typeof tableColumn.default === "string"
+                        ? JSON.parse(
+                              tableColumn.default.substring(
+                                  1,
+                                  tableColumn.default.length - 1,
+                              ),
+                          )
+                        : tableColumn.default
+
+                return OrmUtils.deepCompare(
+                    columnMetadata.default,
+                    tableColumnDefault,
+                )
+            } catch (err) {
+                const columnDefault = this.lowerDefaultValueIfNecessary(
+                    this.normalizeDefault(columnMetadata),
+                )
+                return columnDefault === tableColumn.default
+            }

Add a try...catch block around JSON.parse to handle potential errors from
malformed JSON strings in tableColumn.default.

src/driver/postgres/PostgresDriver.ts [1200-1216]

 if (
     ["json", "jsonb"].includes(columnMetadata.type as string) &&
     !["function", "undefined"].includes(typeof columnMetadata.default)
 ) {
-    const tableColumnDefault =
+    let tableColumnDefault = tableColumn.default
+    if (
         typeof tableColumn.default === "string" &&
         tableColumn.default !== null &&
         tableColumn.default !== undefined
-            ? JSON.parse(
-                  tableColumn.default.substring(
-                      1,
-                      tableColumn.default.length - 1,
-                  ),
-              )
-            : tableColumn.default
+    ) {
+        try {
+            tableColumnDefault = JSON.parse(
+                tableColumn.default.substring(
+                    1,
+                    tableColumn.default.length - 1,
+                ),
+            )
+        } catch (err) {
+            // If parsing fails, use the raw string for comparison
+            return this.normalizeDefault(columnMetadata) === tableColumn.default
+        }
+    }
Suggestion importance[1-10]: 7

__

Why: The suggestion correctly points out that JSON.parse can throw an error if tableColumn.default is not valid JSON, which would crash the application. Adding a try...catch block, similar to what was done for the SQLite driver in this PR, improves robustness and consistency.

Medium
✅ Suggestions up to commit 9e9459b
CategorySuggestion                                                                                                                                    Impact
Possible issue
Restrict JSON stringification to JSON columns
Suggestion Impact:The suggestion was partially implemented. The commit added a check for 'jsonb' type (lines 5-7) but did not restrict the general object stringification case as suggested. Instead, it added special handling for jsonb columns while keeping the original fallback behavior for other object types. The commit also added extensive related changes for JSON/JSONB default value comparison and wrapping functions.

code diff:

         if (typeof defaultValue === "object") {
+            if (columnMetadata.type === "jsonb") {
+                return `jsonb('${JSON.stringify(defaultValue)}')`
+            }
             return `'${JSON.stringify(defaultValue)}'`
         }

In the normalizeDefault method, ensure that object default values are only JSON
stringified if the column type is json or jsonb.

src/driver/sqlite-abstract/AbstractSqliteDriver.ts [652-687]

 normalizeDefault(columnMetadata: ColumnMetadata): string | undefined {
     const defaultValue = columnMetadata.default
 
     if (defaultValue === null || defaultValue === undefined) {
         return undefined
     }
 
     if (typeof defaultValue === "number") {
         return "" + defaultValue
     }
 
     if (typeof defaultValue === "boolean") {
         return defaultValue ? "1" : "0"
     }
 
     if (typeof defaultValue === "function") {
         return defaultValue()
     }
 
     if (typeof defaultValue === "string") {
         return `'${defaultValue}'`
     }
 
     if (
         Array.isArray(defaultValue) &&
         columnMetadata.type === "simple-enum"
     ) {
         return `'${defaultValue.join(",")}'`
     }
 
-    if (typeof defaultValue === "object") {
+    if (
+        typeof defaultValue === "object" &&
+        ["json", "jsonb"].includes(columnMetadata.type as string)
+    ) {
         return `'${JSON.stringify(defaultValue)}'`
     }
 
     return `${defaultValue}`
 }
Suggestion importance[1-10]: 7

__

Why: The suggestion correctly points out that stringifying any object default value is too broad and could cause bugs; restricting this behavior to json and jsonb columns makes the logic safer and more precise.

Medium
Fix fragile JSON string extraction
Suggestion Impact:The suggestion identified the fragile string manipulation issue in JSON default parsing. While the commit didn't use the exact regex approach suggested (`.replace(/^'|'$/g, "")`), it implemented a more comprehensive solution that addresses the same problem. The commit replaced the simple substring method with proper handling of multiple quote formats including parentheses wrapping, jsonb function syntax, and escaped quotes. The core issue of fragile string extraction was resolved, though with a more thorough implementation than suggested.

code diff:

+            try {
+                let tableDefault = tableColumn.default
+                if (typeof tableDefault === "string") {
+                    if (
+                        tableDefault.startsWith("(") &&
+                        tableDefault.endsWith(")")
+                    ) {
+                        tableDefault = tableDefault.substring(
+                            1,
+                            tableDefault.length - 1,
+                        )
+                    }
+
+                    if (
+                        tableDefault.toLowerCase().startsWith("jsonb('") &&
+                        tableDefault.endsWith("')")
+                    ) {
+                        tableDefault = tableDefault
+                            .substring(7, tableDefault.length - 2)
+                            .replace(/''/g, "'")
+                    } else if (
+                        tableDefault.startsWith("'") &&
+                        tableDefault.endsWith("'")
+                    ) {
+                        tableDefault = tableDefault
+                            .substring(1, tableDefault.length - 1)
+                            .replace(/''/g, "'")
+                    }
+                }
+
+                const tableDefaultObj =
+                    typeof tableDefault === "string"
+                        ? JSON.parse(tableDefault)
+                        : tableDefault
+                return OrmUtils.deepCompare(
+                    columnMetadata.default,
+                    tableDefaultObj,
+                )
+            } catch (err) {
+                return (
+                    this.normalizeDefault(columnMetadata) ===
+                    tableColumn.default
+                )
+            }

Replace the fragile substring method for removing quotes from a JSON default
string with a more robust regex-based approach in the compareDefaults function.

src/driver/sqlite-abstract/AbstractSqliteDriver.ts [790-824]

 private compareDefaults(
     columnMetadata: ColumnMetadata,
     tableColumn: TableColumn,
 ): boolean {
     if (
         ["json", "jsonb"].includes(columnMetadata.type as string) &&
         !["function", "undefined"].includes(
             typeof columnMetadata.default,
         ) &&
         columnMetadata.default !== null
     ) {
         try {
             const tableDefaultObj =
                 typeof tableColumn.default === "string"
                     ? JSON.parse(
-                          tableColumn.default.substring(
-                              1,
-                              tableColumn.default.length - 1,
-                          ),
+                          tableColumn.default.replace(/^'|'$/g, ""),
                       )
                     : tableColumn.default
             return OrmUtils.deepCompare(
                 columnMetadata.default,
                 tableDefaultObj,
             )
         } catch (err) {
             return (
                 this.normalizeDefault(columnMetadata) ===
                 tableColumn.default
             )
         }
     }
 
     return this.normalizeDefault(columnMetadata) === tableColumn.default
 }
Suggestion importance[1-10]: 6

__

Why: The suggestion correctly identifies fragile string manipulation for parsing JSON defaults and proposes a more robust regex-based solution, preventing potential errors with complex JSON strings.

Low
✅ Suggestions up to commit 9fbe961
CategorySuggestion                                                                                                                                    Impact
High-level
The PR misrepresents jsonb support

The PR's implementation of jsonb for SQLite is misleading because it's an alias
for json (stored as TEXT), not a true binary type. The documentation should be
updated to clarify that jsonb is functionally identical to json in SQLite.

Examples:

src/driver/sqlite-abstract/AbstractSqliteDriver.ts [348-352]
            columnMetadata.type === "json" ||
            columnMetadata.type === "jsonb" ||
            columnMetadata.type === "simple-json"
        ) {
            return DateUtils.simpleJsonToString(value)
docs/docs/drivers/sqlite.md [78]
`int`, `int2`, `int8`, `integer`, `tinyint`, `smallint`, `mediumint`, `bigint`, `decimal`, `numeric`, `float`, `double`, `real`, `double precision`, `datetime`, `varying character`, `character`, `native character`, `varchar`, `nchar`, `nvarchar2`, `unsigned big int`, `boolean`, `blob`, `text`, `clob`, `date`, `json`, `jsonb`

Solution Walkthrough:

Before:

// src/driver/sqlite-abstract/AbstractSqliteDriver.ts
export abstract class AbstractSqliteDriver {
    supportedDataTypes = [
        //...
        "json",
        "jsonb",
    ];

    preparePersistentValue(value: any, columnMetadata: ColumnMetadata): any {
        //...
        if (columnMetadata.type === "json" || columnMetadata.type === "jsonb") {
            return DateUtils.simpleJsonToString(value);
        }
        //...
    }
}

// docs/docs/drivers/sqlite.md
// ... Column Types
// `...`, `date`, `json`, `jsonb`

After:

// src/driver/sqlite-abstract/AbstractSqliteDriver.ts
// No code change, as the suggestion is about documentation.
// The implementation remains the same, but its nature should be clarified.
export abstract class AbstractSqliteDriver {
    supportedDataTypes = [
        //...
        "json",
        "jsonb",
    ];

    preparePersistentValue(value: any, columnMetadata: ColumnMetadata): any {
        //...
        if (columnMetadata.type === "json" || columnMetadata.type === "jsonb") {
            return DateUtils.simpleJsonToString(value);
        }
        //...
    }
}

// docs/docs/drivers/sqlite.md
// ... Column Types
// `...`, `date`, `json`, `jsonb` (Note: for SQLite, `jsonb` is an alias for `json` and is stored as TEXT)
Suggestion importance[1-10]: 8

__

Why: The suggestion correctly identifies that the PR's implementation of jsonb for SQLite is just an alias for json (stored as TEXT), which is misleading given the performance and storage implications of a true binary jsonb type.

Medium
Possible issue
Add error handling for JSON parsing
Suggestion Impact:The commit implemented the core suggestion by adding a try-catch block around the JSON.parse logic. However, the implementation differs slightly: instead of restructuring the code with if-else blocks as suggested, the commit wrapped the entire existing logic in a try-catch block, maintaining the original ternary operator structure. The fallback behavior on error is identical to the suggestion.

code diff:

+            try {
+                const tableDefaultObj =
+                    typeof tableColumn.default === "string"
+                        ? JSON.parse(
+                              tableColumn.default.substring(
+                                  1,
+                                  tableColumn.default.length - 1,
+                              ),
+                          )
+                        : tableColumn.default
+                return OrmUtils.deepCompare(
+                    columnMetadata.default,
+                    tableDefaultObj,
+                )
+            } catch (err) {
+                return (
+                    this.normalizeDefault(columnMetadata) ===
+                    tableColumn.default
+                )
+            }

Add a try-catch block around the JSON.parse call within the compareDefaults
method to prevent crashes from invalid JSON strings. Fall back to a standard
string comparison on parsing failure.

src/driver/sqlite-abstract/AbstractSqliteDriver.ts [801-810]

-const tableDefaultObj =
-    typeof tableColumn.default === "string"
-        ? JSON.parse(
-              tableColumn.default.substring(
-                  1,
-                  tableColumn.default.length - 1,
-              ),
-          )
-        : tableColumn.default
+let tableDefaultObj
+if (typeof tableColumn.default === "string") {
+    try {
+        // The default value is a string, but it might be a JSON string, e.g. "'{\"a\":1}'"
+        const val = tableColumn.default.substring(
+            1,
+            tableColumn.default.length - 1,
+        )
+        tableDefaultObj = JSON.parse(val)
+    } catch (e) {
+        // If parsing fails, it's not a valid JSON string.
+        // Fallback to string comparison.
+        return this.normalizeDefault(columnMetadata) === tableColumn.default
+    }
+} else {
+    tableDefaultObj = tableColumn.default
+}
 return OrmUtils.deepCompare(columnMetadata.default, tableDefaultObj)
Suggestion importance[1-10]: 8

__

Why: The suggestion correctly identifies a potential crash during schema synchronization if JSON.parse fails on a non-JSON string default value for a json or jsonb column, and proposes a robust try-catch block to handle this, improving error handling.

Medium

@qodo-free-for-open-source-projects
Copy link

qodo-free-for-open-source-projects bot commented Jan 20, 2026

Code Review by Qodo

🐞 Bugs (14) 📘 Rule violations (5) 📎 Requirement gaps (0)

Grey Divider


Action required

1. SQLite jsonb primitive defaults 🐞 Bug ✓ Correctness
Description
SQLite normalizeDefault emits boolean/string defaults as 1/0 or 'foo' even for json/jsonb columns,
but persistence/hydration expects JSON.stringify/JSON.parse semantics. With the new json/jsonb
default comparison path (JSON.parse + deepCompare), these defaults will never compare equal, causing
repeated migration diffs and potential malformed-JSON errors on reads.
Code

src/driver/sqlite-abstract/AbstractSqliteDriver.ts[R672-678]

+        if (defaultValue === null || defaultValue === undefined) {
+            return undefined
+        }
+
     if (typeof defaultValue === "number") {
         return "" + defaultValue
     }
Evidence
For SQLite json/jsonb columns, values are persisted as JSON strings and hydrated via JSON.parse, but
normalizeDefault special-cases booleans/strings as non-JSON SQL literals. The new defaultEqual()
routes json/jsonb defaults through compareJsonDefaults(), which JSON.parse’s the table default and
returns false on SyntaxError, so any non-JSON default (e.g., 'foo') or mismatched primitive encoding
(e.g., true vs 1) makes findChangedColumns think the column changed. Additionally, SQLite inserts
use normalizeDefault because DEFAULT is not supported in INSERT, so these incorrect defaults are
actually written into rows by TypeORM.

src/driver/sqlite-abstract/AbstractSqliteDriver.ts[669-708]
src/driver/sqlite-abstract/AbstractSqliteDriver.ts[321-427]
src/util/DateUtils.ts[264-270]
src/driver/sqlite-abstract/AbstractSqliteDriver.ts[823-901]
src/driver/sqlite-abstract/AbstractSqliteDriver.ts[909-926]
src/query-builder/InsertQueryBuilder.ts[1620-1633]

Agent prompt
The issue below was found during a code review. Follow the provided context and guidance below and implement a solution

## Issue description
SQLite `normalizeDefault()` does not JSON-stringify primitive defaults (`string`, `boolean`) for `json`/`jsonb` columns. After this PR, SQLite compares `json`/`jsonb` defaults by `JSON.parse()` + deep compare, so these non-JSON defaults will never compare equal, leading to repeated schema diffs/migrations and potentially invalid persisted default values for runtime reads.
### Issue Context
- SQLite persists/hydrates `json`/`jsonb` using `JSON.stringify` / `JSON.parse`.
- SQLite INSERT path uses `normalizeDefault()` (since SQLite doesn’t support `DEFAULT` in INSERT).
- New `defaultEqual()` routes `json`/`jsonb` through `compareJsonDefaults()` which parses defaults as JSON.
### Fix Focus Areas
- src/driver/sqlite-abstract/AbstractSqliteDriver.ts[669-711]
- src/driver/sqlite-abstract/AbstractSqliteDriver.ts[823-901]
- src/query-builder/InsertQueryBuilder.ts[1620-1633]
### Suggested approach
1. In `normalizeDefault()`, add an early branch:
- If `columnMetadata.type` is `&amp;amp;amp;quot;json&amp;amp;amp;quot;` or `&amp;amp;amp;quot;jsonb&amp;amp;amp;quot;` and `defaultValue` is not a function:
 - `const json = JSON.stringify(defaultValue).replaceAll(&amp;amp;amp;quot;&amp;amp;amp;#x27;&amp;amp;amp;quot;, &amp;amp;amp;quot;&amp;amp;amp;#x27;&amp;amp;amp;#x27;&amp;amp;amp;quot;)`
 - return `jsonb(&amp;amp;amp;#x27;${json}&amp;amp;amp;#x27;)` for `jsonb`, else return `&amp;amp;amp;#x27;${json}&amp;amp;amp;#x27;`.
2. Ensure this branch runs **before** the generic boolean/string handling so json/jsonb booleans/strings don’t become `1/0` or `&amp;amp;amp;#x27;foo&amp;amp;amp;#x27;`.
3. (Optional) add a small functional test for SQLite with `@Column({ type: &amp;amp;amp;#x27;jsonb&amp;amp;amp;#x27;, default: true })` and/or `default: &amp;amp;amp;quot;foo&amp;amp;amp;quot;` to prevent regressions.

ⓘ Copy this prompt and use it to remediate the issue with your preferred AI generation tools


2. SQLite JSONB ungated 🐞 Bug ⛯ Reliability
Description
• AbstractSqliteDriver now exposes jsonb as supported and QueryBuilders wrap JSONB reads/writes
with SQLite functions jsonb(...)/json(...) unconditionally. • Repo documentation states JSONB
requires SQLite ≥ 3.45.0 and tests explicitly skip the sqlite (sqlite3) driver due to missing
jsonb functions; without a guard, users can pass metadata validation yet fail later with runtime SQL
errors on older SQLite builds. • Because DataSource.initialize() calls driver.connect() before
metadata validation, the driver can detect SQLite capabilities early and either disable jsonb in
supportedDataTypes or throw a clear, fail-fast error when JSONB isn’t supported.
Code

src/driver/sqlite-abstract/AbstractSqliteDriver.ts[R1035-1043]

+    wrapWithJsonFunction(
+        value: string,
+        column: ColumnMetadata,
+        jsonb: boolean = false,
+    ): string {
+        if (column.type === "jsonb") {
+            return jsonb ? `jsonb(${value})` : `json(${value})`
+        }
+        return value
Evidence
SQLite-family query generation will emit jsonb()/json() whenever an entity column is typed as
jsonb, but the repo itself documents a minimum SQLite version and shows sqlite3 lacking support.
Since sqlite drivers generally do not set driver.version nor gate supportedDataTypes, metadata
validation can succeed while runtime queries fail on unsupported SQLite engines.

src/driver/sqlite-abstract/AbstractSqliteDriver.ts[97-131]
src/driver/sqlite-abstract/AbstractSqliteDriver.ts[1035-1044]
src/query-builder/InsertQueryBuilder.ts[1705-1709]
src/query-builder/SelectQueryBuilder.ts[3012-3018]
src/query-builder/UpdateQueryBuilder.ts[637-646]
src/driver/DriverUtils.ts[16-27]
docs/docs/drivers/sqlite.md[80-87]
test/functional/database-schema/column-types/sqlite/column-types-sqlite.test.ts[23-27]
src/data-source/DataSource.ts[252-266]

Agent prompt
The issue below was found during a code review. Follow the provided context and guidance below and implement a solution

## Issue description
SQLite JSONB is enabled unconditionally for all `AbstractSqliteDriver`-based drivers, and QueryBuilders emit `jsonb(...)` / `json(...)` calls whenever a column is typed as `jsonb`. Repo docs/tests indicate JSONB requires SQLite &amp;amp;amp;amp;gt;= 3.45 and that the `sqlite` (sqlite3) driver may not support it. Without capability/version gating, metadata validation can succeed and then queries fail at runtime.
### Issue Context
`DataSource.initialize()` invokes `driver.connect()` **before** metadata validation. This provides an opportunity to detect SQLite capabilities early and either:
- remove `&amp;amp;amp;amp;quot;jsonb&amp;amp;amp;amp;quot;` from `supportedDataTypes` so validation fails fast with `DataTypeNotSupportedError`, or
- throw a clear `TypeORMError` explaining the SQLite version requirement when JSONB columns are present.
Some SQLite-family drivers override `connect()` (e.g., `sqljs`, `capacitor`), so any shared detection logic must be invoked there as well.
### Fix Focus Areas
- src/driver/sqlite-abstract/AbstractSqliteDriver.ts[267-275]
- src/driver/sqlite-abstract/AbstractSqliteDriver.ts[97-131]
- src/driver/sqlite-abstract/AbstractSqliteDriver.ts[1035-1044]
- src/driver/sqljs/SqljsDriver.ts[51-56]
- src/driver/capacitor/CapacitorDriver.ts[31-38]
- src/data-source/DataSource.ts[252-266]

ⓘ Copy this prompt and use it to remediate the issue with your preferred AI generation tools


3. ReactNative query crash 🐞 Bug ✓ Correctness
Description
• Query builders call wrapWithJsonFunction whenever DriverUtils.isSQLiteFamily(driver) is true.
• DriverUtils.isSQLiteFamily includes the react-native driver type, but ReactNativeDriver is
declared as implements Driver (not extending AbstractSqliteDriver). • Since
wrapWithJsonFunction is implemented on AbstractSqliteDriver, react-native connections can hit
TypeError: driver.wrapWithJsonFunction is not a function during SELECT/INSERT/UPDATE query
construction/execution.
Code

src/query-builder/SelectQueryBuilder.ts[R3011-3015]

+            if (DriverUtils.isSQLiteFamily(this.connection.driver)) {
+                selectionPath = (
+                    this.connection.driver as AbstractSqliteDriver
+                ).wrapWithJsonFunction(selectionPath, column, false)
+            }
Evidence
The query builder invokes wrapWithJsonFunction for any SQLite-family driver. The SQLite-family
list explicitly includes react-native, but the react-native driver class does not inherit from
AbstractSqliteDriver (which defines wrapWithJsonFunction), so the cast in the query builder can
be invalid at runtime and lead to an undefined method call.

src/query-builder/SelectQueryBuilder.ts[3011-3015]
src/query-builder/InsertQueryBuilder.ts[1691-1694]
src/query-builder/UpdateQueryBuilder.ts[615-623]
src/driver/DriverUtils.ts[16-26]
src/driver/react-native/ReactNativeDriver.ts[35-41]
src/driver/sqlite-abstract/AbstractSqliteDriver.ts[1037-1046]

Agent prompt
The issue below was found during a code review. Follow the provided context and guidance below and implement a solution

## Issue description
Query builders call `wrapWithJsonFunction` for all SQLite-family drivers, but `react-native` is considered SQLite-family while `ReactNativeDriver` does not extend `AbstractSqliteDriver` (where `wrapWithJsonFunction` is implemented). This can cause runtime `TypeError` when building/executing queries.
### Issue Context
`DriverUtils.isSQLiteFamily()` includes `react-native`, and query builders cast `this.connection.driver` to `AbstractSqliteDriver` and call `wrapWithJsonFunction`.
### Fix Focus Areas
- src/query-builder/SelectQueryBuilder.ts[3011-3015]
- src/query-builder/InsertQueryBuilder.ts[616-640]
- src/query-builder/InsertQueryBuilder.ts[1691-1694]
- src/query-builder/UpdateQueryBuilder.ts[615-623]
- src/driver/react-native/ReactNativeDriver.ts[880-910]
### Suggested approach
Pick one:
1) **Feature-detect in query builders**:
- `const drv: any = this.connection.driver;`
- `if (DriverUtils.isSQLiteFamily(drv) &amp;amp;amp;amp;amp;amp;&amp;amp;amp;amp;amp;amp; typeof drv.wrapWithJsonFunction === &amp;amp;amp;amp;amp;quot;function&amp;amp;amp;amp;amp;quot;) { ... }`
2) **Implement `wrapWithJsonFunction` in `ReactNativeDriver`** (same semantics as `AbstractSqliteDriver`), so the existing query-builder calls are safe for `react-native`.
Option (2) is minimally invasive to call sites; option (1) is more future-proof.

ⓘ Copy this prompt and use it to remediate the issue with your preferred AI generation tools


View more (11)
4. Missing JSONB wrapping in orUpdate overwrite🐞 Bug ✓ Correctness
Description
• The InsertQueryBuilder.orUpdate method has two code paths for handling upserts: one using the
columns parameter (which properly wraps JSONB values) and another using the overwrite parameter
(which does not wrap JSONB values) • When using orUpdate with the overwrite parameter on JSONB
columns in SQLite, the generated SQL uses column = EXCLUDED.column without wrapping the value with
jsonb(), causing type mismatches • SQLite supports the EXCLUDED keyword in ON CONFLICT clauses and
the driver declares support for 'on-conflict-do-update', so this code path is reachable • This
inconsistency means JSONB columns will work correctly with .orUpdate(['column'], ['id']) but fail
with .orUpdate({ overwrite: ['column'], conflict_target: ['id'] })
Code

src/query-builder/InsertQueryBuilder.ts[613]

                   )
Evidence
The code shows two different handling paths for orUpdate. The 'columns' path (lines 616-640)
includes JSONB wrapping via wrapWithJsonFunction for SQLite, while the 'overwrite' path (lines
605-613) uses EXCLUDED.column without any type-specific wrapping. The AbstractSqliteDriver declares
support for 'on-conflict-do-update' at line 137, confirming this code path is active for SQLite.

src/query-builder/InsertQueryBuilder.ts[616-640]
src/driver/sqlite-abstract/AbstractSqliteDriver.ts[137-137]

Agent prompt
The issue below was found during a code review. Follow the provided context and guidance below and implement a solution

The issue below was found during a code review. Follow the provided context and guidance below and implement a solution
The issue below was found during a code review. Follow the provided context and guidance below and implement a solution
The issue below was found during a code review. Follow the provided context and guidance below and implement a solution
The issue below was found during a code review. Follow the provided context and guidance below and implement a solution
The issue below was found during a code review. Follow the provided context and guidance below and implement a solution
## Issue Description
The InsertQueryBuilder.orUpdate method doesn&amp;amp;amp;amp;amp;#x27;t wrap JSONB columns with the required jsonb() function when using the overwrite parameter, causing type mismatches in SQLite.
## Issue Context
SQLite&amp;amp;amp;amp;amp;#x27;s JSONB type requires values to be wrapped with jsonb() for insertion and json() for retrieval. The PR correctly implements this for the &amp;amp;amp;amp;amp;#x27;columns&amp;amp;amp;amp;amp;#x27; parameter path but misses it for the &amp;amp;amp;amp;amp;#x27;overwrite&amp;amp;amp;amp;amp;#x27; parameter path.
## Fix Focus Areas
- src/query-builder/InsertQueryBuilder.ts[605-613]: Add JSONB wrapping logic similar to lines 616-640
- The fix should check if the driver is SQLite, look up column metadata, and wrap EXCLUDED.column with json() function for JSONB columns

ⓘ Copy this prompt and use it to remediate the issue with your preferred AI generation tools


5. Missing jsonb wrapping for EXCLUDED values🐞 Bug ✓ Correctness
Description
• When using orUpdate with the overwrite parameter, the generated SQL uses `column =
EXCLUDED.column` without wrapping EXCLUDED.column with json() function • For jsonb columns in
SQLite, EXCLUDED.column returns raw BLOB data that must be wrapped with json() to be properly
assigned • The columns parameter path correctly applies wrapWithJsonFunction, but the overwrite
parameter path does not • This causes upsert operations using orUpdate(['jsonb_column'], ['id']) to
fail with type mismatch errors
Code

src/query-builder/InsertQueryBuilder.ts[613]

                   )
Evidence
The code shows two different paths for handling orUpdate: the overwrite path (lines 605-613)
generates EXCLUDED-based updates without jsonb wrapping, while the columns path (lines 614-641)
correctly applies wrapWithJsonFunction. The test at line 219 of sqlite-jsonb.test.ts uses
orUpdate(['data'], ['id']) which would exercise this code path and fail for jsonb columns.

src/query-builder/InsertQueryBuilder.ts[605-613]
src/query-builder/InsertQueryBuilder.ts[614-641]
test/functional/json/basic-jsonb/sqlite-jsonb.test.ts[195-226]

Agent prompt
The issue below was found during a code review. Follow the provided context and guidance below and implement a solution

The issue below was found during a code review. Follow the provided context and guidance below and implement a solution
The issue below was found during a code review. Follow the provided context and guidance below and implement a solution
The issue below was found during a code review. Follow the provided context and guidance below and implement a solution
The issue below was found during a code review. Follow the provided context and guidance below and implement a solution
The issue below was found during a code review. Follow the provided context and guidance below and implement a solution
## Issue Description
The orUpdate method with overwrite parameter generates SQL like `column = EXCLUDED.column` without wrapping EXCLUDED.column with json() function for jsonb columns. This causes type mismatch errors because EXCLUDED.column returns raw BLOB data for jsonb columns in SQLite.
## Issue Context
The columns parameter path (lines 614-641) correctly applies wrapWithJsonFunction to handle jsonb columns, but the overwrite parameter path (lines 605-613) does not apply this wrapping.
## Fix Focus Areas
- src/query-builder/InsertQueryBuilder.ts[605-613]
The fix should:
1. Check if the driver is SQLite family
2. For each column in the overwrite array, check if it&amp;amp;amp;amp;amp;#x27;s a jsonb column
3. If it is jsonb, wrap EXCLUDED.column with json() function using the driver&amp;amp;amp;amp;amp;#x27;s wrapWithJsonFunction method
4. Generate SQL like: `column = json(EXCLUDED.column)` for jsonb columns

ⓘ Copy this prompt and use it to remediate the issue with your preferred AI generation tools


6. Test coverage excludes sqlite3 driver🐞 Bug ⛯ Reliability
Description
• The JSONB functionality is only tested with better-sqlite3 and sqljs drivers, completely excluding
the sqlite3 npm package • The comment states 'Current sqlite3 package does not support jsonb or
jsonb functions' but this claim is not verified • Users of the sqlite3 package (the most common
SQLite driver) will not know if JSONB works until runtime, creating a significant risk
Code

test/functional/database-schema/column-types/sqlite/column-types-sqlite.test.ts[R26-27]

+                // Current sqlite3 package does not support jsonb or jsonb functions
+                if (connection.driver.options.type === "sqlite") return
Evidence
The test explicitly skips the sqlite3 driver type, and the new JSONB test file only enables
better-sqlite3 and sqljs. This creates a coverage gap for the most widely used SQLite driver. The
documentation change in sqlite.md claims JSONB support for SQLite without qualifying which driver
packages support it.

test/functional/database-schema/column-types/sqlite/column-types-sqlite.test.ts[26-27]
test/functional/json/basic-jsonb/sqlite-jsonb.test.ts[14-17]
docs/docs/drivers/sqlite.md[85-85]

Agent prompt
The issue below was found during a code review. Follow the provided context and guidance below and implement a solution

The issue below was found during a code review. Follow the provided context and guidance below and implement a solution
The issue below was found during a code review. Follow the provided context and guidance below and implement a solution
The issue below was found during a code review. Follow the provided context and guidance below and implement a solution
The issue below was found during a code review. Follow the provided context and guidance below and implement a solution
The issue below was found during a code review. Follow the provided context and guidance below and implement a solution
The issue below was found during a code review. Follow the provided context and guidance below and implement a solution
## Issue Description
The JSONB feature is not tested with the sqlite3 npm package, only with better-sqlite3 and sqljs. This creates a coverage gap for users of the most common SQLite driver.
## Issue Context
The PR adds JSONB support to SQLite but the test suite explicitly excludes the &amp;amp;amp;amp;amp;amp;#x27;sqlite&amp;amp;amp;amp;amp;amp;#x27; driver type with a comment claiming it doesn&amp;amp;amp;amp;amp;amp;#x27;t support JSONB functions. However, this claim is not verified and the documentation doesn&amp;amp;amp;amp;amp;amp;#x27;t mention this limitation.
## Fix Focus Areas
- test/functional/database-schema/column-types/sqlite/column-types-sqlite.test.ts[26-27]
- test/functional/json/basic-jsonb/sqlite-jsonb.test.ts[16-16]
- docs/docs/drivers/sqlite.md[85-85]
Either:
1. Verify sqlite3 package version and if it supports SQLite 3.45.0+, add it to the test drivers
2. If sqlite3 doesn&amp;amp;amp;amp;amp;amp;#x27;t support JSONB, add clear documentation in sqlite.md explaining which driver packages support JSONB (better-sqlite3, sqljs) and which don&amp;amp;amp;amp;amp;amp;#x27;t (sqlite3)

ⓘ Copy this prompt and use it to remediate the issue with your preferred AI generation tools


7. SQL injection in jsonb default values 🐞 Bug ✓ Correctness
Description
• The normalizeDefault method generates jsonb default values by directly concatenating
JSON.stringify output into SQL without escaping single quotes • JSON strings containing single
quotes (e.g., {"key": "value's"}) produce invalid SQL: jsonb('{"key":"value's"}') • SQLite requires
single quotes to be escaped as '' (doubled), but this escaping is not performed • This causes SQL
syntax errors during schema creation or migration when jsonb columns have object defaults containing
single quotes
Code

src/driver/sqlite-abstract/AbstractSqliteDriver.ts[R682-685]

+        if (typeof defaultValue === "object") {
+            if (columnMetadata.type === "jsonb") {
+                return `jsonb('${JSON.stringify(defaultValue)}')`
+            }
Evidence
The code directly interpolates JSON.stringify output into SQL without escaping single quotes.
PostgresDriver has the same pattern (line 1185) but Postgres uses different quoting rules. For
SQLite, single quotes within string literals must be escaped as '' (doubled). When JSON contains
single quotes, the generated SQL is syntactically invalid.

src/driver/sqlite-abstract/AbstractSqliteDriver.ts[682-687]
src/driver/postgres/PostgresDriver.ts[1184-1186]
src/driver/sqlite-abstract/AbstractSqliteQueryRunner.ts[1976-1978]

Agent prompt
The issue below was found during a code review. Follow the provided context and guidance below and implement a solution

The issue below was found during a code review. Follow the provided context and guidance below and implement a solution
The issue below was found during a code review. Follow the provided context and guidance below and implement a solution
The issue below was found during a code review. Follow the provided context and guidance below and implement a solution
The issue below was found during a code review. Follow the provided context and guidance below and implement a solution
The issue below was found during a code review. Follow the provided context and guidance below and implement a solution
The issue below was found during a code review. Follow the provided context and guidance below and implement a solution
## Issue Description
The normalizeDefault method generates SQL with jsonb() function calls containing JSON strings, but single quotes within the JSON are not escaped according to SQLite syntax rules. This causes SQL syntax errors when the JSON contains single quotes.
## Issue Context
SQLite requires single quotes within string literals to be escaped as &amp;amp;amp;amp;amp;amp;#x27;&amp;amp;amp;amp;amp;amp;#x27; (two single quotes). JSON.stringify may produce strings containing single quotes (e.g., in string values with apostrophes), which must be escaped before being embedded in SQL.
Example:
- Input: { key: &amp;amp;amp;amp;amp;amp;quot;value&amp;amp;amp;amp;amp;amp;#x27;s&amp;amp;amp;amp;amp;amp;quot; }
- JSON.stringify: {&amp;amp;amp;amp;amp;amp;quot;key&amp;amp;amp;amp;amp;amp;quot;:&amp;amp;amp;amp;amp;amp;quot;value&amp;amp;amp;amp;amp;amp;#x27;s&amp;amp;amp;amp;amp;amp;quot;}
- Current SQL: jsonb(&amp;amp;amp;amp;amp;amp;#x27;{&amp;amp;amp;amp;amp;amp;quot;key&amp;amp;amp;amp;amp;amp;quot;:&amp;amp;amp;amp;amp;amp;quot;value&amp;amp;amp;amp;amp;amp;#x27;s&amp;amp;amp;amp;amp;amp;quot;}&amp;amp;amp;amp;amp;amp;#x27;)  // INVALID
- Correct SQL: jsonb(&amp;amp;amp;amp;amp;amp;#x27;{&amp;amp;amp;amp;amp;amp;quot;key&amp;amp;amp;amp;amp;amp;quot;:&amp;amp;amp;amp;amp;amp;quot;value&amp;amp;amp;amp;amp;amp;#x27;&amp;amp;amp;amp;amp;amp;#x27;s&amp;amp;amp;amp;amp;amp;quot;}&amp;amp;amp;amp;amp;amp;#x27;)  // VALID
## Fix Focus Areas
- src/driver/sqlite-abstract/AbstractSqliteDriver.ts[682-687]
The fix should:
1. After JSON.stringify, replace all single quotes with doubled single quotes
2. Apply this escaping for both jsonb and json types
3. Use the pattern: .replace(/&amp;amp;amp;amp;amp;amp;#x27;/g, &amp;amp;amp;amp;amp;amp;quot;&amp;amp;amp;amp;amp;amp;#x27;&amp;amp;amp;amp;amp;amp;#x27;&amp;amp;amp;amp;amp;amp;quot;)

ⓘ Copy this prompt and use it to remediate the issue with your preferred AI generation tools


8. Missing JSONB wrapping in upsert operations🐞 Bug ✓ Correctness
Description
• ON CONFLICT DO UPDATE statements use EXCLUDED.<column> directly without checking if the column is
JSONB type • When JSONB columns are updated via EXCLUDED reference, SQLite may receive values in the
wrong format • The INSERT path wraps JSONB values with jsonb() function, but the UPDATE path in ON
CONFLICT does not apply corresponding handling
Code

src/query-builder/InsertQueryBuilder.ts[1]

              ", " +
Evidence
The InsertQueryBuilder wraps JSONB values with jsonb() function during INSERT operations for SQLite.
However, the ON CONFLICT DO UPDATE clause uses EXCLUDED.<column> directly without any type-specific
handling. While there is a test for orUpdate with JSONB, it only tests the values() path which goes
through the normal INSERT wrapping. The EXCLUDED reference path is not tested and may have issues
with binary JSONB format handling.

src/query-builder/InsertQueryBuilder.ts[604-612]
src/query-builder/InsertQueryBuilder.ts[1669-1673]
test/functional/json/basic-jsonb/sqlite-jsonb.test.ts[195-226]

Agent prompt
The issue below was found during a code review. Follow the provided context and guidance below and implement a solution

The issue below was found during a code review. Follow the provided context and guidance below and implement a solution
The issue below was found during a code review. Follow the provided context and guidance below and implement a solution
The issue below was found during a code review. Follow the provided context and guidance below and implement a solution
The issue below was found during a code review. Follow the provided context and guidance below and implement a solution
The issue below was found during a code review. Follow the provided context and guidance below and implement a solution
The issue below was found during a code review. Follow the provided context and guidance below and implement a solution
## Issue Description
When using orUpdate() with JSONB columns in SQLite, the ON CONFLICT DO UPDATE SET clause uses EXCLUDED.&amp;amp;amp;amp;amp;amp;lt;column&amp;amp;amp;amp;amp;amp;gt; directly without checking if the column needs special JSONB handling. This may cause type mismatches or data corruption.
## Issue Context
The INSERT path wraps JSONB values with jsonb() function for SQLite (InsertQueryBuilder.ts:1669-1673), but the ON CONFLICT DO UPDATE path doesn&amp;amp;amp;amp;amp;amp;#x27;t apply similar handling. The EXCLUDED pseudo-table contains the values from the INSERT that triggered the conflict, which are already in JSONB binary format, but the assignment may need explicit handling.
## Fix Focus Areas
- src/query-builder/InsertQueryBuilder.ts[604-612]
Investigate whether EXCLUDED.&amp;amp;amp;amp;amp;amp;lt;column&amp;amp;amp;amp;amp;amp;gt; for JSONB columns needs to be wrapped with json() function to convert from binary JSONB to a format suitable for assignment, similar to how SELECT queries wrap JSONB columns with json() for retrieval. Consider adding column type checking in the overwrite.map() function to apply appropriate wrapping for JSONB columns.

ⓘ Copy this prompt and use it to remediate the issue with your preferred AI generation tools


9. defaultEqual swallows JSON errors 📘 Rule violation ⛯ Reliability
Description
New defaultEqual logic silently ignores JSON.parse SyntaxError when comparing JSON/JSONB
defaults, which can mask real default mismatches and migration diffs. This adds abnormal defensive
try/catch behavior inconsistent with the checklist.
Code

src/driver/postgres/PostgresDriver.ts[R1241-1257]

+            if (typeof jsonString === "string") {
+                try {
+                    const tableColumnDefault = JSON.parse(jsonString)
+                    return OrmUtils.deepCompare(
+                        columnMetadata.default,
+                        tableColumnDefault,
+                    )
+                } catch (err) {
+                    if (!(err instanceof SyntaxError)) {
+                        throw new TypeORMError(
+                            `Failed to compare default values of ${columnMetadata.propertyName} column`,
+                        )
+                    }
+                }
+            } else {
+                return OrmUtils.deepCompare(columnMetadata.default, jsonString)
+            }
Evidence
Compliance ID 4 disallows abnormal defensive try/catch patterns; the added code catches
SyntaxError from JSON.parse and proceeds without returning or surfacing the comparison failure,
effectively swallowing the error path.

Rule 4: Remove AI-generated noise
src/driver/postgres/PostgresDriver.ts[1241-1257]

Agent prompt
The issue below was found during a code review. Follow the provided context and guidance below and implement a solution

## Issue description
`defaultEqual()` catches `SyntaxError` from `JSON.parse()` and silently continues, which can hide real default mismatches and make migration diffing unreliable.
## Issue Context
The compliance checklist disallows abnormal defensive try/catch patterns (AI-noise). The new JSON/JSONB default comparison should not ignore parse failures without an explicit, deterministic outcome.
## Fix Focus Areas
- src/driver/postgres/PostgresDriver.ts[1241-1257]

ⓘ Copy this prompt and use it to remediate the issue with your preferred AI generation tools


10. defaultEqual swallows JSON errors 📘 Rule violation ⛯ Reliability
Description
New CockroachDB default comparison swallows JSON parsing SyntaxError without a deterministic
fallback, potentially hiding mismatched defaults. This introduces abnormal defensive try/catch
behavior disallowed by the compliance checklist.
Code

src/driver/cockroachdb/CockroachDriver.ts[R823-839]

+            if (typeof jsonString === "string") {
+                try {
+                    const tableColumnDefault = JSON.parse(jsonString)
+                    return OrmUtils.deepCompare(
+                        columnMetadata.default,
+                        tableColumnDefault,
+                    )
+                } catch (err) {
+                    if (!(err instanceof SyntaxError)) {
+                        throw new TypeORMError(
+                            `Failed to compare default values of ${columnMetadata.propertyName} column`,
+                        )
+                    }
+                }
+            } else {
+                return OrmUtils.deepCompare(columnMetadata.default, jsonString)
+            }
Evidence
Compliance ID 4 requires removing abnormal defensive try/catch blocks; the new code attempts to
parse a normalized default string and ignores SyntaxError, allowing comparison to proceed without
validating equivalence.

Rule 4: Remove AI-generated noise
src/driver/cockroachdb/CockroachDriver.ts[823-839]

Agent prompt
The issue below was found during a code review. Follow the provided context and guidance below and implement a solution

## Issue description
`CockroachDriver.defaultEqual()` ignores `SyntaxError` from `JSON.parse()` and continues, which can conceal default mismatches.
## Issue Context
The compliance checklist disallows abnormal defensive try/catch. JSON/JSONB default parsing should not fail silently.
## Fix Focus Areas
- src/driver/cockroachdb/CockroachDriver.ts[823-839]

ⓘ Copy this prompt and use it to remediate the issue with your preferred AI generation tools


11. Broken jsonb resorting test 🐞 Bug ✓ Correctness
Description
The test "should not create updates when resorting object" changes the DB default to a different
value (hello:"world") than the entity metadata default (hello:"world'O"), so the test should not
expect zero schema diffs and will fail or mask regressions.
Code

test/functional/json/basic-jsonb/postgres/jsonb.test.ts[R156-181]

it("should not create updates when resorting object", () =>
    Promise.all(
        dataSources.map(async (connection) => {
-                await connection.query(
-                    `ALTER TABLE record ALTER COLUMN "dataWithDefaultObject" SET DEFAULT '{"foo":"bar", "hello": "world"}';`,
-                )
+                if (DriverUtils.isSQLiteFamily(connection.driver)) {
+                    // Sqlite does not support altering column defaults, so we need to use query runner
+                    const queryRunner =
+                        connection.createQueryRunner() as AbstractSqliteQueryRunner
+                    const table = await queryRunner.getTable("record")
+                    const column = table!.findColumnByName(
+                        "dataWithDefaultObject",
+                    )!
+                    column.default = `'{"foo":"bar", "hello": "world"}'`
+                    await queryRunner.changeColumn(
+                        "record",
+                        "dataWithDefaultObject",
+                        column,
+                    )
+                    await queryRunner.release()
+                } else {
+                    await connection.query(
+                        `ALTER TABLE record ALTER COLUMN "dataWithDefaultObject" SET DEFAULT '{"foo":"bar", "hello": "world"}';`,
+                    )
+                }
            const sqlInMemory = await connection.driver
                .createSchemaBuilder()
Evidence
The entity defines a jsonb default containing a single quote (world'O). The test that claims to only
reorder keys instead changes the value to world, making the defaults semantically different; schema
diff should detect a change.

test/functional/json/basic-jsonb/postgres/entity/Record.ts[14-22]
test/functional/json/basic-jsonb/postgres/jsonb.test.ts[156-186]

Agent prompt
The issue below was found during a code review. Follow the provided context and guidance below and implement a solution

## Issue description
A jsonb default-comparison test intends to verify that key reordering does not produce schema diffs, but it currently changes the *value* of the default (&amp;amp;amp;amp;quot;world&amp;amp;amp;amp;quot; vs &amp;amp;amp;amp;quot;world&amp;amp;amp;amp;#x27;O&amp;amp;amp;amp;quot;), so the expectation of no diffs is incorrect.
### Issue Context
The Record entity default contains a single quote (`world&amp;amp;amp;amp;#x27;O`). SQL literals must escape that quote (`world&amp;amp;amp;amp;#x27;&amp;amp;amp;amp;#x27;O`).
### Fix Focus Areas
- test/functional/json/basic-jsonb/postgres/jsonb.test.ts[156-178]
- test/functional/json/basic-jsonb/postgres/entity/Record.ts[14-22]
### Suggested change
Update both the SQLite and non-SQLite ALTER/default assignments in the &amp;amp;amp;amp;quot;resorting object&amp;amp;amp;amp;quot; test to use a JSON string equivalent to the entity default, e.g.:
- `&amp;amp;amp;amp;#x27;{&amp;amp;amp;amp;quot;foo&amp;amp;amp;amp;quot;:&amp;amp;amp;amp;quot;bar&amp;amp;amp;amp;quot;,&amp;amp;amp;amp;quot;hello&amp;amp;amp;amp;quot;:&amp;amp;amp;amp;quot;world&amp;amp;amp;amp;#x27;&amp;amp;amp;amp;#x27;O&amp;amp;amp;amp;quot;}&amp;amp;amp;amp;#x27;` (or with spacing)

ⓘ Copy this prompt and use it to remediate the issue with your preferred AI generation tools


12. ReactNative jsonb incomplete 🐞 Bug ✓ Correctness
Description
ReactNativeDriver is treated as SQLite-family for jsonb wrapping, but it still does not declare
json/jsonb as supported column types and lacks json/jsonb persistence/hydration and default
normalization, leading to DataTypeNotSupportedError and/or broken persistence if users try to use
jsonb on react-native.
Code

src/driver/react-native/ReactNativeDriver.ts[R946-955]

+    wrapWithJsonFunction(
+        value: string,
+        column: ColumnMetadata,
+        jsonb: boolean = false,
+    ): string {
+        if (column.type === "jsonb") {
+            return jsonb ? `jsonb(${value})` : `json(${value})`
+        }
+        return value
+    }
Evidence
ReactNativeDriver currently lacks json/jsonb in supportedDataTypes so metadata validation will
reject entities using those types; additionally it does not convert json/jsonb values in
preparePersistentValue/prepareHydratedValue, and normalizeDefault does not handle object defaults
(needed for json/jsonb defaults and migrations). This conflicts with the SQLite docs which now claim
json/jsonb support and also document react-native SQLite options.

src/driver/react-native/ReactNativeDriver.ts[97-129]
src/metadata-builder/EntityMetadataValidator.ts[130-143]
src/driver/react-native/ReactNativeDriver.ts[325-358]
src/driver/react-native/ReactNativeDriver.ts[420-439]
src/driver/react-native/ReactNativeDriver.ts[665-689]
src/driver/react-native/ReactNativeDriver.ts[802-832]
src/driver/sqlite-abstract/AbstractSqliteDriver.ts[348-354]
docs/docs/drivers/sqlite.md[67-81]

Agent prompt
The issue below was found during a code review. Follow the provided context and guidance below and implement a solution

## Issue description
ReactNativeDriver is in the SQLite family and is now referenced by query builders for jsonb wrapping, but the driver itself still rejects `json`/`jsonb` at metadata validation time and does not implement the necessary persistence/hydration/default-normalization logic.
### Issue Context
- Entity metadata validation rejects any column types not listed in `driver.supportedDataTypes`.
- ReactNativeDriver currently only supports `simple-json` conversions and will pass objects through unchanged.
- ReactNativeDriver&amp;amp;#x27;s `normalizeDefault` returns `${defaultValue}` for objects and `findChangedColumns` compares defaults as raw strings, which will not work for json/jsonb defaults or jsonb semantic comparisons.
### Fix Focus Areas
- src/driver/react-native/ReactNativeDriver.ts[97-129]
- src/driver/react-native/ReactNativeDriver.ts[325-439]
- src/driver/react-native/ReactNativeDriver.ts[665-689]
- src/driver/react-native/ReactNativeDriver.ts[802-832]
- src/driver/sqlite-abstract/AbstractSqliteDriver.ts[321-443]
- src/driver/sqlite-abstract/AbstractSqliteDriver.ts[669-708]
- src/driver/sqlite-abstract/AbstractSqliteDriver.ts[820-883]

ⓘ Copy this prompt and use it to remediate the issue with your preferred AI generation tools


13. SQLite jsonb WHERE mismatch 🐞 Bug ✓ Correctness
Description
SQLite jsonb values are persisted as JSONB/BLOB via jsonb(...), but WHERE predicates built by
the query builder are not wrapped with jsonb(...) (or otherwise normalized), so equality filtering
on jsonb columns can return wrong results. This makes jsonb behave differently from json for
common where patterns (including those generated by repository find options).
Code

src/query-builder/InsertQueryBuilder.ts[R1705-1708]

+            } else if (DriverUtils.isSQLiteFamily(this.connection.driver)) {
+                expression = (
+                    this.connection.driver as AbstractSqliteDriver
+                ).wrapWithJsonFunction(paramName, column, true)
Evidence
The PR changes SQLite-family INSERT/UPDATE parameter expressions to wrap persisted values with
jsonb(...) for jsonb columns, and wraps selected jsonb columns with json(...) on reads.
However, WHERE predicates are still generated as aliasPath = :param with no jsonb(...) wrapping
of the parameter or normalization of the column expression, so comparisons may not match what was
persisted (binary JSON) and can silently return no rows.

src/query-builder/InsertQueryBuilder.ts[1705-1709]
src/query-builder/UpdateQueryBuilder.ts[637-647]
src/query-builder/SelectQueryBuilder.ts[2979-2985]
src/query-builder/SelectQueryBuilder.ts[4449-4491]
src/query-builder/QueryBuilder.ts[1639-1642]
docs/docs/drivers/sqlite.md[76-81]

Agent prompt
The issue below was found during a code review. Follow the provided context and guidance below and implement a solution

## Issue description
SQLite `jsonb` persistence now stores values as binary JSON (`jsonb(...)`), but WHERE predicates are still generated as plain `column = :param`. This can make equality predicates against `jsonb` columns fail or behave inconsistently because the RHS parameter is not converted to JSONB.
## Issue Context
- INSERT/UPDATE for SQLite-family drivers wraps parameters via `wrapWithJsonFunction(..., jsonb=true)`.
- SELECT wraps `jsonb` column reads via `wrapWithJsonFunction(..., jsonb=false)`.
- WHERE-building paths do not invoke `wrapWithJsonFunction` (or otherwise normalize comparisons) for `jsonb`.
## Fix Focus Areas
- src/query-builder/SelectQueryBuilder.ts[4449-4493]
- src/query-builder/QueryBuilder.ts[1086-1145]
- src/query-builder/QueryBuilder.ts[1535-1643]
## Notes
A pragmatic fix is to special-case SQLite-family + `column.type === &amp;amp;#x27;jsonb&amp;amp;#x27;` in `SelectQueryBuilder.buildWhere`:
- For simple equality (`operator: equal`), generate `aliasPath = jsonb(:param)` (or `aliasPath = jsonb(?)` after parameterization).
- For `IN` / multiple parameters, wrap each parameter: `aliasPath IN (jsonb(:p1), jsonb(:p2), ...)`.
Add a functional test demonstrating filtering by jsonb equality returns the saved row.

ⓘ Copy this prompt and use it to remediate the issue with your preferred AI generation tools


14. ReactNative jsonb unsupported 🐞 Bug ✓ Correctness
Description
ReactNativeDriver is treated as part of the SQLite family in query builders and gets jsonb()/json()
wrapping, but it neither declares json/jsonb as supported types nor serializes/deserializes them.
Using jsonb on the react-native driver will either fail schema validation (unsupported type) or
attempt to bind raw JS objects into sqlite parameters, causing runtime errors and incorrect
hydration.
Code

src/query-builder/InsertQueryBuilder.ts[R1705-1708]

+            } else if (DriverUtils.isSQLiteFamily(this.connection.driver)) {
+                expression = (
+                    this.connection.driver as AbstractSqliteDriver
+                ).wrapWithJsonFunction(paramName, column, true)
Evidence
InsertQueryBuilder always normalizes values via driver.preparePersistentValue before creating a
parameter; for SQLite family it then wraps the placeholder with jsonb()/json() via
wrapWithJsonFunction. DriverUtils considers react-native part of the SQLite family, so
ReactNativeDriver will take this path. However, ReactNativeDriver does not list json/jsonb in
supportedDataTypes and its preparePersistentValue/prepareHydratedValue logic does not handle
json/jsonb (only simple-json), so jsonb values won’t be stringified/parsed and may not be supported
at all.

src/query-builder/InsertQueryBuilder.ts[1568-1571]
src/query-builder/InsertQueryBuilder.ts[1705-1709]
src/driver/DriverUtils.ts[17-27]
src/driver/react-native/ReactNativeDriver.ts[97-129]
src/driver/react-native/ReactNativeDriver.ts[325-358]
src/driver/react-native/ReactNativeDriver.ts[368-430]

Agent prompt
The issue below was found during a code review. Follow the provided context and guidance below and implement a solution

## Issue description
`ReactNativeDriver` is included in the SQLite-family query builder wrapping path for `jsonb`, but the driver itself does not support `json/jsonb` in `supportedDataTypes`, and does not serialize/deserialize `json/jsonb` values in `preparePersistentValue`/`prepareHydratedValue`. This makes `jsonb` unusable (or error-prone) on `react-native`.
### Issue Context
- Query builders call `driver.preparePersistentValue()` and then (for SQLite family) wrap placeholders using `wrapWithJsonFunction(..., jsonb=true)`.
- `DriverUtils.isSQLiteFamily()` includes `react-native`.
- Other SQLite drivers inherit `AbstractSqliteDriver`, which *does* handle `json/jsonb` persistence/hydration.
### Fix Focus Areas
- src/driver/react-native/ReactNativeDriver.ts[97-129]
- src/driver/react-native/ReactNativeDriver.ts[325-439]
- src/driver/react-native/ReactNativeDriver.ts[634-689]
- src/query-builder/InsertQueryBuilder.ts[1568-1571]
- src/query-builder/InsertQueryBuilder.ts[1705-1709]
### Suggested fix approach
1. Add `&amp;amp;quot;json&amp;amp;quot;` and `&amp;amp;quot;jsonb&amp;amp;quot;` to `ReactNativeDriver.supportedDataTypes`.
2. Update `ReactNativeDriver.preparePersistentValue` to treat `json` and `jsonb` like `simple-json` (i.e., `JSON.stringify`), consistent with `AbstractSqliteDriver`.
3. Update `ReactNativeDriver.prepareHydratedValue` to parse `json` and `jsonb` values via `JSON.parse` (like `AbstractSqliteDriver`).
4. Update `ReactNativeDriver.normalizeDefault` to support object defaults and wrap `jsonb` defaults in `jsonb(&amp;amp;#x27;...&amp;amp;#x27;)` with proper quote escaping (mirror `AbstractSqliteDriver.normalizeDefault`).
5. (Optional but recommended) Add a `defaultEqual`-style semantic comparison for json/jsonb defaults to avoid migration churn, similar to the sqlite abstract implementation.

ⓘ Copy this prompt and use it to remediate the issue with your preferred AI generation tools



Remediation recommended

15. qoute key misspelling 📘 Rule violation ✓ Correctness
Description
New tests introduce the misspelled object key qoute, which does not follow consistent naming
conventions and reduces clarity. This risks spreading the typo into future test expectations and
examples.
Code

test/functional/json/basic-jsonb/sqlite/sqlite-jsonb.test.ts[R245-262]

+    it("should handle JSONB with quotes correctly", () =>
+        Promise.all(
+            connections.map(async (connection) => {
+                const recordRepo = connection.getRepository(Record)
+                const record = new Record()
+                record.data = { qoute: "He said, O'Brian" }
+                const savedRecord = await recordRepo.save(record)
+
+                const foundRecord = await recordRepo.findOneBy({
+                    id: savedRecord.id,
+                })
+                expect(foundRecord).to.be.not.undefined
+                expect(foundRecord!).to.deep.include({
+                    data: {
+                        qoute: "He said, O'Brian",
+                    },
+                    dataWithDefaultObject: { hello: "world'O", foo: "bar" },
+                })
Evidence
Compliance ID 1 requires consistent naming; the added test data uses qoute (typo) in multiple new
assertions/fixtures instead of quote.

Rule 1: Consistent Naming Conventions
[test/functional/j...

@pkg-pr-new
Copy link

pkg-pr-new bot commented Jan 20, 2026

commit: b66ca86

@coveralls
Copy link

coveralls commented Jan 20, 2026

Coverage Status

coverage: 73.187% (-0.04%) from 73.225%
when pulling b66ca86 on Cprakhar:feat/jsonb-sqlite
into e1b76c9 on typeorm:master.

@qodo-free-for-open-source-projects

Persistent review updated to latest commit 9e9459b

@qodo-free-for-open-source-projects

Persistent review updated to latest commit 336aa4d

@qodo-free-for-open-source-projects

Persistent review updated to latest commit bf6bec7

@Cprakhar Cprakhar marked this pull request as draft January 21, 2026 08:25
@qodo-free-for-open-source-projects

Persistent review updated to latest commit 0d57335

@Cprakhar Cprakhar marked this pull request as ready for review January 21, 2026 15:54
@qodo-free-for-open-source-projects

User description

Description of Change

This pull request (PR) introduces support for the jsonb datatype in SQLite.

Example:

@Entity()
export class Record {
  @PrimaryGeneratedColumn()
  id: number

  @Column("jsonb")
  data: any

  @Column({
    type: "jsonb",
    default: { foo: "bar" }
  })
  defaultData: any
}
-- Create
CREATE TABLE "record" ("id" integer PRIMARY KEY AUTOINCREMENT NOT NULL, "data" jsonb, "defaultData" jsonb DEFAULT (jsonb('{"foo":"bar"}')))

-- Insert
INSERT INTO "record"("id", "data", "defaultData") VALUES (NULL, jsonb(?), jsonb('{"hello":"world","foo":"bar"}')) -- PARAMETERS: ["{\"key\":\"value\",\"nested\":{\"num\":42}}"]

-- Select
SELECT "Record"."id" AS "Record_id", json("Record"."data") AS "Record_data", json("Record"."defaultData") AS "Record_defaultData" FROM "record" "Record" WHERE (("Record"."id" = 1)) LIMIT 1

Note: Current sqlite3 driver version doesn't support jsonb and jsonb functions, better-sqlite3 and sqljs fully supports jsonb

Closes #11930

Changes Made

  • Implemented logic to handle jsonb in both the preparePersistentValue and prepareHydratedValue methods to ensure proper persistence and retrieval of the value.
  • Included jsonb in the supported data types for the AbstractSqliteDriver.
  • Added a private method to compare default values in order to detect any changes for migrations.
  • Updated docs for sqlite driver to include both json and jsonb in the Column Types section

Pull-Request Checklist

  • Code is up-to-date with the master branch
  • This pull request links relevant issues as Fixes #11930
  • There are new or updated tests validating the change (tests/**.test.ts)
  • Documentation has been updated to reflect this change (docs/docs/**.md)

PR Type

Enhancement


Description

  • Add JSONB column type support for SQLite drivers

  • Implement proper persistence and retrieval handling for JSONB values

  • Add semantic default value comparison for JSON/JSONB columns

  • Wrap JSONB values with jsonb() function in INSERT/UPDATE queries

  • Wrap JSONB columns with json() function in SELECT queries

  • Update documentation and add comprehensive test coverage


Diagram Walkthrough

flowchart LR
  A["SQLite JSONB Support"] --> B["Driver Updates"]
  A --> C["Query Builder Updates"]
  A --> D["Tests & Docs"]
  B --> B1["AbstractSqliteDriver: Add jsonb to supported types"]
  B --> B2["Add defaultEqual method for semantic comparison"]
  B --> B3["Handle jsonb in preparePersistentValue/prepareHydratedValue"]
  C --> C1["InsertQueryBuilder: Wrap jsonb with jsonb function"]
  C --> C2["UpdateQueryBuilder: Wrap jsonb with jsonb function"]
  C --> C3["SelectQueryBuilder: Wrap jsonb with json function"]
  D --> D1["Add sqlite-jsonb.test.ts with comprehensive tests"]
  D --> D2["Update column-types-sqlite.test.ts"]
  D --> D3["Update sqlite.md documentation"]
Loading

File Walkthrough

Relevant files
Enhancement
4 files
AbstractSqliteDriver.ts
Add JSONB support with semantic default comparison             
+83/-5   
InsertQueryBuilder.ts
Wrap JSONB values with jsonb function                                       
+5/-0     
UpdateQueryBuilder.ts
Wrap JSONB values with jsonb function                                       
+7/-0     
SelectQueryBuilder.ts
Wrap JSONB columns with json function                                       
+6/-0     
Error handling
1 files
PostgresDriver.ts
Enhance default value handling with error handling             
+29/-14 
Documentation
2 files
ColumnTypes.ts
Update JSONB type documentation for SQLite                             
+1/-1     
sqlite.md
Document JSON and JSONB column type support                           
+8/-1     
Tests
4 files
Post.ts
Add JSONB column to test entity                                                   
+3/-0     
column-types-sqlite.test.ts
Add JSONB tests and skip for sqlite3 driver                           
+5/-0     
sqlite-jsonb.test.ts
Add comprehensive JSONB functionality tests                           
+244/-0 
jsonb-defaults.test.ts
Enable JSONB defaults tests for SQLite drivers                     
+1/-1     

@qodo-free-for-open-source-projects
Copy link

qodo-free-for-open-source-projects bot commented Jan 21, 2026

PR Code Suggestions ✨

Explore these optional code suggestions:

CategorySuggestion                                                                                                                                    Impact
High-level
Refactor JSONB logic into driver
Suggestion Impact:The commit implements the core idea of the suggestion by moving JSONB logic to the AbstractSqliteDriver. Instead of the suggested method names (formatQueryParam/formatSelectColumn), the implementation uses a single method called wrapWithJsonFunction(). The commit refactors all three query builders (Insert, Update, Select) to call this driver method instead of having inline SQLite-specific JSONB checks, achieving the suggested centralization and deduplication.

code diff:

+import { AbstractSqliteDriver } from "../driver/sqlite-abstract/AbstractSqliteDriver"
 import { SqlServerDriver } from "../driver/sqlserver/SqlServerDriver"
 import { TypeORMError } from "../error"
 import { InsertValuesMissingError } from "../error/InsertValuesMissingError"
@@ -612,10 +613,31 @@
                         )
                     } else if (columns) {
                         updatePart.push(
-                            ...columns.map(
-                                (column) =>
-                                    `${this.escape(column)} = :${column}`,
-                            ),
+                            ...columns.map((column) => {
+                                let expression = `:${column}`
+                                if (
+                                    this.expressionMap.mainAlias!.hasMetadata &&
+                                    DriverUtils.isSQLiteFamily(
+                                        this.connection.driver,
+                                    )
+                                ) {
+                                    const col =
+                                        this.expressionMap.mainAlias?.metadata.findColumnWithDatabaseName(
+                                            column,
+                                        )
+                                    if (col) {
+                                        expression = (
+                                            this.connection
+                                                .driver as AbstractSqliteDriver
+                                        ).wrapWithJsonFunction(
+                                            expression,
+                                            col,
+                                            true,
+                                        )
+                                    }
+                                }
+                                return `${this.escape(column)} = ${expression}`
+                            }),
                         )
                     }
 
@@ -1666,11 +1688,10 @@
                     ", " +
                     (column.srid || "0") +
                     ")"
-            } else if (
-                DriverUtils.isSQLiteFamily(this.connection.driver) &&
-                column.type === "jsonb"
-            ) {
-                expression = `jsonb(${paramName})`
+            } else if (DriverUtils.isSQLiteFamily(this.connection.driver)) {
+                expression = (
+                    this.connection.driver as AbstractSqliteDriver
+                ).wrapWithJsonFunction(paramName, column, true)
             } else {
                 expression += paramName
             }

# File: src/query-builder/SelectQueryBuilder.ts
@@ -30,6 +30,7 @@
 import { SelectQueryBuilderOption } from "./SelectQueryBuilderOption"
 import { ObjectUtils } from "../util/ObjectUtils"
 import { DriverUtils } from "../driver/DriverUtils"
+import { AbstractSqliteDriver } from "../driver/sqlite-abstract/AbstractSqliteDriver"
 import { EntityNotFoundError } from "../error/EntityNotFoundError"
 import { TypeORMError } from "../error"
 import { FindManyOptions } from "../find-options/FindManyOptions"
@@ -2906,9 +2907,9 @@
             }
 
             if (DriverUtils.isSQLiteFamily(this.connection.driver)) {
-                if (column.type === "jsonb") {
-                    selectionPath = `json(${selectionPath})`
-                }
+                selectionPath = (
+                    this.connection.driver as AbstractSqliteDriver
+                ).wrapWithJsonFunction(selectionPath, column, false)

The suggestion is to move the SQLite-specific jsonb handling logic from the
InsertQueryBuilder, UpdateQueryBuilder, and SelectQueryBuilder into the
AbstractSqliteDriver. This will centralize the logic, reduce duplication, and
improve code modularity.

Examples:

src/query-builder/InsertQueryBuilder.ts [1669-1674]
            } else if (
                DriverUtils.isSQLiteFamily(this.connection.driver) &&
                column.type === "jsonb"
            ) {
                expression = `jsonb(${paramName})`
            } else {
src/query-builder/SelectQueryBuilder.ts [2908-2912]
            if (DriverUtils.isSQLiteFamily(this.connection.driver)) {
                if (column.type === "jsonb") {
                    selectionPath = `json(${selectionPath})`
                }
            }

Solution Walkthrough:

Before:

// In InsertQueryBuilder.ts & UpdateQueryBuilder.ts
// ... inside value expression creation
if (DriverUtils.isSQLiteFamily(driver) && column.type === "jsonb") {
    expression = `jsonb(${paramName})`;
} else {
    expression = paramName;
}

// In SelectQueryBuilder.ts
// ... inside select expression creation
if (DriverUtils.isSQLiteFamily(driver)) {
    if (column.type === "jsonb") {
        selectionPath = `json(${selectionPath})`;
    }
}

After:

// In AbstractSqliteDriver.ts
class AbstractSqliteDriver {
  // ...
  formatQueryParam(paramName: string, column: ColumnMetadata): string {
    if (column.type === "jsonb") {
      return `jsonb(${paramName})`;
    }
    return paramName;
  }

  formatSelectColumn(selectionPath: string, column: ColumnMetadata): string {
    if (column.type === "jsonb") {
      return `json(${selectionPath})`;
    }
    return selectionPath;
  }
}

// In QueryBuilders (Insert, Update, Select)
// The specific driver methods would be called instead of the if-conditions.
Suggestion importance[1-10]: 8

__

Why: This is a strong architectural suggestion that correctly identifies scattered database-specific logic and proposes centralizing it in the driver, improving modularity and maintainability.

Medium
Possible issue
Escape single quotes in JSON defaults
Suggestion Impact:Added escaping of single quotes in JSON stringified defaults (JSON.stringify(...).replace(/'/g, "''")) and used the escaped string for both jsonb(...) and plain quoted JSON defaults; also adjusted JSON default comparison to unescape doubled quotes before JSON.parse.

code diff:

         if (typeof defaultValue === "object") {
+            const jsonString = JSON.stringify(defaultValue).replace(/'/g, "''")
             if (columnMetadata.type === "jsonb") {
-                return `jsonb('${JSON.stringify(defaultValue)}')`
+                return `jsonb('${jsonString}')`
             }
-            return `'${JSON.stringify(defaultValue)}'`
+            return `'${jsonString}'`
         }
 
         return `${defaultValue}`
@@ -691,6 +709,7 @@
 
     /**
      * Normalizes "isUnique" value of the column.
+     * @param column
      */
     normalizeIsUnique(column: ColumnMetadata): boolean {
         return column.entityMetadata.uniques.some(
@@ -700,6 +719,7 @@
 
     /**
      * Calculates column length taking into account the default length values.
+     * @param column
      */
     getColumnLength(column: ColumnMetadata): string {
         return column.length ? column.length.toString() : ""
@@ -707,6 +727,7 @@
 
     /**
      * Normalizes "default" value of the column.
+     * @param column
      */
     createFullType(column: TableColumn): string {
         let type = column.type
@@ -754,6 +775,10 @@
 
     /**
      * Creates generated map of values generated or returned by database after INSERT query.
+     * @param metadata
+     * @param insertResult
+     * @param entityIndex
+     * @param entityNum
      */
     createGeneratedMap(
         metadata: EntityMetadata,
@@ -789,6 +814,8 @@
 
     /**
      * Compares column default values, handling JSON/JSONB types semantically.
+     * @param columnMetadata
+     * @param tableColumn
      */
     private defaultEqual(
         columnMetadata: ColumnMetadata,
@@ -823,22 +850,24 @@
                         tableDefault.toLowerCase().startsWith("jsonb('") &&
                         tableDefault.endsWith("')")
                     ) {
-                        tableDefault = tableDefault
-                            .substring(7, tableDefault.length - 2)
-                            .replace(/''/g, "'")
+                        tableDefault = tableDefault.substring(
+                            7,
+                            tableDefault.length - 2,
+                        )
                     } else if (
                         tableDefault.startsWith("'") &&
                         tableDefault.endsWith("'")
                     ) {
-                        tableDefault = tableDefault
-                            .substring(1, tableDefault.length - 1)
-                            .replace(/''/g, "'")
+                        tableDefault = tableDefault.substring(
+                            1,
+                            tableDefault.length - 1,
+                        )
                     }
                 }
 
                 const tableDefaultObj =
                     typeof tableDefault === "string"
-                        ? JSON.parse(tableDefault)
+                        ? JSON.parse(tableDefault.replace(/''/g, "'"))
                         : tableDefault

Escape single quotes in JSON default values to prevent SQL syntax errors. The
current implementation does not handle single quotes within the JSON string,
which will break the query.

src/driver/sqlite-abstract/AbstractSqliteDriver.ts [682-687]

 if (typeof defaultValue === "object") {
+    const jsonString = JSON.stringify(defaultValue).replace(/'/g, "''")
     if (columnMetadata.type === "jsonb") {
-        return `jsonb('${JSON.stringify(defaultValue)}')`
+        return `jsonb('${jsonString}')`
     }
-    return `'${JSON.stringify(defaultValue)}'`
+    return `'${jsonString}'`
 }

[Suggestion processed]

Suggestion importance[1-10]: 8

__

Why: This suggestion correctly identifies a bug where a JSON default value containing a single quote would generate invalid SQL, causing an error. The proposed fix correctly escapes the quotes, ensuring the generated default value is always a valid SQL string literal.

Medium
General
Validate quote wrapping before substring extraction
Suggestion Impact:The commit modified the same JSON default parsing logic: it still strips the first/last character via substring, but additionally unescapes doubled single quotes ('' -> ') before JSON.parse, and also escapes single quotes when generating JSON defaults. It did not add the suggested startsWith/endsWith validation, but it did adjust quote-handling robustness in this area.

code diff:

@@ -1184,7 +1202,7 @@
         }
 
         if (typeof defaultValue === "object") {
-            return `'${JSON.stringify(defaultValue)}'`
+            return `'${JSON.stringify(defaultValue).replace(/'/g, "''")}'`
         }
 
         return `${defaultValue}`
@@ -1193,6 +1211,8 @@
     /**
      * Compares "default" value of the column.
      * Postgres sorts json values before it is saved, so in that case a deep comparison has to be performed to see if has changed.
+     * @param columnMetadata
+     * @param tableColumn
      */
     private defaultEqual(
         columnMetadata: ColumnMetadata,
@@ -1214,10 +1234,9 @@
                 const tableColumnDefault =
                     typeof tableColumn.default === "string"
                         ? JSON.parse(
-                              tableColumn.default.substring(
-                                  1,
-                                  tableColumn.default.length - 1,
-                              ),
+                              tableColumn.default
+                                  .substring(1, tableColumn.default.length - 1)
+                                  .replace(/''/g, "'"),
                           )
                         : tableColumn.default

Improve JSON default value parsing in Postgres by checking for wrapping single
quotes before attempting to remove them with substring. This makes the logic
more robust for different default value formats.

src/driver/postgres/PostgresDriver.ts [1211-1231]

 try {
-    const tableColumnDefault =
-        typeof tableColumn.default === "string"
-            ? JSON.parse(
-                  tableColumn.default.substring(
-                      1,
-                      tableColumn.default.length - 1,
-                  ),
-              )
-            : tableColumn.default
+    let tableColumnDefault = tableColumn.default
+    if (typeof tableColumnDefault === "string") {
+        // Remove wrapping quotes if present
+        if (tableColumnDefault.startsWith("'") && tableColumnDefault.endsWith("'")) {
+            tableColumnDefault = tableColumnDefault.substring(1, tableColumnDefault.length - 1)
+        }
+        tableColumnDefault = JSON.parse(tableColumnDefault)
+    }
 
     return OrmUtils.deepCompare(
         columnMetadata.default,
         tableColumnDefault,
     )
 } catch (err) {
     const columnDefault = this.lowerDefaultValueIfNecessary(
         this.normalizeDefault(columnMetadata),
     )
     return columnDefault === tableColumn.default
 }

[Suggestion processed]

Suggestion importance[1-10]: 5

__

Why: The suggestion correctly points out that blindly using substring to remove quotes is brittle. The proposed change to conditionally remove quotes only if they exist makes the default value parsing more robust against different formats returned by Postgres.

Low
  • More

Copy link
Collaborator

@gioboa gioboa left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

it looks great to me 🚀 @Cprakhar

@gioboa gioboa requested review from G0maa and alumni January 26, 2026 22:10
@qodo-free-for-open-source-projects

Code Review by Qodo

🐞 Bugs (13) 📘 Rule violations (7) 📎 Requirement gaps (0)

Grey Divider


Action required

1. defaultEqual swallows JSON errors 📘 Rule violation ⛯ Reliability ⭐ New
Description
New defaultEqual logic silently ignores JSON.parse SyntaxError when comparing JSON/JSONB
defaults, which can mask real default mismatches and migration diffs. This adds abnormal defensive
try/catch behavior inconsistent with the checklist.
Code

src/driver/postgres/PostgresDriver.ts[R1241-1257]

+            if (typeof jsonString === "string") {
+                try {
+                    const tableColumnDefault = JSON.parse(jsonString)
+                    return OrmUtils.deepCompare(
+                        columnMetadata.default,
+                        tableColumnDefault,
+                    )
+                } catch (err) {
+                    if (!(err instanceof SyntaxError)) {
+                        throw new TypeORMError(
+                            `Failed to compare default values of ${columnMetadata.propertyName} column`,
+                        )
+                    }
+                }
+            } else {
+                return OrmUtils.deepCompare(columnMetadata.default, jsonString)
+            }
Evidence
Compliance ID 4 disallows abnormal defensive try/catch patterns; the added code catches
SyntaxError from JSON.parse and proceeds without returning or surfacing the comparison failure,
effectively swallowing the error path.

Rule 4: Remove AI-generated noise
src/driver/postgres/PostgresDriver.ts[1241-1257]

Agent prompt
The issue below was found during a code review. Follow the provided context and guidance below and implement a solution

## Issue description
`defaultEqual()` catches `SyntaxError` from `JSON.parse()` and silently continues, which can hide real default mismatches and make migration diffing unreliable.

## Issue Context
The compliance checklist disallows abnormal defensive try/catch patterns (AI-noise). The new JSON/JSONB default comparison should not ignore parse failures without an explicit, deterministic outcome.

## Fix Focus Areas
- src/driver/postgres/PostgresDriver.ts[1241-1257]

ⓘ Copy this prompt and use it to remediate the issue with your preferred AI generation tools


2. defaultEqual swallows JSON errors 📘 Rule violation ⛯ Reliability ⭐ New
Description
New CockroachDB default comparison swallows JSON parsing SyntaxError without a deterministic
fallback, potentially hiding mismatched defaults. This introduces abnormal defensive try/catch
behavior disallowed by the compliance checklist.
Code

src/driver/cockroachdb/CockroachDriver.ts[R823-839]

+            if (typeof jsonString === "string") {
+                try {
+                    const tableColumnDefault = JSON.parse(jsonString)
+                    return OrmUtils.deepCompare(
+                        columnMetadata.default,
+                        tableColumnDefault,
+                    )
+                } catch (err) {
+                    if (!(err instanceof SyntaxError)) {
+                        throw new TypeORMError(
+                            `Failed to compare default values of ${columnMetadata.propertyName} column`,
+                        )
+                    }
+                }
+            } else {
+                return OrmUtils.deepCompare(columnMetadata.default, jsonString)
+            }
Evidence
Compliance ID 4 requires removing abnormal defensive try/catch blocks; the new code attempts to
parse a normalized default string and ignores SyntaxError, allowing comparison to proceed without
validating equivalence.

Rule 4: Remove AI-generated noise
src/driver/cockroachdb/CockroachDriver.ts[823-839]

Agent prompt
The issue below was found during a code review. Follow the provided context and guidance below and implement a solution

## Issue description
`CockroachDriver.defaultEqual()` ignores `SyntaxError` from `JSON.parse()` and continues, which can conceal default mismatches.

## Issue Context
The compliance checklist disallows abnormal defensive try/catch. JSON/JSONB default parsing should not fail silently.

## Fix Focus Areas
- src/driver/cockroachdb/CockroachDriver.ts[823-839]

ⓘ Copy this prompt and use it to remediate the issue with your preferred AI generation tools


3. Broken jsonb resorting test 🐞 Bug ✓ Correctness ⭐ New
Description
The test "should not create updates when resorting object" changes the DB default to a different
value (hello:"world") than the entity metadata default (hello:"world'O"), so the test should not
expect zero schema diffs and will fail or mask regressions.
Code

test/functional/json/basic-jsonb/postgres/jsonb.test.ts[R156-181]

    it("should not create updates when resorting object", () =>
        Promise.all(
            dataSources.map(async (connection) => {
-                await connection.query(
-                    `ALTER TABLE record ALTER COLUMN "dataWithDefaultObject" SET DEFAULT '{"foo":"bar", "hello": "world"}';`,
-                )
+                if (DriverUtils.isSQLiteFamily(connection.driver)) {
+                    // Sqlite does not support altering column defaults, so we need to use query runner
+                    const queryRunner =
+                        connection.createQueryRunner() as AbstractSqliteQueryRunner
+                    const table = await queryRunner.getTable("record")
+                    const column = table!.findColumnByName(
+                        "dataWithDefaultObject",
+                    )!
+                    column.default = `'{"foo":"bar", "hello": "world"}'`
+                    await queryRunner.changeColumn(
+                        "record",
+                        "dataWithDefaultObject",
+                        column,
+                    )
+                    await queryRunner.release()
+                } else {
+                    await connection.query(
+                        `ALTER TABLE record ALTER COLUMN "dataWithDefaultObject" SET DEFAULT '{"foo":"bar", "hello": "world"}';`,
+                    )
+                }

                const sqlInMemory = await connection.driver
                    .createSchemaBuilder()
Evidence
The entity defines a jsonb default containing a single quote (world'O). The test that claims to only
reorder keys instead changes the value to world, making the defaults semantically different; schema
diff should detect a change.

test/functional/json/basic-jsonb/postgres/entity/Record.ts[14-22]
test/functional/json/basic-jsonb/postgres/jsonb.test.ts[156-186]

Agent prompt
The issue below was found during a code review. Follow the provided context and guidance below and implement a solution

### Issue description
A jsonb default-comparison test intends to verify that key reordering does not produce schema diffs, but it currently changes the *value* of the default (&quot;world&quot; vs &quot;world&#x27;O&quot;), so the expectation of no diffs is incorrect.

### Issue Context
The Record entity default contains a single quote (`world&#x27;O`). SQL literals must escape that quote (`world&#x27;&#x27;O`).

### Fix Focus Areas
- test/functional/json/basic-jsonb/postgres/jsonb.test.ts[156-178]
- test/functional/json/basic-jsonb/postgres/entity/Record.ts[14-22]

### Suggested change
Update both the SQLite and non-SQLite ALTER/default assignments in the &quot;resorting object&quot; test to use a JSON string equivalent to the entity default, e.g.:
- `&#x27;{&quot;foo&quot;:&quot;bar&quot;,&quot;hello&quot;:&quot;world&#x27;&#x27;O&quot;}&#x27;` (or with spacing)

ⓘ Copy this prompt and use it to remediate the issue with your preferred AI generation tools


View more (9)
4. SQLite JSONB ungated 🐞 Bug ⛯ Reliability
Description
• AbstractSqliteDriver now exposes jsonb as supported and QueryBuilders wrap JSONB reads/writes
with SQLite functions jsonb(...)/json(...) unconditionally. • Repo documentation states JSONB
requires SQLite ≥ 3.45.0 and tests explicitly skip the sqlite (sqlite3) driver due to missing
jsonb functions; without a guard, users can pass metadata validation yet fail later with runtime SQL
errors on older SQLite builds. • Because DataSource.initialize() calls driver.connect() before
metadata validation, the driver can detect SQLite capabilities early and either disable jsonb in
supportedDataTypes or throw a clear, fail-fast error when JSONB isn’t supported.
Code

src/driver/sqlite-abstract/AbstractSqliteDriver.ts[R1035-1043]

+    wrapWithJsonFunction(
+        value: string,
+        column: ColumnMetadata,
+        jsonb: boolean = false,
+    ): string {
+        if (column.type === "jsonb") {
+            return jsonb ? `jsonb(${value})` : `json(${value})`
+        }
+        return value
Evidence
SQLite-family query generation will emit jsonb()/json() whenever an entity column is typed as
jsonb, but the repo itself documents a minimum SQLite version and shows sqlite3 lacking support.
Since sqlite drivers generally do not set driver.version nor gate supportedDataTypes, metadata
validation can succeed while runtime queries fail on unsupported SQLite engines.

src/driver/sqlite-abstract/AbstractSqliteDriver.ts[97-131]
src/driver/sqlite-abstract/AbstractSqliteDriver.ts[1035-1044]
src/query-builder/InsertQueryBuilder.ts[1705-1709]
src/query-builder/SelectQueryBuilder.ts[3012-3018]
src/query-builder/UpdateQueryBuilder.ts[637-646]
src/driver/DriverUtils.ts[16-27]
docs/docs/drivers/sqlite.md[80-87]
test/functional/database-schema/column-types/sqlite/column-types-sqlite.test.ts[23-27]
src/data-source/DataSource.ts[252-266]

Agent prompt
The issue below was found during a code review. Follow the provided context and guidance below and implement a solution

## Issue description
SQLite JSONB is enabled unconditionally for all `AbstractSqliteDriver`-based drivers, and QueryBuilders emit `jsonb(...)` / `json(...)` calls whenever a column is typed as `jsonb`. Repo docs/tests indicate JSONB requires SQLite &amp;gt;= 3.45 and that the `sqlite` (sqlite3) driver may not support it. Without capability/version gating, metadata validation can succeed and then queries fail at runtime.
### Issue Context
`DataSource.initialize()` invokes `driver.connect()` **before** metadata validation. This provides an opportunity to detect SQLite capabilities early and either:
- remove `&amp;quot;jsonb&amp;quot;` from `supportedDataTypes` so validation fails fast with `DataTypeNotSupportedError`, or
- throw a clear `TypeORMError` explaining the SQLite version requirement when JSONB columns are present.
Some SQLite-family drivers override `connect()` (e.g., `sqljs`, `capacitor`), so any shared detection logic must be invoked there as well.
### Fix Focus Areas
- src/driver/sqlite-abstract/AbstractSqliteDriver.ts[267-275]
- src/driver/sqlite-abstract/AbstractSqliteDriver.ts[97-131]
- src/driver/sqlite-abstract/AbstractSqliteDriver.ts[1035-1044]
- src/driver/sqljs/SqljsDriver.ts[51-56]
- src/driver/capacitor/CapacitorDriver.ts[31-38]
- src/data-source/DataSource.ts[252-266]

ⓘ Copy this prompt and use it to remediate the issue with your preferred AI generation tools


5. ReactNative query crash 🐞 Bug ✓ Correctness
Description
• Query builders call wrapWithJsonFunction whenever DriverUtils.isSQLiteFamily(driver) is true.
• DriverUtils.isSQLiteFamily includes the react-native driver type, but ReactNativeDriver is
declared as implements Driver (not extending AbstractSqliteDriver). • Since
wrapWithJsonFunction is implemented on AbstractSqliteDriver, react-native connections can hit
TypeError: driver.wrapWithJsonFunction is not a function during SELECT/INSERT/UPDATE query
construction/execution.
Code

src/query-builder/SelectQueryBuilder.ts[R3011-3015]

+            if (DriverUtils.isSQLiteFamily(this.connection.driver)) {
+                selectionPath = (
+                    this.connection.driver as AbstractSqliteDriver
+                ).wrapWithJsonFunction(selectionPath, column, false)
+            }
Evidence
The query builder invokes wrapWithJsonFunction for any SQLite-family driver. The SQLite-family
list explicitly includes react-native, but the react-native driver class does not inherit from
AbstractSqliteDriver (which defines wrapWithJsonFunction), so the cast in the query builder can
be invalid at runtime and lead to an undefined method call.

src/query-builder/SelectQueryBuilder.ts[3011-3015]
src/query-builder/InsertQueryBuilder.ts[1691-1694]
src/query-builder/UpdateQueryBuilder.ts[615-623]
src/driver/DriverUtils.ts[16-26]
src/driver/react-native/ReactNativeDriver.ts[35-41]
src/driver/sqlite-abstract/AbstractSqliteDriver.ts[1037-1046]

Agent prompt
The issue below was found during a code review. Follow the provided context and guidance below and implement a solution

## Issue description
Query builders call `wrapWithJsonFunction` for all SQLite-family drivers, but `react-native` is considered SQLite-family while `ReactNativeDriver` does not extend `AbstractSqliteDriver` (where `wrapWithJsonFunction` is implemented). This can cause runtime `TypeError` when building/executing queries.
### Issue Context
`DriverUtils.isSQLiteFamily()` includes `react-native`, and query builders cast `this.connection.driver` to `AbstractSqliteDriver` and call `wrapWithJsonFunction`.
### Fix Focus Areas
- src/query-builder/SelectQueryBuilder.ts[3011-3015]
- src/query-builder/InsertQueryBuilder.ts[616-640]
- src/query-builder/InsertQueryBuilder.ts[1691-1694]
- src/query-builder/UpdateQueryBuilder.ts[615-623]
- src/driver/react-native/ReactNativeDriver.ts[880-910]
### Suggested approach
Pick one:
1) **Feature-detect in query builders**:
- `const drv: any = this.connection.driver;`
- `if (DriverUtils.isSQLiteFamily(drv) &amp;amp;amp;&amp;amp;amp; typeof drv.wrapWithJsonFunction === &amp;amp;quot;function&amp;amp;quot;) { ... }`
2) **Implement `wrapWithJsonFunction` in `ReactNativeDriver`** (same semantics as `AbstractSqliteDriver`), so the existing query-builder calls are safe for `react-native`.
Option (2) is minimally invasive to call sites; option (1) is more future-proof.

ⓘ Copy this prompt and use it to remediate the issue with your preferred AI generation tools


6. Missing JSONB wrapping in orUpdate overwrite🐞 Bug ✓ Correctness
Description
• The InsertQueryBuilder.orUpdate method has two code paths for handling upserts: one using the
columns parameter (which properly wraps JSONB values) and another using the overwrite parameter
(which does not wrap JSONB values) • When using orUpdate with the overwrite parameter on JSONB
columns in SQLite, the generated SQL uses column = EXCLUDED.column without wrapping the value with
jsonb(), causing type mismatches • SQLite supports the EXCLUDED keyword in ON CONFLICT clauses and
the driver declares support for 'on-conflict-do-update', so this code path is reachable • This
inconsistency means JSONB columns will work correctly with .orUpdate(['column'], ['id']) but fail
with .orUpdate({ overwrite: ['column'], conflict_target: ['id'] })
Code

src/query-builder/InsertQueryBuilder.ts[613]

                      )
Evidence
The code shows two different handling paths for orUpdate. The 'columns' path (lines 616-640)
includes JSONB wrapping via wrapWithJsonFunction for SQLite, while the 'overwrite' path (lines
605-613) uses EXCLUDED.column without any type-specific wrapping. The AbstractSqliteDriver declares
support for 'on-conflict-do-update' at line 137, confirming this code path is active for SQLite.

src/query-builder/InsertQueryBuilder.ts[616-640]
src/driver/sqlite-abstract/AbstractSqliteDriver.ts[137-137]

Agent prompt
The issue below was found during a code review. Follow the provided context and guidance below and implement a solution

The issue below was found during a code review. Follow the provided context and guidance below and implement a solution
The issue below was found during a code review. Follow the provided context and guidance below and implement a solution
## Issue Description
The InsertQueryBuilder.orUpdate method doesn&amp;amp;#x27;t wrap JSONB columns with the required jsonb() function when using the overwrite parameter, causing type mismatches in SQLite.
## Issue Context
SQLite&amp;amp;#x27;s JSONB type requires values to be wrapped with jsonb() for insertion and json() for retrieval. The PR correctly implements this for the &amp;amp;#x27;columns&amp;amp;#x27; parameter path but misses it for the &amp;amp;#x27;overwrite&amp;amp;#x27; parameter path.
## Fix Focus Areas
- src/query-builder/InsertQueryBuilder.ts[605-613]: Add JSONB wrapping logic similar to lines 616-640
- The fix should check if the driver is SQLite, look up column metadata, and wrap EXCLUDED.column with json() function for JSONB columns

ⓘ Copy this prompt and use it to remediate the issue with your preferred AI generation tools


7. Missing jsonb wrapping for EXCLUDED values🐞 Bug ✓ Correctness
Description
• When using orUpdate with the overwrite parameter, the generated SQL uses `column =
EXCLUDED.column` without wrapping EXCLUDED.column with json() function • For jsonb columns in
SQLite, EXCLUDED.column returns raw BLOB data that must be wrapped with json() to be properly
assigned • The columns parameter path correctly applies wrapWithJsonFunction, but the overwrite
parameter path does not • This causes upsert operations using orUpdate(['jsonb_column'], ['id']) to
fail with type mismatch errors
Code

src/query-builder/InsertQueryBuilder.ts[613]

                      )
Evidence
The code shows two different paths for handling orUpdate: the overwrite path (lines 605-613)
generates EXCLUDED-based updates without jsonb wrapping, while the columns path (lines 614-641)
correctly applies wrapWithJsonFunction. The test at line 219 of sqlite-jsonb.test.ts uses
orUpdate(['data'], ['id']) which would exercise this code path and fail for jsonb columns.

src/query-builder/InsertQueryBuilder.ts[605-613]
src/query-builder/InsertQueryBuilder.ts[614-641]
test/functional/json/basic-jsonb/sqlite-jsonb.test.ts[195-226]

Agent prompt
The issue below was found during a code review. Follow the provided context and guidance below and implement a solution

The issue below was found during a code review. Follow the provided context and guidance below and implement a solution
The issue below was found during a code review. Follow the provided context and guidance below and implement a solution
## Issue Description
The orUpdate method with overwrite parameter generates SQL like `column = EXCLUDED.column` without wrapping EXCLUDED.column with json() function for jsonb columns. This causes type mismatch errors because EXCLUDED.column returns raw BLOB data for jsonb columns in SQLite.
## Issue Context
The columns parameter path (lines 614-641) correctly applies wrapWithJsonFunction to handle jsonb columns, but the overwrite parameter path (lines 605-613) does not apply this wrapping.
## Fix Focus Areas
- src/query-builder/InsertQueryBuilder.ts[605-613]
The fix should:
1. Check if the driver is SQLite family
2. For each column in the overwrite array, check if it&amp;amp;#x27;s a jsonb column
3. If it is jsonb, wrap EXCLUDED.column with json() function using the driver&amp;amp;#x27;s wrapWithJsonFunction method
4. Generate SQL like: `column = json(EXCLUDED.column)` for jsonb columns

ⓘ Copy this prompt and use it to remediate the issue with your preferred AI generation tools


8. Missing JSONB wrapping in orUpdate overwrite🐞 Bug ✓ Correctness
Description
• The InsertQueryBuilder.orUpdate method has two code paths for handling upserts: one using the
columns parameter (which properly wraps JSONB values) and another using the overwrite parameter
(which does not wrap JSONB values) • When using orUpdate with the overwrite parameter on JSONB
columns in SQLite, the generated SQL uses column = EXCLUDED.column without wrapping the value with
jsonb(), causing type mismatches • SQLite supports the EXCLUDED keyword in ON CONFLICT clauses and
the driver declares support for 'on-conflict-do-update', so this code path is reachable • This
inconsistency means JSONB columns will work correctly with .orUpdate(['column'], ['id']) but fail
with .orUpdate({ overwrite: ['column'], conflict_target: ['id'] })
Code

src/query-builder/InsertQueryBuilder.ts[613]

                     )
Evidence
The code shows two different handling paths for orUpdate. The 'columns' path (lines 616-640)
includes JSONB wrapping via wrapWithJsonFunction for SQLite, while the 'overwrite' path (lines
605-613) uses EXCLUDED.column without any type-specific wrapping. The AbstractSqliteDriver declares
support for 'on-conflict-do-update' at line 137, confirming this code path is active for SQLite.

src/query-builder/InsertQueryBuilder.ts[616-640]
src/driver/sqlite-abstract/AbstractSqliteDriver.ts[137-137]

Agent prompt
The issue below was found during a code review. Follow the provided context and guidance below and implement a solution

The issue below was found during a code review. Follow the provided context and guidance below and implement a solution
The issue below was found during a code review. Follow the provided context and guidance below and implement a solution
The issue below was found during a code review. Follow the provided context and guidance below and implement a solution
## Issue Description
The InsertQueryBuilder.orUpdate method doesn&amp;amp;amp;#x27;t wrap JSONB columns with the required jsonb() function when using the overwrite parameter, causing type mismatches in SQLite.
## Issue Context
SQLite&amp;amp;amp;#x27;s JSONB type requires values to be wrapped with jsonb() for insertion and json() for retrieval. The PR correctly implements this for the &amp;amp;amp;#x27;columns&amp;amp;amp;#x27; parameter path but misses it for the &amp;amp;amp;#x27;overwrite&amp;amp;amp;#x27; parameter path.
## Fix Focus Areas
- src/query-builder/InsertQueryBuilder.ts[605-613]: Add JSONB wrapping logic similar to lines 616-640
- The fix should check if the driver is SQLite, look up column metadata, and wrap EXCLUDED.column with json() function for JSONB columns

ⓘ Copy this prompt and use it to remediate the issue with your preferred AI generation tools


9. Missing jsonb wrapping for EXCLUDED values🐞 Bug ✓ Correctness
Description
• When using orUpdate with the overwrite parameter, the generated SQL uses `column =
EXCLUDED.column` without wrapping EXCLUDED.column with json() function • For jsonb columns in
SQLite, EXCLUDED.column returns raw BLOB data that must be wrapped with json() to be properly
assigned • The columns parameter path correctly applies wrapWithJsonFunction, but the overwrite
parameter path does not • This causes upsert operations using orUpdate(['jsonb_column'], ['id']) to
fail with type mismatch errors
Code

src/query-builder/InsertQueryBuilder.ts[613]

                     )
Evidence
The code shows two different paths for handling orUpdate: the overwrite path (lines 605-613)
generates EXCLUDED-based updates without jsonb wrapping, while the columns path (lines 614-641)
correctly applies wrapWithJsonFunction. The test at line 219 of sqlite-jsonb.test.ts uses
orUpdate(['data'], ['id']) which would exercise this code path and fail for jsonb columns.

src/query-builder/InsertQueryBuilder.ts[605-613]
src/query-builder/InsertQueryBuilder.ts[614-641]
test/functional/json/basic-jsonb/sqlite-jsonb.test.ts[195-226]

Agent prompt
The issue below was found during a code review. Follow the provided context and guidance below and implement a solution

The issue below was found during a code review. Follow the provided context and guidance below and implement a solution
The issue below was found during a code review. Follow the provided context and guidance below and implement a solution
The issue below was found during a code review. Follow the provided context and guidance below and implement a solution
## Issue Description
The orUpdate method with overwrite parameter generates SQL like `column = EXCLUDED.column` without wrapping EXCLUDED.column with json() function for jsonb columns. This causes type mismatch errors because EXCLUDED.column returns raw BLOB data for jsonb columns in SQLite.
## Issue Context
The columns parameter path (lines 614-641) correctly applies wrapWithJsonFunction to handle jsonb columns, but the overwrite parameter path (lines 605-613) does not apply this wrapping.
## Fix Focus Areas
- src/query-builder/InsertQueryBuilder.ts[605-613]
The fix should:
1. Check if the driver is SQLite family
2. For each column in the overwrite array, check if it&amp;amp;amp;#x27;s a jsonb column
3. If it is jsonb, wrap EXCLUDED.column with json() function using the driver&amp;amp;amp;#x27;s wrapWithJsonFunction method
4. Generate SQL like: `column = json(EXCLUDED.column)` for jsonb columns

ⓘ Copy this prompt and use it to remediate the issue with your preferred AI generation tools


10. Test coverage excludes sqlite3 driver🐞 Bug ⛯ Reliability
Description
• The JSONB functionality is only tested with better-sqlite3 and sqljs drivers, completely excluding
the sqlite3 npm package • The comment states 'Current sqlite3 package does not support jsonb or
jsonb functions' but this claim is not verified • Users of the sqlite3 package (the most common
SQLite driver) will not know if JSONB works until runtime, creating a significant risk
Code

test/functional/database-schema/column-types/sqlite/column-types-sqlite.test.ts[R26-27]

+                // Current sqlite3 package does not support jsonb or jsonb functions
+                if (connection.driver.options.type === "sqlite") return
Evidence
The test explicitly skips the sqlite3 driver type, and the new JSONB test file only enables
better-sqlite3 and sqljs. This creates a coverage gap for the most widely used SQLite driver. The
documentation change in sqlite.md claims JSONB support for SQLite without qualifying which driver
packages support it.

test/functional/database-schema/column-types/sqlite/column-types-sqlite.test.ts[26-27]
test/functional/json/basic-jsonb/sqlite-jsonb.test.ts[14-17]
docs/docs/drivers/sqlite.md[85-85]

Agent prompt
The issue below was found during a code review. Follow the provided context and guidance below and implement a solution

The issue below was found during a code review. Follow the provided context and guidance below and implement a solution
The issue below was found during a code review. Follow the provided context and guidance below and implement a solution
The issue below was found during a code review. Follow the provided context and guidance below and implement a solution
## Issue Description
The JSONB feature is not tested with the sqlite3 npm package, only with better-sqlite3 and sqljs. This creates a coverage gap for users of the most common SQLite driver.
## Issue Context
The PR adds JSONB support to SQLite but the test suite explicitly excludes the &amp;amp;amp;#x27;sqlite&amp;amp;amp;#x27; driver type with a comment claiming it doesn&amp;amp;amp;#x27;t support JSONB functions. However, this claim is not verified and the documentation doesn&amp;amp;amp;#x27;t mention this limitation.
## Fix Focus Areas
- test/functional/database-schema/column-types/sqlite/column-types-sqlite.test.ts[26-27]
- test/functional/json/basic-jsonb/sqlite-jsonb.test.ts[16-16]
- docs/docs/drivers/sqlite.md[85-85]
Either:
1. Verify sqlite3 package version and if it supports SQLite 3.45.0+, add it to the test drivers
2. If sqlite3 doesn&amp;amp;amp;#x27;t support JSONB, add clear documentation in sqlite.md explaining which driver packages support JSONB (better-sqlite3, sqljs) and which don&amp;amp;amp;#x27;t (sqlite3)

ⓘ Copy this prompt and use it to remediate the issue with your preferred AI generation tools


11. SQL injection in jsonb default values 🐞 Bug ✓ Correctness
Description
• The normalizeDefault method generates jsonb default values by directly concatenating
JSON.stringify output into SQL without escaping single quotes • JSON strings containing single
quotes (e.g., {"key": "value's"}) produce invalid SQL: jsonb('{"key":"value's"}') • SQLite requires
single quotes to be escaped as '' (doubled), but this escaping is not performed • This causes SQL
syntax errors during schema creation or migration when jsonb columns have object defaults containing
single quotes
Code

src/driver/sqlite-abstract/AbstractSqliteDriver.ts[R682-685]

+        if (typeof defaultValue === "object") {
+            if (columnMetadata.type === "jsonb") {
+                return `jsonb('${JSON.stringify(defaultValue)}')`
+            }
Evidence
The code directly interpolates JSON.stringify output into SQL without escaping single quotes.
PostgresDriver has the same pattern (line 1185) but Postgres uses different quoting rules. For
SQLite, single quotes within string literals must be escaped as '' (doubled). When JSON contains
single quotes, the generated SQL is syntactically invalid.

src/driver/sqlite-abstract/AbstractSqliteDriver.ts[682-687]
src/driver/postgres/PostgresDriver.ts[1184-1186]
src/driver/sqlite-abstract/AbstractSqliteQueryRunner.ts[1976-1978]

Agent prompt
The issue below was found during a code review. Follow the provided context and guidance below and implement a solution

The issue below was found during a code review. Follow the provided context and guidance below and implement a solution
The issue below was found during a code review. Follow the provided context and guidance below and implement a solution
The issue below was found during a code review. Follow the provided context and guidance below and implement a solution
## Issue Description
The normalizeDefault method generates SQL with jsonb() function calls containing JSON strings, but single quotes within the JSON are not escaped according to SQLite syntax rules. This causes SQL syntax errors when the JSON contains single quotes.
## Issue Context
SQLite requires single quotes within string literals to be escaped as &amp;amp;amp;#x27;&amp;amp;amp;#x27; (two single quotes). JSON.stringify may produce strings containing single quotes (e.g., in string values with apostrophes), which must be escaped before being embedded in SQL.
Example:
- Input: { key: &amp;amp;amp;quot;value&amp;amp;amp;#x27;s&amp;amp;amp;quot; }
- JSON.stringify: {&amp;amp;amp;quot;key&amp;amp;amp;quot;:&amp;amp;amp;quot;value&amp;amp;amp;#x27;s&amp;amp;amp;quot;}
- Current SQL: jsonb(&amp;amp;amp;#x27;{&amp;amp;amp;quot;key&amp;amp;amp;quot;:&amp;amp;amp;quot;value&amp;amp;amp;#x27;s&amp;amp;amp;quot;}&amp;amp;amp;#x27;)  // INVALID
- Correct SQL: jsonb(&amp;amp;amp;#x27;{&amp;amp;amp;quot;key&amp;amp;amp;quot;:&amp;amp;amp;quot;value&amp;amp;amp;#x27;&amp;amp;amp;#x27;s&amp;amp;amp;quot;}&amp;amp;amp;#x27;)  // VALID
## Fix Focus Areas
- src/driver/sqlite-abstract/AbstractSqliteDriver.ts[682-687]
The fix should:
1. After JSON.stringify, replace all single quotes with doubled single quotes
2. Apply this escaping for both jsonb and json types
3. Use the pattern: .replace(/&amp;amp;amp;#x27;/g, &amp;amp;amp;quot;&amp;amp;amp;#x27;&amp;amp;amp;#x27;&amp;amp;amp;quot;)

ⓘ Copy this prompt and use it to remediate the issue with your preferred AI generation tools


12. Missing JSONB wrapping in upsert operations🐞 Bug ✓ Correctness
Description
• ON CONFLICT DO UPDATE statements use EXCLUDED.<column> directly without checking if the column is
JSONB type • When JSONB columns are updated via EXCLUDED reference, SQLite may receive values in the
wrong format • The INSERT path wraps JSONB values with jsonb() function, but the UPDATE path in ON
CONFLICT does not apply corresponding handling
Code

src/query-builder/InsertQueryBuilder.ts[1]

                 ", " +
Evidence
The InsertQueryBuilder wraps JSONB values with jsonb() function during INSERT operations for SQLite.
However, the ON CONFLICT DO UPDATE clause uses EXCLUDED.<column> directly without any type-specific
handling. While there is a test for orUpdate with JSONB, it only tests the values() path which goes
through the normal INSERT wrapping. The EXCLUDED reference path is not tested and may have issues
with binary JSONB format handling.

src/query-builder/InsertQueryBuilder.ts[604-612]
src/query-builder/InsertQueryBuilder.ts[1669-1673]
test/functional/json/basic-jsonb/sqlite-jsonb.test.ts[195-226]

Agent prompt
The issue below was found during a code review. Follow the provided context and guidance below and implement a solution

The issue below was found during a code review. Follow the provided context and guidance below and implement a solution
The issue below was found during a code review. Follow the provided context and guidance below and implement a solution
The issue below was found during a code review. Follow the provided context and guidance below and implement a solution
## Issue Description
When using orUpdate() with JSONB columns in SQLite, the ON CONFLICT DO UPDATE SET clause uses EXCLUDED.&amp;amp;amp;lt;column&amp;amp;amp;gt; directly without checking if the column needs special JSONB handling. This may cause type mismatches or data corruption.
## Issue Context
The INSERT path wraps JSONB values with jsonb() function for SQLite (InsertQueryBuilder.ts:1669-1673), but the ON CONFLICT DO UPDATE path doesn&amp;amp;amp;#x27;t apply similar handling. The EXCLUDED pseudo-table contains the values from the INSERT that triggered the conflict, which are already in JSONB binary format, but the assignment may need explicit handling.
## Fix Focus Areas
- src/query-builder/InsertQueryBuilder.ts[604-612]
Investigate whether EXCLUDED.&amp;amp;amp;lt;column&amp;amp;amp;gt; for JSONB columns needs to be wrapped with json() function to convert from binary JSONB to a format suitable for assignment, similar to how SELECT queries wrap JSONB columns with json() for retrieval. Consider adding column type checking in the overwrite.map() function to apply appropriate wrapping for JSONB columns.

ⓘ Copy this prompt and use it to remediate the issue with your preferred AI generation tools



Remediation recommended

13. qoute key misspelling 📘 Rule violation ✓ Correctness ⭐ New
Description
New tests introduce the misspelled object key qoute, which does not follow consistent naming
conventions and reduces clarity. This risks spreading the typo into future test expectations and
examples.
Code

test/functional/json/basic-jsonb/sqlite/sqlite-jsonb.test.ts[R245-262]

+    it("should handle JSONB with quotes correctly", () =>
+        Promise.all(
+            connections.map(async (connection) => {
+                const recordRepo = connection.getRepository(Record)
+                const record = new Record()
+                record.data = { qoute: "He said, O'Brian" }
+                const savedRecord = await recordRepo.save(record)
+
+                const foundRecord = await recordRepo.findOneBy({
+                    id: savedRecord.id,
+                })
+                expect(foundRecord).to.be.not.undefined
+                expect(foundRecord!).to.deep.include({
+                    data: {
+                        qoute: "He said, O'Brian",
+                    },
+                    dataWithDefaultObject: { hello: "world'O", foo: "bar" },
+                })
Evidence
Compliance ID 1 requires consistent naming; the added test data uses qoute (typo) in multiple new
assertions/fixtures instead of quote.

Rule 1: Consistent Naming Conventions
test/functional/json/basic-jsonb/sqlite/sqlite-jsonb.test.ts[249-262]
test/functional/json/basic-jsonb/postgres/jsonb.test.ts[205-218]

Agent prompt
The issue below was found during a code review. Follow the provided context and guidance below and implement a solution

## Issue description
New tests use a misspelled property name `qoute`, which violates consistent naming and harms readability.

## Issue Context
The key is used in test fixtures and assertions; renaming should be safe as it is test-only data introduced by this PR.

## Fix Focus Areas
- test/functional/json/basic-jsonb/sqlite/sqlite-jsonb.test.ts[249-262]
- test/functional/json/basic-jsonb/postgres/jsonb.test.ts[205-218]

ⓘ Copy this prompt and use it to remediate the issue with your preferred AI generation tools


14. Unneeded runtime driver imports 🐞 Bug ➹ Performance ⭐ New
Description
SelectQueryBuilder and UpdateQueryBuilder import sqlite driver classes as runtime values even though
they are only used for type assertions, which is unnecessary and can hinder tree-shaking / increase
bundle surface area.
Code

src/query-builder/SelectQueryBuilder.ts[R30-35]

import type { SelectQueryBuilderOption } from "./SelectQueryBuilderOption"
import { ObjectUtils } from "../util/ObjectUtils"
import { DriverUtils } from "../driver/DriverUtils"
+import { AbstractSqliteDriver } from "../driver/sqlite-abstract/AbstractSqliteDriver"
import { EntityNotFoundError } from "../error/EntityNotFoundError"
import { TypeORMError } from "../error"
Evidence
The imported classes are not used in any runtime way (no instanceof/static access), only in as
assertions. Using import type avoids emitting these requires in compiled JS. The repo explicitly
uses browser driver remaps, indicating sensitivity to what gets imported into browser bundles.

src/query-builder/SelectQueryBuilder.ts[30-35]
src/query-builder/SelectQueryBuilder.ts[2979-2985]
src/query-builder/UpdateQueryBuilder.ts[20-23]
package.json[48-64]

Agent prompt
The issue below was found during a code review. Follow the provided context and guidance below and implement a solution

### Issue description
Some query builder files introduced runtime imports of driver classes that are only used for typing (`as ...`). This is unnecessary and can negatively affect bundle output / tree-shaking.

### Issue Context
`InsertQueryBuilder` already uses `import type` for these drivers; `SelectQueryBuilder` and `UpdateQueryBuilder` should follow the same pattern.

### Fix Focus Areas
- src/query-builder/SelectQueryBuilder.ts[30-35]
- src/query-builder/UpdateQueryBuilder.ts[20-23]

### Suggested change
- Replace `import { AbstractSqliteDriver } ...` with `import type { AbstractSqliteDriver } ...`
- Replace `import { ReactNativeDriver } ...` with `import type { ReactNativeDriver } ...`
- Ensure no runtime usage depends on these symbols (they appear only in type assertions).

ⓘ Copy this prompt and use it to remediate the issue with your preferred AI generation tools


15. Case-sensitive JSONB default value parsing 🐞 Bug ⛯ Reliability
Description
• The defaultEqual method uses toLowerCase() to detect 'jsonb(' prefix but performs substring
extraction on the original cased string • If SQLite returns 'JSONB(...)' instead of 'jsonb(...)',
the substring(7) operation extracts from the wrong position • This causes JSON.parse to fail and
falls back to string comparison, potentially triggering unnecessary schema migrations • While SQLite
typically returns lowercase function names, the SQL standard doesn't guarantee this behavior
Code

src/driver/sqlite-abstract/AbstractSqliteDriver.ts[R822-828]

+                    if (
+                        tableDefault.toLowerCase().startsWith("jsonb('") &&
+                        tableDefault.endsWith("')")
+                    ) {
+                        tableDefault = tableDefault
+                            .substring(7, tableDefault.length - 2)
+                            .replace(/''/g, "'")
Evidence
The code checks for 'jsonb(' using toLowerCase() but then uses the original string for substring
operations. If the database returns mixed or uppercase function names, the substring extraction will
be incorrect. For example, if tableDefault is 'JSONB('{"key":"value"}')' after parentheses removal,
toLowerCase().startsWith('jsonb(') returns true, but substring(7) extracts '('{"key":"value"}')'
instead of '{"key":"value"}', causing JSON.parse to fail.

src/driver/sqlite-abstract/AbstractSqliteDriver.ts[822-828]
src/driver/sqlite-abstract/AbstractSqliteDriver.ts[839-842]

Agent prompt
The issue below was found during a code review. Follow the provided context and guidance below and implement a solution

The issue below was found during a code review. Follow the provided context and guidance below and implement a solution
The issue below was found during a code review. Follow the provided context and guidance below and implement a solution
## Issue Description
The defaultEqual method in AbstractSqliteDriver has a case-sensitivity bug when parsing JSONB default values. It uses toLowerCase() to check for the &amp;amp;#x27;jsonb(&amp;amp;#x27; prefix but then performs substring operations on the original cased string, which can cause incorrect extraction if SQLite returns uppercase or mixed-case function names.
## Issue Context
When comparing default values for JSON/JSONB columns during schema synchronization, the code needs to extract the JSON string from function calls like &amp;amp;quot;jsonb(&amp;amp;#x27;{&amp;amp;quot;key&amp;amp;quot;:&amp;amp;quot;value&amp;amp;quot;}&amp;amp;#x27;)&amp;amp;quot; or &amp;amp;quot;&amp;amp;#x27;{&amp;amp;#x27;key&amp;amp;#x27;:&amp;amp;#x27;value&amp;amp;#x27;}&amp;amp;#x27;&amp;amp;quot;. The current implementation checks for the jsonb function using case-insensitive comparison but extracts using the original string&amp;amp;#x27;s case.
## Fix Focus Areas
- src/driver/sqlite-abstract/AbstractSqliteDriver.ts[822-828] - Update the substring extraction to use the lowercased version of tableDefault

ⓘ Copy this prompt and use it to remediate the issue with your preferred AI generation tools


View more (5)
16. Missing issue reference in functional test 📘 Rule violation ✓ Correctness
Description
• The new functional test file does not include a reference to issue #11930 mentioned in the PR
description • Per compliance rule 3, functional tests should include an issue reference in a comment
when applicable • This helps maintain traceability between issues and their test coverage
Code

test/functional/json/basic-jsonb/sqlite-jsonb.test.ts[R1-10]

+import { expect } from "chai"
+import { DataSource } from "../../../../src"
+import {
+    createTestingConnections,
+    reloadTestingDatabases,
+    closeTestingConnections,
+} from "../../../utils/test-utils"
+import { Record } from "./entity/Record"
+
+describe("jsonb type > sqlite", () => {
Evidence
The PR description states 'Closes #11930', indicating this is an issue fix. Compliance rule 3
requires that issue fixes should reference the issue in test comments when applicable. Other
functional tests in the codebase follow this pattern (e.g., 'GitHub issue #7738', 'Github issue
#5321').

Rule 3: Prefer functional tests over per-issue tests
test/functional/connection/connection.test.ts[422-422]

Agent prompt
The issue below was found during a code review. Follow the provided context and guidance below and implement a solution

## Issue description
The functional test for SQLite jsonb support is missing a reference to the originating issue #11930.
## Issue Context
The PR description states &amp;amp;#x27;Closes #11930&amp;amp;#x27;. Per project conventions, functional tests should include issue references in comments when the test is related to a specific issue fix.
## Fix Focus Areas
- test/functional/json/basic-jsonb/sqlite-jsonb.test.ts[1-10]

ⓘ Copy this prompt and use it to remediate the issue with your preferred AI generation tools


17. Redundant @param JSDoc tags 📘 Rule violation ⛯ Reliability
Description
• Multiple methods add @param tags without adding meaningful documentation, creating comment churn
that looks auto-generated and inconsistent with the surrounding existing doc style. • This violates
the requirement to avoid AI-generated noise and makes diffs larger/harder to review without
improving behavior.
Code

src/driver/postgres/PostgresDriver.ts[R715-727]

  /**
   * Creates a query runner used to execute database queries.
+     * @param mode
   */
  createQueryRunner(mode: ReplicationMode): PostgresQueryRunner {
      return new PostgresQueryRunner(this, mode)
  }
  /**
   * Prepares given value to a value to be persisted, based on its column type and metadata.
+     * @param value
+     * @param columnMetadata
   */
Evidence
PR Compliance ID 4 requires avoiding AI-generated noise such as extra comments. The PR adds new
@param lines across multiple drivers (example shown in Postgres and Cockroach) without substantive
documentation changes, indicating noisy comment-only edits.

Rule 4: Remove AI-generated noise
src/driver/postgres/PostgresDriver.ts[715-727]
src/driver/cockroachdb/CockroachDriver.ts[365-377]

Agent prompt
The issue below was found during a code review. Follow the provided context and guidance below and implement a solution

## Issue description
New JSDoc `@param` tags were added broadly without meaningful documentation, creating noisy diffs that look auto-generated.
## Issue Context
Compliance requires avoiding AI-generated noise, including extra comments that don’t add value.
## Fix Focus Areas
- src/driver/postgres/PostgresDriver.ts[715-727]
- src/driver/cockroachdb/CockroachDriver.ts[365-377]
- src/driver/sqlite-abstract/AbstractSqliteDriver.ts[665-713]

ⓘ Copy this prompt and use it to remediate the issue with your preferred AI generation tools


18. Broad defaultEqual() try-catch parsing 📘 Rule violation ⛯ Reliability
Description
• New defaultEqual() implementations use broad try/catch around JSON parsing to decide
schema-default equality, which can mask unexpected default formats and silently fall back to string
comparison. • This defensive pattern is explicitly called out as undesirable “AI-generated noise” in
the checklist and may hide real migration-diff bugs.
Code

@Cprakhar Cprakhar force-pushed the feat/jsonb-sqlite branch 3 times, most recently from d328328 to fce4d84 Compare March 6, 2026 13:45
@Cprakhar Cprakhar force-pushed the feat/jsonb-sqlite branch from fce4d84 to c3fcbbc Compare March 7, 2026 08:37
@Cprakhar Cprakhar force-pushed the feat/jsonb-sqlite branch from c3fcbbc to 7869adb Compare March 13, 2026 18:40
@qodo-free-for-open-source-projects
Copy link

qodo-free-for-open-source-projects bot commented Mar 14, 2026

Persistent review updated to latest commit b66ca86

@sonarqubecloud
Copy link

@gioboa gioboa merged commit 0b8e937 into typeorm:master Mar 15, 2026
72 checks passed
@github-actions github-actions bot added this to the 2.0 milestone Mar 15, 2026
@pkuczynski pkuczynski modified the milestones: Next, 1.0 Mar 17, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Development

Successfully merging this pull request may close these issues.

TypeORM does not allow jsonb on sqlite

6 participants