quaerateum
Version:
Simple typescript ORM for node.js based on data-mapper, unit-of-work and identity-map patterns. Supports MongoDB, MySQL, PostgreSQL and SQLite databases as well as usage with vanilla JS.
314 lines (271 loc) • 15 kB
text/typescript
import { Author2, Book2, BookTag2, FooBar2, FooBaz2, Publisher2, PublisherType, Test2 } from './entities-sql';
import { initORMMySql } from './bootstrap';
import { MikroORM, QueryOrder } from '../lib';
/**
* @class QueryBuilderTest
*/
describe('QueryBuilder', () => {
let orm: MikroORM;
beforeAll(async () => orm = await initORMMySql());
test('select query', async () => {
const qb = orm.em.createQueryBuilder(Publisher2);
qb.select('*').where({ name: 'test 123', type: PublisherType.GLOBAL }).orderBy({ name: QueryOrder.DESC, type: QueryOrder.ASC }).limit(2, 1);
expect(qb.getQuery()).toEqual('SELECT `e0`.* FROM `publisher2` AS `e0` WHERE `e0`.`name` = ? AND `e0`.`type` = ? ORDER BY `e0`.`name` DESC, `e0`.`type` ASC LIMIT ? OFFSET ?');
expect(qb.getParams()).toEqual(['test 123', PublisherType.GLOBAL, 2, 1]);
});
test('select in query', async () => {
const qb = orm.em.createQueryBuilder(Publisher2);
qb.select(['id', 'name', 'type']).where({ name: { $in: ['test 123', 'lol 321'] }, type: PublisherType.GLOBAL }).limit(2, 1);
expect(qb.getQuery()).toEqual('SELECT `e0`.`id`, `e0`.`name`, `e0`.`type` FROM `publisher2` AS `e0` WHERE `e0`.`name` IN (?, ?) AND `e0`.`type` = ? LIMIT ? OFFSET ?');
expect(qb.getParams()).toEqual(['test 123', 'lol 321', PublisherType.GLOBAL, 2, 1]);
});
test('select andWhere/orWhere', async () => {
const qb = orm.em.createQueryBuilder(Publisher2);
qb.select('*')
.where({ name: 'test 123' })
.andWhere({ type: PublisherType.GLOBAL })
.orWhere({ name: 'lol 321' })
.limit(2, 1);
expect(qb.getQuery()).toEqual('SELECT `e0`.* FROM `publisher2` AS `e0` WHERE ((`e0`.`name` = ? AND `e0`.`type` = ?) OR `e0`.`name` = ?) LIMIT ? OFFSET ?');
expect(qb.getParams()).toEqual(['test 123', PublisherType.GLOBAL, 'lol 321', 2, 1]);
});
test('select multiple andWhere', async () => {
const qb = orm.em.createQueryBuilder(Publisher2);
qb.select('*')
.where({ name: 'test 123' })
.andWhere({ type: PublisherType.GLOBAL })
.andWhere({ name: 'test 321' })
.andWhere({ name: 'lol 321' })
.limit(2, 1);
expect(qb.getQuery()).toEqual('SELECT `e0`.* FROM `publisher2` AS `e0` WHERE (`e0`.`name` = ? AND `e0`.`type` = ? AND `e0`.`name` = ? AND `e0`.`name` = ?) LIMIT ? OFFSET ?');
expect(qb.getParams()).toEqual(['test 123', PublisherType.GLOBAL, 'test 321', 'lol 321', 2, 1]);
});
test('select multiple orWhere', async () => {
const qb = orm.em.createQueryBuilder(Publisher2);
qb.select('*')
.where({ name: 'test 123' })
.orWhere({ type: PublisherType.GLOBAL })
.orWhere({ name: 'test 321' })
.orWhere({ name: 'lol 321' })
.limit(2, 1);
expect(qb.getQuery()).toEqual('SELECT `e0`.* FROM `publisher2` AS `e0` WHERE (`e0`.`name` = ? OR `e0`.`type` = ? OR `e0`.`name` = ? OR `e0`.`name` = ?) LIMIT ? OFFSET ?');
expect(qb.getParams()).toEqual(['test 123', PublisherType.GLOBAL, 'test 321', 'lol 321', 2, 1]);
});
test('select with boolean', async () => {
const qb = orm.em.createQueryBuilder(Author2);
qb.select('*').where({ termsAccepted: false });
expect(qb.getQuery()).toEqual('SELECT `e0`.* FROM `author2` AS `e0` WHERE `e0`.`terms_accepted` = ?');
expect(qb.getParams()).toEqual([false]);
});
test('select with custom expression', async () => {
const qb1 = orm.em.createQueryBuilder(Book2);
qb1.select('*').where({ 'JSON_CONTAINS(`e0`.`meta`, ?)': [{ foo: 'bar' }, true] });
expect(qb1.getQuery()).toEqual('SELECT `e0`.* FROM `book2` AS `e0` WHERE JSON_CONTAINS(`e0`.`meta`, ?) = ?');
expect(qb1.getParams()).toEqual(['{"foo":"bar"}', true]);
const qb2 = orm.em.createQueryBuilder(Book2);
qb2.select('*').where({ 'JSON_CONTAINS(`e0`.`meta`, ?)': [{ foo: 'baz' }, false] });
expect(qb2.getQuery()).toEqual('SELECT `e0`.* FROM `book2` AS `e0` WHERE JSON_CONTAINS(`e0`.`meta`, ?) = ?');
expect(qb2.getParams()).toEqual(['{"foo":"baz"}', false]);
});
test('select by regexp', async () => {
let qb = orm.em.createQueryBuilder(Publisher2);
qb.select('*').where({ name: /test/ });
expect(qb.getQuery()).toEqual('SELECT `e0`.* FROM `publisher2` AS `e0` WHERE `e0`.`name` LIKE ?');
expect(qb.getParams()).toEqual(['%test%']);
qb = orm.em.createQueryBuilder(Publisher2);
qb.select('*').where({ name: /^test/ });
expect(qb.getQuery()).toEqual('SELECT `e0`.* FROM `publisher2` AS `e0` WHERE `e0`.`name` LIKE ?');
expect(qb.getParams()).toEqual(['test%']);
qb = orm.em.createQueryBuilder(Publisher2);
qb.select('*').where({ name: /t.st$/ });
expect(qb.getQuery()).toEqual('SELECT `e0`.* FROM `publisher2` AS `e0` WHERE `e0`.`name` LIKE ?');
expect(qb.getParams()).toEqual(['%t_st']);
qb = orm.em.createQueryBuilder(Publisher2);
qb.select('*').where({ name: /^c.o.*l-te.*st\.c.m$/ });
expect(qb.getQuery()).toEqual('SELECT `e0`.* FROM `publisher2` AS `e0` WHERE `e0`.`name` LIKE ?');
expect(qb.getParams()).toEqual(['c_o%l-te%st.c_m']);
});
test('select by m:1', async () => {
const qb = orm.em.createQueryBuilder(Author2);
qb.select('*').where({ favouriteBook: 123 });
expect(qb.getQuery()).toEqual('SELECT `e0`.* FROM `author2` AS `e0` WHERE `e0`.`favourite_book_uuid_pk` = ?');
expect(qb.getParams()).toEqual([123]);
});
test('select by 1:m', async () => {
const qb = orm.em.createQueryBuilder(Author2);
qb.select('*').where({ books: { $in: [123, 321] } });
expect(qb.getQuery()).toEqual('SELECT `e0`.* FROM `author2` AS `e0` LEFT JOIN `book2` AS `e1` ON `e0`.`id` = `e1`.`author_id` WHERE `e1`.`id` IN (?, ?)');
expect(qb.getParams()).toEqual([123, 321]);
});
test('select by 1:1', async () => {
const qb = orm.em.createQueryBuilder(FooBar2);
qb.select('*').where({ baz: 123 });
expect(qb.getQuery()).toEqual('SELECT `e0`.* FROM `foo_bar2` AS `e0` WHERE `e0`.`baz_id` = ?');
expect(qb.getParams()).toEqual([123]);
});
test('select by 1:1 inversed', async () => {
const qb = orm.em.createQueryBuilder(FooBaz2);
qb.select('*').where({ bar: 123 });
expect(qb.getQuery()).toEqual('SELECT `e0`.*, `e1`.`id` AS `bar_id` FROM `foo_baz2` AS `e0` LEFT JOIN `foo_bar2` AS `e1` ON `e0`.`id` = `e1`.`baz_id` WHERE `e1`.`id` = ?');
expect(qb.getParams()).toEqual([123]);
});
test('select by 1:1 inversed with populate', async () => {
const qb = orm.em.createQueryBuilder(FooBaz2);
qb.select('*').where({ id: 123 }).populate(['bar']);
expect(qb.getQuery()).toEqual('SELECT `e0`.*, `e1`.`id` AS `bar_id` FROM `foo_baz2` AS `e0` LEFT JOIN `foo_bar2` AS `e1` ON `e0`.`id` = `e1`.`baz_id` WHERE `e0`.`id` = ?');
expect(qb.getParams()).toEqual([123]);
});
test('select by 1:1 inversed (uuid pk)', async () => {
const qb = orm.em.createQueryBuilder(Book2);
qb.select('*').where({ test: 123 });
expect(qb.getQuery()).toEqual('SELECT `e0`.*, `e1`.`id` AS `test_id` FROM `book2` AS `e0` LEFT JOIN `test2` AS `e1` ON `e0`.`uuid_pk` = `e1`.`book_uuid_pk` WHERE `e1`.`id` = ?');
expect(qb.getParams()).toEqual([123]);
});
test('select by 1:1 inversed with populate (uuid pk)', async () => {
const qb = orm.em.createQueryBuilder(Book2);
qb.select('*').where({ test: 123 }).populate(['test']);
expect(qb.getQuery()).toEqual('SELECT `e0`.*, `e1`.`id` AS `test_id` FROM `book2` AS `e0` LEFT JOIN `test2` AS `e1` ON `e0`.`uuid_pk` = `e1`.`book_uuid_pk` WHERE `e1`.`id` = ?');
expect(qb.getParams()).toEqual([123]);
});
test('select by 1:1 inversed with populate() before where() (uuid pk)', async () => {
const qb = orm.em.createQueryBuilder(Book2);
qb.select('*').populate(['test']).where({ test: 123 });
expect(qb.getQuery()).toEqual('SELECT `e0`.*, `e1`.`id` AS `test_id` FROM `book2` AS `e0` LEFT JOIN `test2` AS `e1` ON `e0`.`uuid_pk` = `e1`.`book_uuid_pk` WHERE `e1`.`id` = ?');
expect(qb.getParams()).toEqual([123]);
});
test('select by m:n', async () => {
const qb = orm.em.createQueryBuilder(Book2);
qb.select('*').where({ tags: 123 });
expect(qb.getQuery()).toEqual('SELECT `e0`.*, `e1`.`book2_uuid_pk`, `e1`.`book_tag2_id` FROM `book2` AS `e0` LEFT JOIN `book2_to_book_tag2` AS `e1` ON `e0`.`uuid_pk` = `e1`.`book2_uuid_pk` WHERE `e1`.`book_tag2_id` = ?');
expect(qb.getParams()).toEqual([123]);
});
test('select by m:n inversed', async () => {
const qb = orm.em.createQueryBuilder(BookTag2);
qb.select('*').where({ books: 123 });
expect(qb.getQuery()).toEqual('SELECT `e0`.*, `e1`.`book_tag2_id`, `e1`.`book2_uuid_pk` FROM `book_tag2` AS `e0` LEFT JOIN `book2_to_book_tag2` AS `e1` ON `e0`.`id` = `e1`.`book_tag2_id` WHERE `e1`.`book2_uuid_pk` = ?');
expect(qb.getParams()).toEqual([123]);
});
test('select by m:n with populate', async () => {
const qb = orm.em.createQueryBuilder(Test2);
qb.select('*').populate(['publisher2_to_test2']).where({ publisher2_id: { $in: [ 1, 2 ] } }).orderBy({ ['publisher2_to_test2.id']: QueryOrder.ASC });
let sql = 'SELECT `e0`.*, `e1`.`test2_id`, `e1`.`publisher2_id` FROM `test2` AS `e0`';
sql += ' LEFT JOIN `publisher2_to_test2` AS `e1` ON `e0`.`id` = `e1`.`test2_id`';
sql += ' WHERE `e1`.`publisher2_id` IN (?, ?)';
sql += ' ORDER BY `e1`.`id` ASC';
expect(qb.getQuery()).toEqual(sql);
expect(qb.getParams()).toEqual([1, 2]);
});
test('select by m:n with unknown populate ignored', async () => {
const qb = orm.em.createQueryBuilder(Test2);
qb.select('*').populate(['not_existing']);
expect(qb.getQuery()).toEqual('SELECT `e0`.* FROM `test2` AS `e0`');
expect(qb.getParams()).toEqual([]);
});
test('select with operator (simple)', async () => {
const qb = orm.em.createQueryBuilder(Test2);
qb.select('*').where({ id: { $nin: [3, 4] } });
expect(qb.getQuery()).toEqual('SELECT `e0`.* FROM `test2` AS `e0` WHERE `e0`.`id` NOT IN (?, ?)');
expect(qb.getParams()).toEqual([3, 4]);
});
test('select with operator (wrapped)', async () => {
const qb1 = orm.em.createQueryBuilder(Test2);
qb1.select('*').where({ $and: [{ id: { $nin: [3, 4] } }, { id: { $gt: 2 } }] });
expect(qb1.getQuery()).toEqual('SELECT `e0`.* FROM `test2` AS `e0` WHERE (`e0`.`id` NOT IN (?, ?) AND `e0`.`id` > ?)');
expect(qb1.getParams()).toEqual([3, 4, 2]);
const qb2 = orm.em.createQueryBuilder(Test2);
qb2.select('*').where({ id: { $nin: [3, 4], $gt: 2 } });
expect(qb2.getQuery()).toEqual(qb1.getQuery());
expect(qb2.getParams()).toEqual(qb1.getParams());
});
test('select with operator (NOT)', async () => {
const qb = orm.em.createQueryBuilder(Test2);
qb.select('*').where({ $not: { id: { $in: [3, 4] } } });
expect(qb.getQuery()).toEqual('SELECT `e0`.* FROM `test2` AS `e0` WHERE NOT (`e0`.`id` IN (?, ?))');
expect(qb.getParams()).toEqual([3, 4]);
});
test('select with operator (AND)', async () => {
const qb = orm.em.createQueryBuilder(Test2);
qb.select('*').where({ $and: [
{ id: { $in: [1, 2, 7] }, },
{ id: { $nin: [3, 4] }, },
{ id: { $gt: 5 }, },
{ id: { $lt: 10 }, },
{ id: { $gte: 7 }, },
{ id: { $lte: 8 }, },
{ id: { $ne: 9 }, },
{ $not: { id: { $eq: 10 } } },
] });
expect(qb.getQuery()).toEqual('SELECT `e0`.* FROM `test2` AS `e0` ' +
'WHERE (`e0`.`id` IN (?, ?, ?) ' +
'AND `e0`.`id` NOT IN (?, ?) ' +
'AND `e0`.`id` > ? ' +
'AND `e0`.`id` < ? ' +
'AND `e0`.`id` >= ? ' +
'AND `e0`.`id` <= ? ' +
'AND `e0`.`id` != ? ' +
'AND NOT (`e0`.`id` = ?))');
expect(qb.getParams()).toEqual([1, 2, 7, 3, 4, 5, 10, 7, 8, 9, 10]);
});
test('select with operator (OR)', async () => {
const qb = orm.em.createQueryBuilder(Test2);
qb.select('*').where({ $or: [
{ id: { $in: [1, 2, 7] }, },
{ id: { $nin: [3, 4] }, },
{ id: { $gt: 5 }, },
{ id: { $lt: 10 }, },
{ id: { $gte: 7 }, },
{ id: { $lte: 8 }, },
{ id: { $ne: 9 }, },
{ $not: { id: { $eq: 10 } } },
] });
expect(qb.getQuery()).toEqual('SELECT `e0`.* FROM `test2` AS `e0` ' +
'WHERE (`e0`.`id` IN (?, ?, ?) ' +
'OR `e0`.`id` NOT IN (?, ?) ' +
'OR `e0`.`id` > ? ' +
'OR `e0`.`id` < ? ' +
'OR `e0`.`id` >= ? ' +
'OR `e0`.`id` <= ? ' +
'OR `e0`.`id` != ? ' +
'OR NOT (`e0`.`id` = ?))');
expect(qb.getParams()).toEqual([1, 2, 7, 3, 4, 5, 10, 7, 8, 9, 10]);
});
test('select count query', async () => {
const qb = orm.em.createQueryBuilder(Publisher2);
qb.count().where({ name: 'test 123', type: PublisherType.GLOBAL });
expect(qb.getQuery()).toEqual('SELECT COUNT(`e0`.`id`) AS `count` FROM `publisher2` AS `e0` WHERE `e0`.`name` = ? AND `e0`.`type` = ?');
expect(qb.getParams()).toEqual(['test 123', PublisherType.GLOBAL]);
});
test('select count distinct query', async () => {
const qb = orm.em.createQueryBuilder(Publisher2);
qb.count('id', true).where({ name: 'test 123', type: PublisherType.GLOBAL });
expect(qb.getQuery()).toEqual('SELECT COUNT(DISTINCT `e0`.`id`) AS `count` FROM `publisher2` AS `e0` WHERE `e0`.`name` = ? AND `e0`.`type` = ?');
expect(qb.getParams()).toEqual(['test 123', PublisherType.GLOBAL]);
});
test('insert query', async () => {
const qb1 = orm.em.createQueryBuilder(Publisher2);
qb1.insert({ name: 'test 123', type: PublisherType.GLOBAL });
expect(qb1.getQuery()).toEqual('INSERT INTO `publisher2` (`name`, `type`) VALUES (?, ?)');
expect(qb1.getParams()).toEqual(['test 123', PublisherType.GLOBAL]);
const qb2 = orm.em.createQueryBuilder(Author2);
qb2.insert({ name: 'test 123', favouriteBook: 2359, termsAccepted: true });
expect(qb2.getQuery()).toEqual('INSERT INTO `author2` (`name`, `favourite_book_uuid_pk`, `terms_accepted`) VALUES (?, ?, ?)');
expect(qb2.getParams()).toEqual(['test 123', 2359, true]);
const qb3 = orm.em.createQueryBuilder(BookTag2);
qb3.insert({ books: 123 });
expect(qb3.getQuery()).toEqual('INSERT INTO `book_tag2` (`books`) VALUES (?)');
expect(qb3.getParams()).toEqual([123]);
});
test('update query', async () => {
const qb = orm.em.createQueryBuilder(Publisher2);
qb.update({ name: 'test 123', type: PublisherType.GLOBAL }).where({ id: 123, type: PublisherType.LOCAL });
expect(qb.getQuery()).toEqual('UPDATE `publisher2` SET `name` = ?, `type` = ? WHERE `id` = ? AND `type` = ?');
expect(qb.getParams()).toEqual(['test 123', PublisherType.GLOBAL, 123, PublisherType.LOCAL]);
});
test('delete query', async () => {
const qb = orm.em.createQueryBuilder(Publisher2);
qb.delete({ name: 'test 123', type: PublisherType.GLOBAL });
expect(qb.getQuery()).toEqual('DELETE FROM `publisher2` WHERE `name` = ? AND `type` = ?');
expect(qb.getParams()).toEqual(['test 123', PublisherType.GLOBAL]);
});
afterAll(async () => orm.close(true));
});