-
-
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:generate continuously updates default values #3076
Comments
I have a similar issue where with a migration I've set the default for an integer to 0, yet at each migration the following line is added: EDIT: I've just noticed that both the up and down migration contain the same query:
|
👍 |
Same here |
1 similar comment
Same here |
Is there any update on this? My migration looks like this: import { MigrationInterface, QueryRunner } from 'typeorm';
export class ViewTable1562766869548 implements MigrationInterface {
public async up(queryRunner: QueryRunner): Promise<void> {
await queryRunner.query('CREATE TABLE "view" ("id" uuid NOT NULL DEFAULT uuid_generate_v4(), "createdAt" TIMESTAMP NOT NULL DEFAULT now(), "updatedAt" TIMESTAMP NOT NULL DEFAULT now(), "eppn" character varying NOT NULL, "columns" character varying array NOT NULL DEFAULT \'{}\'::varchar[], CONSTRAINT "PK_86cfb9e426c77d60b900fe2b543" PRIMARY KEY ("id"))');
}
public async down(queryRunner: QueryRunner): Promise<void> {
await queryRunner.query('DROP TABLE "view"');
}
} and every subsequent migration contains this: import { MigrationInterface, QueryRunner } from 'typeorm';
export class Foo1565623082602 implements MigrationInterface {
public async up(queryRunner: QueryRunner): Promise<any> {
await queryRunner.query('ALTER TABLE "view" ALTER COLUMN "columns" SET DEFAULT \'{}\'::varchar[]');
}
public async down(queryRunner: QueryRunner): Promise<any> {
await queryRunner.query('ALTER TABLE "view" ALTER COLUMN "columns" SET DEFAULT \'{}\'');
}
} |
I've done some digging. I can't find an elegant solution, so I'm giving up and leaving my findings here. There are two compounding issues:
The avenues I see for moving forward, in order from most to least likely to succeed:
|
This has been very problematic for me as well. Any update? |
Having the same problem on MySQL; |
Same issue here using MySQL. No information yet? |
The same problem, I want to set default value -1 in postgres. I tried(each example run generate twice):
It will generate So I changed the default schema value like that:
It will still generate repeatedly.
Obviously, typeorm generator checked and generated wrong file for default value -1. |
Having the same issue; TypeORM is regenerating the same migration because, in certain cases, despite determining the correct value when outputting the migration, it uses an invalid value when comparing the Seems like this has gone unaddressed for a while. Any solution besides forking and modifying the default-value comparison code? |
Are there any versions for which this problem is not occurring? |
I have the same case with Postgres. Tried to find out why it is happening and found that the problem is in this file:
left part of the condition in my case, the column has the following config:
and
|
When I use a function, for default values, it dosen't update values, after the first migration. I return all values as string, too. @column('int', { default: () => '0' }) For Typescript enum types, I don't use function: @column('enum', { enum: TypeEnum, default: TypeEnum.Type1 }) |
A hack is to set the default value as value generated by typeorm So:
- @Column({ type: 'jsonb', default: () => "'{}'::jsonb" })
+ @Column({ type: 'jsonb', default: () => "'{}'" })
settings: any;
|
@mastilver @csvwolf you can use this dirty hack as a reference until typeorm collaborators decide to do something with this stupid defaults normalization. 🤦🏿♂️
|
And similarly, for array columns set it to |
Just simple overview. I think we should consider I have such case: typeorm/src/driver/postgres/PostgresQueryRunner.ts Lines 1645 to 1646 in d27dd2a
(now() + ((60 || ' minutes' .
So I consider this as a bug, which could be resolved by keeping retrieved default values from DB untouched before matching. Or maybe adding a new flag to meta, like "raw: true", which will prevent from "normalization" in QueryRunner. Also, regenerated migration contains invalid query inside |
This comment has been minimized.
This comment has been minimized.
This is not a simple issue to correct. There are a 1200 other open issues. You're welcome to investigate, design a workaround, implement it, handle regressions, and help us with releasing it. Instead you found that a better use of your time is to choose to insult folks that are giving you their time. |
for enum types within a schema the comparison issue still exists with postgres and typeorm @ 0.2.38
with adding "." like tableColumn.default = dbColumn["column_default"].replace(/::[\w\s\.\[\]\"]+/g, "");
|
Experienced a similar issue with
An alternative syntax exists in this case where the problem is not present:
|
Doing a plus one. Keeps us giving the following migration after manually changing the first migration: import { MigrationInterface, QueryRunner } from "typeorm";
export class automatic1666120427520 implements MigrationInterface {
name = 'automatic1666120427520'
public async up(queryRunner: QueryRunner): Promise<void> {
await queryRunner.query(`ALTER TABLE "notification" ALTER COLUMN "time_sent" SET DEFAULT 'now()'`);
}
public async down(queryRunner: QueryRunner): Promise<void> {
await queryRunner.query(`ALTER TABLE "notification" ALTER COLUMN "time_sent" SET DEFAULT now()`);
}
} Could an option to be given that input in the |
@helmsonsen this seems to be the issue with not only enums but also column defaults that have cast calls with :: ... this is an issue for postgres since even if you try to use cast(generate_id() as text), in "information_schema"."columns"."default" postgres stores it as: (generate_id())::text ... A workaround I'm thinking is to wrap the function into one that casts it. I observed I have this issue with my id default columns, trial period end and secret generator default columns:
Here's an example, dropped the default for trial_period_ends_at which was using :: cast to interval, and tried to use the interval function notation. Postgres stores it with a :: cast anyways ... : So what I ended up doing, is I just wrapped my functions into functions that return exactly what I need:
My defaults now look like this, and the problem is gone: Tried to generate a migration after migrating everything and saw what I needed:
I hope this helps someone else, since I spent a few hours scratching my head over this. I have not dug into typeorm internals so I'm not sure why that line in the migration generator ( |
I believe solution №1 is the most suitable. It allows users to deal with complex defaults while keep the interface as is. |
This is a bug in typeorm, see: typeorm/typeorm#3076 (comment)
This is a bug in typeorm, see: typeorm/typeorm#3076 (comment)
This is a bug in typeorm, see: typeorm/typeorm#3076 (comment)
Encountered this bug with
which I narrowed down to an issue in typeorm/src/driver/postgres/PostgresDriver.ts Line 1055 in 83567f5
default values and generated values are different concepts (ColumnMetadata has separate fields for generationStrategy /isGenerated and default ). So this column has generationStrategy /isGenerated set but default is undefined.
This does not match the implementation of
So we end up comparing:
with
so obviously the migration generator thinks that the column has changed. We should either merge |
The workaround that I found worked was:
to
|
Same here. @Column({ type: "text", default: () => "0" })
status: TemplateDraftStatus;
public async up(queryRunner: QueryRunner): Promise<void> {
await queryRunner.query(
`ALTER TABLE "template-drafts" ALTER COLUMN "status" SET DEFAULT 0`,
);
}
public async down(queryRunner: QueryRunner): Promise<void> {
await queryRunner.query(
`ALTER TABLE "template-drafts" ALTER COLUMN "status" SET DEFAULT '0'`,
);
} |
What happens if you try setting default to "'0'"? |
Nice! Thanks! I didn't consider that. It works. |
Issue type:
[x?] 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:
[x]
latest
0.2.8[ ]
@next
[ ]
0.x.x
(or put your version here)Steps to reproduce or a small repository showing the problem:
Somewhat relevant other issue #2943 (?)
Maybe this is just me misunderstanding how postgresql works, but since (seen in the screenshots below) the default values are correctly set. If the default values are really just supposed to be
'{}'
andARRAY[]
please feel free to close this issue 🙇Playlists.ts
Settings.js
1541719937415-Init.ts
Every subsequent migration file:
Edit:
I actually just tried it out, changing the array to just
ARRAY[]
will produce:QueryFailedError: cannot determine type of empty array
with a hint to:
'Explicitly cast to the desired type, for example ARRAY[]::integer[].'
Changing
'{}'::jsonb
to'{}'
produces the same result as having'{}'::jsonb
(so that's good)and it also does not show up in the migration file anymore (like above)
The array however still does since that one cannot be simply
ARRAY[]
as mentioned above.Edit2:
Went ahead and tried the other notation for postgres to initialize an empty array
'{}'
(funnily enough)@Column({ type: 'text', array: true, default: '{}' })
Which produces this query in the initial migration:
"songs" text array NOT NULL DEFAULT '{}'::text[]
(looks correct so far)But in every subsequent migration it will again try to change it:
Which means I am pretty much out of ideas at this point for defaulting to empty arrays.
The text was updated successfully, but these errors were encountered: