Skip to content

fix: use ALTER COLUMN instead of drop/create for type and length changes - #12754

Open
parastejpal987-cmyk wants to merge 2 commits into
typeorm:masterfrom
parastejpal987-cmyk:fix/issue-3357
Open

fix: use ALTER COLUMN instead of drop/create for type and length changes#12754
parastejpal987-cmyk wants to merge 2 commits into
typeorm:masterfrom
parastejpal987-cmyk:fix/issue-3357

Conversation

@parastejpal987-cmyk

Copy link
Copy Markdown

Closes #3357

What changed?

Currently, if you change the length, type, or isArray property of an existing column, TypeORM's migration generator creates a DROP COLUMN and ADD COLUMN query. This causes silent and catastrophic data loss in production.

This PR updates the changeColumn implementation for Postgres, CockroachDB, and Spanner. Instead of dropping the column, it now correctly generates an ALTER TABLE ... ALTER COLUMN ... TYPE ... query for these modifications to preserve data. We fallback to the old drop/recreate behavior only if the generatedType expression changes (since Postgres still requires a hard recreate for STORED generated columns).

Testing

  • Verified boolean conditions correctly bypass drop/recreate for type/length updates and correctly push ALTER COLUMN queries in the drivers.
  • Ran formatting and checks.

…p/create

Signed-off-by: parastejpal987-cmyk <parastejpal987@gmail.com>
@github-actions github-actions Bot added linked-issue PR references an issue possible-duplicate PR may duplicate an existing open PR labels Aug 4, 2026
@github-actions

github-actions Bot commented Aug 4, 2026

Copy link
Copy Markdown

Other open PRs also reference #3357: #12532,#12541,#12543,#12544,#12657,#12717,#12738,#12740,#12751. Maintainers may want to coordinate.

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

qodo-free-for-open-source-projects Bot commented Aug 4, 2026

Copy link
Copy Markdown

Code Review by Qodo

🐞 Bugs (1) 📘 Rule violations (1) 📎 Requirement gaps (0) 📜 Skill insights (0)

Context used

Grey Divider


Action required

1. Cockroach enum ALTER invalid 🐞 Bug ≡ Correctness
Description
CockroachQueryRunner.changeColumn and PostgresQueryRunner.changeColumn can now generate `ALTER TABLE
... ALTER COLUMN ... TYPE enum / TYPE simple-enum` during transitions to/from enums because the
new ALTER path uses createFullType(), which returns the literal column.type. This bypasses the
enum-aware buildEnumName(...) and enum-type creation previously handled in the drop/add flow
(e.g., addColumn()), causing invalid SQL and/or missing enum-type failures (including in down
migrations when the old column is an enum).
Code

src/driver/cockroachdb/CockroachQueryRunner.ts[R1658-1661]

+                newColumn.scale !== oldColumn.scale ||
+                newColumn.length !== oldColumn.length ||
+                newColumn.type !== oldColumn.type ||
+                newColumn.isArray !== oldColumn.isArray
Evidence
The cited change routes type/length/isArray modifications through a generic `ALTER COLUMN ...
TYPE ${createFullType(...)} block; however, for enum columns TableColumn.type` is the string
"enum"/"simple-enum", and both Cockroach and Postgres createFullType() build from that literal
value, yielding enum/simple-enum rather than the database enum type name. In contrast, the
drivers’ column-creation and addColumn() logic use buildEnumName(table, column) and create the
enum type via createEnumTypeSql(...), so the new ALTER path bypasses both the correct type name
generation and the enum-type creation that prevents missing-type errors.

src/driver/cockroachdb/CockroachQueryRunner.ts[1656-1677]
src/driver/cockroachdb/CockroachDriver.ts[920-949]
src/driver/cockroachdb/CockroachQueryRunner.ts[4485-4490]
src/driver/cockroachdb/CockroachQueryRunner.ts[1138-1162]
src/driver/postgres/PostgresQueryRunner.ts[1618-1639]
src/driver/postgres/PostgresDriver.ts[1336-1341]
src/driver/postgres/PostgresQueryRunner.ts[5164-5169]
src/driver/postgres/PostgresQueryRunner.ts[1067-1084]

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

## Issue description
`changeColumn()` in both CockroachQueryRunner and PostgresQueryRunner now builds `ALTER TABLE ... ALTER COLUMN ... TYPE ${this.driver.createFullType(...)}` for `type/length/isArray` changes, but for enum/simple-enum columns `createFullType()` yields the literal `enum`/`simple-enum` and does not ensure the underlying enum type exists. This generates invalid SQL and/or migrations that fail due to missing enum types, and can also break down migrations when `oldColumn` is enum/simple-enum.
## Issue Context
Enum columns are not supposed to use the literal `enum`/`simple-enum` in SQL; they must use `buildEnumName(table, column)` (and add `array` if needed). Additionally, enum types often need to be created before the column is altered/added (as done in `addColumn()` / column creation via `createEnumTypeSql(...)`), and any down migration should only drop the enum type if it was created by this migration.
## Fix Focus Areas
- src/driver/cockroachdb/CockroachQueryRunner.ts[1656-1677]
- src/driver/cockroachdb/CockroachQueryRunner.ts[1138-1162]
- src/driver/cockroachdb/CockroachQueryRunner.ts[4485-4490]
- src/driver/cockroachdb/CockroachDriver.ts[920-949]
- src/driver/postgres/PostgresQueryRunner.ts[1618-1639]
- src/driver/postgres/PostgresQueryRunner.ts[1067-1084]
- src/driver/postgres/PostgresQueryRunner.ts[5164-5169]
- src/driver/postgres/PostgresDriver.ts[1336-1341]

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



Remediation recommended

2. No functional test coverage 📘 Rule violation ☼ Reliability ⭐ New
Description
The PR changes core changeColumn SQL generation behavior for multiple drivers, but the PR diff
includes no additions/updates under test/functional to prevent regressions for issue #3357
scenarios. This risks reintroducing DROP+ADD behavior (and data loss) without a failing test.
Code

src/driver/postgres/PostgresQueryRunner.ts[R1628-1630]

+                newColumn.length !== oldColumn.length ||
+                newColumn.type !== oldColumn.type ||
+                newColumn.isArray !== oldColumn.isArray
Evidence
The checklist prefers functional tests for issue fixes. The diff modifies changeColumn logic to
treat length, type, and isArray changes as ALTER-able, but no test changes are present in this
PR diff to assert the generated SQL no longer uses drop/recreate for these cases.

Rule 3: Prefer functional tests over per-issue tests
src/driver/postgres/PostgresQueryRunner.ts[1625-1646]

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 fix is not covered by a functional test that asserts migration generation uses in-place `ALTER COLUMN` (and not `DROP COLUMN` + `ADD COLUMN`) for safe changes like length/type/isArray.

## Issue Context
Rule requires issue fixes to live in `test/functional` rather than relying on per-issue tests or manual verification.

## Fix Focus Areas
- test/functional/migrations/generate-command/command.test.ts[1-45]
- test/functional/migrations/generate-command/entity/post.entity.ts[1-24]

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


3. Collation may drop length ✓ Resolved 🐞 Bug ≡ Correctness
Description
In PostgresQueryRunner.changeColumn, collation changes are applied via `ALTER COLUMN ... TYPE
${newColumn.type} COLLATE ...`, which omits length/precision/scale. With this PR keeping length/type
changes on the ALTER-based path (instead of drop/add), a combined change (e.g., varchar length +
collation) can end up with the collation statement removing the explicit length constraint.
Code

src/driver/postgres/PostgresQueryRunner.ts[L1330-1332]

-            oldColumn.type !== newColumn.type ||
-            oldColumn.length !== newColumn.length ||
-            newColumn.isArray !== oldColumn.isArray ||
Evidence
The PR removes length/type/isArray from the early drop/recreate guard, making length changes stay in
the ALTER-based path. Later, the collation branch alters the type using only newColumn.type (not
createFullType()), while createFullType() is the method that includes (length) modifiers.

src/driver/postgres/PostgresQueryRunner.ts[1329-1334]
src/driver/postgres/PostgresQueryRunner.ts[2346-2367]
src/driver/postgres/PostgresDriver.ts[1336-1341]

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

## Issue description
When `newColumn.collation !== oldColumn.collation`, the code emits `ALTER COLUMN ... TYPE ${newColumn.type} COLLATE ...`, which does not include `length` (or other modifiers) even though `createFullType()` would. After this PR, length/type changes no longer force a drop/add, so this collation statement can run in the same migration and unintentionally widen the type (e.g. `character varying(51)` -> `character varying`).
### Issue Context
`createFullType()` is responsible for including `(length)` / `(precision,scale)` in Postgres. The collation update currently uses only `newColumn.type`.
### Fix Focus Areas
- src/driver/postgres/PostgresQueryRunner.ts[1330-1334]
- src/driver/postgres/PostgresQueryRunner.ts[2346-2367]
- src/driver/postgres/PostgresDriver.ts[1336-1341]
### What to change
- Update the collation-change SQL to preserve type modifiers by using `this.driver.createFullType(newColumn)` (and similarly `createFullType(oldColumn)` for the down query) instead of the bare `newColumn.type`.
- Ensure the resulting SQL remains valid for the subset of types that support collation (typically text types).

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


Grey Divider

  • Author self-review: I have reviewed the code review findings, and addressed the relevant ones.

To customize comments, go to the Qodo configuration screen, or learn more in the docs.

Previous review results

Review updated until commit 6ae69fb ⚖️ Balanced

Results up to commit ecf7d35


🐞 Bugs (2) 📘 Rule violations (0) 📎 Requirement gaps (0) 📜 Skill insights (0)

Context used

Action required
1. Cockroach enum ALTER invalid 🐞 Bug ≡ Correctness
Description
CockroachQueryRunner.changeColumn and PostgresQueryRunner.changeColumn can now generate `ALTER TABLE
... ALTER COLUMN ... TYPE enum / TYPE simple-enum` during transitions to/from enums because the
new ALTER path uses createFullType(), which returns the literal column.type. This bypasses the
enum-aware buildEnumName(...) and enum-type creation previously handled in the drop/add flow
(e.g., addColumn()), causing invalid SQL and/or missing enum-type failures (including in down
migrations when the old column is an enum).
Code

src/driver/cockroachdb/CockroachQueryRunner.ts[R1658-1661]

+                newColumn.scale !== oldColumn.scale ||
+                newColumn.length !== oldColumn.length ||
+                newColumn.type !== oldColumn.type ||
+                newColumn.isArray !== oldColumn.isArray
Evidence
The cited change routes type/length/isArray modifications through a generic `ALTER COLUMN ...
TYPE ${createFullType(...)} block; however, for enum columns TableColumn.type` is the string
"enum"/"simple-enum", and both Cockroach and Postgres createFullType() build from that literal
value, yielding enum/simple-enum rather than the database enum type name. In contrast, the
drivers’ column-creation and addColumn() logic use buildEnumName(table, column) and create the
enum type via createEnumTypeSql(...), so the new ALTER path bypasses both the correct type name
generation and the enum-type creation that prevents missing-type errors.

src/driver/cockroachdb/CockroachQueryRunner.ts[1656-1677]
src/driver/cockroachdb/CockroachDriver.ts[920-949]
src/driver/cockroachdb/CockroachQueryRunner.ts[4485-4490]
src/driver/cockroachdb/CockroachQueryRunner.ts[1138-1162]
src/driver/postgres/PostgresQueryRunner.ts[1618-1639]
src/driver/postgres/PostgresDriver.ts[1336-1341]
src/driver/postgres/PostgresQueryRunner.ts[5164-5169]
src/driver/postgres/PostgresQueryRunner.ts[1067-1084]

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

## Issue description
`changeColumn()` in both CockroachQueryRunner and PostgresQueryRunner now builds `ALTER TABLE ... ALTER COLUMN ... TYPE ${this.driver.createFullType(...)}` for `type/length/isArray` changes, but for enum/simple-enum columns `createFullType()` yields the literal `enum`/`simple-enum` and does not ensure the underlying enum type exists. This generates invalid SQL and/or migrations that fail due to missing enum types, and can also break down migrations when `oldColumn` is enum/simple-enum.

## Issue Context
Enum columns are not supposed to use the literal `enum`/`simple-enum` in SQL; they must use `buildEnumName(table, column)` (and add `array` if needed). Additionally, enum types often need to be created before the column is altered/added (as done in `addColumn()` / column creation via `createEnumTypeSql(...)`), and any down migration should only drop the enum type if it was created by this migration.

## Fix Focus Areas
- src/driver/cockroachdb/CockroachQueryRunner.ts[1656-1677]
- src/driver/cockroachdb/CockroachQueryRunner.ts[1138-1162]
- src/driver/cockroachdb/CockroachQueryRunner.ts[4485-4490]
- src/driver/cockroachdb/CockroachDriver.ts[920-949]
- src/driver/postgres/PostgresQueryRunner.ts[1618-1639]
- src/driver/postgres/PostgresQueryRunner.ts[1067-1084]
- src/driver/postgres/PostgresQueryRunner.ts[5164-5169]
- src/driver/postgres/PostgresDriver.ts[1336-1341]

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



Remediation recommended
2. Collation may drop length 🐞 Bug ≡ Correctness
Description
In PostgresQueryRunner.changeColumn, collation changes are applied via `ALTER COLUMN ... TYPE
${newColumn.type} COLLATE ...`, which omits length/precision/scale. With this PR keeping length/type
changes on the ALTER-based path (instead of drop/add), a combined change (e.g., varchar length +
collation) can end up with the collation statement removing the explicit length constraint.
Code

src/driver/postgres/PostgresQueryRunner.ts[L1330-1332]

-            oldColumn.type !== newColumn.type ||
-            oldColumn.length !== newColumn.length ||
-            newColumn.isArray !== oldColumn.isArray ||
Evidence
The PR removes length/type/isArray from the early drop/recreate guard, making length changes stay in
the ALTER-based path. Later, the collation branch alters the type using only newColumn.type (not
createFullType()), while createFullType() is the method that includes (length) modifiers.

src/driver/postgres/PostgresQueryRunner.ts[1329-1334]
src/driver/postgres/PostgresQueryRunner.ts[2346-2367]
src/driver/postgres/PostgresDriver.ts[1336-1341]

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

### Issue description
When `newColumn.collation !== oldColumn.collation`, the code emits `ALTER COLUMN ... TYPE ${newColumn.type} COLLATE ...`, which does not include `length` (or other modifiers) even though `createFullType()` would. After this PR, length/type changes no longer force a drop/add, so this collation statement can run in the same migration and unintentionally widen the type (e.g. `character varying(51)` -> `character varying`).

### Issue Context
`createFullType()` is responsible for including `(length)` / `(precision,scale)` in Postgres. The collation update currently uses only `newColumn.type`.

### Fix Focus Areas
- src/driver/postgres/PostgresQueryRunner.ts[1330-1334]
- src/driver/postgres/PostgresQueryRunner.ts[2346-2367]
- src/driver/postgres/PostgresDriver.ts[1336-1341]

### What to change
- Update the collation-change SQL to preserve type modifiers by using `this.driver.createFullType(newColumn)` (and similarly `createFullType(oldColumn)` for the down query) instead of the bare `newColumn.type`.
- Ensure the resulting SQL remains valid for the subset of types that support collation (typically text types).

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


Qodo Logo

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

Labels

Compliance violation linked-issue PR references an issue possible-duplicate PR may duplicate an existing open PR

Development

Successfully merging this pull request may close these issues.

Migration generation drops and creates columns instead of altering resulting in data loss

1 participant