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

MikroORM should merge all changes of one record into one sql update statement #5510

Closed
5 tasks done
ssljivic opened this issue Apr 26, 2024 · 1 comment
Closed
5 tasks done

Comments

@ssljivic
Copy link

Describe the bug

I have an entity that has updatedAt column that is updated with the current date on each update of the entity.

When I make a change to the entity - in this case I have updated FK column/property - and flush the changes to the database, I get 2 UPDATE SQL queries for the same record in the DB. One that updates updated_at column and another that updated the FK column.

Those 2 UPDATEs should be merged into one.

Reproduction

import { Entity, OneToOne, PrimaryKey, Property } from '@mikro-orm/core'
import { MikroORM, PostgreSqlDriver } from '@mikro-orm/postgresql'

import { mockLogger } from '../helpers'

@Entity()
export class Other {
  @PrimaryKey()
  id!: number

  @Property()
  name!: string

  @Property({ length: 0, nullable: true, onUpdate: () => new Date() })
  updatedAt?: Date
}

@Entity()
export class Test {
  @PrimaryKey()
  id!: number

  @Property()
  name!: string

  @Property({ length: 0, nullable: true, onUpdate: () => new Date() })
  updatedAt?: Date

  @OneToOne(() => Other, { nullable: true, owner: true })
  other?: Other
}

describe('MikroORM', () => {
  let orm: MikroORM

  beforeAll(async () => {
    orm = await MikroORM.init({
      host: 'localhost',
      port: 5432,
      user: 'mikro-orm-test',
      password: 'mikro-orm-test',
      dbName: 'mikro-orm-test',

      driver: PostgreSqlDriver,

      allowGlobalContext: true,
      debug: true,
      entities: [Test],
    })
    await orm.schema.refreshDatabase({ wrap: true })
  })

  afterAll(async () => {
    await orm.close(true)
  })

  it('should merge all changes of one record into one sql update statement', async () => {
    const tid = await orm.em.insert(Test, { name: 'Foo' })
    await orm.em.flush()

    const test = await orm.em.findOne(Test, { id: tid })

    const other = new Other()
    other.name = 'Foo'
    orm.em.persist(other)
    test!.other = other

    const mock = mockLogger(orm)
    await orm.em.flush()

    expect(mock.mock.calls).toHaveLength(
      [['begin'], ['insert into other'], ['update test'], ['commit']].length,
    )
  })
})

The executed SQLs statements are:

begin;
insert into "other" ("name") values ('Foo') returning "id";
update "test" set "updated_at" = '2024-04-26T12:49:50.788Z' where "id" = 1;
update "test" set "other_id" = 1, "updated_at" = '2024-04-26T12:49:50.841Z' where "id" = 1;
commit;

but I would expect them to be:

begin;
insert into "other" ("name") values ('Foo') returning "id";
update "test" set "updated_at" = '2024-04-26T12:49:50.788Z', "other_id" = 1 where "id" = 1;
commit;

What driver are you using?

@mikro-orm/postgresql

MikroORM version

6.2.3

Node.js version

18.17.1

Operating system

MacOS 14.0

Validations

@rubiin
Copy link
Contributor

rubiin commented Apr 27, 2024

Never noticed this however it seems to be an issue .

@B4nan B4nan closed this as completed in 03934d0 May 1, 2024
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants