@simplysm/orm-common 13.0.75 → 13.0.77
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.
- package/README.md +575 -50
- package/dist/create-db-context.d.ts +1 -1
- package/dist/create-db-context.d.ts.map +1 -1
- package/dist/create-db-context.js +34 -27
- package/dist/create-db-context.js.map +1 -1
- package/dist/ddl/initialize.js +4 -4
- package/dist/ddl/initialize.js.map +1 -1
- package/dist/ddl/relation-ddl.d.ts +7 -7
- package/dist/ddl/relation-ddl.d.ts.map +1 -1
- package/dist/ddl/relation-ddl.js +18 -18
- package/dist/ddl/relation-ddl.js.map +1 -1
- package/dist/ddl/schema-ddl.d.ts +1 -1
- package/dist/ddl/schema-ddl.d.ts.map +1 -1
- package/dist/ddl/schema-ddl.js +2 -2
- package/dist/ddl/schema-ddl.js.map +1 -1
- package/dist/ddl/table-ddl.js +2 -2
- package/dist/ddl/table-ddl.js.map +1 -1
- package/dist/exec/queryable.d.ts +24 -24
- package/dist/exec/queryable.d.ts.map +1 -1
- package/dist/exec/queryable.js +37 -37
- package/dist/exec/queryable.js.map +1 -1
- package/dist/expr/expr-unit.js +1 -1
- package/dist/expr/expr-unit.js.map +1 -1
- package/dist/expr/expr.d.ts +9 -9
- package/dist/expr/expr.d.ts.map +1 -1
- package/dist/expr/expr.js +10 -10
- package/dist/expr/expr.js.map +1 -1
- package/dist/query-builder/base/expr-renderer-base.d.ts +2 -2
- package/dist/query-builder/base/expr-renderer-base.d.ts.map +1 -1
- package/dist/query-builder/base/query-builder-base.d.ts +7 -15
- package/dist/query-builder/base/query-builder-base.d.ts.map +1 -1
- package/dist/query-builder/base/query-builder-base.js +2 -2
- package/dist/query-builder/base/query-builder-base.js.map +1 -1
- package/dist/query-builder/mssql/mssql-expr-renderer.d.ts +4 -4
- package/dist/query-builder/mssql/mssql-expr-renderer.d.ts.map +1 -1
- package/dist/query-builder/mssql/mssql-expr-renderer.js +8 -8
- package/dist/query-builder/mssql/mssql-expr-renderer.js.map +1 -1
- package/dist/query-builder/mssql/mssql-query-builder.d.ts +7 -7
- package/dist/query-builder/mssql/mssql-query-builder.d.ts.map +1 -1
- package/dist/query-builder/mssql/mssql-query-builder.js +7 -7
- package/dist/query-builder/mssql/mssql-query-builder.js.map +1 -1
- package/dist/query-builder/mysql/mysql-expr-renderer.d.ts +4 -4
- package/dist/query-builder/mysql/mysql-expr-renderer.d.ts.map +1 -1
- package/dist/query-builder/mysql/mysql-expr-renderer.js +9 -9
- package/dist/query-builder/mysql/mysql-expr-renderer.js.map +1 -1
- package/dist/query-builder/mysql/mysql-query-builder.d.ts +7 -7
- package/dist/query-builder/mysql/mysql-query-builder.d.ts.map +1 -1
- package/dist/query-builder/mysql/mysql-query-builder.js +11 -11
- package/dist/query-builder/mysql/mysql-query-builder.js.map +1 -1
- package/dist/query-builder/postgresql/postgresql-expr-renderer.d.ts +4 -4
- package/dist/query-builder/postgresql/postgresql-expr-renderer.d.ts.map +1 -1
- package/dist/query-builder/postgresql/postgresql-expr-renderer.js +8 -8
- package/dist/query-builder/postgresql/postgresql-expr-renderer.js.map +1 -1
- package/dist/query-builder/postgresql/postgresql-query-builder.d.ts +7 -7
- package/dist/query-builder/postgresql/postgresql-query-builder.d.ts.map +1 -1
- package/dist/query-builder/postgresql/postgresql-query-builder.js +7 -7
- package/dist/query-builder/postgresql/postgresql-query-builder.js.map +1 -1
- package/dist/schema/procedure-builder.d.ts +1 -1
- package/dist/schema/table-builder.d.ts +1 -1
- package/dist/schema/table-builder.d.ts.map +1 -1
- package/dist/schema/table-builder.js +1 -1
- package/dist/schema/view-builder.d.ts +1 -1
- package/dist/schema/view-builder.d.ts.map +1 -1
- package/dist/schema/view-builder.js +1 -1
- package/dist/types/db-context-def.d.ts +18 -18
- package/dist/types/db-context-def.d.ts.map +1 -1
- package/dist/types/expr.d.ts +6 -6
- package/dist/types/expr.d.ts.map +1 -1
- package/dist/types/query-def.d.ts +15 -15
- package/dist/types/query-def.d.ts.map +1 -1
- package/dist/types/query-def.js +6 -6
- package/dist/utils/result-parser.d.ts.map +1 -1
- package/dist/utils/result-parser.js +44 -16
- package/dist/utils/result-parser.js.map +1 -1
- package/package.json +2 -2
- package/src/create-db-context.ts +36 -29
- package/src/ddl/initialize.ts +4 -4
- package/src/ddl/relation-ddl.ts +16 -16
- package/src/ddl/schema-ddl.ts +2 -2
- package/src/ddl/table-ddl.ts +2 -2
- package/src/exec/queryable.ts +58 -58
- package/src/expr/expr-unit.ts +1 -1
- package/src/expr/expr.ts +13 -13
- package/src/query-builder/base/expr-renderer-base.ts +2 -2
- package/src/query-builder/base/query-builder-base.ts +18 -14
- package/src/query-builder/mssql/mssql-expr-renderer.ts +11 -10
- package/src/query-builder/mssql/mssql-query-builder.ts +13 -13
- package/src/query-builder/mysql/mysql-expr-renderer.ts +12 -11
- package/src/query-builder/mysql/mysql-query-builder.ts +17 -17
- package/src/query-builder/postgresql/postgresql-expr-renderer.ts +11 -10
- package/src/query-builder/postgresql/postgresql-query-builder.ts +13 -13
- package/src/schema/procedure-builder.ts +1 -1
- package/src/schema/table-builder.ts +1 -1
- package/src/schema/view-builder.ts +1 -1
- package/src/types/db-context-def.ts +18 -18
- package/src/types/expr.ts +6 -6
- package/src/types/query-def.ts +31 -31
- package/src/utils/result-parser.ts +60 -16
- package/tests/db-context/create-db-context.spec.ts +6 -37
- package/tests/db-context/define-db-context.spec.ts +0 -51
- package/tests/ddl/basic.expected.ts +8 -8
- package/tests/ddl/basic.spec.ts +24 -181
- package/tests/ddl/column-builder.spec.ts +0 -112
- package/tests/ddl/index-builder.spec.ts +10 -64
- package/tests/ddl/procedure-builder.spec.ts +0 -106
- package/tests/ddl/relation-builder.spec.ts +4 -205
- package/tests/ddl/table-builder.spec.ts +0 -34
- package/tests/ddl/view-builder.spec.ts +0 -60
- package/tests/dml/delete.spec.ts +0 -33
- package/tests/dml/insert.spec.ts +0 -78
- package/tests/dml/update.spec.ts +2 -98
- package/tests/dml/upsert.spec.ts +0 -52
- package/tests/errors/queryable-errors.spec.ts +0 -51
- package/tests/escape.spec.ts +0 -41
- package/tests/examples/pivot.spec.ts +0 -333
- package/tests/examples/sampling.spec.ts +0 -63
- package/tests/examples/unpivot.spec.ts +0 -65
- package/tests/exec/search-parser.spec.ts +0 -16
- package/tests/expr/comparison.spec.ts +0 -66
- package/tests/expr/conditional.expected.ts +2 -2
- package/tests/expr/conditional.spec.ts +8 -35
- package/tests/expr/date.spec.ts +5 -72
- package/tests/expr/math.spec.ts +0 -47
- package/tests/expr/string.spec.ts +0 -56
- package/tests/expr/utility.spec.ts +0 -27
- package/tests/select/basic.spec.ts +5 -74
- package/tests/select/filter.spec.ts +0 -114
- package/tests/select/group.spec.ts +0 -85
- package/tests/select/join.spec.ts +0 -113
- package/tests/select/order.spec.ts +0 -49
- package/tests/select/subquery.spec.ts +0 -96
- package/tests/select/window.spec.ts +0 -185
- package/tests/types/nullable-queryable-record.spec.ts +0 -48
- package/tests/utils/result-parser-perf.spec.ts +0 -67
- package/tests/utils/result-parser.spec.ts +4 -38
|
@@ -279,64 +279,6 @@ describe("SELECT - UNION", () => {
|
|
|
279
279
|
});
|
|
280
280
|
});
|
|
281
281
|
|
|
282
|
-
describe("3 or more", () => {
|
|
283
|
-
const db = createTestDb();
|
|
284
|
-
const qr1 = db.user().where((item) => [expr.eq(item.age, 20)]);
|
|
285
|
-
const qr2 = db.user().where((item) => [expr.eq(item.age, 30)]);
|
|
286
|
-
const qr3 = db.user().where((item) => [expr.eq(item.age, 40)]);
|
|
287
|
-
const def = Queryable.union(qr1, qr2, qr3).getSelectQueryDef();
|
|
288
|
-
|
|
289
|
-
it("Verify QueryDef", () => {
|
|
290
|
-
expect(def).toEqual({
|
|
291
|
-
type: "select",
|
|
292
|
-
as: "T4",
|
|
293
|
-
from: [
|
|
294
|
-
{
|
|
295
|
-
type: "select",
|
|
296
|
-
as: "T1",
|
|
297
|
-
from: { database: "TestDb", schema: "TestSchema", name: "User" },
|
|
298
|
-
where: [
|
|
299
|
-
{
|
|
300
|
-
type: "eq",
|
|
301
|
-
source: { type: "column", path: ["T1", "age"] },
|
|
302
|
-
target: { type: "value", value: 20 },
|
|
303
|
-
},
|
|
304
|
-
],
|
|
305
|
-
},
|
|
306
|
-
{
|
|
307
|
-
type: "select",
|
|
308
|
-
as: "T2",
|
|
309
|
-
from: { database: "TestDb", schema: "TestSchema", name: "User" },
|
|
310
|
-
where: [
|
|
311
|
-
{
|
|
312
|
-
type: "eq",
|
|
313
|
-
source: { type: "column", path: ["T2", "age"] },
|
|
314
|
-
target: { type: "value", value: 30 },
|
|
315
|
-
},
|
|
316
|
-
],
|
|
317
|
-
},
|
|
318
|
-
{
|
|
319
|
-
type: "select",
|
|
320
|
-
as: "T3",
|
|
321
|
-
from: { database: "TestDb", schema: "TestSchema", name: "User" },
|
|
322
|
-
where: [
|
|
323
|
-
{
|
|
324
|
-
type: "eq",
|
|
325
|
-
source: { type: "column", path: ["T3", "age"] },
|
|
326
|
-
target: { type: "value", value: 40 },
|
|
327
|
-
},
|
|
328
|
-
],
|
|
329
|
-
},
|
|
330
|
-
],
|
|
331
|
-
});
|
|
332
|
-
});
|
|
333
|
-
|
|
334
|
-
it.each(dialects)("[%s] Verify SQL", (dialect) => {
|
|
335
|
-
const builder = createQueryBuilder(dialect);
|
|
336
|
-
expect(builder.build(def)).toMatchSql(expected.unionThree[dialect]);
|
|
337
|
-
});
|
|
338
|
-
});
|
|
339
|
-
|
|
340
282
|
describe("UNION -> WHERE (apply to each query)", () => {
|
|
341
283
|
const db = createTestDb();
|
|
342
284
|
const qr1 = db.user();
|
|
@@ -439,44 +381,6 @@ describe("SELECT - UNION", () => {
|
|
|
439
381
|
});
|
|
440
382
|
});
|
|
441
383
|
|
|
442
|
-
describe("UNION -> SELECT", () => {
|
|
443
|
-
const db = createTestDb();
|
|
444
|
-
const qr1 = db.user().select((item) => ({ id: item.id, name: item.name }));
|
|
445
|
-
const qr2 = db.user().select((item) => ({ id: item.id, name: item.name }));
|
|
446
|
-
const def = Queryable.union(qr1, qr2).getSelectQueryDef();
|
|
447
|
-
|
|
448
|
-
it("Verify QueryDef", () => {
|
|
449
|
-
expect(def).toEqual({
|
|
450
|
-
type: "select",
|
|
451
|
-
as: "T3",
|
|
452
|
-
from: [
|
|
453
|
-
{
|
|
454
|
-
type: "select",
|
|
455
|
-
as: "T1",
|
|
456
|
-
from: { database: "TestDb", schema: "TestSchema", name: "User" },
|
|
457
|
-
select: {
|
|
458
|
-
id: { type: "column", path: ["T1", "id"] },
|
|
459
|
-
name: { type: "column", path: ["T1", "name"] },
|
|
460
|
-
},
|
|
461
|
-
},
|
|
462
|
-
{
|
|
463
|
-
type: "select",
|
|
464
|
-
as: "T2",
|
|
465
|
-
from: { database: "TestDb", schema: "TestSchema", name: "User" },
|
|
466
|
-
select: {
|
|
467
|
-
id: { type: "column", path: ["T2", "id"] },
|
|
468
|
-
name: { type: "column", path: ["T2", "name"] },
|
|
469
|
-
},
|
|
470
|
-
},
|
|
471
|
-
],
|
|
472
|
-
});
|
|
473
|
-
});
|
|
474
|
-
|
|
475
|
-
it.each(dialects)("[%s] Verify SQL", (dialect) => {
|
|
476
|
-
const builder = createQueryBuilder(dialect);
|
|
477
|
-
expect(builder.build(def)).toMatchSql(expected.unionThenSelect[dialect]);
|
|
478
|
-
});
|
|
479
|
-
});
|
|
480
384
|
});
|
|
481
385
|
|
|
482
386
|
//#region ========== SCALAR SUBQUERY ==========
|
|
@@ -57,25 +57,6 @@ describe("SELECT - Window Functions", () => {
|
|
|
57
57
|
}))
|
|
58
58
|
.getSelectQueryDef();
|
|
59
59
|
|
|
60
|
-
it("Verify QueryDef", () => {
|
|
61
|
-
expect(def).toEqual({
|
|
62
|
-
type: "select",
|
|
63
|
-
as: "T1",
|
|
64
|
-
from: { database: "TestDb", schema: "TestSchema", name: "Employee" },
|
|
65
|
-
select: {
|
|
66
|
-
id: { type: "column", path: ["T1", "id"] },
|
|
67
|
-
name: { type: "column", path: ["T1", "name"] },
|
|
68
|
-
rank: {
|
|
69
|
-
type: "window",
|
|
70
|
-
fn: { type: "rank" },
|
|
71
|
-
spec: {
|
|
72
|
-
orderBy: [[{ type: "column", path: ["T1", "id"] }, "DESC"]],
|
|
73
|
-
},
|
|
74
|
-
},
|
|
75
|
-
},
|
|
76
|
-
});
|
|
77
|
-
});
|
|
78
|
-
|
|
79
60
|
it.each(dialects)("[%s] Verify SQL", (dialect) => {
|
|
80
61
|
const builder = createQueryBuilder(dialect);
|
|
81
62
|
expect(builder.build(def)).toMatchSql(expected.rank[dialect]);
|
|
@@ -92,24 +73,6 @@ describe("SELECT - Window Functions", () => {
|
|
|
92
73
|
}))
|
|
93
74
|
.getSelectQueryDef();
|
|
94
75
|
|
|
95
|
-
it("Verify QueryDef", () => {
|
|
96
|
-
expect(def).toEqual({
|
|
97
|
-
type: "select",
|
|
98
|
-
as: "T1",
|
|
99
|
-
from: { database: "TestDb", schema: "TestSchema", name: "Employee" },
|
|
100
|
-
select: {
|
|
101
|
-
id: { type: "column", path: ["T1", "id"] },
|
|
102
|
-
denseRank: {
|
|
103
|
-
type: "window",
|
|
104
|
-
fn: { type: "denseRank" },
|
|
105
|
-
spec: {
|
|
106
|
-
orderBy: [[{ type: "column", path: ["T1", "id"] }, "DESC"]],
|
|
107
|
-
},
|
|
108
|
-
},
|
|
109
|
-
},
|
|
110
|
-
});
|
|
111
|
-
});
|
|
112
|
-
|
|
113
76
|
it.each(dialects)("[%s] Verify SQL", (dialect) => {
|
|
114
77
|
const builder = createQueryBuilder(dialect);
|
|
115
78
|
expect(builder.build(def)).toMatchSql(expected.denseRank[dialect]);
|
|
@@ -205,28 +168,6 @@ describe("SELECT - Window Functions", () => {
|
|
|
205
168
|
}))
|
|
206
169
|
.getSelectQueryDef();
|
|
207
170
|
|
|
208
|
-
it("Verify QueryDef", () => {
|
|
209
|
-
expect(def).toEqual({
|
|
210
|
-
type: "select",
|
|
211
|
-
as: "T1",
|
|
212
|
-
from: { database: "TestDb", schema: "TestSchema", name: "Employee" },
|
|
213
|
-
select: {
|
|
214
|
-
id: { type: "column", path: ["T1", "id"] },
|
|
215
|
-
nextId: {
|
|
216
|
-
type: "window",
|
|
217
|
-
fn: {
|
|
218
|
-
type: "lead",
|
|
219
|
-
column: { type: "column", path: ["T1", "id"] },
|
|
220
|
-
offset: 1,
|
|
221
|
-
},
|
|
222
|
-
spec: {
|
|
223
|
-
orderBy: [[{ type: "column", path: ["T1", "id"] }, "ASC"]],
|
|
224
|
-
},
|
|
225
|
-
},
|
|
226
|
-
},
|
|
227
|
-
});
|
|
228
|
-
});
|
|
229
|
-
|
|
230
171
|
it.each(dialects)("[%s] Verify SQL", (dialect) => {
|
|
231
172
|
const builder = createQueryBuilder(dialect);
|
|
232
173
|
expect(builder.build(def)).toMatchSql(expected.lead[dialect]);
|
|
@@ -282,29 +223,6 @@ describe("SELECT - Window Functions", () => {
|
|
|
282
223
|
}))
|
|
283
224
|
.getSelectQueryDef();
|
|
284
225
|
|
|
285
|
-
it("Verify QueryDef", () => {
|
|
286
|
-
expect(def).toEqual({
|
|
287
|
-
type: "select",
|
|
288
|
-
as: "T1",
|
|
289
|
-
from: { database: "TestDb", schema: "TestSchema", name: "Employee" },
|
|
290
|
-
select: {
|
|
291
|
-
id: { type: "column", path: ["T1", "id"] },
|
|
292
|
-
nextId: {
|
|
293
|
-
type: "window",
|
|
294
|
-
fn: {
|
|
295
|
-
type: "lead",
|
|
296
|
-
column: { type: "column", path: ["T1", "id"] },
|
|
297
|
-
offset: 1,
|
|
298
|
-
default: { type: "value", value: -1 },
|
|
299
|
-
},
|
|
300
|
-
spec: {
|
|
301
|
-
orderBy: [[{ type: "column", path: ["T1", "id"] }, "ASC"]],
|
|
302
|
-
},
|
|
303
|
-
},
|
|
304
|
-
},
|
|
305
|
-
});
|
|
306
|
-
});
|
|
307
|
-
|
|
308
226
|
it.each(dialects)("[%s] Verify SQL", (dialect) => {
|
|
309
227
|
const builder = createQueryBuilder(dialect);
|
|
310
228
|
expect(builder.build(def)).toMatchSql(expected.leadWithDefault[dialect]);
|
|
@@ -362,27 +280,6 @@ describe("SELECT - Window Functions", () => {
|
|
|
362
280
|
}))
|
|
363
281
|
.getSelectQueryDef();
|
|
364
282
|
|
|
365
|
-
it("Verify QueryDef", () => {
|
|
366
|
-
expect(def).toEqual({
|
|
367
|
-
type: "select",
|
|
368
|
-
as: "T1",
|
|
369
|
-
from: { database: "TestDb", schema: "TestSchema", name: "Employee" },
|
|
370
|
-
select: {
|
|
371
|
-
id: { type: "column", path: ["T1", "id"] },
|
|
372
|
-
avgId: {
|
|
373
|
-
type: "window",
|
|
374
|
-
fn: {
|
|
375
|
-
type: "avg",
|
|
376
|
-
column: { type: "column", path: ["T1", "id"] },
|
|
377
|
-
},
|
|
378
|
-
spec: {
|
|
379
|
-
partitionBy: [{ type: "column", path: ["T1", "departmentId"] }],
|
|
380
|
-
},
|
|
381
|
-
},
|
|
382
|
-
},
|
|
383
|
-
});
|
|
384
|
-
});
|
|
385
|
-
|
|
386
283
|
it.each(dialects)("[%s] Verify SQL", (dialect) => {
|
|
387
284
|
const builder = createQueryBuilder(dialect);
|
|
388
285
|
expect(builder.build(def)).toMatchSql(expected.avgOver[dialect]);
|
|
@@ -496,46 +393,6 @@ describe("SELECT - Window Functions", () => {
|
|
|
496
393
|
}))
|
|
497
394
|
.getSelectQueryDef();
|
|
498
395
|
|
|
499
|
-
it("Verify QueryDef", () => {
|
|
500
|
-
expect(def).toEqual({
|
|
501
|
-
type: "select",
|
|
502
|
-
as: "T1",
|
|
503
|
-
from: { database: "TestDb", schema: "TestSchema", name: "Employee" },
|
|
504
|
-
select: {
|
|
505
|
-
id: { type: "column", path: ["T1", "id"] },
|
|
506
|
-
name: { type: "column", path: ["T1", "name"] },
|
|
507
|
-
rowNum: {
|
|
508
|
-
type: "window",
|
|
509
|
-
fn: { type: "rowNumber" },
|
|
510
|
-
spec: {
|
|
511
|
-
partitionBy: [{ type: "column", path: ["T1", "departmentId"] }],
|
|
512
|
-
orderBy: [[{ type: "column", path: ["T1", "id"] }, "ASC"]],
|
|
513
|
-
},
|
|
514
|
-
},
|
|
515
|
-
rank: {
|
|
516
|
-
type: "window",
|
|
517
|
-
fn: { type: "rank" },
|
|
518
|
-
spec: {
|
|
519
|
-
partitionBy: [{ type: "column", path: ["T1", "departmentId"] }],
|
|
520
|
-
orderBy: [[{ type: "column", path: ["T1", "id"] }, "DESC"]],
|
|
521
|
-
},
|
|
522
|
-
},
|
|
523
|
-
prevName: {
|
|
524
|
-
type: "window",
|
|
525
|
-
fn: {
|
|
526
|
-
type: "lag",
|
|
527
|
-
column: { type: "column", path: ["T1", "name"] },
|
|
528
|
-
offset: 1,
|
|
529
|
-
},
|
|
530
|
-
spec: {
|
|
531
|
-
partitionBy: [{ type: "column", path: ["T1", "departmentId"] }],
|
|
532
|
-
orderBy: [[{ type: "column", path: ["T1", "id"] }, "ASC"]],
|
|
533
|
-
},
|
|
534
|
-
},
|
|
535
|
-
},
|
|
536
|
-
});
|
|
537
|
-
});
|
|
538
|
-
|
|
539
396
|
it.each(dialects)("[%s] Verify SQL", (dialect) => {
|
|
540
397
|
const builder = createQueryBuilder(dialect);
|
|
541
398
|
expect(builder.build(def)).toMatchSql(expected.combined[dialect]);
|
|
@@ -552,27 +409,6 @@ describe("SELECT - Window Functions", () => {
|
|
|
552
409
|
}))
|
|
553
410
|
.getSelectQueryDef();
|
|
554
411
|
|
|
555
|
-
it("Verify QueryDef", () => {
|
|
556
|
-
expect(def).toEqual({
|
|
557
|
-
type: "select",
|
|
558
|
-
as: "T1",
|
|
559
|
-
from: { database: "TestDb", schema: "TestSchema", name: "Employee" },
|
|
560
|
-
select: {
|
|
561
|
-
id: { type: "column", path: ["T1", "id"] },
|
|
562
|
-
minId: {
|
|
563
|
-
type: "window",
|
|
564
|
-
fn: {
|
|
565
|
-
type: "min",
|
|
566
|
-
column: { type: "column", path: ["T1", "id"] },
|
|
567
|
-
},
|
|
568
|
-
spec: {
|
|
569
|
-
partitionBy: [{ type: "column", path: ["T1", "departmentId"] }],
|
|
570
|
-
},
|
|
571
|
-
},
|
|
572
|
-
},
|
|
573
|
-
});
|
|
574
|
-
});
|
|
575
|
-
|
|
576
412
|
it.each(dialects)("[%s] Verify SQL", (dialect) => {
|
|
577
413
|
const builder = createQueryBuilder(dialect);
|
|
578
414
|
expect(builder.build(def)).toMatchSql(expected.minOver[dialect]);
|
|
@@ -589,27 +425,6 @@ describe("SELECT - Window Functions", () => {
|
|
|
589
425
|
}))
|
|
590
426
|
.getSelectQueryDef();
|
|
591
427
|
|
|
592
|
-
it("Verify QueryDef", () => {
|
|
593
|
-
expect(def).toEqual({
|
|
594
|
-
type: "select",
|
|
595
|
-
as: "T1",
|
|
596
|
-
from: { database: "TestDb", schema: "TestSchema", name: "Employee" },
|
|
597
|
-
select: {
|
|
598
|
-
id: { type: "column", path: ["T1", "id"] },
|
|
599
|
-
maxId: {
|
|
600
|
-
type: "window",
|
|
601
|
-
fn: {
|
|
602
|
-
type: "max",
|
|
603
|
-
column: { type: "column", path: ["T1", "id"] },
|
|
604
|
-
},
|
|
605
|
-
spec: {
|
|
606
|
-
partitionBy: [{ type: "column", path: ["T1", "departmentId"] }],
|
|
607
|
-
},
|
|
608
|
-
},
|
|
609
|
-
},
|
|
610
|
-
});
|
|
611
|
-
});
|
|
612
|
-
|
|
613
428
|
it.each(dialects)("[%s] Verify SQL", (dialect) => {
|
|
614
429
|
const builder = createQueryBuilder(dialect);
|
|
615
430
|
expect(builder.build(def)).toMatchSql(expected.maxOver[dialect]);
|
|
@@ -31,21 +31,6 @@ describe("NullableQueryableRecord type inference", () => {
|
|
|
31
31
|
expect(q).toBeDefined();
|
|
32
32
|
});
|
|
33
33
|
|
|
34
|
-
it("non-optional relation (required object) fields should remain ExprUnit<T>", () => {
|
|
35
|
-
const db = createTestDb();
|
|
36
|
-
const q = db.post().select((item) => ({
|
|
37
|
-
title: item.title,
|
|
38
|
-
viewCount: item.viewCount,
|
|
39
|
-
}));
|
|
40
|
-
|
|
41
|
-
type Result = typeof q extends { meta: { columns: infer C } } ? C : never;
|
|
42
|
-
type TitleType = Result extends { title: { $infer: infer T } } ? T : never;
|
|
43
|
-
|
|
44
|
-
expectTypeOf<TitleType>().toEqualTypeOf<string>();
|
|
45
|
-
|
|
46
|
-
expect(q).toBeDefined();
|
|
47
|
-
});
|
|
48
|
-
|
|
49
34
|
it("QueryableRecord preserves optional modifier (for select output)", () => {
|
|
50
35
|
type OptionalData = { id?: number; name: string };
|
|
51
36
|
type Result = QueryableRecord<OptionalData>;
|
|
@@ -57,17 +42,6 @@ describe("NullableQueryableRecord type inference", () => {
|
|
|
57
42
|
expect(true).toBe(true);
|
|
58
43
|
});
|
|
59
44
|
|
|
60
|
-
it("QueryableRecord preserves optional modifier for write operations", () => {
|
|
61
|
-
type OptionalData = { id?: number; name: string };
|
|
62
|
-
type WriteResult = QueryableRecord<OptionalData>;
|
|
63
|
-
|
|
64
|
-
// QueryableRecord preserves optional keys (for update/insert operations)
|
|
65
|
-
expectTypeOf<Required<WriteResult>["id"]>().toMatchTypeOf<{ $infer: number | undefined }>();
|
|
66
|
-
expectTypeOf<WriteResult["name"]>().toMatchTypeOf<{ $infer: string }>();
|
|
67
|
-
|
|
68
|
-
expect(true).toBe(true);
|
|
69
|
-
});
|
|
70
|
-
|
|
71
45
|
it("select auto-infers result type from callback return", () => {
|
|
72
46
|
const db = createTestDb();
|
|
73
47
|
|
|
@@ -109,28 +83,6 @@ describe("NullableQueryableRecord type inference", () => {
|
|
|
109
83
|
expect(true).toBe(true);
|
|
110
84
|
});
|
|
111
85
|
|
|
112
|
-
it("select with optional properties then orderBy should compile", () => {
|
|
113
|
-
const db = createTestDb();
|
|
114
|
-
|
|
115
|
-
/*type IUserItem = {
|
|
116
|
-
id?: number;
|
|
117
|
-
name?: string;
|
|
118
|
-
isActive: boolean;
|
|
119
|
-
};*/
|
|
120
|
-
|
|
121
|
-
const q = db
|
|
122
|
-
.user()
|
|
123
|
-
.where((u) => [expr.eq(u.isActive, true)])
|
|
124
|
-
.select((c) => ({
|
|
125
|
-
id: c.id,
|
|
126
|
-
name: c.name,
|
|
127
|
-
isActive: c.isActive,
|
|
128
|
-
}))
|
|
129
|
-
.orderBy((c) => c.id, "DESC");
|
|
130
|
-
|
|
131
|
-
expect(q).toBeDefined();
|
|
132
|
-
});
|
|
133
|
-
|
|
134
86
|
it("NullableQueryableRecord wraps primitives with | undefined", () => {
|
|
135
87
|
// Type-only test — verified by pnpm typecheck
|
|
136
88
|
type TestData = { name: string; age: number | undefined };
|
|
@@ -85,27 +85,6 @@ describe("result-parser performance", () => {
|
|
|
85
85
|
console.log(` simple 10,000: ${elapsed.toFixed(2)}ms`);
|
|
86
86
|
});
|
|
87
87
|
|
|
88
|
-
it("50,000 records processing - within 3000ms", async () => {
|
|
89
|
-
const raw = generateSimpleRecords(50_000);
|
|
90
|
-
const meta: ResultMeta = {
|
|
91
|
-
columns: {
|
|
92
|
-
id: "number",
|
|
93
|
-
name: "string",
|
|
94
|
-
email: "string",
|
|
95
|
-
age: "number",
|
|
96
|
-
active: "boolean",
|
|
97
|
-
},
|
|
98
|
-
joins: {},
|
|
99
|
-
};
|
|
100
|
-
|
|
101
|
-
const start = performance.now();
|
|
102
|
-
const result = await parseQueryResult(raw, meta);
|
|
103
|
-
const elapsed = performance.now() - start;
|
|
104
|
-
|
|
105
|
-
expect(result).toHaveLength(50_000);
|
|
106
|
-
expect(elapsed).toBeLessThan(3000);
|
|
107
|
-
console.log(` simple 50,000: ${elapsed.toFixed(2)}ms`);
|
|
108
|
-
});
|
|
109
88
|
});
|
|
110
89
|
|
|
111
90
|
describe("1-level JOIN processing", () => {
|
|
@@ -131,27 +110,6 @@ describe("result-parser performance", () => {
|
|
|
131
110
|
console.log(` JOIN 10,000 (1000×10): ${elapsed.toFixed(2)}ms`);
|
|
132
111
|
});
|
|
133
112
|
|
|
134
|
-
it("5,000 users × 10 posts = 50,000 records - within 3000ms", async () => {
|
|
135
|
-
const raw = generateJoinRecords(5_000, 10);
|
|
136
|
-
const meta: ResultMeta = {
|
|
137
|
-
columns: {
|
|
138
|
-
"id": "number",
|
|
139
|
-
"name": "string",
|
|
140
|
-
"posts.id": "number",
|
|
141
|
-
"posts.title": "string",
|
|
142
|
-
"posts.content": "string",
|
|
143
|
-
},
|
|
144
|
-
joins: { posts: { isSingle: false } },
|
|
145
|
-
};
|
|
146
|
-
|
|
147
|
-
const start = performance.now();
|
|
148
|
-
const result = await parseQueryResult(raw, meta);
|
|
149
|
-
const elapsed = performance.now() - start;
|
|
150
|
-
|
|
151
|
-
expect(result).toHaveLength(5_000);
|
|
152
|
-
expect(elapsed).toBeLessThan(3000);
|
|
153
|
-
console.log(` JOIN 50,000 (5000×10): ${elapsed.toFixed(2)}ms`);
|
|
154
|
-
});
|
|
155
113
|
});
|
|
156
114
|
|
|
157
115
|
describe("2-level nested JOIN processing", () => {
|
|
@@ -181,30 +139,5 @@ describe("result-parser performance", () => {
|
|
|
181
139
|
console.log(` nested JOIN 5,000 (100×10×5): ${elapsed.toFixed(2)}ms`);
|
|
182
140
|
});
|
|
183
141
|
|
|
184
|
-
it("500 users × 10 posts × 5 comments = 25,000 records - within 2000ms", async () => {
|
|
185
|
-
const raw = generateNestedJoinRecords(500, 10, 5);
|
|
186
|
-
const meta: ResultMeta = {
|
|
187
|
-
columns: {
|
|
188
|
-
"id": "number",
|
|
189
|
-
"name": "string",
|
|
190
|
-
"posts.id": "number",
|
|
191
|
-
"posts.title": "string",
|
|
192
|
-
"posts.comments.id": "number",
|
|
193
|
-
"posts.comments.text": "string",
|
|
194
|
-
},
|
|
195
|
-
joins: {
|
|
196
|
-
"posts": { isSingle: false },
|
|
197
|
-
"posts.comments": { isSingle: false },
|
|
198
|
-
},
|
|
199
|
-
};
|
|
200
|
-
|
|
201
|
-
const start = performance.now();
|
|
202
|
-
const result = await parseQueryResult(raw, meta);
|
|
203
|
-
const elapsed = performance.now() - start;
|
|
204
|
-
|
|
205
|
-
expect(result).toHaveLength(500);
|
|
206
|
-
expect(elapsed).toBeLessThan(2000);
|
|
207
|
-
console.log(` nested JOIN 25,000 (500×10×5): ${elapsed.toFixed(2)}ms`);
|
|
208
|
-
});
|
|
209
142
|
});
|
|
210
143
|
});
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { describe, expect, it } from "vitest";
|
|
2
|
-
import {
|
|
2
|
+
import { bytes, DateOnly, DateTime, Time, Uuid } from "@simplysm/core-common";
|
|
3
3
|
import { parseQueryResult } from "../../src/utils/result-parser";
|
|
4
4
|
import type { ResultMeta } from "../../src/types/db";
|
|
5
5
|
|
|
@@ -40,17 +40,6 @@ describe("result-parser", () => {
|
|
|
40
40
|
expect(result).toEqual([{ active: true, deleted: false }]);
|
|
41
41
|
});
|
|
42
42
|
|
|
43
|
-
it("boolean conversion - true/false", async () => {
|
|
44
|
-
const raw = [{ active: true, deleted: false }];
|
|
45
|
-
const meta: ResultMeta = {
|
|
46
|
-
columns: { active: "boolean", deleted: "boolean" },
|
|
47
|
-
joins: {},
|
|
48
|
-
};
|
|
49
|
-
|
|
50
|
-
const result = await parseQueryResult(raw, meta);
|
|
51
|
-
expect(result).toEqual([{ active: true, deleted: false }]);
|
|
52
|
-
});
|
|
53
|
-
|
|
54
43
|
it('boolean conversion - "0"/"1" strings', async () => {
|
|
55
44
|
const raw = [{ active: "1", deleted: "0" }];
|
|
56
45
|
const meta: ResultMeta = {
|
|
@@ -123,7 +112,7 @@ describe("result-parser", () => {
|
|
|
123
112
|
|
|
124
113
|
it("Uuid conversion - Uint8Array", async () => {
|
|
125
114
|
const uuidStr = "550e8400-e29b-41d4-a716-446655440000";
|
|
126
|
-
const uuidBytes =
|
|
115
|
+
const uuidBytes = bytes.fromHex(uuidStr.replace(/-/g, ""));
|
|
127
116
|
const raw = [{ id: uuidBytes }];
|
|
128
117
|
const meta: ResultMeta = {
|
|
129
118
|
columns: { id: "Uuid" },
|
|
@@ -137,8 +126,8 @@ describe("result-parser", () => {
|
|
|
137
126
|
});
|
|
138
127
|
|
|
139
128
|
it("Bytes conversion - Uint8Array passthrough", async () => {
|
|
140
|
-
const
|
|
141
|
-
const raw = [{ data:
|
|
129
|
+
const rawBytes = new Uint8Array([0x01, 0x02, 0x03]);
|
|
130
|
+
const raw = [{ data: rawBytes }];
|
|
142
131
|
const meta: ResultMeta = {
|
|
143
132
|
columns: { data: "Bytes" },
|
|
144
133
|
joins: {},
|
|
@@ -183,18 +172,6 @@ describe("result-parser", () => {
|
|
|
183
172
|
expect(result![0]).not.toHaveProperty("name");
|
|
184
173
|
});
|
|
185
174
|
|
|
186
|
-
it("undefined value removes the key", async () => {
|
|
187
|
-
const raw = [{ id: 1, name: undefined }];
|
|
188
|
-
const meta: ResultMeta = {
|
|
189
|
-
columns: { id: "number", name: "string" },
|
|
190
|
-
joins: {},
|
|
191
|
-
};
|
|
192
|
-
|
|
193
|
-
const result = await parseQueryResult(raw, meta);
|
|
194
|
-
expect(result).toEqual([{ id: 1 }]);
|
|
195
|
-
expect(result![0]).not.toHaveProperty("name");
|
|
196
|
-
});
|
|
197
|
-
|
|
198
175
|
it("record with all null values is excluded", async () => {
|
|
199
176
|
const raw = [{ id: null, name: null }];
|
|
200
177
|
const meta: ResultMeta = {
|
|
@@ -618,17 +595,6 @@ describe("result-parser", () => {
|
|
|
618
595
|
//#region ========== edge cases ==========
|
|
619
596
|
|
|
620
597
|
describe("edge cases", () => {
|
|
621
|
-
it("joins is an empty object", async () => {
|
|
622
|
-
const raw = [{ id: 1, name: "User1" }];
|
|
623
|
-
const meta: ResultMeta = {
|
|
624
|
-
columns: { id: "number", name: "string" },
|
|
625
|
-
joins: {},
|
|
626
|
-
};
|
|
627
|
-
|
|
628
|
-
const result = await parseQueryResult(raw, meta);
|
|
629
|
-
expect(result).toEqual([{ id: 1, name: "User1" }]);
|
|
630
|
-
});
|
|
631
|
-
|
|
632
598
|
it("deduplicates duplicate data", async () => {
|
|
633
599
|
const raw = [
|
|
634
600
|
{ "id": 1, "name": "User1", "posts.id": 10, "posts.title": "Post1" },
|