@ts-awesome/orm 1.7.0 → 2.0.0-alpha.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -1,1068 +0,0 @@
1
- import {alias, and, asc, Delete, desc, Insert, max, Select, sum, TableMetadataSymbol, Update, Upsert, of} from '../dist';
2
- import {Employee, MailingList, Person, Tag} from './models';
3
- import { TableRef, readModelMeta, Window } from '../dist/builder';
4
- import {count, dbField, dbTable, exists, case_, cast, first_value, IOperandable} from "../dist";
5
- import {FunctionCall} from "../src/wrappers";
6
-
7
-
8
- const tableInfo = readModelMeta(Person);
9
- const tableName = tableInfo.tableName;
10
- const person: InstanceType<typeof Person> = {id: 1, name: 'Name', age: 18, city: 'City', profiles: ["profile-a"]};
11
-
12
- describe('Select', () => {
13
-
14
- it('Check query info', () => {
15
- const query = Select(Person);
16
- expect(query._type).toBe('SELECT');
17
- expect(query._table).toStrictEqual(tableInfo);
18
- });
19
-
20
- it('Columns through array list', () => {
21
- const nameAlias = 'PersonName';
22
- const coefficient = 2;
23
-
24
- const columnsThroughList = Select(Person).columns(['name', 'age']);
25
- const columnsThroughBuilder = Select(Person).columns(({name, age}) => [name, age]);
26
- const columnsWithAlias = Select(Person).columns(({name}) => [alias(name, nameAlias)]);
27
- const columnsWithOf = Select(Person).columns(() => [of(Employee, 'company')]);
28
- const columnsWithExpression = Select(Person).columns(({age}) => [age.mul(coefficient), max(age)]);
29
-
30
- const expectation = {
31
- default: [
32
- {_column: {table: tableName, name: 'name'}},
33
- {_column: {table: tableName, name: 'age'}}
34
- ],
35
- alias: [
36
- {_alias: nameAlias, _operands: [{_column: {table: tableName, name: 'name'}}]}
37
- ],
38
- of: [
39
- {_column: {table: readModelMeta(Employee).tableName, name: 'company'}}
40
- ],
41
- expression: [
42
- {_operator: '*', _operands: [{_column: {table: tableName, name: 'age'}}, coefficient]},
43
- {_func: 'MAX', _args: [{_column: {table: tableName, name: 'age'}}]}
44
- ]
45
- };
46
-
47
- expect(columnsThroughList._columns).toStrictEqual(expectation.default);
48
- expect(columnsThroughBuilder._columns).toStrictEqual(expectation.default);
49
- expect(columnsWithAlias._columns).toStrictEqual(expectation.alias);
50
- expect(columnsWithOf._columns).toStrictEqual(expectation.of);
51
- expect(columnsWithExpression._columns).toStrictEqual(expectation.expression);
52
- });
53
-
54
- it('Joins', () => {
55
- const enum joinTypes {inner = 'INNER', left = 'LEFT', right = 'RIGHT', full = 'FULL OUTER'}
56
-
57
- const employeeTableInfo = readModelMeta(Employee);
58
-
59
- const innerJoin = Select(Person).join(Employee, ({id}, {personId}) => id.eq(personId));
60
- const leftJoin = Select(Person).joinLeft(Employee, ({id}, {personId}) => id.eq(personId));
61
- const rightJoin = Select(Person).joinRight(Employee, ({id}, {personId}) => id.eq(personId));
62
- const fullJoin = Select(Person).joinFull(Employee, ({id}, {personId}) => id.eq(personId));
63
-
64
- const innerJoinExpectation = [{
65
- _tableName: employeeTableInfo.tableName,
66
- _alias: undefined,
67
- _type: joinTypes.inner,
68
- _condition: {
69
- _operands: [{_column: {table: tableName, name: 'id'}}, {_column: {table: employeeTableInfo.tableName, name: `personId`}}],
70
- _operator: '='
71
- }
72
- }];
73
- const leftJoinExpectation = [{
74
- _tableName: employeeTableInfo.tableName,
75
- _alias: undefined,
76
- _type: joinTypes.left,
77
- _condition: {
78
- _operands: [{_column: {table: tableName, name: 'id'}}, {_column: {table: employeeTableInfo.tableName, name: `personId`}}],
79
- _operator: '='
80
- }
81
- }];
82
- const rightJoinExpectation = [{
83
- _tableName: employeeTableInfo.tableName,
84
- _alias: undefined,
85
- _type: joinTypes.right,
86
- _condition: {
87
- _operands: [{_column: {table: tableName, name: 'id'}}, {_column: {table: employeeTableInfo.tableName, name: `personId`}}],
88
- _operator: '='
89
- }
90
- }];
91
- const fullJoinExpectation = [{
92
- _tableName: employeeTableInfo.tableName,
93
- _alias: undefined,
94
- _type: joinTypes.full,
95
- _condition: {
96
- _operands: [{_column: {table: tableName, name: 'id'}}, {_column: {table: employeeTableInfo.tableName, name: `personId`}}],
97
- _operator: '='
98
- }
99
- }];
100
-
101
- expect(innerJoin._joins).toStrictEqual(innerJoinExpectation);
102
- expect(leftJoin._joins).toStrictEqual(leftJoinExpectation);
103
- expect(rightJoin._joins).toStrictEqual(rightJoinExpectation);
104
- expect(fullJoin._joins).toStrictEqual(fullJoinExpectation);
105
- });
106
-
107
- it('Joins with alias', () => {
108
- const tableRef = new TableRef(Employee);
109
- const employeeTableInfo = readModelMeta(Employee);
110
-
111
- const enum joinTypes {inner = 'INNER', left = 'LEFT', right = 'RIGHT', full = 'FULL OUTER'}
112
-
113
- const innerJoin = Select(Person).join(Employee, tableRef, ({id}, {personId}) => id.eq(personId));
114
- const leftJoin = Select(Person).joinLeft(Employee, tableRef, ({id}, {personId}) => id.eq(personId));
115
- const rightJoin = Select(Person).joinRight(Employee, tableRef, ({id}, {personId}) => id.eq(personId));
116
- const fullJoin = Select(Person).joinFull(Employee, tableRef, ({id}, {personId}) => id.eq(personId));
117
-
118
- const innerJoinExpectation = [{
119
- _tableName: employeeTableInfo.tableName,
120
- _alias: tableRef.tableName,
121
- _type: joinTypes.inner,
122
- _condition: {
123
- _operands: [{_column: {table: tableName, name: 'id'}}, {_column: {table: tableRef.tableName, name: `personId`}}],
124
- _operator: '='
125
- }
126
- }];
127
- const leftJoinExpectation = [{
128
- _tableName: employeeTableInfo.tableName,
129
- _alias: tableRef.tableName,
130
- _type: joinTypes.left,
131
- _condition: {
132
- _operands: [{_column: {table: tableName, name: 'id'}}, {_column: {table: tableRef.tableName, name: `personId`}}],
133
- _operator: '='
134
- }
135
- }];
136
- const rightJoinExpectation = [{
137
- _tableName: employeeTableInfo.tableName,
138
- _alias: tableRef.tableName,
139
- _type: joinTypes.right,
140
- _condition: {
141
- _operands: [{_column: {table: tableName, name: 'id'}}, {_column: {table: tableRef.tableName, name: `personId`}}],
142
- _operator: '='
143
- }
144
- }];
145
- const fullJoinExpectation = [{
146
- _tableName: employeeTableInfo.tableName,
147
- _alias: tableRef.tableName,
148
- _type: joinTypes.full,
149
- _condition: {
150
- _operands: [{_column: {table: tableName, name: 'id'}}, {_column: {table: tableRef.tableName, name: `personId`}}],
151
- _operator: '='
152
- }
153
- }];
154
-
155
- expect(innerJoin._joins).toStrictEqual(innerJoinExpectation);
156
- expect(leftJoin._joins).toStrictEqual(leftJoinExpectation);
157
- expect(rightJoin._joins).toStrictEqual(rightJoinExpectation);
158
- expect(fullJoin._joins).toStrictEqual(fullJoinExpectation);
159
- });
160
-
161
- it('Where', () => {
162
- const query = Select(Person).where(({age, name}) => and(age.eq(person.age), name.like(person.name)));
163
- const expectation = [{
164
- _operator: 'AND',
165
- _operands: [
166
- {_operator: '=', _operands: [{_column: {table: tableName, name: 'age'}}, person.age]},
167
- {_operator: 'LIKE', _operands: [{_column: {table: tableName, name: 'name'}}, person.name]},
168
- ]
169
- }];
170
- expect(query._where).toStrictEqual(expectation);
171
- });
172
-
173
- describe('Where filter fields', () => {
174
- it ('simple many to many', () => {
175
- const query = Select(Person).where(({profiles}) => profiles.has('test'));
176
- const expectation = [{
177
- _operands: [
178
- "test",
179
- {
180
- _operator: 'SUBQUERY',
181
- _operands: [
182
- {
183
- _columns: [{_column: { table: "employee", name: "title"}}],
184
- _table: { fields: null, tableName: "employee"},
185
- _type: "SELECT",
186
- _where: [
187
- {
188
- _operands: [
189
- { _column: { table: "employee", name: "person"}},
190
- { _column: { table: tableName, name: "id"}}
191
- ],
192
- _operator: "="
193
- }
194
- ],
195
- }
196
- ]},
197
- ],
198
- _operator: "IN",
199
- }];
200
- expect(query._where).toStrictEqual(expectation);
201
- });
202
-
203
- it ('with builder', () => {
204
- const query = Select(Person).where(({tags}) => tags.has('tag'));
205
- const expectation = [{
206
- _operands: [
207
- "tag",
208
- {
209
- _operator: 'SUBQUERY',
210
- _operands: [
211
- {
212
- _columns: [{_column: { table: "Tag", name: "name"}}],
213
- _table: readModelMeta(Tag),
214
- _alias: null,
215
- _type: "SELECT",
216
- _distinct: false,
217
- "_for": undefined,
218
- _joins: [
219
- {
220
- _alias: undefined,
221
- _tableName: "TagPerson",
222
- _type: "INNER",
223
- _condition: {
224
- _operands: [
225
- {
226
- _operands: [
227
- {
228
- _column: {
229
- name: 'id',
230
- table: "Tag",
231
- }
232
- },
233
- {
234
- _column: {
235
- name: 'tag',
236
- table: "TagPerson",
237
- }
238
- }
239
- ],
240
- _operator: '='
241
- },
242
- {
243
- _operands: [
244
- {
245
- _column: {
246
- name: 'person',
247
- table: "TagPerson",
248
- }
249
- },
250
- {
251
- _column: {
252
- name: 'id',
253
- table: "Person",
254
- }
255
- }
256
- ],
257
- _operator: '='
258
- },
259
- ],
260
- _operator: 'AND'
261
- }
262
- }
263
- ]
264
- }
265
- ]},
266
- ],
267
- _operator: "IN",
268
- }];
269
- expect(query._where).toStrictEqual(expectation);
270
- });
271
- });
272
-
273
- it('Having', () => {
274
- const employeeTableName = readModelMeta(Employee).tableName;
275
- const salaryRate = 2000;
276
- const query = Select(Employee)
277
- .columns(({salary}) => [sum(salary)])
278
- .groupBy(['company'])
279
- .having(({salary}) => sum(salary).gt(salaryRate));
280
-
281
- const expectation = {
282
- _columns: [{_func: 'SUM', _args: [{_column: {table: employeeTableName, name: 'salary'}}]}],
283
- _groupBy: [{_column: {table: employeeTableName, name: 'company'}}],
284
- _having: [{
285
- _operator: '>',
286
- _operands: [{
287
- _func: 'SUM',
288
- _args: [{_column: {table: employeeTableName, name: 'salary'}}]
289
- }, salaryRate]
290
- }]
291
- };
292
-
293
- expect(query._columns).toStrictEqual(expectation._columns);
294
- expect(query._groupBy).toStrictEqual(expectation._groupBy);
295
- expect(query._having).toStrictEqual(expectation._having);
296
- });
297
-
298
- it('Group by list', () => {
299
- const queryThroughList = Select(Person).groupBy(['city']);
300
- const expectation = [{_column: {table: tableName, name: 'city'}}];
301
-
302
- expect(queryThroughList._groupBy).toStrictEqual(expectation);
303
- });
304
-
305
- it('Group by builder', () => {
306
- const queryThroughBuilder = Select(Person).groupBy(({city}) => [city]);
307
- const expectation = [{_column: {table: tableName, name: 'city'}}];
308
-
309
- expect(queryThroughBuilder._groupBy).toStrictEqual(expectation);
310
- });
311
-
312
- it('Group by index', () => {
313
- const queryThroughBuilder = Select(Person).groupBy([1]);
314
- const expectation = [{_column: {name: 1}}];
315
-
316
- expect(queryThroughBuilder._groupBy).toStrictEqual(expectation);
317
- });
318
-
319
- it('Order By', () => {
320
- const orderByThroughList = Select(Person).orderBy(['city']);
321
- const defaultOrder = Select(Person).orderBy(({city}) => [city]);
322
- const ascOrder = Select(Person).orderBy(({city}) => [asc(city)]);
323
- const descOrder = Select(Person).orderBy(({city}) => [desc(city)]);
324
- const numberedOrder = Select(Person).orderBy(() => [asc(0), desc(1)]);
325
-
326
- const expectation = {
327
- default: [{_column: {table: tableName, name: 'city'}}],
328
- asc: [{_column: {table: tableName, name: 'city'}, _order: 'ASC', _nulls: undefined}],
329
- desc: [{_column: {table: tableName, name: 'city'}, _order: 'DESC', _nulls: undefined}],
330
- numbered: [{_column: 0, _order: 'ASC', _nulls: undefined}, {_column: 1, _order: 'DESC', _nulls: undefined}],
331
- };
332
-
333
- expect(orderByThroughList._orderBy).toStrictEqual(expectation.default);
334
- expect(defaultOrder._orderBy).toStrictEqual(expectation.default);
335
- expect(ascOrder._orderBy).toStrictEqual(expectation.asc);
336
- expect(descOrder._orderBy).toStrictEqual(expectation.desc);
337
- expect(numberedOrder._orderBy).toStrictEqual(expectation.numbered);
338
- });
339
-
340
- it('Limit', () => {
341
- const limit = 10;
342
- const query = Select(Person).limit(limit);
343
- expect(query._limit).toBe(limit);
344
- });
345
-
346
- it('Offset', () => {
347
- const offset = 3;
348
- const query = Select(Person).offset(offset);
349
- expect(query._offset).toBe(offset);
350
- });
351
-
352
- it('subquery on self', () => {
353
- const query = Select(Person).where(({id}) => exists(Select(alias(Person, 'person_filter')).where(({id: _}) => _.eq(id))));
354
-
355
- const expectation = {
356
- _where: [{
357
- "_operands": [{
358
- "_alias": "person_filter",
359
- "_columns": [
360
- { "_column": { name: 'id', table: 'person_filter' }},
361
- { "_column": { name: 'uid', table: 'person_filter' }},
362
- { "_column": { name: 'name', table: 'person_filter' }},
363
- { "_column": { name: 'age', table: 'person_filter' }},
364
- { "_column": { name: 'city', table: 'person_filter' }},
365
- ],
366
- "_distinct": false,
367
- "_for": undefined,
368
- "_table": Person[TableMetadataSymbol],
369
- "_type": "SELECT",
370
- "_where": [{
371
- "_operands": [{
372
- "_column": { "name": "id", "table": "person_filter", },
373
- }, {
374
- "_column": { "name": "id", "table": "Person", },
375
- }],
376
- "_operator": "=",
377
- }]
378
- }],
379
- "_operator": "EXISTS",
380
- }]
381
- };
382
-
383
- expect(query._where).toStrictEqual(expectation._where);
384
- })
385
-
386
- it ('sum of subqueries', () => {
387
- @dbTable('actions')
388
- class PersonAction {
389
- @dbField public personId!: number;
390
- @dbField public action!: string;
391
- @dbField public created!: Date;
392
- }
393
-
394
- const ts = new Date(Date.now() - 3600);
395
-
396
- const query = Select(Person)
397
- .columns(({uid}) => [
398
- uid,
399
- alias(
400
- Select(PersonAction)
401
- .columns(() => [count()])
402
- .where(({personId, action, created}) => and(
403
- personId.eq(of(Person, 'id')),
404
- action.eq('a'),
405
- created.gte(ts)
406
- ))
407
- .asScalar()
408
- .mul(1).add(
409
- Select(PersonAction)
410
- .columns(() => [count()])
411
- .where(({personId, action, created}) => and(
412
- personId.eq(of(Person, 'id')),
413
- action.eq('b'),
414
- created.gte(ts)
415
- ))
416
- .asScalar().mul(100),
417
- ).add(
418
- Select(PersonAction)
419
- .columns(() => [count()])
420
- .where(({personId, action, created}) => and(
421
- personId.eq(of(Person, 'id')),
422
- action.eq('c'),
423
- created.gte(ts)
424
- ))
425
- .asScalar().mul(100),
426
- ),
427
- 'score'
428
- )
429
- ]).orderBy(() => [desc(of(null, 'score'))])
430
-
431
- const expected = [{"_column": {"table": "Person", "name": "uid"}}, {
432
- "_alias": "score", "_operands": [{
433
- "_operator": "+", "_operands": [{
434
- "_operator": "+",
435
- "_operands": [{
436
- "_operator": "*",
437
- "_operands": [{
438
- "_operator": "SUBQUERY",
439
- "_operands": [{
440
- "_type": "SELECT",
441
- "_table": PersonAction[TableMetadataSymbol],
442
- "_alias": null,
443
- "_distinct": false,
444
- "_for": undefined,
445
- "_columns": [{"_func": "COUNT", "_args": ["*"]}],
446
- "_where": [{
447
- "_operator": "AND",
448
- "_operands": [{
449
- "_operator": "=",
450
- "_operands": [{"_column": {"table": "actions", "name": "personId"}}, {
451
- "_column": {
452
- "table": "Person",
453
- "name": "id"
454
- }
455
- }]
456
- }, {
457
- "_operator": "=",
458
- "_operands": [{"_column": {"table": "actions", "name": "action"}}, "a"]
459
- }, {
460
- "_operator": ">=",
461
- "_operands": [{"_column": {"table": "actions", "name": "created"}}, ts]
462
- }]
463
- }]
464
- }]
465
- }, 1]
466
- }, {
467
- "_operator": "*",
468
- "_operands": [{
469
- "_operator": "SUBQUERY",
470
- "_operands": [{
471
- "_type": "SELECT",
472
- "_table": PersonAction[TableMetadataSymbol],
473
- "_alias": null,
474
- "_distinct": false,
475
- "_for": undefined,
476
- "_columns": [{"_func": "COUNT", "_args": ["*"]}],
477
- "_where": [{
478
- "_operator": "AND",
479
- "_operands": [{
480
- "_operator": "=",
481
- "_operands": [{"_column": {"table": "actions", "name": "personId"}}, {
482
- "_column": {
483
- "table": "Person",
484
- "name": "id"
485
- }
486
- }]
487
- }, {
488
- "_operator": "=",
489
- "_operands": [{"_column": {"table": "actions", "name": "action"}}, "b"]
490
- }, {
491
- "_operator": ">=",
492
- "_operands": [{"_column": {"table": "actions", "name": "created"}}, ts]
493
- }]
494
- }]
495
- }]
496
- }, 100]
497
- }]
498
- }, {
499
- "_operator": "*",
500
- "_operands": [{
501
- "_operator": "SUBQUERY",
502
- "_operands": [{
503
- "_type": "SELECT",
504
- "_table": PersonAction[TableMetadataSymbol],
505
- "_alias": null,
506
- "_distinct": false,
507
- "_for": undefined,
508
- "_columns": [{"_func": "COUNT", "_args": ["*"]}],
509
- "_where": [{
510
- "_operator": "AND",
511
- "_operands": [{
512
- "_operator": "=",
513
- "_operands": [{"_column": {"table": "actions", "name": "personId"}}, {
514
- "_column": {
515
- "table": "Person",
516
- "name": "id"
517
- }
518
- }]
519
- }, {
520
- "_operator": "=",
521
- "_operands": [{"_column": {"table": "actions", "name": "action"}}, "c"]
522
- }, {
523
- "_operator": ">=",
524
- "_operands": [{"_column": {"table": "actions", "name": "created"}}, ts]
525
- }]
526
- }]
527
- }]
528
- }, 100]
529
- }]
530
- }]
531
- }];
532
-
533
- expect(query._columns).toStrictEqual(expected);
534
-
535
- expect(query._orderBy).toStrictEqual([{
536
- _column: {
537
- name: 'score',
538
- },
539
- _order: "DESC",
540
- _nulls: undefined
541
- }]);
542
- })
543
-
544
- it ('invalid sub queries', () => {
545
- try {
546
- Select(Person).columns(['age', 'uid']).asScalar();
547
- fail('expected to throw');
548
- } catch (e) {
549
- // ignore
550
- }
551
- });
552
-
553
- it ('union operator', () => {
554
- const query = Select(Person)
555
- .columns(['name'])
556
- .union(true, Select(Person)
557
- .columns(['name'])
558
- .where(x => x.age.lt(18))
559
- )
560
- .where(x => x.age.gte(18))
561
- .orderBy(['name']);
562
-
563
- expect(query._operators).toStrictEqual([{
564
- _operator: 'UNION',
565
- _distinct: true,
566
- _operand: {
567
- "_type": "SELECT",
568
- "_table": Person[TableMetadataSymbol],
569
- "_alias": null,
570
- "_distinct": false,
571
- "_for": undefined,
572
- "_columns": [{"_column": {"table": "Person", "name": "name"}}],
573
- "_where": [{
574
- "_operator": "<",
575
- "_operands": [
576
- {"_column": {"table": "Person", "name": "age"}},
577
- 18
578
- ]
579
- }]
580
- }
581
- }])
582
- })
583
-
584
- it('CASE operator', () => {
585
- const query = Select(Person)
586
- .columns(x => [alias(case_({when: x.age.gte(2), then: 'yes'}, {else: 'no'}), 'dynamic')])
587
-
588
- expect(query._columns).toStrictEqual([{
589
- "_alias": "dynamic",
590
- "_operands": [{
591
- "_operator": "CASE",
592
- "_operands": [
593
- {
594
- "when": {
595
- "_operator": ">=",
596
- "_operands": [
597
- { "_column": {"name": "age", "table": "Person"}},
598
- 2
599
- ]
600
- },
601
- "then": "yes",
602
- },
603
- {"else": "no"}
604
- ]
605
- }]
606
- }])
607
- })
608
-
609
- it ('intersect operator', () => {
610
- const query = Select(Person)
611
- .columns(['name'])
612
- .intersect(Select(Person)
613
- .columns(['name'])
614
- .where(x => x.age.lt(18))
615
- )
616
- .where(x => x.age.gte(18))
617
- .orderBy(['name']);
618
-
619
- expect(query._operators).toStrictEqual([{
620
- _operator: 'INTERSECT',
621
- _distinct: false,
622
- _operand: {
623
- "_type": "SELECT",
624
- "_table": Person[TableMetadataSymbol],
625
- "_alias": null,
626
- "_distinct": false,
627
- "_for": undefined,
628
- "_columns": [{"_column": {"table": "Person", "name": "name"}}],
629
- "_where": [{
630
- "_operator": "<",
631
- "_operands": [
632
- {"_column": {"table": "Person", "name": "age"}},
633
- 18
634
- ]
635
- }]
636
- }
637
- }])
638
- })
639
-
640
- it ('except operator', () => {
641
- const query = Select(Person)
642
- .columns(['name'])
643
- .except(Select(Person)
644
- .columns(['name'])
645
- .where(x => x.age.lt(18))
646
- )
647
- .where(x => x.age.gte(18))
648
- .orderBy(['name']);
649
-
650
- expect(query._operators).toStrictEqual([{
651
- _operator: 'EXCEPT',
652
- _distinct: false,
653
- _operand: {
654
- "_type": "SELECT",
655
- "_table": Person[TableMetadataSymbol],
656
- "_alias": null,
657
- "_distinct": false,
658
- "_for": undefined,
659
- "_columns": [{"_column": {"table": "Person", "name": "name"}}],
660
- "_where": [{
661
- "_operator": "<",
662
- "_operands": [
663
- {"_column": {"table": "Person", "name": "age"}},
664
- 18
665
- ]
666
- }]
667
- }
668
- }])
669
- })
670
-
671
- it('COUNT unique', () => {
672
- const query = Select(Person)
673
- .columns(x => [count(x.id, true)]);
674
-
675
- expect(query._columns).toStrictEqual([{
676
- _func: "COUNT",
677
- _args: [
678
- "DISTINCT",
679
- {
680
- _column: {
681
- name: 'id',
682
- table: 'Person'
683
- }
684
- }
685
- ]
686
- }])
687
- });
688
-
689
- it('SELECT over subquery', () => {
690
- const query = Select(
691
- Select(Person)
692
- .columns(x => [count(x.id)])
693
- .groupBy(x => [x.age])
694
- )
695
- .columns(() => [count(undefined, true)]);
696
-
697
- expect(query).toStrictEqual({
698
- "_alias": "Person_SUBQUERY",
699
- _columns: [{
700
- _func: "COUNT",
701
- _args: [
702
- "DISTINCT",
703
- '*'
704
- ]
705
- }],
706
- "_distinct": false,
707
- "_for": undefined,
708
- "_table": {
709
- "_alias": null,
710
- "_columns": [{
711
- "_func": "COUNT",
712
- "_args": [{
713
- "_column": {
714
- "name": "id",
715
- "table": "Person",
716
- }
717
- }]
718
- }],
719
- "_distinct": false,
720
- "_for": undefined,
721
- "_groupBy": [{
722
- "_column": {
723
- "name": "age",
724
- "table": "Person",
725
- }
726
- }],
727
- "_table": Person[TableMetadataSymbol],
728
- "_type": "SELECT",
729
- "fields": new Map,
730
- "tableName": "Person_SUBQUERY",
731
- },
732
- "_type": "SELECT",
733
- })
734
- });
735
-
736
- // it('Select with lookup field', () => {
737
- // const np = new NamedParameter('keyNP')
738
- // @dbTable('other_table')
739
- // class SubModel {
740
- // @dbField({primaryKey: true})
741
- // id!: number;
742
- // @dbField
743
- // key!: number;
744
- // @dbField
745
- // value!: Date;
746
- // }
747
- // @dbTable('person')
748
- // class Person {
749
- // @dbField({primaryKey: true})
750
- // id!: number;
751
- // @dbField
752
- // value!: string;
753
- // @dbLookupField<Person, SubModel>({
754
- // model: Date,
755
- // nullable: true,
756
- // source: 'value',
757
- // relation: SubModel,
758
- // where(prime, other) {
759
- // return and(
760
- // prime.id.eq(other.id),
761
- // other.key.eq(np)
762
- // )
763
- // }
764
- // })
765
- // lastAccess!: Date | null
766
- // }
767
- //
768
- // const query = Select(Person)
769
- // .where(x => x.lastAccess.neq(null));
770
- //
771
- // expect(query).toStrictEqual({
772
- // "_alias": null,
773
- // "_type": "SELECT",
774
- // })
775
- // })
776
-
777
- it('SELECT with WINDOW', () => {
778
- const win1 = new Window(Person)
779
- .partitionBy(['id'])
780
- .orderBy(['id']);
781
-
782
- const win2 = new Window(Person, win1)
783
- .partitionBy(['id'])
784
- .orderBy(['id'])
785
- .groups()
786
- .start(5, 'PRECEDING')
787
- .end(5, 'FOLLOWING')
788
- .exclusion('CURRENT ROW');
789
-
790
- const query = Select(Person)
791
- .columns(x => [
792
- x.id,
793
- alias(first_value(x.name, win2 as never, x.city.like('test%')), 'first_value_of_name'),
794
- ]);
795
-
796
- expect(query).toStrictEqual({
797
- "_alias": null,
798
- _columns: [
799
- { _column: {name: 'id', table: "Person"} },
800
- {
801
- _alias: 'first_value_of_name',
802
- _operands: [
803
- {
804
- _func: "first_value",
805
- _args: [
806
- { _column: {name: 'name', table: "Person"} },
807
- ],
808
- _filter: {
809
- _operands: [
810
- { _column: {name: 'city', table: "Person"} },
811
- "test%",
812
- ],
813
- _operator: "LIKE",
814
- },
815
- _over: {
816
- _extends: {
817
- _extends: undefined,
818
- _mode: undefined,
819
- _start: undefined,
820
- _end: undefined,
821
- _exclusion: undefined,
822
- _groupBy: [
823
- { _column: {name: 'id', table: "Person"} },
824
- ],
825
- _orderBy: [
826
- { _column: {name: 'id', table: "Person"} },
827
- ],
828
- },
829
- _mode: "GROUPS",
830
- _start: "5 PRECEDING",
831
- _end: "5 FOLLOWING",
832
- _exclusion: "CURRENT ROW",
833
- _groupBy: [
834
- { _column: {name: 'id', table: "Person"} },
835
- ],
836
- _orderBy: [
837
- { _column: {name: 'id', table: "Person"} },
838
- ],
839
- },
840
- }
841
- ]
842
- }
843
- ],
844
- "_distinct": false,
845
- "_for": undefined,
846
- "_table": Person[TableMetadataSymbol],
847
- "_type": "SELECT",
848
- });
849
- })
850
- });
851
-
852
- describe('Insert', () => {
853
-
854
- it('Check query info', () => {
855
- const query = Insert(Person);
856
- expect(query._type).toBe('INSERT');
857
- expect(query._table).toStrictEqual(tableInfo);
858
- });
859
-
860
- it('Insert record', () => {
861
- const query = Insert(Person).values(person);
862
- const expectation = {
863
- id: person.id,
864
- name: person.name,
865
- age: person.age,
866
- city: person.city,
867
- };
868
- expect(query._values).toStrictEqual(expectation);
869
- });
870
-
871
- it('Insert record with cast', () => {
872
- const query = Insert(Person).values({...person, city: cast(person.city, 'text')});
873
- const expectation = {
874
- id: person.id,
875
- name: person.name,
876
- age: person.age,
877
- city: {
878
- _operator: 'CAST',
879
- _operands: [ person.city, 'text']
880
- },
881
- };
882
- expect(query._values).toStrictEqual(expectation);
883
- });
884
-
885
- it('Insert record with function', () => {
886
- function test<T>(value: IOperandable<T> | T): IOperandable<T> {
887
- return new FunctionCall('TEST', [value]) as IOperandable<T>
888
- }
889
-
890
- const query = Insert(Person).values({...person, city: test(person.city)});
891
- const expectation = {
892
- id: person.id,
893
- name: person.name,
894
- age: person.age,
895
- city: {
896
- _func: 'TEST',
897
- _args: [ person.city]
898
- },
899
- };
900
- expect(query._values).toStrictEqual(expectation);
901
- });
902
- });
903
-
904
- describe('Upsert', () => {
905
-
906
- const infoMock = {
907
- [TableMetadataSymbol]: {}
908
- };
909
-
910
- it('Check query info', () => {
911
- const query = Upsert(Person);
912
- expect(query._type).toBe('UPSERT');
913
- expect(query._table).toStrictEqual(tableInfo);
914
- });
915
-
916
- it('Upsert record', () => {
917
- const defaultUpsert = Upsert(Person).values(person);
918
- const withConflict = Upsert(Person).values(person).conflict('idx');
919
- const expectation = {
920
- values: {
921
- id: person.id,
922
- name: person.name,
923
- age: person.age,
924
- city: person.city,
925
- },
926
- conflictExp: {_columns: ['id'], _where: undefined}
927
- };
928
-
929
- expect(defaultUpsert._values).toStrictEqual(expectation.values);
930
- expect(defaultUpsert._conflictExp).toBeUndefined();
931
- expect(withConflict._values).toStrictEqual(expectation.values);
932
- expect(withConflict._conflictExp).toStrictEqual(expectation.conflictExp);
933
- });
934
-
935
- it('Should fail if table has no primary key', () => {
936
- expect(() => {
937
- Upsert(infoMock as any).conflict();
938
- }).toThrowError('Current table has no primary key. Please provide unique index for upsert');
939
- });
940
-
941
- it('Should fail if table indexes meta is empty', () => {
942
- expect(() => {
943
- Upsert(infoMock as any).conflict('id');
944
- }).toThrowError('Table indexes meta is empty');
945
- });
946
-
947
- it('Should fail if index is not declared', () => {
948
- expect(() => {
949
- Upsert(Person).conflict('name');
950
- }).toThrowError(`Index name is not declared for table ${tableName}`);
951
- });
952
- });
953
-
954
- describe('Update', () => {
955
-
956
- it('Check query info', () => {
957
- const query = Update(Person);
958
- expect(query._type).toBe('UPDATE');
959
- expect(query._table).toStrictEqual(tableInfo);
960
- });
961
-
962
- it('Update record', () => {
963
- const limit = 10;
964
- const query = Update(Person).values(person).where(({id}) => id.eq(person.id)).limit(limit);
965
- const expectation = {
966
- values: {
967
- id: person.id,
968
- name: person.name,
969
- age: person.age,
970
- city: person.city,
971
- },
972
- where: [{
973
- _operator: '=',
974
- _operands: [{_column: {table: tableName, name: 'id'}}, person.id]
975
- }]
976
- };
977
- expect(query._values).toStrictEqual(expectation.values);
978
- expect(query._where).toStrictEqual(expectation.where);
979
- expect(query._limit).toBe(limit);
980
- });
981
-
982
- it('Update record with updater and cast', () => {
983
- const limit = 10;
984
- const query = Update(Person)
985
- .values(x => ({...person, city: cast(x.city, 'email')}))
986
- .limit(limit);
987
- const expectation = {
988
- values: {
989
- id: person.id,
990
- name: person.name,
991
- age: person.age,
992
- city: {
993
- _operator: 'CAST',
994
- _operands: [
995
- { _column: { name: 'city', table: 'Person' } },
996
- 'email'
997
- ]
998
- },
999
- }
1000
- };
1001
- expect(query._values).toStrictEqual(expectation.values);
1002
- expect(query._limit).toBe(limit);
1003
- });
1004
-
1005
- it('Update record with values with kinds', () => {
1006
- const limit = 10;
1007
- const email = 'Some@EXAMPLE.org';
1008
- const query = Update(MailingList)
1009
- .values({name: 'test', email}) //cast('some@example.org', 'email')})
1010
- .limit(limit);
1011
- const expectation = {
1012
- values: {
1013
- name: 'test',
1014
- email: {
1015
- _operator: 'CAST',
1016
- _operands: [
1017
- {_value: email.toLowerCase()},
1018
- 'Email'
1019
- ]
1020
- },
1021
- }
1022
- };
1023
- expect(query._values).toStrictEqual(expectation.values);
1024
- expect(query._limit).toBe(limit);
1025
- });
1026
-
1027
- it('Update record with updater with kinds', () => {
1028
- const limit = 10;
1029
- const email = 'Some@EXAMPLE.org';
1030
- const query = Update(MailingList)
1031
- .values(() => ({name: 'test', email}))
1032
- .limit(limit);
1033
- const expectation = {
1034
- values: {
1035
- name: 'test',
1036
- email: {
1037
- _operator: 'CAST',
1038
- _operands: [
1039
- {_value: email.toLowerCase()},
1040
- 'Email'
1041
- ]
1042
- },
1043
- }
1044
- };
1045
- expect(query._values).toStrictEqual(expectation.values);
1046
- expect(query._limit).toBe(limit);
1047
- });
1048
- });
1049
-
1050
- describe('Delete', () => {
1051
-
1052
- it('Check query info', () => {
1053
- const query = Delete(Person);
1054
- expect(query._type).toBe('DELETE');
1055
- expect(query._table).toStrictEqual(tableInfo);
1056
- });
1057
-
1058
- it('Delete record', () => {
1059
- const limit = 10;
1060
- const query = Delete(Person).where(({id}) => id.eq(person.id)).limit(limit);
1061
- const expectation = [{
1062
- _operator: '=',
1063
- _operands: [{_column: {table: tableName, name: 'id'}}, person.id]
1064
- }];
1065
- expect(query._where).toStrictEqual(expectation);
1066
- expect(query._limit).toBe(limit);
1067
- });
1068
- });