Skip to content
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

Typeorm Migrations ignore existing default value on column #7110

Closed
2 of 21 tasks
fabianskii opened this issue Nov 26, 2020 · 2 comments · Fixed by #7681
Closed
2 of 21 tasks

Typeorm Migrations ignore existing default value on column #7110

fabianskii opened this issue Nov 26, 2020 · 2 comments · Fixed by #7681

Comments

@fabianskii
Copy link

fabianskii commented Nov 26, 2020

Issue Description

In Postgres, it's possible to apply current_setting values as a column default value.

CREATE TABLE "coffee" ("id" int ,"tenant_id" text DEFAULT current_setting('coffee.current_tenant'::text));

  Column   |  Type   | Collation | Nullable |                    Default                     
-----------+---------+-----------+----------+------------------------------------------------
 id        | integer |           |          | 
 tenant_id | text    |           |          | current_setting('coffee.current_tenant'::text)

Thus, when executing 'SET valuename=value', this value is applied as a default for that column.

What happens actually?
Typeorm ignores such a present default value. From my investigation so far, I suspect that it is related to the function parameter and the quotes ('coffee.current_tenant'). Using a function without parameters (e.g hotfix()) works perfectly.

Here's an example entity:

import { Column, Entity, PrimaryGeneratedColumn } from "typeorm";

@Entity()
export class Coffee {
    @PrimaryGeneratedColumn()
    id: number;

    @Column()
    name: string;
    
    @Column({
        type: "text",
        nullable: false,
        default: () => "current_setting('coffee.current_tenant'::text)",
    })
    tenant_id: string;
}

When executing $ npm run start:dev the database is generated (synchronize: true) and contains the default setting as expected.

postgres=# \d coffee
                                         Table "public.coffee"
  Column   |       Type        | Collation | Nullable |                    Default                     
-----------+-------------------+-----------+----------+------------------------------------------------
 id        | integer           |           | not null | nextval('coffee_id_seq'::regclass)
 name      | character varying |           | not null | 
 tenant_id | text              |           | not null | current_setting('coffee.current_tenant'::text)
Indexes:
    "PK_4d27239ee0b99a491ad806aec46" PRIMARY KEY, btree (id)

However, it seems that Typeorm Migrations does not recognize this type of default value when generating or checking for migrations using either typeorm schema:log or typeorm migrations:generate -n row-level.

After generating an additional migration, that migration contains the suggested changes. After applying that new migration, Typeorm still adds the same line for further migrations.

Expected Behavior

$ npx typeorm schema:log
Your schema is up to date - there are no queries to be executed by schema synchronization.

Actual Behavior

$ npx typeorm schema:log
----------------------------------------------------------------
-- Schema syncronization will execute following sql queries (1):
----------------------------------------------------------------
ALTER TABLE "coffee" ALTER COLUMN "tenant_id" SET DEFAULT current_setting('coffee.current_tenant'::text);

Steps to Reproduce

I created a minimal example that shows the behaviour and a workaround. It's available here: https://github.com/fabianskii/typeorm-migration-ignores-default-bug

  1. $ git clone https://github.com/fabianskii/typeorm-migration-ignores-default-bug
  2. $ cd typeorm-migration-ignores-default-bug/ && npm install
  3. start provided postgres docker: $ docker-compose up -d
  4. $ npm run build (after each migration change)
  5. `$ typeorm migration:run
  6. $ typeorm schema:log
  7. `$ typeorm migrations:generate -n row-level
  8. $ npm run build
  9. $ typeorm schema:log
----------------------------------------------------------------
-- Schema syncronization will execute following sql queries (1):
----------------------------------------------------------------
ALTER TABLE "coffee" ALTER COLUMN "tenant_id" SET DEFAULT current_setting('coffee.current_tenant'::text);

My Environment

Dependency Version
Operating System popOS 20.10
Node.js version tried with: v10.19.0; 14.15.1; 15.3.0
Typescript version v4.1.2
TypeORM version v0.2.29

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?

  • Yes, I have the time, and I know how to start.
  • Yes, I have the time, but I don't know how to start. I would need guidance.
  • No, I don't have the time, although I believe I could do it if I had the time...
  • No, I don't have the time and I wouldn't even know how to start.
@kauz
Copy link
Contributor

kauz commented May 25, 2021

This is likely to be a posgtgres-specific issue. Explicit type conversions are stripped when loading schema from database, but in some cases this is done inaccurately, which causes this schema change to appear in all further generated migrations. In my case value
to_char(nextval('orders_display_id_seq'::regclass), 'FMU999'::text) was stripped to just to_char(nextval('orders_display_id_seq'.

With the next schema it causes this change to appear again and again in every migration, that I generate:

export class Order  {

    @PrimaryGeneratedColumn('uuid')
    id: string;

    @Column({
      nullable: false,
      type: 'varchar',
      default: () => "TO_CHAR(NEXTVAL('orders_display_id_seq'), 'FMU999')",
    })
    @Index({ unique: true })
    displayId: string;
}

@kauz
Copy link
Contributor

kauz commented May 25, 2021

I've submitted a PR to improve parsing default values of columns with Postgres driver: #7681

pleerock pushed a commit that referenced this issue Nov 4, 2021
* fix: defaults type cast filtering

This fixes column default value in cockroachdb continuously producing schema changes when there should be none

Refs: #7110

* fix: defaults type cast filtering

Remove debugging code

Refs: #7110
HeartPattern pushed a commit to HeartPattern/typeorm that referenced this issue Nov 29, 2021
* fix: defaults type cast filtering

This fixes column default value in cockroachdb continuously producing schema changes when there should be none

Refs: typeorm#7110

* fix: defaults type cast filtering

Remove debugging code

Refs: typeorm#7110
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

Successfully merging a pull request may close this issue.

2 participants