Skip to content

Commit

Permalink
fix: allow for complex jsonb primary key columns (typeorm#6834)
Browse files Browse the repository at this point in the history
* fix: allow for complex jsonb primary key columns

When using PrimaryColumn with a 'jsonb' type column
( on a postgres database ) the RawSqlResultsToEntityTransformer
would simply convert the key to '[object Object]' instead of a
unique value based on the key value. It would then wrongly consider each
entity as having the same key.

To allow for complex keys the transformer now uses JSON.stringify()
to convert the keys value if they are of type obejct to a unique
string that can be compared
to other entities.

fixes typeorm#6833

* test: add tests for jsonb primarykey columns

These tests verify that Entities with jsonb primary columns are correctly
converted to Entites
  • Loading branch information
maddimax authored and Svetlozar committed Jan 12, 2021
1 parent 0bd6ca4 commit c886cc4
Show file tree
Hide file tree
Showing 3 changed files with 97 additions and 0 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -70,6 +70,10 @@ export class RawSqlResultsToEntityTransformer {
return keyValue.toString("hex");
}

if (typeof keyValue === "object") {
return JSON.stringify(keyValue);
}

return keyValue;
}).join("_"); // todo: check partial

Expand Down
12 changes: 12 additions & 0 deletions test/github-issues/6833/entity/test.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
import { Entity, PrimaryColumn } from "../../../../src";

export class MyId {
first: number;
second: number;
}

@Entity({ name: "jsonb_key_tests" })
export class JSONBKeyTest {
@PrimaryColumn("jsonb")
id: MyId;
}
81 changes: 81 additions & 0 deletions test/github-issues/6833/issue-6833.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,81 @@
import "reflect-metadata";
import {
createTestingConnections,
closeTestingConnections,
reloadTestingDatabases,
} from "../../utils/test-utils";
import { Connection } from "../../../src/connection/Connection";
import { expect } from "chai";
import { JSONBKeyTest } from "./entity/test";

describe("github issues > #6833 Entities with JSON key columns are incorrectly grouped", () => {
let connections: Connection[];
before(async () => connections = await createTestingConnections({
entities: [JSONBKeyTest],
dropSchema: true,
schemaCreate: true,
enabledDrivers: ["postgres"]
}));
beforeEach(() => reloadTestingDatabases(connections));
after(() => closeTestingConnections(connections));

it("jsonB keys are correctly resolved", () => Promise.all(connections.map(async connection => {
await connection.transaction(async manager => {
await manager.save(manager.create(JSONBKeyTest, { id: { first: 1, second: 2 } }));
await manager.save(manager.create(JSONBKeyTest, { id: { first: 1, second: 3 } }));

const entities = await manager.createQueryBuilder(JSONBKeyTest, "json_test").select().getMany();
expect(entities.length).to.equal(2);
});
})));

it("jsonB keys can be found", () => Promise.all(connections.map(async connection => {
await connection.transaction(async manager => {
await manager.save(manager.create(JSONBKeyTest, { id: { first: 3, second: 3 } }));
await manager.save(manager.create(JSONBKeyTest, { id: { first: 4, second: 3 } }));

const entities = await manager.find(JSONBKeyTest, { where: { id: { first: 3, second: 3 } } } );
expect(entities.length).to.equal(1);
expect(entities[0].id).to.deep.equal({ first: 3, second: 3 });
});
})));

it("jsonB keys can be found with IN", () => Promise.all(connections.map(async connection => {
await connection.transaction(async manager => {
await manager.save(manager.create(JSONBKeyTest, { id: { first: 3, second: 3 } }));
await manager.save(manager.create(JSONBKeyTest, { id: { first: 4, second: 3 } }));
await manager.save(manager.create(JSONBKeyTest, { id: { first: 5, second: 3 } }));
await manager.save(manager.create(JSONBKeyTest, { id: { first: 6, second: 4 } }));

const entities = await manager
.createQueryBuilder(JSONBKeyTest, "json_test")
.select()
.where("id IN (:...ids)", { ids: [{first: 5, second: 3}, {first: 6, second: 4}]})
.getMany();
expect(entities.length).to.equal(2);
expect(entities[0].id).to.deep.equal({ first: 5, second: 3 });
expect(entities[1].id).to.deep.equal({ first: 6, second: 4 });
});
})));

it("jsonB keys can be found regardless of order", () => Promise.all(connections.map(async connection => {
await connection.transaction(async manager => {
await manager.save(manager.create(JSONBKeyTest, { id: { first: 3, second: 3 } }));
await manager.save(manager.create(JSONBKeyTest, { id: { first: 4, second: 3 } }));
await manager.save(manager.create(JSONBKeyTest, { id: { first: 5, second: 3 } }));
await manager.save(manager.create(JSONBKeyTest, { id: { first: 6, second: 4 } }));


const payload = { second: 2, first: 1 };
await manager.save(manager.create(JSONBKeyTest, { id: payload }));
const entities = await manager.find(JSONBKeyTest, { where: { id: payload } });
expect(entities.length).to.equal(1);
expect(entities[0].id).to.deep.equal({ first: 1, second: 2 });

const entitiesOtherOrder = await manager.find(JSONBKeyTest, { where: { id: {first: 1, second: 2} } });
expect(entitiesOtherOrder.length).to.equal(1);
expect(entitiesOtherOrder[0].id).to.deep.equal({ first: 1, second: 2 });

});
})));
});

0 comments on commit c886cc4

Please sign in to comment.