metal-orm 1.0.51 → 1.0.53
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 +18 -15
- package/dist/index.cjs +103 -30
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +68 -3
- package/dist/index.d.ts +68 -3
- package/dist/index.js +101 -30
- package/dist/index.js.map +1 -1
- package/package.json +1 -1
- package/src/core/ast/aggregate-functions.ts +10 -0
- package/src/core/functions/standard-strategy.ts +1 -1
- package/src/index.ts +4 -2
- package/src/orm/execute.ts +37 -36
- package/src/orm/jsonify.ts +27 -0
- package/src/orm/orm-session.ts +28 -22
- package/src/orm/save-graph-types.ts +55 -0
- package/src/orm/save-graph.ts +141 -105
- package/src/query-builder/delete.ts +5 -4
- package/src/query-builder/select.ts +68 -10
- package/src/query-builder/update.ts +5 -4
|
@@ -533,16 +533,74 @@ export class SelectQueryBuilder<T = unknown, TTable extends TableDef = TableDef>
|
|
|
533
533
|
* @param ctx - ORM session context
|
|
534
534
|
* @returns Promise of entity instances
|
|
535
535
|
*/
|
|
536
|
-
async execute(ctx: OrmSession): Promise<EntityInstance<TTable>[]> {
|
|
537
|
-
return executeHydrated(ctx, this);
|
|
538
|
-
}
|
|
539
|
-
|
|
540
|
-
|
|
541
|
-
|
|
542
|
-
|
|
543
|
-
|
|
544
|
-
|
|
545
|
-
|
|
536
|
+
async execute(ctx: OrmSession): Promise<EntityInstance<TTable>[]> {
|
|
537
|
+
return executeHydrated(ctx, this);
|
|
538
|
+
}
|
|
539
|
+
|
|
540
|
+
private withAst(ast: SelectQueryNode): SelectQueryBuilder<T, TTable> {
|
|
541
|
+
const nextState = new SelectQueryState(this.env.table as TTable, ast);
|
|
542
|
+
const nextContext: SelectQueryBuilderContext = {
|
|
543
|
+
...this.context,
|
|
544
|
+
state: nextState
|
|
545
|
+
};
|
|
546
|
+
return this.clone(nextContext);
|
|
547
|
+
}
|
|
548
|
+
|
|
549
|
+
async count(session: OrmSession): Promise<number> {
|
|
550
|
+
const unpagedAst: SelectQueryNode = {
|
|
551
|
+
...this.context.state.ast,
|
|
552
|
+
orderBy: undefined,
|
|
553
|
+
limit: undefined,
|
|
554
|
+
offset: undefined
|
|
555
|
+
};
|
|
556
|
+
|
|
557
|
+
const subAst = this.withAst(unpagedAst).getAST();
|
|
558
|
+
|
|
559
|
+
const countQuery: SelectQueryNode = {
|
|
560
|
+
type: 'SelectQuery',
|
|
561
|
+
from: derivedTable(subAst, '__metal_count'),
|
|
562
|
+
columns: [{ type: 'Function', name: 'COUNT', args: [], alias: 'total' } as FunctionNode],
|
|
563
|
+
joins: []
|
|
564
|
+
};
|
|
565
|
+
|
|
566
|
+
const execCtx = session.getExecutionContext();
|
|
567
|
+
const compiled = execCtx.dialect.compileSelect(countQuery);
|
|
568
|
+
const results = await execCtx.interceptors.run({ sql: compiled.sql, params: compiled.params }, execCtx.executor);
|
|
569
|
+
const value = results[0]?.values?.[0]?.[0];
|
|
570
|
+
|
|
571
|
+
if (typeof value === 'number') return value;
|
|
572
|
+
if (typeof value === 'bigint') return Number(value);
|
|
573
|
+
if (typeof value === 'string') return Number(value);
|
|
574
|
+
return value === null || value === undefined ? 0 : Number(value);
|
|
575
|
+
}
|
|
576
|
+
|
|
577
|
+
async executePaged(
|
|
578
|
+
session: OrmSession,
|
|
579
|
+
options: { page: number; pageSize: number }
|
|
580
|
+
): Promise<{ items: EntityInstance<TTable>[]; totalItems: number }> {
|
|
581
|
+
const { page, pageSize } = options;
|
|
582
|
+
if (!Number.isInteger(page) || page < 1) {
|
|
583
|
+
throw new Error('executePaged: page must be an integer >= 1');
|
|
584
|
+
}
|
|
585
|
+
if (!Number.isInteger(pageSize) || pageSize < 1) {
|
|
586
|
+
throw new Error('executePaged: pageSize must be an integer >= 1');
|
|
587
|
+
}
|
|
588
|
+
|
|
589
|
+
const offset = (page - 1) * pageSize;
|
|
590
|
+
const [items, totalItems] = await Promise.all([
|
|
591
|
+
this.limit(pageSize).offset(offset).execute(session),
|
|
592
|
+
this.count(session)
|
|
593
|
+
]);
|
|
594
|
+
|
|
595
|
+
return { items, totalItems };
|
|
596
|
+
}
|
|
597
|
+
|
|
598
|
+
/**
|
|
599
|
+
* Executes the query with provided execution and hydration contexts
|
|
600
|
+
* @param execCtx - Execution context
|
|
601
|
+
* @param hydCtx - Hydration context
|
|
602
|
+
* @returns Promise of entity instances
|
|
603
|
+
*/
|
|
546
604
|
async executeWithContexts(execCtx: ExecutionContext, hydCtx: HydrationContext): Promise<EntityInstance<TTable>[]> {
|
|
547
605
|
return executeHydratedWithContexts(execCtx, hydCtx, this);
|
|
548
606
|
}
|
|
@@ -137,10 +137,11 @@ export class UpdateQueryBuilder<T> {
|
|
|
137
137
|
* @param session - The ORM session to execute the query with
|
|
138
138
|
* @returns A promise that resolves to the query results
|
|
139
139
|
*/
|
|
140
|
-
async execute(session: OrmSession): Promise<QueryResult[]> {
|
|
141
|
-
const
|
|
142
|
-
|
|
143
|
-
|
|
140
|
+
async execute(session: OrmSession): Promise<QueryResult[]> {
|
|
141
|
+
const execCtx = session.getExecutionContext();
|
|
142
|
+
const compiled = this.compile(execCtx.dialect);
|
|
143
|
+
return execCtx.interceptors.run({ sql: compiled.sql, params: compiled.params }, execCtx.executor);
|
|
144
|
+
}
|
|
144
145
|
|
|
145
146
|
/**
|
|
146
147
|
* Returns the Abstract Syntax Tree (AST) representation of the query
|