@simplysm/orm-common 13.0.76 → 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 -6
- package/tests/ddl/basic.expected.ts +8 -8
- package/tests/ddl/basic.spec.ts +24 -24
- package/tests/ddl/index-builder.spec.ts +10 -10
- package/tests/ddl/relation-builder.spec.ts +4 -4
- package/tests/dml/update.spec.ts +2 -2
- package/tests/expr/conditional.expected.ts +2 -2
- package/tests/expr/conditional.spec.ts +8 -8
- package/tests/expr/date.spec.ts +5 -5
- package/tests/select/basic.spec.ts +5 -5
- package/tests/utils/result-parser.spec.ts +4 -4
package/src/types/query-def.ts
CHANGED
|
@@ -174,7 +174,7 @@ export interface UpsertQueryDef {
|
|
|
174
174
|
export interface SwitchFkQueryDef {
|
|
175
175
|
type: "switchFk";
|
|
176
176
|
table: QueryDefObjectName;
|
|
177
|
-
|
|
177
|
+
enabled: boolean;
|
|
178
178
|
}
|
|
179
179
|
|
|
180
180
|
//#endregion
|
|
@@ -275,21 +275,21 @@ export interface RenameColumnQueryDef {
|
|
|
275
275
|
//#region ========== DDL - PK/FK/Index ==========
|
|
276
276
|
|
|
277
277
|
/** DROP PRIMARY KEY */
|
|
278
|
-
export interface
|
|
279
|
-
type: "
|
|
278
|
+
export interface DropPrimaryKeyQueryDef {
|
|
279
|
+
type: "dropPrimaryKey";
|
|
280
280
|
table: QueryDefObjectName;
|
|
281
281
|
}
|
|
282
282
|
|
|
283
283
|
/** ADD PRIMARY KEY */
|
|
284
|
-
export interface
|
|
285
|
-
type: "
|
|
284
|
+
export interface AddPrimaryKeyQueryDef {
|
|
285
|
+
type: "addPrimaryKey";
|
|
286
286
|
table: QueryDefObjectName;
|
|
287
287
|
columns: string[];
|
|
288
288
|
}
|
|
289
289
|
|
|
290
290
|
/** ADD FOREIGN KEY */
|
|
291
|
-
export interface
|
|
292
|
-
type: "
|
|
291
|
+
export interface AddForeignKeyQueryDef {
|
|
292
|
+
type: "addForeignKey";
|
|
293
293
|
table: QueryDefObjectName;
|
|
294
294
|
foreignKey: {
|
|
295
295
|
name: string;
|
|
@@ -300,15 +300,15 @@ export interface AddFkQueryDef {
|
|
|
300
300
|
}
|
|
301
301
|
|
|
302
302
|
/** DROP FOREIGN KEY */
|
|
303
|
-
export interface
|
|
304
|
-
type: "
|
|
303
|
+
export interface DropForeignKeyQueryDef {
|
|
304
|
+
type: "dropForeignKey";
|
|
305
305
|
table: QueryDefObjectName;
|
|
306
306
|
foreignKey: string;
|
|
307
307
|
}
|
|
308
308
|
|
|
309
309
|
/** CREATE INDEX */
|
|
310
|
-
export interface
|
|
311
|
-
type: "
|
|
310
|
+
export interface AddIndexQueryDef {
|
|
311
|
+
type: "addIndex";
|
|
312
312
|
table: QueryDefObjectName;
|
|
313
313
|
index: {
|
|
314
314
|
name: string;
|
|
@@ -318,8 +318,8 @@ export interface AddIdxQueryDef {
|
|
|
318
318
|
}
|
|
319
319
|
|
|
320
320
|
/** DROP INDEX */
|
|
321
|
-
export interface
|
|
322
|
-
type: "
|
|
321
|
+
export interface DropIndexQueryDef {
|
|
322
|
+
type: "dropIndex";
|
|
323
323
|
table: QueryDefObjectName;
|
|
324
324
|
index: string;
|
|
325
325
|
}
|
|
@@ -403,12 +403,12 @@ type DdlQueryDef =
|
|
|
403
403
|
| DropColumnQueryDef
|
|
404
404
|
| ModifyColumnQueryDef
|
|
405
405
|
| RenameColumnQueryDef
|
|
406
|
-
|
|
|
407
|
-
|
|
|
408
|
-
|
|
|
409
|
-
|
|
|
410
|
-
|
|
|
411
|
-
|
|
|
406
|
+
| DropPrimaryKeyQueryDef
|
|
407
|
+
| AddPrimaryKeyQueryDef
|
|
408
|
+
| AddForeignKeyQueryDef
|
|
409
|
+
| DropForeignKeyQueryDef
|
|
410
|
+
| AddIndexQueryDef
|
|
411
|
+
| DropIndexQueryDef
|
|
412
412
|
| CreateViewQueryDef
|
|
413
413
|
| DropViewQueryDef
|
|
414
414
|
| CreateProcQueryDef
|
|
@@ -433,12 +433,12 @@ export const DDL_TYPES = [
|
|
|
433
433
|
"dropColumn",
|
|
434
434
|
"modifyColumn",
|
|
435
435
|
"renameColumn",
|
|
436
|
-
"
|
|
437
|
-
"
|
|
438
|
-
"
|
|
439
|
-
"
|
|
440
|
-
"
|
|
441
|
-
"
|
|
436
|
+
"dropPrimaryKey",
|
|
437
|
+
"addPrimaryKey",
|
|
438
|
+
"addForeignKey",
|
|
439
|
+
"dropForeignKey",
|
|
440
|
+
"addIndex",
|
|
441
|
+
"dropIndex",
|
|
442
442
|
"createView",
|
|
443
443
|
"dropView",
|
|
444
444
|
"createProc",
|
|
@@ -490,12 +490,12 @@ export type QueryDef =
|
|
|
490
490
|
| RenameColumnQueryDef
|
|
491
491
|
|
|
492
492
|
// DDL - PK/FK/Index
|
|
493
|
-
|
|
|
494
|
-
|
|
|
495
|
-
|
|
|
496
|
-
|
|
|
497
|
-
|
|
|
498
|
-
|
|
|
493
|
+
| DropPrimaryKeyQueryDef
|
|
494
|
+
| AddPrimaryKeyQueryDef
|
|
495
|
+
| AddForeignKeyQueryDef
|
|
496
|
+
| DropForeignKeyQueryDef
|
|
497
|
+
| AddIndexQueryDef
|
|
498
|
+
| DropIndexQueryDef
|
|
499
499
|
|
|
500
500
|
// DDL - View/Procedure
|
|
501
501
|
| CreateViewQueryDef
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { bytes, obj, DateOnly, DateTime, Time, Uuid } from "@simplysm/core-common";
|
|
2
2
|
import type { ColumnPrimitiveStr } from "../types/column";
|
|
3
3
|
import type { ResultMeta } from "../types/db";
|
|
4
4
|
|
|
@@ -55,7 +55,7 @@ function parseValue(value: unknown, type: ColumnPrimitiveStr): unknown {
|
|
|
55
55
|
|
|
56
56
|
case "Bytes":
|
|
57
57
|
if (value instanceof Uint8Array) return value;
|
|
58
|
-
if (typeof value === "string") return
|
|
58
|
+
if (typeof value === "string") return bytes.fromHex(value);
|
|
59
59
|
throw new Error(`Failed to parse Bytes: ${typeof value}`);
|
|
60
60
|
}
|
|
61
61
|
}
|
|
@@ -64,6 +64,22 @@ function parseValue(value: unknown, type: ColumnPrimitiveStr): unknown {
|
|
|
64
64
|
// Grouping Utilities
|
|
65
65
|
// ============================================
|
|
66
66
|
|
|
67
|
+
/** Precomputed column metadata for flatToNested */
|
|
68
|
+
interface ColumnInfo {
|
|
69
|
+
key: string;
|
|
70
|
+
type: ColumnPrimitiveStr;
|
|
71
|
+
parts: string[] | undefined; // undefined for simple keys, string[] for nested keys
|
|
72
|
+
}
|
|
73
|
+
|
|
74
|
+
/** Precompute column info once per unique columns object */
|
|
75
|
+
function buildColumnInfos(columns: Record<string, ColumnPrimitiveStr>): ColumnInfo[] {
|
|
76
|
+
return Object.entries(columns).map(([key, type]) => ({
|
|
77
|
+
key,
|
|
78
|
+
type,
|
|
79
|
+
parts: key.includes(".") ? key.split(".") : undefined,
|
|
80
|
+
}));
|
|
81
|
+
}
|
|
82
|
+
|
|
67
83
|
/**
|
|
68
84
|
* Transform flat record to nested object
|
|
69
85
|
*
|
|
@@ -72,20 +88,19 @@ function parseValue(value: unknown, type: ColumnPrimitiveStr): unknown {
|
|
|
72
88
|
*/
|
|
73
89
|
function flatToNested(
|
|
74
90
|
record: Record<string, unknown>,
|
|
75
|
-
|
|
91
|
+
columnInfos: ColumnInfo[],
|
|
76
92
|
): Record<string, unknown> {
|
|
77
93
|
const result: Record<string, unknown> = {};
|
|
78
94
|
|
|
79
|
-
for (const
|
|
95
|
+
for (const { key, type, parts } of columnInfos) {
|
|
80
96
|
const rawValue = record[key];
|
|
81
97
|
const parsedValue = parseValue(rawValue, type);
|
|
82
98
|
|
|
83
99
|
// undefined values are not added as keys
|
|
84
100
|
if (parsedValue === undefined) continue;
|
|
85
101
|
|
|
86
|
-
if (
|
|
102
|
+
if (parts != null) {
|
|
87
103
|
// Nested key: "posts.id" → { posts: { id: ... } }
|
|
88
|
-
const parts = key.split(".");
|
|
89
104
|
let current = result;
|
|
90
105
|
for (let i = 0; i < parts.length - 1; i++) {
|
|
91
106
|
const part = parts[i];
|
|
@@ -107,8 +122,8 @@ function flatToNested(
|
|
|
107
122
|
/**
|
|
108
123
|
* Check if object is empty (all values are undefined)
|
|
109
124
|
*/
|
|
110
|
-
function isEmptyObject(
|
|
111
|
-
return Object.keys(
|
|
125
|
+
function isEmptyObject(record: Record<string, unknown>): boolean {
|
|
126
|
+
return Object.keys(record).length === 0;
|
|
112
127
|
}
|
|
113
128
|
|
|
114
129
|
// ============================================
|
|
@@ -186,6 +201,7 @@ async function parseSimpleRecords<TRecord>(
|
|
|
186
201
|
rawResults: Record<string, unknown>[],
|
|
187
202
|
columns: Record<string, ColumnPrimitiveStr>,
|
|
188
203
|
): Promise<TRecord[] | undefined> {
|
|
204
|
+
const columnInfos = buildColumnInfos(columns);
|
|
189
205
|
const results: Record<string, unknown>[] = [];
|
|
190
206
|
|
|
191
207
|
for (let i = 0; i < rawResults.length; i++) {
|
|
@@ -194,7 +210,7 @@ async function parseSimpleRecords<TRecord>(
|
|
|
194
210
|
await yieldToEventLoop();
|
|
195
211
|
}
|
|
196
212
|
|
|
197
|
-
const parsed = flatToNested(rawResults[i],
|
|
213
|
+
const parsed = flatToNested(rawResults[i], columnInfos);
|
|
198
214
|
|
|
199
215
|
// Exclude empty objects
|
|
200
216
|
if (!isEmptyObject(parsed)) {
|
|
@@ -226,12 +242,13 @@ async function parseJoinedRecords<TRecord>(
|
|
|
226
242
|
meta: ResultMeta,
|
|
227
243
|
): Promise<TRecord[] | undefined> {
|
|
228
244
|
// 1. Transform all records to nested structure
|
|
245
|
+
const columnInfos = buildColumnInfos(meta.columns);
|
|
229
246
|
const nestedRecords: Record<string, unknown>[] = [];
|
|
230
247
|
for (let i = 0; i < rawResults.length; i++) {
|
|
231
248
|
if (i > 0 && i % YIELD_INTERVAL === 0) {
|
|
232
249
|
await yieldToEventLoop();
|
|
233
250
|
}
|
|
234
|
-
nestedRecords.push(flatToNested(rawResults[i],
|
|
251
|
+
nestedRecords.push(flatToNested(rawResults[i], columnInfos));
|
|
235
252
|
}
|
|
236
253
|
|
|
237
254
|
// 2. Sort JOIN keys by depth (shallower ones first)
|
|
@@ -253,7 +270,15 @@ async function parseJoinedRecords<TRecord>(
|
|
|
253
270
|
*/
|
|
254
271
|
function serializeGroupKey(groupKey: Record<string, unknown>, cachedKeyOrder?: string[]): string {
|
|
255
272
|
const keys = cachedKeyOrder ?? Object.keys(groupKey).sort((a, b) => a.localeCompare(b));
|
|
256
|
-
|
|
273
|
+
let result = "";
|
|
274
|
+
for (let i = 0; i < keys.length; i++) {
|
|
275
|
+
if (i > 0) result += "|";
|
|
276
|
+
const v = groupKey[keys[i]];
|
|
277
|
+
result += keys[i];
|
|
278
|
+
result += ":";
|
|
279
|
+
result += v === null ? "null" : String(v);
|
|
280
|
+
}
|
|
281
|
+
return result;
|
|
257
282
|
}
|
|
258
283
|
|
|
259
284
|
/**
|
|
@@ -295,12 +320,15 @@ function groupRecordsRecursively(
|
|
|
295
320
|
// Map-based grouping (O(n) complexity)
|
|
296
321
|
const groupMap = new Map<string, Record<string, unknown>>();
|
|
297
322
|
|
|
323
|
+
// Precompute join key exclusion set for O(1) lookup
|
|
324
|
+
const joinKeyExclusions = buildJoinKeyExclusionSet(childJoinKeys);
|
|
325
|
+
|
|
298
326
|
// Key order caching (determined from first record and reused)
|
|
299
327
|
let groupKeyOrder: string[] | undefined;
|
|
300
328
|
|
|
301
329
|
for (const record of records) {
|
|
302
330
|
// Extract and serialize group key (excluding JOIN keys)
|
|
303
|
-
const groupKey = extractGroupKey(record,
|
|
331
|
+
const groupKey = extractGroupKey(record, joinKeyExclusions);
|
|
304
332
|
if (groupKeyOrder == null) {
|
|
305
333
|
groupKeyOrder = Object.keys(groupKey).sort((a, b) => a.localeCompare(b));
|
|
306
334
|
}
|
|
@@ -382,17 +410,33 @@ function groupRecordsRecursively(
|
|
|
382
410
|
return grouped;
|
|
383
411
|
}
|
|
384
412
|
|
|
413
|
+
/**
|
|
414
|
+
* Build a Set of keys that should be excluded from group key (join keys and their prefixes)
|
|
415
|
+
*/
|
|
416
|
+
function buildJoinKeyExclusionSet(joinKeys: string[]): Set<string> {
|
|
417
|
+
const exclusions = new Set<string>();
|
|
418
|
+
for (const jk of joinKeys) {
|
|
419
|
+
exclusions.add(jk);
|
|
420
|
+
// Also exclude parent paths (e.g., "posts" for join key "posts.comments")
|
|
421
|
+
const parts = jk.split(".");
|
|
422
|
+
for (let i = 1; i < parts.length; i++) {
|
|
423
|
+
exclusions.add(parts.slice(0, i).join("."));
|
|
424
|
+
}
|
|
425
|
+
}
|
|
426
|
+
return exclusions;
|
|
427
|
+
}
|
|
428
|
+
|
|
385
429
|
/**
|
|
386
430
|
* Extract group key from record excluding JOIN keys
|
|
387
431
|
*/
|
|
388
432
|
function extractGroupKey(
|
|
389
433
|
record: Record<string, unknown>,
|
|
390
|
-
|
|
434
|
+
joinKeyExclusions: Set<string>,
|
|
391
435
|
): Record<string, unknown> {
|
|
392
436
|
const result: Record<string, unknown> = {};
|
|
393
437
|
for (const [key, value] of Object.entries(record)) {
|
|
394
438
|
// Only include non-JOIN keys
|
|
395
|
-
if (!
|
|
439
|
+
if (!joinKeyExclusions.has(key)) {
|
|
396
440
|
// Only use primitive values (not object/array) as group key
|
|
397
441
|
if (value == null || typeof value !== "object") {
|
|
398
442
|
result[key] = value;
|
|
@@ -422,7 +466,7 @@ function mergeJoinData(
|
|
|
422
466
|
if (isSingle) {
|
|
423
467
|
// isSingle: true - error if data exists and values differ
|
|
424
468
|
if (existingJoinData != null) {
|
|
425
|
-
if (!
|
|
469
|
+
if (!obj.equal(existingJoinData as Record<string, unknown>, newJoinData)) {
|
|
426
470
|
throw new Error(`isSingle relationship '${localKey}' has multiple different results.`);
|
|
427
471
|
}
|
|
428
472
|
} else {
|
|
@@ -447,7 +491,7 @@ function mergeJoinData(
|
|
|
447
491
|
} else {
|
|
448
492
|
// Fallback without hashSet (legacy approach)
|
|
449
493
|
const isDuplicate = existingJoinData.some((item) =>
|
|
450
|
-
|
|
494
|
+
obj.equal(item as Record<string, unknown>, newJoinData),
|
|
451
495
|
);
|
|
452
496
|
if (!isDuplicate) {
|
|
453
497
|
existingJoinData.push(newJoinData);
|
|
@@ -64,14 +64,14 @@ describe("createDbContext", () => {
|
|
|
64
64
|
});
|
|
65
65
|
});
|
|
66
66
|
|
|
67
|
-
it("connect/
|
|
67
|
+
it("connect/transaction methods exist", () => {
|
|
68
68
|
const db = createDbContext(TestDb, new MockExecutor(), {
|
|
69
69
|
database: "TestDb",
|
|
70
70
|
});
|
|
71
71
|
|
|
72
72
|
expect(typeof db.connect).toBe("function");
|
|
73
73
|
expect(typeof db.connectWithoutTransaction).toBe("function");
|
|
74
|
-
expect(typeof db.
|
|
74
|
+
expect(typeof db.transaction).toBe("function");
|
|
75
75
|
});
|
|
76
76
|
|
|
77
77
|
it("connect manages status lifecycle", async () => {
|
|
@@ -100,7 +100,7 @@ describe("createDbContext", () => {
|
|
|
100
100
|
expect(db.status).toBe("ready");
|
|
101
101
|
});
|
|
102
102
|
|
|
103
|
-
it("
|
|
103
|
+
it("transaction manages status lifecycle within connectWithoutTransaction", async () => {
|
|
104
104
|
const db = createDbContext(TestDb, new MockExecutor(), {
|
|
105
105
|
database: "TestDb",
|
|
106
106
|
});
|
|
@@ -108,7 +108,7 @@ describe("createDbContext", () => {
|
|
|
108
108
|
await db.connectWithoutTransaction(async () => {
|
|
109
109
|
await Promise.resolve();
|
|
110
110
|
expect(db.status).toBe("connect");
|
|
111
|
-
await db.
|
|
111
|
+
await db.transaction(async () => {
|
|
112
112
|
await Promise.resolve();
|
|
113
113
|
expect(db.status).toBe("transact");
|
|
114
114
|
});
|
|
@@ -166,14 +166,14 @@ describe("createDbContext", () => {
|
|
|
166
166
|
expect(db.status).toBe("ready");
|
|
167
167
|
});
|
|
168
168
|
|
|
169
|
-
it("
|
|
169
|
+
it("transaction throws when already in transaction state", async () => {
|
|
170
170
|
const db = createDbContext(TestDb, new MockExecutor(), {
|
|
171
171
|
database: "TestDb",
|
|
172
172
|
});
|
|
173
173
|
|
|
174
174
|
await db.connect(async () => {
|
|
175
175
|
// Already in transact state via connect
|
|
176
|
-
await expect(db.
|
|
176
|
+
await expect(db.transaction(async () => {})).rejects.toThrow("Already in TRANSACTION state.");
|
|
177
177
|
});
|
|
178
178
|
});
|
|
179
179
|
|
|
@@ -212,19 +212,19 @@ export const renameColumn: ExpectedSql = {
|
|
|
212
212
|
|
|
213
213
|
//#region ========== Primary Key ==========
|
|
214
214
|
|
|
215
|
-
export const
|
|
215
|
+
export const dropPrimaryKey: ExpectedSql = {
|
|
216
216
|
mysql: mysql`ALTER TABLE \`TestDb\`.\`User\` DROP PRIMARY KEY`,
|
|
217
217
|
mssql: tsql`ALTER TABLE [TestDb].[TestSchema].[User] DROP CONSTRAINT [PK_User]`,
|
|
218
218
|
postgresql: pgsql`ALTER TABLE "TestSchema"."User" DROP CONSTRAINT "PK_User"`,
|
|
219
219
|
};
|
|
220
220
|
|
|
221
|
-
export const
|
|
221
|
+
export const addPrimaryKey: ExpectedSql = {
|
|
222
222
|
mysql: mysql`ALTER TABLE \`TestDb\`.\`User\` ADD PRIMARY KEY (\`id\`)`,
|
|
223
223
|
mssql: tsql`ALTER TABLE [TestDb].[TestSchema].[User] ADD CONSTRAINT [PK_User] PRIMARY KEY ([id])`,
|
|
224
224
|
postgresql: pgsql`ALTER TABLE "TestSchema"."User" ADD CONSTRAINT "PK_User" PRIMARY KEY ("id")`,
|
|
225
225
|
};
|
|
226
226
|
|
|
227
|
-
export const
|
|
227
|
+
export const addPrimaryKeyComposite: ExpectedSql = {
|
|
228
228
|
mysql: mysql`ALTER TABLE \`TestDb\`.\`UserRole\` ADD PRIMARY KEY (\`userId\`, \`roleId\`)`,
|
|
229
229
|
mssql: tsql`ALTER TABLE [TestDb].[TestSchema].[UserRole] ADD CONSTRAINT [PK_UserRole] PRIMARY KEY ([userId], [roleId])`,
|
|
230
230
|
postgresql: pgsql`ALTER TABLE "TestSchema"."UserRole" ADD CONSTRAINT "PK_UserRole" PRIMARY KEY ("userId", "roleId")`,
|
|
@@ -234,7 +234,7 @@ export const addPkComposite: ExpectedSql = {
|
|
|
234
234
|
|
|
235
235
|
//#region ========== Foreign Key / Index ==========
|
|
236
236
|
|
|
237
|
-
export const
|
|
237
|
+
export const addForeignKey: ExpectedSql = {
|
|
238
238
|
mysql: mysql`
|
|
239
239
|
ALTER TABLE \`TestDb\`.\`Post\` ADD CONSTRAINT \`FK_Post_user\`
|
|
240
240
|
FOREIGN KEY (\`userId\`) REFERENCES \`TestDb\`.\`User\` (\`id\`)
|
|
@@ -251,25 +251,25 @@ CREATE INDEX "IDX_Post_Post_user" ON "TestSchema"."Post" ("userId");
|
|
|
251
251
|
`,
|
|
252
252
|
};
|
|
253
253
|
|
|
254
|
-
export const
|
|
254
|
+
export const dropForeignKey: ExpectedSql = {
|
|
255
255
|
mysql: mysql`ALTER TABLE \`TestDb\`.\`Post\` DROP FOREIGN KEY \`FK_Post_user\``,
|
|
256
256
|
mssql: tsql`ALTER TABLE [TestDb].[TestSchema].[Post] DROP CONSTRAINT [FK_Post_user]`,
|
|
257
257
|
postgresql: pgsql`ALTER TABLE "TestSchema"."Post" DROP CONSTRAINT "FK_Post_user"`,
|
|
258
258
|
};
|
|
259
259
|
|
|
260
|
-
export const
|
|
260
|
+
export const addIndex: ExpectedSql = {
|
|
261
261
|
mysql: mysql`CREATE UNIQUE INDEX \`IDX_User_email\` ON \`TestDb\`.\`User\` (\`email\` ASC)`,
|
|
262
262
|
mssql: tsql`CREATE UNIQUE INDEX [IDX_User_email] ON [TestDb].[TestSchema].[User] ([email] ASC)`,
|
|
263
263
|
postgresql: pgsql`CREATE UNIQUE INDEX "IDX_User_email" ON "TestSchema"."User" ("email" ASC)`,
|
|
264
264
|
};
|
|
265
265
|
|
|
266
|
-
export const
|
|
266
|
+
export const dropIndex: ExpectedSql = {
|
|
267
267
|
mysql: mysql`DROP INDEX \`IDX_User_email\` ON \`TestDb\`.\`User\``,
|
|
268
268
|
mssql: tsql`DROP INDEX [IDX_User_email] ON [TestDb].[TestSchema].[User]`,
|
|
269
269
|
postgresql: pgsql`DROP INDEX "TestSchema"."IDX_User_email"`,
|
|
270
270
|
};
|
|
271
271
|
|
|
272
|
-
export const
|
|
272
|
+
export const dropIndexComposite: ExpectedSql = {
|
|
273
273
|
mysql: mysql`DROP INDEX \`IDX_User_name_email\` ON \`TestDb\`.\`User\``,
|
|
274
274
|
mssql: tsql`DROP INDEX [IDX_User_name_email] ON [TestDb].[TestSchema].[User]`,
|
|
275
275
|
postgresql: pgsql`DROP INDEX "TestSchema"."IDX_User_name_email"`,
|
package/tests/ddl/basic.spec.ts
CHANGED
|
@@ -295,32 +295,32 @@ describe("DDL - Column", () => {
|
|
|
295
295
|
});
|
|
296
296
|
|
|
297
297
|
describe("DDL - Primary Key", () => {
|
|
298
|
-
describe("
|
|
298
|
+
describe("getDropPrimaryKeyQueryDef", () => {
|
|
299
299
|
const db = createTestDb();
|
|
300
|
-
const def = db.
|
|
300
|
+
const def = db.getDropPrimaryKeyQueryDef({ database: "TestDb", schema: "TestSchema", name: "User" });
|
|
301
301
|
|
|
302
302
|
it("should validate QueryDef", () => {
|
|
303
303
|
expect(def).toEqual({
|
|
304
|
-
type: "
|
|
304
|
+
type: "dropPrimaryKey",
|
|
305
305
|
table: { database: "TestDb", schema: "TestSchema", name: "User" },
|
|
306
306
|
});
|
|
307
307
|
});
|
|
308
308
|
|
|
309
309
|
it.each(dialects)("[%s] should validate SQL", (dialect) => {
|
|
310
310
|
const builder = createQueryBuilder(dialect);
|
|
311
|
-
expect(builder.build(def)).toMatchSql(expected.
|
|
311
|
+
expect(builder.build(def)).toMatchSql(expected.dropPrimaryKey[dialect]);
|
|
312
312
|
});
|
|
313
313
|
});
|
|
314
314
|
|
|
315
|
-
describe("
|
|
315
|
+
describe("getAddPrimaryKeyQueryDef", () => {
|
|
316
316
|
const db = createTestDb();
|
|
317
|
-
const def = db.
|
|
317
|
+
const def = db.getAddPrimaryKeyQueryDef({ database: "TestDb", schema: "TestSchema", name: "User" }, [
|
|
318
318
|
"id",
|
|
319
319
|
]);
|
|
320
320
|
|
|
321
321
|
it("should validate QueryDef", () => {
|
|
322
322
|
expect(def).toEqual({
|
|
323
|
-
type: "
|
|
323
|
+
type: "addPrimaryKey",
|
|
324
324
|
table: { database: "TestDb", schema: "TestSchema", name: "User" },
|
|
325
325
|
columns: ["id"],
|
|
326
326
|
});
|
|
@@ -328,21 +328,21 @@ describe("DDL - Primary Key", () => {
|
|
|
328
328
|
|
|
329
329
|
it.each(dialects)("[%s] should validate SQL", (dialect) => {
|
|
330
330
|
const builder = createQueryBuilder(dialect);
|
|
331
|
-
expect(builder.build(def)).toMatchSql(expected.
|
|
331
|
+
expect(builder.build(def)).toMatchSql(expected.addPrimaryKey[dialect]);
|
|
332
332
|
});
|
|
333
333
|
});
|
|
334
334
|
|
|
335
335
|
});
|
|
336
336
|
|
|
337
337
|
describe("DDL - Foreign Key / Index", () => {
|
|
338
|
-
describe("
|
|
338
|
+
describe("getAddForeignKeyQueryDef", () => {
|
|
339
339
|
const db = createTestDb();
|
|
340
340
|
const userRelation = Post.meta.relations?.["user"];
|
|
341
341
|
if (!(userRelation instanceof ForeignKeyBuilder)) {
|
|
342
342
|
throw new Error("user relation not found");
|
|
343
343
|
}
|
|
344
344
|
|
|
345
|
-
const def = db.
|
|
345
|
+
const def = db.getAddForeignKeyQueryDef(
|
|
346
346
|
{ database: "TestDb", schema: "TestSchema", name: "Post" },
|
|
347
347
|
"user",
|
|
348
348
|
userRelation,
|
|
@@ -350,7 +350,7 @@ describe("DDL - Foreign Key / Index", () => {
|
|
|
350
350
|
|
|
351
351
|
it("should validate QueryDef", () => {
|
|
352
352
|
expect(def).toEqual({
|
|
353
|
-
type: "
|
|
353
|
+
type: "addForeignKey",
|
|
354
354
|
table: { database: "TestDb", schema: "TestSchema", name: "Post" },
|
|
355
355
|
foreignKey: {
|
|
356
356
|
name: "FK_Post_user",
|
|
@@ -363,20 +363,20 @@ describe("DDL - Foreign Key / Index", () => {
|
|
|
363
363
|
|
|
364
364
|
it.each(dialects)("[%s] should validate SQL", (dialect) => {
|
|
365
365
|
const builder = createQueryBuilder(dialect);
|
|
366
|
-
expect(builder.build(def)).toMatchSql(expected.
|
|
366
|
+
expect(builder.build(def)).toMatchSql(expected.addForeignKey[dialect]);
|
|
367
367
|
});
|
|
368
368
|
});
|
|
369
369
|
|
|
370
|
-
describe("
|
|
370
|
+
describe("getDropForeignKeyQueryDef", () => {
|
|
371
371
|
const db = createTestDb();
|
|
372
|
-
const def = db.
|
|
372
|
+
const def = db.getDropForeignKeyQueryDef(
|
|
373
373
|
{ database: "TestDb", schema: "TestSchema", name: "Post" },
|
|
374
374
|
"user",
|
|
375
375
|
);
|
|
376
376
|
|
|
377
377
|
it("should validate QueryDef", () => {
|
|
378
378
|
expect(def).toEqual({
|
|
379
|
-
type: "
|
|
379
|
+
type: "dropForeignKey",
|
|
380
380
|
table: { database: "TestDb", schema: "TestSchema", name: "Post" },
|
|
381
381
|
foreignKey: "FK_Post_user",
|
|
382
382
|
});
|
|
@@ -384,22 +384,22 @@ describe("DDL - Foreign Key / Index", () => {
|
|
|
384
384
|
|
|
385
385
|
it.each(dialects)("[%s] should validate SQL", (dialect) => {
|
|
386
386
|
const builder = createQueryBuilder(dialect);
|
|
387
|
-
expect(builder.build(def)).toMatchSql(expected.
|
|
387
|
+
expect(builder.build(def)).toMatchSql(expected.dropForeignKey[dialect]);
|
|
388
388
|
});
|
|
389
389
|
});
|
|
390
390
|
|
|
391
|
-
describe("
|
|
391
|
+
describe("getAddIndexQueryDef", () => {
|
|
392
392
|
const db = createTestDb();
|
|
393
393
|
const indexBuilder = new IndexBuilder({ columns: ["email"] as string[], unique: true });
|
|
394
394
|
|
|
395
|
-
const def = db.
|
|
395
|
+
const def = db.getAddIndexQueryDef(
|
|
396
396
|
{ database: "TestDb", schema: "TestSchema", name: "User" },
|
|
397
397
|
indexBuilder,
|
|
398
398
|
);
|
|
399
399
|
|
|
400
400
|
it("should validate QueryDef", () => {
|
|
401
401
|
expect(def).toEqual({
|
|
402
|
-
type: "
|
|
402
|
+
type: "addIndex",
|
|
403
403
|
table: { database: "TestDb", schema: "TestSchema", name: "User" },
|
|
404
404
|
index: {
|
|
405
405
|
name: "IDX_User_email",
|
|
@@ -411,19 +411,19 @@ describe("DDL - Foreign Key / Index", () => {
|
|
|
411
411
|
|
|
412
412
|
it.each(dialects)("[%s] should validate SQL", (dialect) => {
|
|
413
413
|
const builder = createQueryBuilder(dialect);
|
|
414
|
-
expect(builder.build(def)).toMatchSql(expected.
|
|
414
|
+
expect(builder.build(def)).toMatchSql(expected.addIndex[dialect]);
|
|
415
415
|
});
|
|
416
416
|
});
|
|
417
417
|
|
|
418
|
-
describe("
|
|
418
|
+
describe("getDropIndexQueryDef", () => {
|
|
419
419
|
const db = createTestDb();
|
|
420
|
-
const def = db.
|
|
420
|
+
const def = db.getDropIndexQueryDef({ database: "TestDb", schema: "TestSchema", name: "User" }, [
|
|
421
421
|
"email",
|
|
422
422
|
]);
|
|
423
423
|
|
|
424
424
|
it("should validate QueryDef", () => {
|
|
425
425
|
expect(def).toEqual({
|
|
426
|
-
type: "
|
|
426
|
+
type: "dropIndex",
|
|
427
427
|
table: { database: "TestDb", schema: "TestSchema", name: "User" },
|
|
428
428
|
index: "IDX_User_email",
|
|
429
429
|
});
|
|
@@ -431,7 +431,7 @@ describe("DDL - Foreign Key / Index", () => {
|
|
|
431
431
|
|
|
432
432
|
it.each(dialects)("[%s] should validate SQL", (dialect) => {
|
|
433
433
|
const builder = createQueryBuilder(dialect);
|
|
434
|
-
expect(builder.build(def)).toMatchSql(expected.
|
|
434
|
+
expect(builder.build(def)).toMatchSql(expected.dropIndex[dialect]);
|
|
435
435
|
});
|
|
436
436
|
});
|
|
437
437
|
|
|
@@ -12,14 +12,14 @@ describe("DDL - Index Builder", () => {
|
|
|
12
12
|
describe("IndexBuilder - single column index", () => {
|
|
13
13
|
const db = createTestDb();
|
|
14
14
|
const indexBuilder = IndexFactory.index("email");
|
|
15
|
-
const def = db.
|
|
15
|
+
const def = db.getAddIndexQueryDef(
|
|
16
16
|
{ database: "TestDb", schema: "TestSchema", name: "User" },
|
|
17
17
|
indexBuilder,
|
|
18
18
|
);
|
|
19
19
|
|
|
20
20
|
it("should validate QueryDef", () => {
|
|
21
21
|
expect(def).toEqual({
|
|
22
|
-
type: "
|
|
22
|
+
type: "addIndex",
|
|
23
23
|
table: { database: "TestDb", schema: "TestSchema", name: "User" },
|
|
24
24
|
index: {
|
|
25
25
|
name: "IDX_User_email",
|
|
@@ -38,14 +38,14 @@ describe("DDL - Index Builder", () => {
|
|
|
38
38
|
describe("IndexBuilder - unique index", () => {
|
|
39
39
|
const db = createTestDb();
|
|
40
40
|
const indexBuilder = IndexFactory.index("email").unique();
|
|
41
|
-
const def = db.
|
|
41
|
+
const def = db.getAddIndexQueryDef(
|
|
42
42
|
{ database: "TestDb", schema: "TestSchema", name: "User" },
|
|
43
43
|
indexBuilder,
|
|
44
44
|
);
|
|
45
45
|
|
|
46
46
|
it("should validate QueryDef", () => {
|
|
47
47
|
expect(def).toEqual({
|
|
48
|
-
type: "
|
|
48
|
+
type: "addIndex",
|
|
49
49
|
table: { database: "TestDb", schema: "TestSchema", name: "User" },
|
|
50
50
|
index: {
|
|
51
51
|
name: "IDX_User_email",
|
|
@@ -64,14 +64,14 @@ describe("DDL - Index Builder", () => {
|
|
|
64
64
|
describe("IndexBuilder - composite index", () => {
|
|
65
65
|
const db = createTestDb();
|
|
66
66
|
const indexBuilder = IndexFactory.index("name", "email");
|
|
67
|
-
const def = db.
|
|
67
|
+
const def = db.getAddIndexQueryDef(
|
|
68
68
|
{ database: "TestDb", schema: "TestSchema", name: "User" },
|
|
69
69
|
indexBuilder,
|
|
70
70
|
);
|
|
71
71
|
|
|
72
72
|
it("should validate QueryDef", () => {
|
|
73
73
|
expect(def).toEqual({
|
|
74
|
-
type: "
|
|
74
|
+
type: "addIndex",
|
|
75
75
|
table: { database: "TestDb", schema: "TestSchema", name: "User" },
|
|
76
76
|
index: {
|
|
77
77
|
name: "IDX_User_name_email",
|
|
@@ -93,14 +93,14 @@ describe("DDL - Index Builder", () => {
|
|
|
93
93
|
describe("IndexBuilder - orderBy specified", () => {
|
|
94
94
|
const db = createTestDb();
|
|
95
95
|
const indexBuilder = IndexFactory.index("name", "email").orderBy("DESC", "ASC");
|
|
96
|
-
const def = db.
|
|
96
|
+
const def = db.getAddIndexQueryDef(
|
|
97
97
|
{ database: "TestDb", schema: "TestSchema", name: "User" },
|
|
98
98
|
indexBuilder,
|
|
99
99
|
);
|
|
100
100
|
|
|
101
101
|
it("should validate QueryDef", () => {
|
|
102
102
|
expect(def).toEqual({
|
|
103
|
-
type: "
|
|
103
|
+
type: "addIndex",
|
|
104
104
|
table: { database: "TestDb", schema: "TestSchema", name: "User" },
|
|
105
105
|
index: {
|
|
106
106
|
name: "IDX_User_name_email",
|
|
@@ -122,14 +122,14 @@ describe("DDL - Index Builder", () => {
|
|
|
122
122
|
describe("IndexBuilder - name specified", () => {
|
|
123
123
|
const db = createTestDb();
|
|
124
124
|
const indexBuilder = IndexFactory.index("email").name("UQ_User_email");
|
|
125
|
-
const def = db.
|
|
125
|
+
const def = db.getAddIndexQueryDef(
|
|
126
126
|
{ database: "TestDb", schema: "TestSchema", name: "User" },
|
|
127
127
|
indexBuilder,
|
|
128
128
|
);
|
|
129
129
|
|
|
130
130
|
it("should validate QueryDef", () => {
|
|
131
131
|
expect(def).toEqual({
|
|
132
|
-
type: "
|
|
132
|
+
type: "addIndex",
|
|
133
133
|
table: { database: "TestDb", schema: "TestSchema", name: "User" },
|
|
134
134
|
index: {
|
|
135
135
|
name: "UQ_User_email",
|