Skip to content

Commit

Permalink
fix: alter relation loader to use transforms when present (#8691)
Browse files Browse the repository at this point in the history
Use column transforms when rendering queries during relation loading. Previously, transforms were ignored by the relation loader, causing unexpected values to be put into sql queries.

Closes: #8690
  • Loading branch information
blueskymonster committed Feb 23, 2022
1 parent 948d328 commit 2c2fb29
Show file tree
Hide file tree
Showing 3 changed files with 77 additions and 6 deletions.
12 changes: 6 additions & 6 deletions src/query-builder/RelationLoader.ts
Expand Up @@ -65,13 +65,13 @@ export class RelationLoader {

if (columns.length === 1) {
qb.where(`${joinAliasName}.${columns[0].propertyPath} IN (:...${joinAliasName + "_" + columns[0].propertyName})`);
qb.setParameter(joinAliasName + "_" + columns[0].propertyName, entities.map(entity => columns[0].getEntityValue(entity)));
qb.setParameter(joinAliasName + "_" + columns[0].propertyName, entities.map(entity => columns[0].getEntityValue(entity, true)));

} else {
const condition = entities.map((entity, entityIndex) => {
return columns.map((column, columnIndex) => {
const paramName = joinAliasName + "_entity_" + entityIndex + "_" + columnIndex;
qb.setParameter(paramName, column.getEntityValue(entity));
qb.setParameter(paramName, column.getEntityValue(entity, true));
return joinAliasName + "." + column.propertyPath + " = :" + paramName;
}).join(" AND ");
}).map(condition => "(" + condition + ")").join(" OR ");
Expand Down Expand Up @@ -102,13 +102,13 @@ export class RelationLoader {

if (columns.length === 1) {
qb.where(`${aliasName}.${columns[0].propertyPath} IN (:...${aliasName + "_" + columns[0].propertyName})`);
qb.setParameter(aliasName + "_" + columns[0].propertyName, entities.map(entity => columns[0].referencedColumn!.getEntityValue(entity)));
qb.setParameter(aliasName + "_" + columns[0].propertyName, entities.map(entity => columns[0].referencedColumn!.getEntityValue(entity, true)));

} else {
const condition = entities.map((entity, entityIndex) => {
return columns.map((column, columnIndex) => {
const paramName = aliasName + "_entity_" + entityIndex + "_" + columnIndex;
qb.setParameter(paramName, column.referencedColumn!.getEntityValue(entity));
qb.setParameter(paramName, column.referencedColumn!.getEntityValue(entity, true));
return aliasName + "." + column.propertyPath + " = :" + paramName;
}).join(" AND ");
}).map(condition => "(" + condition + ")").join(" OR ");
Expand Down Expand Up @@ -141,7 +141,7 @@ export class RelationLoader {
return `${joinAlias}.${inverseJoinColumn.propertyName}=${mainAlias}.${inverseJoinColumn.referencedColumn!.propertyName}`;
});
const parameters = relation.joinColumns.reduce((parameters, joinColumn) => {
parameters[joinColumn.propertyName] = entities.map(entity => joinColumn.referencedColumn!.getEntityValue(entity));
parameters[joinColumn.propertyName] = entities.map(entity => joinColumn.referencedColumn!.getEntityValue(entity, true));
return parameters;
}, {} as ObjectLiteral);

Expand Down Expand Up @@ -177,7 +177,7 @@ export class RelationLoader {
return `${joinAlias}.${inverseJoinColumn.propertyName} IN (:...${inverseJoinColumn.propertyName})`;
});
const parameters = relation.inverseRelation!.inverseJoinColumns.reduce((parameters, joinColumn) => {
parameters[joinColumn.propertyName] = entities.map(entity => joinColumn.referencedColumn!.getEntityValue(entity));
parameters[joinColumn.propertyName] = entities.map(entity => joinColumn.referencedColumn!.getEntityValue(entity, true));
return parameters;
}, {} as ObjectLiteral);

Expand Down
40 changes: 40 additions & 0 deletions test/github-issues/8690/entity/entities.ts
@@ -0,0 +1,40 @@
import {
Column,
Entity,
ManyToOne,
OneToMany,
JoinColumn,
PrimaryColumn,
} from "../../../../src";

// This is a contrived and silly example of a primary
// column transformer but it's enough to show the issue.
const WrappedIntTransformer = {
from: (value: number) => `"${value}"`,
to: (value: string | undefined | null) => value ? parseInt(value.slice(1, value.length - 1)) : null,
}

@Entity()
export class User {
@PrimaryColumn({ type: "int", transformer: WrappedIntTransformer, nullable: false })
id: string;

@OneToMany(() => Photo, (photo) => photo.user)
photos: Promise<Photo[]>;
}

@Entity()
export class Photo {
@PrimaryColumn({ type: "int", transformer: WrappedIntTransformer, nullable: false })
id: string;

@Column({ type: "text" })
url: string;

@Column({ type: "int", transformer: WrappedIntTransformer, nullable: false })
userId: string;

@ManyToOne(() => User, (user) => user.photos)
@JoinColumn({ name: "userId", referencedColumnName: "id" })
user: Promise<User>;
}
31 changes: 31 additions & 0 deletions test/github-issues/8690/issue-8690.ts
@@ -0,0 +1,31 @@
import "reflect-metadata";
import { createTestingConnections, closeTestingConnections, reloadTestingDatabases } from "../../utils/test-utils";
import { Connection } from "../../../src/connection/Connection";
import { expect } from "chai";
import { getRepository } from "../../../src";
import { User, Photo } from "./entity/entities";

describe("github issues > #8690 Relations do not render primary key column values correctly when transformers present", () => {

let connections: Connection[];
before(async () => connections = await createTestingConnections({
entities: [__dirname + "/entity/*{.js,.ts}"],
schemaCreate: true,
dropSchema: true,
}));
beforeEach(() => reloadTestingDatabases(connections));
after(() => closeTestingConnections(connections));

it("should load relations correctly when primary columns have transformers", () => Promise.all(connections.map(async connection => {
const userRepository = getRepository(User);
const photoRepository = getRepository(Photo);
const user = userRepository.create({id: `"1"`});
await userRepository.save(user);
const photo = photoRepository.create({id: `"42"`, url: "example.com/photo1", userId: user.id})
await photoRepository.save(photo);
const userPhotos = await user.photos;
expect(userPhotos.length === 1)
expect(userPhotos[0].id === photo.id)
expect(userPhotos[0].userId === user.id)
})));
});

0 comments on commit 2c2fb29

Please sign in to comment.