-
-
Notifications
You must be signed in to change notification settings - Fork 6.2k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Migration generation drops and creates columns instead of altering resulting in data loss #3357
Comments
no, its not related to #3352. We already had this question before, I'll provide answer once again. Its by design. Let's say you have length equal to |
Thanks for getting back to me! It makes sense that data truncation would result in some data loss; but not the entire column. However, something like increasing the size of a column would surely not result in data loss? I think this is worth pursuing. Understandably something like SQLite which does not support I think migration generation is a killer feature of many ORMs and TypeORM should not be left out. We personally chose TypeORM for our production app based on the fact that it at has migration generation where something like Sequelize has very limited support. |
I'll left it open, maybe some day we'll find time to improve this already quite complex part. Everything comes down into resources. You probably have seen - we have a separate topic for that (#3267). |
Thank you! I understand completely. |
We are having exactly the same issue, where we had set a PK of a table to a length, and now after increasing it to a larger one, we got this column deleted and recreated across all the rest of tables (this column is a relation used in many other tables). Luckily I saw it in the migration before applying it, though, not sure if anyone does pre checks of autogenerated code! I also see the logic (just a proposal at the moment) that:
I'd be willing to find some time in a couple of weeks to try to discuss/implement this feature as I see it could be beneficial to TypeORM :) I cannot give time just right now, but by mid February I should have some free time to do so, if its okay for you :) |
I think that ALTER COLUMN (or equivalent) should always be used when available- even if the column is being truncated. If it is being truncated, then that's on purpose. A warning when a column is being dropped would be nice though! |
Current behavior leads to MySQL error when trying to alter primary key column referenced by one or more foreign keys in other tables. |
@pleerock Do you have any documentation on what cases will result in drop column? Does renameColumn method have possibility to drop column? Thanks. |
To make matters worse, even Please take throw hard errors/exceptions instead of silently deleting data. |
Edit: This implementation is unique per driver! The tedious part is that each driver needs to have its implementation re-worked!
|
We have same problem. Sorry guys, I love your work, but migrations really suck for now. 👎 |
I confirm, migration generator is broken. I wanted to remove only import {MigrationInterface, QueryRunner} from "typeorm";
export class RemoveStartDateSubscription1564382101607 implements MigrationInterface {
public async up(queryRunner: QueryRunner): Promise<any> {
await queryRunner.query(`ALTER TABLE "subscription" DROP COLUMN "startDate"`);
await queryRunner.query(`ALTER TABLE "user" DROP COLUMN "name"`);
await queryRunner.query(`ALTER TABLE "project" DROP COLUMN "description"`);
await queryRunner.query(`ALTER TABLE "team" DROP COLUMN "description"`);
await queryRunner.query(`ALTER TABLE "user" DROP COLUMN "username"`);
await queryRunner.query(`ALTER TABLE "user" DROP COLUMN "displayName"`);
await queryRunner.query(`ALTER TABLE "project" ADD "description" character varying`);
await queryRunner.query(`ALTER TABLE "team" ADD "description" character varying`);
await queryRunner.query(`ALTER TABLE "user" ADD "username" character varying`);
await queryRunner.query(`ALTER TABLE "user" ADD "displayName" character varying`);
await queryRunner.query(`ALTER TABLE "subscription" ADD "startDate" date NOT NULL DEFAULT now()`);
await queryRunner.query(`ALTER TABLE "user" ADD "name" character varying`);
await queryRunner.query(`ALTER TABLE "subscription" ALTER COLUMN "usersCapacity" DROP DEFAULT`);
await queryRunner.query(`ALTER TABLE "subscription" ALTER COLUMN "endDate" SET NOT NULL`);
}
public async down(queryRunner: QueryRunner): Promise<any> {
await queryRunner.query(`ALTER TABLE "subscription" ALTER COLUMN "endDate" DROP NOT NULL`);
await queryRunner.query(`ALTER TABLE "subscription" ALTER COLUMN "usersCapacity" SET DEFAULT 1`);
await queryRunner.query(`ALTER TABLE "user" DROP COLUMN "name"`);
await queryRunner.query(`ALTER TABLE "subscription" DROP COLUMN "startDate"`);
await queryRunner.query(`ALTER TABLE "user" DROP COLUMN "displayName"`);
await queryRunner.query(`ALTER TABLE "user" DROP COLUMN "username"`);
await queryRunner.query(`ALTER TABLE "team" DROP COLUMN "description"`);
await queryRunner.query(`ALTER TABLE "project" DROP COLUMN "description"`);
await queryRunner.query(`ALTER TABLE "user" ADD "displayName" character varying`);
await queryRunner.query(`ALTER TABLE "user" ADD "username" character varying`);
await queryRunner.query(`ALTER TABLE "team" ADD "description" character varying`);
await queryRunner.query(`ALTER TABLE "project" ADD "description" character varying`);
await queryRunner.query(`ALTER TABLE "user" ADD "name" character varying`);
await queryRunner.query(`ALTER TABLE "subscription" ADD "startDate" date NOT NULL DEFAULT now()`);
}
} As you can see, the generator is changed ALL of the entity columns (drop and add them again). typeorm: 0.2.18 |
I'm seeing something similar in #4577. Can someone confirm if this is the same bug? |
I'm seeing something similar when trying to run However, after that the migration seems to get confused and proceeds to DROP all the columns one by one for the lease table. And then re-adding them back again. This does not seem to happen for the user table. Finally the down migration also seems weird. It's also dropping all columns of lease first one by one, then re-adding them one by one, and then finally simply dropping the tables. I tried removing most of the attributes from my lease entity to see if there was some feature I'm using that seems to throw off typeorm. I found it was quite easy to confuse the migration generator and make it add seemingly useless statements. |
This is a pretty bad wrinkle in an otherwise nice migration system. Would seem that running the alter column is a pretty reasonable solution for databases that support this (of which many do). It's would be a good idea to take the path of least data loss for any operation, so naively drop + add'ng would seem to be the worst choice when alter column is available. Using the alter is the equivalent of what a user would expect when hand-writing an SQL query to change the size of a column. Btw, there's also the situation where the user increases the size of the column (which is vastly more common and which should result in NO data loss). Naively dropping and adding is simple, but has pretty huge ramifications for anyone looking to generate migration files that are useful (without modification) in a non-dev environment. Here's what a migration looked like after simply setting a property to have a length of 129 (from 128). Interestingly, it also saw fit to add in a no-op alter for the 'sub_type' property, which had no actual changes at all.
Understandably, resources may not be able to tackle this improvement right now. |
When I change anything and generate migrations it always drop the datas in the many to many tables related to that model, even if what I changed has nothing to do with it. Is this related to this issue or is there a fix for this |
I'm also experiencing this issue, do we know if there's a temporary workaround for this issue? |
I'm also experiencing this on MySQL which is making |
I've run into this as well, on 0.2.24. I probably would need to edit the migration file and hand craft it. Is that how you guys above dealt with it? edit:
|
I am also experiencing this issue on MySQL. Can't use migrations this way. This is a pretty old issue. Is there any information on if this will be fixed in the near future? |
I've had to drop back to writing the migrations by hand. The migration generator drops and adds columns and constraints willy nilly. It's a nice idea but I suspect the complexities make it difficult to maintain. |
I'm just starting to learn Typeorm in relation to NestJS. Took me a while to find this issue, and I agree. It seems odd that the default behavior of a migration is dataloss. Even when renaming a column, the generator does a DROP/ADD. |
Using postgres as well, I have noticed that on a new database I run |
I noticed this behavior when trying to change a |
I've experienced this issue with MariaDB. I realize it's impossible to cover all specific cases, but lengthening a varchar column seems to me a common enough and uncontroversially data-preserving change to warrant special handling in the migration generator. Would it be possible to add? |
Has this still not been fixed since 2019? We're having the same issues on better-sqlite3 (which supports altering tables) and it's causing some nasty |
I understand it's hard to cover all situation.But at least, a common and simple length-changing shouldn't always just drop columns. |
It's a shame this hasn't been resolved yet . I faced this issue today and the way of this is treated in the core is so bad. I hope team is thinking a workaround for the problem. |
So the best choice for now would be |
I'm facing same issue. Now I have to manually check for any migration which I generate to make sure that in the case it has DROP command, I'll have no data lost. Funny :) |
Same bug using |
Same issue on |
Data loss is the worst solution .. renders migrations as worthless |
I think may be a good solution would be get an option to set if we want or not DROP when create a migration, any ways, thanks for this. |
I'm also facing the same issue. I'm glad i discovered this in the development phase. |
I had the same problem - changing column length from 2000 -> 20000 So, I used this SQL method - and it worked for me. The length was changed - no error was shown during the migration
|
Can we have an option having rename the column to |
Changing a column type from |
It's 2024, let's wait another four years :( |
it must be fixed. it is big big big problem. |
+1 it's a problem for next migration and a terrible tripwire |
It's been 5 years. I guess yuuji3 has switched to Prisma by now. Nest.js should really consider acquiring TypeORM to clean this mess. |
A dangerous problem that almost got into production !!!!! |
@RubenRuCh created a $1,000.00 reward using Opire How to earn this reward?Since this project does not have Opire bot installed yet 😞 you need to go to Opire and claim the rewards through your programmer's dashboard once you have your PR ready 💪 |
This issue has been affecting me for several years. Had to write custom migrations to avoid losing data. And a few times I forgot about this and almost screw production. Seeing that the issue has been open for several years and the maintainers have been clear about lack of resources, I think it's time for me to stop complaining about the problem and try to actually collaborate to see it solved. I created a $1000 reward for the developer (either a TypeORM maintainer or an external dev) that manage to solve this. I'm aware it's a complex issue and that it will probably take more effort than $1k worth's. But it's all I can afford at the moment. Bear in mind that if this get fixed, we all will benefit from it. So if every one of us who has asked for this issue to be solved put a small amount ($50, $100...) it can actually sum to be a great reward that could help to incentive having this issue solved. |
This is how I solved this. https://github.com/Rafael-rgsousa/typeorm-safer-migrations I've created a code to allow me to backup the columns' data into a temporary table and restore it after the migration is completed. The "start" command starts the backup process Example: import { MigrationInterface, QueryRunner } from 'typeorm';
import { SaferMigrations, TableBackupConfig } from './path-to/safer-migration';
export class ExampleMigration implements MigrationInterface {
tableConfigs: TableBackupConfig[] = [
{ tableName: 'products', primaryKeyColumns: ['id'], backupColumns: ['description'] },
{ tableName: 'orders', primaryKeyColumns: ['order_id', 'product_id'], backupColumns: ['quantity'] }
];
public async up(queryRunner: QueryRunner): Promise<void> {
await SaferMigrations.start(queryRunner, this.tableConfigs);
// Your migration code...
await SaferMigrations.done(queryRunner, this.tableConfigs);
}
public async down(queryRunner: QueryRunner): Promise<void> {
await SaferMigrations.start(queryRunner, this.tableConfigs);
// Your migration code...
await SaferMigrations.done(queryRunner, this.tableConfigs);
}
} |
🔥 The user @Rafael-rgsousa has claimed all rewards for this issue using Opire. |
Thanks @Rafael-rgsousa! Let's see if someone with permissions to merge can take a look at your PR |
Issue type:
[ ] question
[x] bug report
[ ] feature request
[ ] documentation issue
Database system/driver:
[ ]
cordova
[ ]
mongodb
[ ]
mssql
[ ]
mysql
/mariadb
[ ]
oracle
[x ]
postgres
[ ]
sqlite
[ ]
sqljs
[ ]
react-native
[ ]
expo
TypeORM version:
[ ]
latest
[ ]
@next
[x]
0.2.11
(or put your version here)Steps to reproduce or a small repository showing the problem:
I apologize- I can't help but think I've seen a similar issue but I couldn't find it in opened or closed issues.
Let's say I have a varchar column with length of 50;
Which results in this migration:
And then I go ahead and change the length to 51;
The resulting generated migration code is:
Which obviously would result in data loss.
I would have expected;
I did see something in #3352 which I think could be related? Although its for schema sync.
The text was updated successfully, but these errors were encountered: