-
-
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
Postgres array column dropped and re-added during synchronization when no change is made. #6990
Postgres array column dropped and re-added during synchronization when no change is made. #6990
Comments
Any luck fixing this? I have the same behaviour. My project is pretty simple in terms of database and I don't want to complicate it with migrations, as synchronise did a good job until now. @Entity()
export default class ModelAccount implements WithId {
@Column("char",{
array: true,
length: 2,
name: "banned_countries",
default: ()=>"array[]::char(2)[]",
})
bannedCountries: string[];
} Every time I run it with synchronize : true the logs show:
|
@alexandrucancescu - I haven't had much time to dig into this. I looked at it a little bit, and I believe the problem is occurring in PostGresQueryRunner.loadTables: // check only columns that have length property
if (this.driver.withLengthColumnTypes.indexOf(tableColumn.type as ColumnType) !== -1 && dbColumn["character_maximum_length"]) {
const length = dbColumn["character_maximum_length"].toString();
tableColumn.length = !this.isDefaultColumnLength(table, tableColumn, length) ? length : "";
} The loadTables method relies on the value returned by Postgres for character_maximum_length in the information_schema.columns view, but that value is null for array types. So, I think the answer is probably to check if the column is an array, and if so, get the length from somewhere else. It looks like the length can be obtained from the pg_attribute systems catalog in the atttypmod column. (Thanks to this Stackoverflow answer.) But I don't know if that's the best way to do it. |
It also occurs to me to wonder why that column is null for arrays. I tested the last three major postgres versions and got the same result. |
Nice find. As a workaround, I changed my Regarding what you found, maybe typeorm doesn't consider a fixed size char array as a column with length as it only analyses the final column type (array), and not the subtype of the array (char(2)). Just a guess. Thanks for investing your time into this! |
I've also replicated this issue and I wonder if it's related to #2712? |
Due to typeorm/typeorm#6990, in synchronize mode arrays are dropped and recreated. We work around this by using the json data type
@kevinlul - I don't think it's related to the issue you mention, that is a Mysql issue and this looks to be specific to Postgres and how Typeorm gets information on array columns. I looked at your workaround, and that is worth mentioning, if someone runs into this: Use json instead. You could also just turn of synchronization, which is only really useful for dev, or setup a migration or other method to reimport your test data on startup. |
Hi Ed, I'm not sure what you mean. I am using Postgres and since we are in the early stages, I had synchronization enabled for rapid development. I was using Postgres arrays as they seemed to be the natural match for storing an array after all but I discovered the same pattern as you did with the array columns being dropped and recreated at startup. I found this issue after investigating and simply implemented Alexandru's workaround with the json column type and we haven't had problems with that yet. |
I just meant I don't think it's related to the MySQL issue you linked, as it seems to be a product of how Typeorm queries Postgres and how Postgres reports array columns. I started work on a pull request for this issue. I'm not sure if my fix is the best way, but maybe I can get some feedback on it. I don't see how it would break anything else, so at worst it is simply not very elegant. Once it's ready to go I'll link it here. |
Use pg_catalog.pg_attribute to get length of data type for array columns when loading tables in PostgresQueryRunner. Previously, it relied on information_schema.tables, which doesn't provide this for array columns. Closes: typeorm#6990
Use pg_catalog.pg_attribute table to get length of data type for array columns when loading tables in PostgresQueryRunner. Previously, it relied on solely on information_schema.tables, which doesn't provide this for array columns. Closes: typeorm#6990
Use pg_catalog.pg_attribute table to get length of data type for array columns when loading tables in PostgresQueryRunner. Previously, it relied on solely on character_maximum_length in information_schema.columns, which is null for array columns. Closes: typeorm#6990
Use pg_catalog.pg_attribute table to get length of data type for array columns when loading tables in PostgresQueryRunner. Previously, it relied solely on character_maximum_length in information_schema.columns, which is null for array columns. Closes: typeorm#6990
…columns unnecessarily change loadTables in PostgresQueryRunner to use pg_catalog to find length attribute of array columns Closes: typeorm#6990
Change loadTables in PostgresQueryRunner to use pg_catalog to find length attribute of array columns. Previously, it relied on information_schema.columns character_maximum_length, which is null for array columns. This caused synchronize to always drop and recreate array columns. Closes: typeorm#6990
Change loadTables in PostgresQueryRunner to use pg_catalog to find length attribute of array columns. Previously, it relied on information_schema.columns character_maximum_length, which is null for array columns. This caused synchronize to always drop and recreate array columns. Closes: #6990
Issue Description
When using Postgres, if a length is specified for an array of type varchar and synchronization is enabled, Typeorm will drop and re-add the column on startup even if there are no schema changes.
If the length property is removed, the behavior will stop occurring.
Expected Behavior
When there are no changes to the column, Typeorm should recognize the current database schema matches the column configuration, and not drop and re-add the column during synchronization.
Actual Behavior
When synchronizing on startup, Typeorm issues SQL queries to drop and re-add the column, even though nothing has changed.
From the console output at startup:
Steps to Reproduce
For a small example, see: https://github.com/edcolvin/array-sync-issue
My Environment
Additional Context
Tested using Postgres:11 Docker image
PostgreSQL 11.9 (Debian 11.9-1.pgdg90+1) on x86_64-pc-linux-gnu, compiled by gcc (Debian 6.3.0-18+deb9u1) 6.3.0 20170516, 64-bit
Relevant Database Driver(s)
aurora-data-api
aurora-data-api-pg
better-sqlite3
cockroachdb
cordova
expo
mongodb
mysql
nativescript
oracle
postgres
react-native
sap
sqlite
sqlite-abstract
sqljs
sqlserver
Are you willing to resolve this issue by submitting a Pull Request?
The text was updated successfully, but these errors were encountered: