Skip to content

composite keys with custom type PK that uses object value #910

@B4nan

Description

@B4nan

Describe the bug
When one of the PKs uses a custom type that has a runtime object value, it failed to extract this PK in update queries

To Reproduce

export class Sku {

  private constructor(private readonly value: string) {}

  static create(value: string): Sku {
    return new Sku(value);
  }

  toString(): string {
    return this.value;
  }

}

export class SkuType extends Type<Sku, string> {

  convertToDatabaseValue(value: Sku | string, platform: Platform, fromQuery?: boolean): string {
    return value.toString();
  }

  convertToJSValue(value: Sku | string, platform: Platform): Sku {
    if (value instanceof Sku) {
      return value;
    }

    return Sku.create(value);
  }

}

@Entity()
export class Cart {

  @PrimaryKey()
  public readonly id: string;

  @OneToMany({ entity: 'CartItem', mappedBy: 'cart', cascade: [Cascade.MERGE, Cascade.PERSIST] })
  public readonly items = new Collection<CartItem>(this);

  constructor(id: string, items: CartItem[]) {
    this.id = id;
    this.items.add(...items);
  }

  addItem(item: CartItem): void {
    this.items.add(item);
  }

  removeItem(item: CartItem): void {
    this.items.remove(item);
  }

}

@Entity()
export class CartItem {

  @ManyToOne({ primary: true, entity: 'Cart' })
  public readonly cart!: Cart;

  @PrimaryKey({ type: SkuType })
  public readonly sku: Sku;

  [PrimaryKeyType]: [string, string];

  @Property()
  public quantity: number;

  constructor(sku: Sku, quantity: number) {
    this.sku = sku;
    this.quantity = quantity;
  }

  updateQuantity(quantity: number) {
    this.quantity = quantity;
  }

}

const orm = await MikroORM.init({
  entities: [Cart, CartItem],
  type: 'sqlite',
  dbName: ':memory:',
});
await orm.getSchemaGenerator().createSchema();

const id = '123';
const item1 = new CartItem(Sku.create('sku1'), 10);
const item2 = new CartItem(Sku.create('sku2'), 10);
const cart = new Cart(id, [item1, item2]);
await orm.em.persistAndFlush(cart);

const item3 = new CartItem(Sku.create('sku3'), 100);
await orm.em.flush();

item2.updateQuantity(33);
await orm.em.flush();  // bad update query issued

Versions

Dependency Version
node 14
typescript 4
mikro-orm 4.0.7
your-driver all

Metadata

Metadata

Assignees

Labels

bugSomething isn't working

Type

No type

Projects

No projects

Milestone

No milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions