Skip to content

Commit

Permalink
fix(core): fix querying by JSON properties
Browse files Browse the repository at this point in the history
Closes #1673
  • Loading branch information
B4nan committed Apr 18, 2021
1 parent 4a345fd commit 73108b1
Show file tree
Hide file tree
Showing 15 changed files with 78 additions and 50 deletions.
2 changes: 1 addition & 1 deletion packages/core/src/utils/QueryHelper.ts
Original file line number Diff line number Diff line change
Expand Up @@ -120,7 +120,7 @@ export class QueryHelper {
}

if (prop?.customType instanceof JsonType && Utils.isPlainObject(value) && !platform.isRaw(value)) {
return this.processJsonCondition(o, value, [key], platform);
return this.processJsonCondition(o, value, [prop.fieldNames[0]], platform);
}

if (Array.isArray(value) && !Utils.isOperator(key) && !QueryHelper.isSupportedOperator(key) && !key.includes('?')) {
Expand Down
3 changes: 2 additions & 1 deletion packages/knex/src/query/QueryBuilderHelper.ts
Original file line number Diff line number Diff line change
Expand Up @@ -322,7 +322,8 @@ export class QueryBuilderHelper {
const k = this.mapper(key, type, params1);

if (params2.length > 0) {
return void clause[m](k, this.knex.raw('?', params2));
const val = params2.length === 1 && params2[0] === null ? null : this.knex.raw('?', params2);
return void clause[m](k, val);
}

clause[m](k);
Expand Down
4 changes: 2 additions & 2 deletions tests/EntityHelper.mysql.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -31,7 +31,7 @@ describe('EntityHelperMySql', () => {
bar: {
id: 1,
name: 'fb',
object: null,
objectProperty: null,
random: 123,
version: a.version,
array: null,
Expand All @@ -48,7 +48,7 @@ describe('EntityHelperMySql', () => {
random: 123,
version: a.version,
array: null,
object: null,
objectProperty: null,
blob: null,
});
});
Expand Down
24 changes: 12 additions & 12 deletions tests/EntityManager.mysql.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2303,7 +2303,7 @@ describe('EntityManagerMySql', () => {
const bar = FooBar2.create('b1');
bar.blob = Buffer.from([1, 2, 3, 4, 5]);
bar.array = [];
bar.object = { foo: 'bar', bar: 3 };
bar.objectProperty = { foo: 'bar', bar: 3 };
await orm.em.persistAndFlush(bar);
orm.em.clear();

Expand All @@ -2312,35 +2312,35 @@ describe('EntityManagerMySql', () => {
expect(b1.blob).toBeInstanceOf(Buffer);
expect(b1.array).toEqual([]);
expect(b1.array).toBeInstanceOf(Array);
expect(b1.object).toEqual({ foo: 'bar', bar: 3 });
expect(b1.object).toBeInstanceOf(Object);
expect(b1.object!.bar).toBe(3);
expect(b1.objectProperty).toEqual({ foo: 'bar', bar: 3 });
expect(b1.objectProperty).toBeInstanceOf(Object);
expect(b1.objectProperty!.bar).toBe(3);

b1.object = 'foo';
b1.objectProperty = 'foo';
b1.array = [1, 2, 3, 4, 5];
await orm.em.flush();
orm.em.clear();

const b2 = await orm.em.findOneOrFail(FooBar2, bar.id);
expect(b2.array).toEqual([1, 2, 3, 4, 5]);
expect(b2.array![2]).toBe(3);
expect(b2.object).toBe('foo');
expect(b2.objectProperty).toBe('foo');

b2.object = [1, 2, '3'];
b2.objectProperty = [1, 2, '3'];
await orm.em.flush();
orm.em.clear();

const b3 = await orm.em.findOneOrFail(FooBar2, bar.id);
expect(b3.object[0]).toBe(1);
expect(b3.object[1]).toBe(2);
expect(b3.object[2]).toBe('3');
expect(b3.objectProperty[0]).toBe(1);
expect(b3.objectProperty[1]).toBe(2);
expect(b3.objectProperty[2]).toBe('3');

b3.object = 123;
b3.objectProperty = 123;
await orm.em.flush();
orm.em.clear();

const b4 = await orm.em.findOneOrFail(FooBar2, bar.id);
expect(b4.object).toBe(123);
expect(b4.objectProperty).toBe(123);
});

test('exceptions', async () => {
Expand Down
51 changes: 39 additions & 12 deletions tests/EntityManager.postgre.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -420,6 +420,33 @@ describe('EntityManagerPostgre', () => {
expect(b1).toBe(b7);
});

test('json properties respect field names', async () => {
const bar = new FooBar2();
bar.name = 'b';
bar.objectProperty = { myPropName: { nestedProperty: 123, somethingElse: null } };
await orm.em.fork().persistAndFlush(bar);

const mock = jest.fn();
const logger = new Logger(mock, ['query', 'query-params']);
Object.assign(orm.config, { logger });

const b0 = await orm.em.findOneOrFail(FooBar2, bar);
expect(b0.objectProperty).toEqual({ myPropName: { nestedProperty: 123, somethingElse: null } });

const b1 = await orm.em.findOneOrFail(FooBar2, { objectProperty: { myPropName: { nestedProperty: 123 } } });
const b2 = await orm.em.findOneOrFail(FooBar2, { objectProperty: { myPropName: { somethingElse: null } } });
const b3 = await orm.em.findOneOrFail(FooBar2, { objectProperty: { myPropName: { nestedProperty: 123, somethingElse: null } } });
expect(b0).toBe(b1);
expect(b0).toBe(b2);
expect(b0).toBe(b3);

expect(mock.mock.calls).toHaveLength(4);
expect(mock.mock.calls[0][0]).toMatch(`select "e0".*, (select 123) as "random" from "foo_bar2" as "e0" where "e0"."id" = 1 limit 1`);
expect(mock.mock.calls[1][0]).toMatch(`select "e0".*, (select 123) as "random" from "foo_bar2" as "e0" where ("object_property"->'myPropName'->>'nestedProperty')::float8 = 123 limit 1`);
expect(mock.mock.calls[2][0]).toMatch(`select "e0".*, (select 123) as "random" from "foo_bar2" as "e0" where "object_property"->'myPropName'->>'somethingElse' is null limit 1`);
expect(mock.mock.calls[3][0]).toMatch(`select "e0".*, (select 123) as "random" from "foo_bar2" as "e0" where ("object_property"->'myPropName'->>'nestedProperty')::float8 = 123 and "object_property"->'myPropName'->>'somethingElse' is null limit 1`);
});

test('findOne should initialize entity that is already in IM', async () => {
const god = new Author2('God', 'hello@heaven.god');
const bible = new Book2('Bible', god);
Expand Down Expand Up @@ -1515,7 +1542,7 @@ describe('EntityManagerPostgre', () => {
const bar = FooBar2.create('b1 "b" \'1\'');
bar.blob = Buffer.from([1, 2, 3, 4, 5]);
bar.array = [];
bar.object = { foo: `bar 'lol' baz "foo"`, bar: 3 };
bar.objectProperty = { foo: `bar 'lol' baz "foo"`, bar: 3 };
await orm.em.persistAndFlush(bar);
orm.em.clear();

Expand All @@ -1524,35 +1551,35 @@ describe('EntityManagerPostgre', () => {
expect(b1.blob).toBeInstanceOf(Buffer);
expect(b1.array).toEqual([]);
expect(b1.array).toBeInstanceOf(Array);
expect(b1.object).toEqual({ foo: `bar 'lol' baz "foo"`, bar: 3 });
expect(b1.object).toBeInstanceOf(Object);
expect(b1.object!.bar).toBe(3);
expect(b1.objectProperty).toEqual({ foo: `bar 'lol' baz "foo"`, bar: 3 });
expect(b1.objectProperty).toBeInstanceOf(Object);
expect(b1.objectProperty!.bar).toBe(3);

b1.object = 'foo';
b1.objectProperty = 'foo';
b1.array = [1, 2, 3, 4, 5];
await orm.em.flush();
orm.em.clear();

const b2 = await orm.em.findOneOrFail(FooBar2, bar.id);
expect(b2.object).toBe('foo');
expect(b2.objectProperty).toBe('foo');
expect(b2.array).toEqual([1, 2, 3, 4, 5]);
expect(b2.array![2]).toBe(3);

b2.object = [1, 2, '3'];
b2.objectProperty = [1, 2, '3'];
await orm.em.flush();
orm.em.clear();

const b3 = await orm.em.findOneOrFail(FooBar2, bar.id);
expect(b3.object[0]).toBe(1);
expect(b3.object[1]).toBe(2);
expect(b3.object[2]).toBe('3');
expect(b3.objectProperty[0]).toBe(1);
expect(b3.objectProperty[1]).toBe(2);
expect(b3.objectProperty[2]).toBe('3');

b3.object = 123;
b3.objectProperty = 123;
await orm.em.flush();
orm.em.clear();

const b4 = await orm.em.findOneOrFail(FooBar2, bar.id);
expect(b4.object).toBe(123);
expect(b4.objectProperty).toBe(123);
});

test('using $contains', async () => {
Expand Down
2 changes: 1 addition & 1 deletion tests/QueryBuilder.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -205,7 +205,7 @@ describe('QueryBuilder', () => {
.limit(1);
const sql = 'select `fb1`.*, ' +
'`fz`.`id` as `fz__id`, `fz`.`name` as `fz__name`, `fz`.`version` as `fz__version`, ' +
'`fb2`.`id` as `fb2__id`, `fb2`.`name` as `fb2__name`, `fb2`.`baz_id` as `fb2__baz_id`, `fb2`.`foo_bar_id` as `fb2__foo_bar_id`, `fb2`.`version` as `fb2__version`, `fb2`.`blob` as `fb2__blob`, `fb2`.`array` as `fb2__array`, `fb2`.`object` as `fb2__object`, (select 123) as `fb2__random`, ' +
'`fb2`.`id` as `fb2__id`, `fb2`.`name` as `fb2__name`, `fb2`.`baz_id` as `fb2__baz_id`, `fb2`.`foo_bar_id` as `fb2__foo_bar_id`, `fb2`.`version` as `fb2__version`, `fb2`.`blob` as `fb2__blob`, `fb2`.`array` as `fb2__array`, `fb2`.`object_property` as `fb2__object_property`, (select 123) as `fb2__random`, ' +
'(select 123) as `random` from `foo_bar2` as `fb1` ' +
'inner join `foo_baz2` as `fz` on `fb1`.`baz_id` = `fz`.`id` ' +
'left join `foo_bar2` as `fb2` on `fz`.`id` = `fb2`.`baz_id` ' +
Expand Down
4 changes: 2 additions & 2 deletions tests/__snapshots__/EntityGenerator.test.ts.snap
Original file line number Diff line number Diff line change
Expand Up @@ -309,7 +309,7 @@ export class FooBar2 {
array?: string;
@Property({ columnType: 'json', nullable: true })
object?: any;
objectProperty?: any;
}
",
Expand Down Expand Up @@ -745,7 +745,7 @@ export class FooBar2 {
array?: string[];
@Property({ columnType: 'jsonb', nullable: true })
object?: any;
objectProperty?: any;
}
",
Expand Down
8 changes: 4 additions & 4 deletions tests/__snapshots__/Migrator.postgres.test.ts.snap
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@ export class Migration20191013214813 extends Migration {
this.addSql('create table \\"foo_baz2\\" (\\"id\\" serial primary key, \\"name\\" varchar(255) not null, \\"version\\" timestamptz(3) not null default current_timestamp(3));');
this.addSql('create table \\"foo_bar2\\" (\\"id\\" serial primary key, \\"name\\" varchar(255) not null, \\"baz_id\\" int null, \\"foo_bar_id\\" int null, \\"version\\" timestamptz(0) not null default current_timestamp(0), \\"blob\\" bytea null, \\"array\\" text[] null, \\"object\\" jsonb null);');
this.addSql('create table \\"foo_bar2\\" (\\"id\\" serial primary key, \\"name\\" varchar(255) not null, \\"baz_id\\" int null, \\"foo_bar_id\\" int null, \\"version\\" timestamptz(0) not null default current_timestamp(0), \\"blob\\" bytea null, \\"array\\" text[] null, \\"object_property\\" jsonb null);');
this.addSql('alter table \\"foo_bar2\\" add constraint \\"foo_bar2_baz_id_unique\\" unique (\\"baz_id\\");');
this.addSql('alter table \\"foo_bar2\\" add constraint \\"foo_bar2_foo_bar_id_unique\\" unique (\\"foo_bar_id\\");');
Expand Down Expand Up @@ -109,7 +109,7 @@ export class Migration20191013214813 extends Migration {
"",
"create table \\"foo_baz2\\" (\\"id\\" serial primary key, \\"name\\" varchar(255) not null, \\"version\\" timestamptz(3) not null default current_timestamp(3));",
"",
"create table \\"foo_bar2\\" (\\"id\\" serial primary key, \\"name\\" varchar(255) not null, \\"baz_id\\" int null, \\"foo_bar_id\\" int null, \\"version\\" timestamptz(0) not null default current_timestamp(0), \\"blob\\" bytea null, \\"array\\" text[] null, \\"object\\" jsonb null);",
"create table \\"foo_bar2\\" (\\"id\\" serial primary key, \\"name\\" varchar(255) not null, \\"baz_id\\" int null, \\"foo_bar_id\\" int null, \\"version\\" timestamptz(0) not null default current_timestamp(0), \\"blob\\" bytea null, \\"array\\" text[] null, \\"object_property\\" jsonb null);",
"alter table \\"foo_bar2\\" add constraint \\"foo_bar2_baz_id_unique\\" unique (\\"baz_id\\");",
"alter table \\"foo_bar2\\" add constraint \\"foo_bar2_foo_bar_id_unique\\" unique (\\"foo_bar_id\\");",
"",
Expand Down Expand Up @@ -213,7 +213,7 @@ export class Migration20191013214813 extends Migration {
this.addSql('create table \\"foo_baz2\\" (\\"id\\" serial primary key, \\"name\\" varchar(255) not null, \\"version\\" timestamptz(3) not null default current_timestamp(3));');
this.addSql('create table \\"foo_bar2\\" (\\"id\\" serial primary key, \\"name\\" varchar(255) not null, \\"baz_id\\" int null, \\"foo_bar_id\\" int null, \\"version\\" timestamptz(0) not null default current_timestamp(0), \\"blob\\" bytea null, \\"array\\" text[] null, \\"object\\" jsonb null);');
this.addSql('create table \\"foo_bar2\\" (\\"id\\" serial primary key, \\"name\\" varchar(255) not null, \\"baz_id\\" int null, \\"foo_bar_id\\" int null, \\"version\\" timestamptz(0) not null default current_timestamp(0), \\"blob\\" bytea null, \\"array\\" text[] null, \\"object_property\\" jsonb null);');
this.addSql('alter table \\"foo_bar2\\" add constraint \\"foo_bar2_baz_id_unique\\" unique (\\"baz_id\\");');
this.addSql('alter table \\"foo_bar2\\" add constraint \\"foo_bar2_foo_bar_id_unique\\" unique (\\"foo_bar_id\\");');
Expand Down Expand Up @@ -310,7 +310,7 @@ export class Migration20191013214813 extends Migration {
"",
"create table \\"foo_baz2\\" (\\"id\\" serial primary key, \\"name\\" varchar(255) not null, \\"version\\" timestamptz(3) not null default current_timestamp(3));",
"",
"create table \\"foo_bar2\\" (\\"id\\" serial primary key, \\"name\\" varchar(255) not null, \\"baz_id\\" int null, \\"foo_bar_id\\" int null, \\"version\\" timestamptz(0) not null default current_timestamp(0), \\"blob\\" bytea null, \\"array\\" text[] null, \\"object\\" jsonb null);",
"create table \\"foo_bar2\\" (\\"id\\" serial primary key, \\"name\\" varchar(255) not null, \\"baz_id\\" int null, \\"foo_bar_id\\" int null, \\"version\\" timestamptz(0) not null default current_timestamp(0), \\"blob\\" bytea null, \\"array\\" text[] null, \\"object_property\\" jsonb null);",
"alter table \\"foo_bar2\\" add constraint \\"foo_bar2_baz_id_unique\\" unique (\\"baz_id\\");",
"alter table \\"foo_bar2\\" add constraint \\"foo_bar2_foo_bar_id_unique\\" unique (\\"foo_bar_id\\");",
"",
Expand Down
8 changes: 4 additions & 4 deletions tests/__snapshots__/Migrator.test.ts.snap
Original file line number Diff line number Diff line change
Expand Up @@ -30,7 +30,7 @@ export class Migration20191013214813 extends Migration {
this.addSql('create table \`foo_baz2\` (\`id\` int unsigned not null auto_increment primary key, \`name\` varchar(255) not null, \`version\` datetime(3) not null default current_timestamp(3)) default character set utf8mb4 engine = InnoDB;');
this.addSql('create table \`foo_bar2\` (\`id\` int unsigned not null auto_increment primary key, \`name\` varchar(255) not null, \`baz_id\` int unsigned null, \`foo_bar_id\` int unsigned null, \`version\` datetime not null default current_timestamp, \`blob\` blob null, \`array\` text null, \`object\` json null) default character set utf8mb4 engine = InnoDB;');
this.addSql('create table \`foo_bar2\` (\`id\` int unsigned not null auto_increment primary key, \`name\` varchar(255) not null, \`baz_id\` int unsigned null, \`foo_bar_id\` int unsigned null, \`version\` datetime not null default current_timestamp, \`blob\` blob null, \`array\` text null, \`object_property\` json null) default character set utf8mb4 engine = InnoDB;');
this.addSql('alter table \`foo_bar2\` add index \`foo_bar2_baz_id_index\`(\`baz_id\`);');
this.addSql('alter table \`foo_bar2\` add unique \`foo_bar2_baz_id_unique\`(\`baz_id\`);');
this.addSql('alter table \`foo_bar2\` add index \`foo_bar2_foo_bar_id_index\`(\`foo_bar_id\`);');
Expand Down Expand Up @@ -192,7 +192,7 @@ export class Migration20191013214813 extends Migration {
"",
"create table \`foo_baz2\` (\`id\` int unsigned not null auto_increment primary key, \`name\` varchar(255) not null, \`version\` datetime(3) not null default current_timestamp(3)) default character set utf8mb4 engine = InnoDB;",
"",
"create table \`foo_bar2\` (\`id\` int unsigned not null auto_increment primary key, \`name\` varchar(255) not null, \`baz_id\` int unsigned null, \`foo_bar_id\` int unsigned null, \`version\` datetime not null default current_timestamp, \`blob\` blob null, \`array\` text null, \`object\` json null) default character set utf8mb4 engine = InnoDB;",
"create table \`foo_bar2\` (\`id\` int unsigned not null auto_increment primary key, \`name\` varchar(255) not null, \`baz_id\` int unsigned null, \`foo_bar_id\` int unsigned null, \`version\` datetime not null default current_timestamp, \`blob\` blob null, \`array\` text null, \`object_property\` json null) default character set utf8mb4 engine = InnoDB;",
"alter table \`foo_bar2\` add index \`foo_bar2_baz_id_index\`(\`baz_id\`);",
"alter table \`foo_bar2\` add unique \`foo_bar2_baz_id_unique\`(\`baz_id\`);",
"alter table \`foo_bar2\` add index \`foo_bar2_foo_bar_id_index\`(\`foo_bar_id\`);",
Expand Down Expand Up @@ -361,7 +361,7 @@ export class Migration20191013214813 extends Migration {
this.addSql('create table \`foo_baz2\` (\`id\` int unsigned not null auto_increment primary key, \`name\` varchar(255) not null, \`version\` datetime(3) not null default current_timestamp(3)) default character set utf8mb4 engine = InnoDB;');
this.addSql('create table \`foo_bar2\` (\`id\` int unsigned not null auto_increment primary key, \`name\` varchar(255) not null, \`baz_id\` int unsigned null, \`foo_bar_id\` int unsigned null, \`version\` datetime not null default current_timestamp, \`blob\` blob null, \`array\` text null, \`object\` json null) default character set utf8mb4 engine = InnoDB;');
this.addSql('create table \`foo_bar2\` (\`id\` int unsigned not null auto_increment primary key, \`name\` varchar(255) not null, \`baz_id\` int unsigned null, \`foo_bar_id\` int unsigned null, \`version\` datetime not null default current_timestamp, \`blob\` blob null, \`array\` text null, \`object_property\` json null) default character set utf8mb4 engine = InnoDB;');
this.addSql('alter table \`foo_bar2\` add index \`foo_bar2_baz_id_index\`(\`baz_id\`);');
this.addSql('alter table \`foo_bar2\` add unique \`foo_bar2_baz_id_unique\`(\`baz_id\`);');
this.addSql('alter table \`foo_bar2\` add index \`foo_bar2_foo_bar_id_index\`(\`foo_bar_id\`);');
Expand Down Expand Up @@ -523,7 +523,7 @@ export class Migration20191013214813 extends Migration {
"",
"create table \`foo_baz2\` (\`id\` int unsigned not null auto_increment primary key, \`name\` varchar(255) not null, \`version\` datetime(3) not null default current_timestamp(3)) default character set utf8mb4 engine = InnoDB;",
"",
"create table \`foo_bar2\` (\`id\` int unsigned not null auto_increment primary key, \`name\` varchar(255) not null, \`baz_id\` int unsigned null, \`foo_bar_id\` int unsigned null, \`version\` datetime not null default current_timestamp, \`blob\` blob null, \`array\` text null, \`object\` json null) default character set utf8mb4 engine = InnoDB;",
"create table \`foo_bar2\` (\`id\` int unsigned not null auto_increment primary key, \`name\` varchar(255) not null, \`baz_id\` int unsigned null, \`foo_bar_id\` int unsigned null, \`version\` datetime not null default current_timestamp, \`blob\` blob null, \`array\` text null, \`object_property\` json null) default character set utf8mb4 engine = InnoDB;",
"alter table \`foo_bar2\` add index \`foo_bar2_baz_id_index\`(\`baz_id\`);",
"alter table \`foo_bar2\` add unique \`foo_bar2_baz_id_unique\`(\`baz_id\`);",
"alter table \`foo_bar2\` add index \`foo_bar2_foo_bar_id_index\`(\`foo_bar_id\`);",
Expand Down
2 changes: 1 addition & 1 deletion tests/entities-sql/FooBar2.ts
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,7 @@ export class FooBar2 extends BaseEntity22 {
array?: number[];

@Property({ type: JsonType, nullable: true })
object?: { foo: string; bar: number } | any;
objectProperty?: { foo: string; bar: number } | any;

@Formula(`(select 123)`)
random?: number;
Expand Down
Loading

0 comments on commit 73108b1

Please sign in to comment.