Skip to content

Commit

Permalink
fix: handle overlapping property / database names in querybuilder (#7042
Browse files Browse the repository at this point in the history
)

we should always prioritize replacement of any property path first,
then property names, then database names, then relation values
whenever there's ambiguous values

fixes #7030
  • Loading branch information
imnotjames committed Nov 10, 2020
1 parent b35397e commit b518fa1
Show file tree
Hide file tree
Showing 3 changed files with 82 additions and 12 deletions.
37 changes: 25 additions & 12 deletions src/query-builder/QueryBuilder.ts
Original file line number Diff line number Diff line change
Expand Up @@ -587,24 +587,37 @@ export abstract class QueryBuilder<Entity> {

const replacements: { [key: string]: string } = {};

for (const column of alias.metadata.columns) {
if (!(column.propertyPath in replacements))
replacements[column.propertyPath] = column.databaseName;
if (!(column.propertyName in replacements))
replacements[column.propertyName] = column.databaseName;
if (!(column.databaseName in replacements))
replacements[column.databaseName] = column.databaseName;
// Insert & overwrite the replacements from least to most relevant in our replacements object.
// To do this we iterate and overwrite in the order of relevance.
// Least to Most Relevant:
// * Relation Property Path to first join column key
// * Relation Property Path + Column Path
// * Column Database Name
// * Column Propety Name
// * Column Property Path

for (const relation of alias.metadata.relations) {
if (relation.joinColumns.length > 0)
replacements[relation.propertyPath] = relation.joinColumns[0].databaseName;
}

for (const relation of alias.metadata.relations) {
for (const joinColumn of [...relation.joinColumns, ...relation.inverseJoinColumns]) {
const key = `${relation.propertyPath}.${joinColumn.referencedColumn!.propertyPath}`;
if (!(key in replacements))
replacements[key] = joinColumn.databaseName;
const propertyKey = `${relation.propertyPath}.${joinColumn.referencedColumn!.propertyPath}`;
replacements[propertyKey] = joinColumn.databaseName;
}
}

if (relation.joinColumns.length > 0 && !(relation.propertyPath in replacements))
replacements[relation.propertyPath] = relation.joinColumns[0].databaseName;
for (const column of alias.metadata.columns) {
replacements[column.databaseName] = column.databaseName;
}

for (const column of alias.metadata.columns) {
replacements[column.propertyName] = column.databaseName;
}

for (const column of alias.metadata.columns) {
replacements[column.propertyPath] = column.databaseName;
}

const replacementKeys = Object.keys(replacements);
Expand Down
20 changes: 20 additions & 0 deletions test/github-issues/7030/entity/Post.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
import { Column, Entity, PrimaryGeneratedColumn } from '../../../../src';


@Entity()
export class Post {

@PrimaryGeneratedColumn({
type: 'integer',
name: 'id',
})
oldId: number;

@Column({
nullable: false,
unique: true,
length: 38,
name: 'new_id',
})
id: string;
}
37 changes: 37 additions & 0 deletions test/github-issues/7030/issue-7030.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,37 @@
import { expect } from "chai";
import {Connection} from "../../../src/connection/Connection";
import {
createTestingConnections,
closeTestingConnections,
reloadTestingDatabases,
} from "../../utils/test-utils";
import {Post} from "./entity/Post";

describe("github issues > #7030", () => {
let connections: Connection[];

before(async () => connections = await createTestingConnections({
entities: [Post],
schemaCreate: true,
dropSchema: true,
enabledDrivers: ["postgres"]
}));

beforeEach(() => reloadTestingDatabases(connections));
after(() => closeTestingConnections(connections));

it("should insert and fetch from the expected column", () => Promise.all(connections.map(async connection => {
const id = '123e4567-e89b-12d3-a456-426614174000'

const post = new Post();
post.id = id;

let postRepository = connection.getRepository(Post);

await postRepository.save(post);

const actualPost = await postRepository.findOneOrFail({ id });

expect(actualPost!.id).to.be.equal(id);
})));
});

0 comments on commit b518fa1

Please sign in to comment.