Skip to content

Commit

Permalink
fix(sql): respect timezone when mapping joined properties to Date
Browse files Browse the repository at this point in the history
Closes #5577
  • Loading branch information
B4nan committed May 20, 2024
1 parent ef5d14a commit 7f9bb0b
Show file tree
Hide file tree
Showing 2 changed files with 110 additions and 2 deletions.
12 changes: 10 additions & 2 deletions packages/knex/src/AbstractSqlDriver.ts
Original file line number Diff line number Diff line change
Expand Up @@ -363,6 +363,7 @@ export abstract class AbstractSqlDriver<Connection extends AbstractSqlConnection
const targetProps = ref
? meta2.getPrimaryProps()
: meta2.props.filter(prop => this.platform.shouldHaveColumn(prop, hint.children as any || []));
const tz = this.platform.getTimezone();

for (const prop of targetProps) {
if (prop.fieldNames.length > 1) { // composite keys
Expand All @@ -371,8 +372,15 @@ export abstract class AbstractSqlDriver<Connection extends AbstractSqlConnection
relationPojo[prop.name] = pk.every(val => val != null) ? pk as EntityValue<T> : null;
} else if (prop.runtimeType === 'Date') {
const alias = `${relationAlias}__${prop.fieldNames[0]}` as EntityKey<T>;
const type = typeof root![alias];
relationPojo[prop.name] = (['string', 'number'].includes(type) ? this.platform.parseDate(root![alias] as string) : root![alias]) as EntityValue<T>;
const value = root![alias] as unknown;

if (tz && tz !== 'local' && typeof value === 'string' && !value.includes('+') && !value.endsWith('Z')) {
relationPojo[prop.name] = this.platform.parseDate(value + tz) as EntityValue<T>;
} else if (['string', 'number'].includes(typeof value)) {
relationPojo[prop.name] = this.platform.parseDate(value as string) as EntityValue<T>;
} else {
relationPojo[prop.name] = value as EntityValue<T>;
}
} else {
const alias = `${relationAlias}__${prop.fieldNames[0]}` as EntityKey<T>;
relationPojo[prop.name] = root![alias];
Expand Down
100 changes: 100 additions & 0 deletions tests/issues/GH5577.test.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,100 @@
import {
Collection,
Entity,
ManyToOne,
MikroORM,
OneToMany,
PrimaryKey,
Property,
} from '@mikro-orm/mysql';

@Entity()
class Recipe {

@PrimaryKey()
id!: number;

@Property()
title: string;

@Property({ onCreate: () => new Date() })
createdAt!: Date;

@OneToMany(() => Ingredient, ingredient => ingredient.recipe)
ingredients = new Collection<Ingredient>(this);

constructor(title: string) {
this.title = title;
}

}

@Entity()
class Ingredient {

@PrimaryKey()
id!: number;

@Property()
name: string;

@Property()
quantity: number;

@Property({
onCreate: () => new Date(),
})
createdAt!: Date;

@ManyToOne(() => Recipe)
recipe!: Recipe;

constructor(name: string, quantity: number) {
this.name = name;
this.quantity = quantity;
}

}

let orm: MikroORM;

beforeAll(async () => {
orm = await MikroORM.init({
entities: [Recipe, Ingredient],
dbName: '5577',
port: 3308,
timezone: '+05:00',
});
await orm.schema.refreshDatabase();
});

afterAll(() => orm.close(true));

test('5577', async () => {
const r = new Recipe('My first recipe');
r.ingredients.add(new Ingredient('Flour', 500));
r.ingredients.add(new Ingredient('Sugar', 200));
r.ingredients.add(new Ingredient('Milk', 200));
orm.em.persist(r);
await orm.em.flush();

const recipe = await orm.em.fork().findOneOrFail(
Recipe,
{ title: 'My first recipe' },
{ populate: ['ingredients'] },
);

const withPopulate = recipe.ingredients
.getItems()
.find(x => x.name === 'Flour');

const ingredients = await orm.em.fork().find(
Ingredient,
{
recipe: { id: recipe.id },
},
);

const withoutPopulate = ingredients.find(x => x.name === 'Flour');
expect(withPopulate?.createdAt).toEqual(withoutPopulate?.createdAt);
});

0 comments on commit 7f9bb0b

Please sign in to comment.