metal-orm 1.0.58 → 1.0.59
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 +34 -31
- package/dist/index.cjs +1463 -1003
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +148 -129
- package/dist/index.d.ts +148 -129
- package/dist/index.js +1459 -1003
- package/dist/index.js.map +1 -1
- package/package.json +1 -1
- package/src/core/ddl/schema-generator.ts +44 -1
- package/src/decorators/bootstrap.ts +183 -146
- package/src/decorators/column-decorator.ts +8 -49
- package/src/decorators/decorator-metadata.ts +10 -46
- package/src/decorators/entity.ts +30 -40
- package/src/decorators/relations.ts +30 -56
- package/src/orm/entity-hydration.ts +72 -0
- package/src/orm/entity-meta.ts +13 -11
- package/src/orm/entity-metadata.ts +240 -238
- package/src/orm/entity-relation-cache.ts +39 -0
- package/src/orm/entity-relations.ts +207 -0
- package/src/orm/entity.ts +124 -410
- package/src/orm/execute.ts +4 -4
- package/src/orm/lazy-batch/belongs-to-many.ts +134 -0
- package/src/orm/lazy-batch/belongs-to.ts +108 -0
- package/src/orm/lazy-batch/has-many.ts +69 -0
- package/src/orm/lazy-batch/has-one.ts +68 -0
- package/src/orm/lazy-batch/shared.ts +125 -0
- package/src/orm/lazy-batch.ts +4 -492
- package/src/orm/relations/many-to-many.ts +2 -1
- package/src/query-builder/relation-cte-builder.ts +63 -0
- package/src/query-builder/relation-filter-utils.ts +159 -0
- package/src/query-builder/relation-include-strategies.ts +177 -0
- package/src/query-builder/relation-join-planner.ts +80 -0
- package/src/query-builder/relation-service.ts +119 -479
- package/src/query-builder/relation-types.ts +41 -10
- package/src/query-builder/select/projection-facet.ts +23 -23
- package/src/query-builder/select/select-operations.ts +145 -0
- package/src/query-builder/select.ts +351 -422
- package/src/schema/relation.ts +22 -18
- package/src/schema/table.ts +22 -9
- package/src/schema/types.ts +14 -12
package/dist/index.cjs
CHANGED
|
@@ -143,6 +143,8 @@ __export(index_exports, {
|
|
|
143
143
|
esel: () => esel,
|
|
144
144
|
executeHydrated: () => executeHydrated,
|
|
145
145
|
executeHydratedWithContexts: () => executeHydratedWithContexts,
|
|
146
|
+
executeSchemaSql: () => executeSchemaSql,
|
|
147
|
+
executeSchemaSqlFor: () => executeSchemaSqlFor,
|
|
146
148
|
exists: () => exists,
|
|
147
149
|
exp: () => exp,
|
|
148
150
|
extract: () => extract,
|
|
@@ -151,6 +153,7 @@ __export(index_exports, {
|
|
|
151
153
|
fromUnixTime: () => fromUnixTime,
|
|
152
154
|
generateCreateTableSql: () => generateCreateTableSql,
|
|
153
155
|
generateSchemaSql: () => generateSchemaSql,
|
|
156
|
+
generateSchemaSqlFor: () => generateSchemaSqlFor,
|
|
154
157
|
getColumn: () => getColumn,
|
|
155
158
|
getDecoratorMetadata: () => getDecoratorMetadata,
|
|
156
159
|
getSchemaIntrospector: () => getSchemaIntrospector,
|
|
@@ -256,6 +259,7 @@ __export(index_exports, {
|
|
|
256
259
|
second: () => second,
|
|
257
260
|
sel: () => sel,
|
|
258
261
|
selectFromEntity: () => selectFromEntity,
|
|
262
|
+
setRelations: () => setRelations,
|
|
259
263
|
sha1: () => sha1,
|
|
260
264
|
sha2: () => sha2,
|
|
261
265
|
shiftLeft: () => shiftLeft,
|
|
@@ -311,6 +315,9 @@ var defineTable = (name, columns, relations = {}, hooks, options = {}) => {
|
|
|
311
315
|
collation: options.collation
|
|
312
316
|
};
|
|
313
317
|
};
|
|
318
|
+
function setRelations(table, relations) {
|
|
319
|
+
table.relations = relations;
|
|
320
|
+
}
|
|
314
321
|
var TABLE_REF_CACHE = /* @__PURE__ */ new WeakMap();
|
|
315
322
|
var withColumnProps = (table) => {
|
|
316
323
|
const cached = TABLE_REF_CACHE.get(table);
|
|
@@ -954,6 +961,7 @@ var variance = buildAggregate("VARIANCE");
|
|
|
954
961
|
|
|
955
962
|
// src/core/ast/expression-visitor.ts
|
|
956
963
|
var DispatcherRegistry = class _DispatcherRegistry {
|
|
964
|
+
dispatchers;
|
|
957
965
|
constructor(dispatchers = /* @__PURE__ */ new Map()) {
|
|
958
966
|
this.dispatchers = dispatchers;
|
|
959
967
|
}
|
|
@@ -1087,61 +1095,9 @@ var toTableRef = (table) => ({
|
|
|
1087
1095
|
alias: hasAlias(table) ? table.alias : void 0
|
|
1088
1096
|
});
|
|
1089
1097
|
|
|
1090
|
-
// src/core/ast/builders.ts
|
|
1091
|
-
var isColumnNode = (col2) => "type" in col2 && col2.type === "Column";
|
|
1092
|
-
var resolveTableName = (def, table) => {
|
|
1093
|
-
if (!def.table) {
|
|
1094
|
-
return table.alias || table.name;
|
|
1095
|
-
}
|
|
1096
|
-
if (table.alias && def.table === table.name) {
|
|
1097
|
-
return table.alias;
|
|
1098
|
-
}
|
|
1099
|
-
return def.table;
|
|
1100
|
-
};
|
|
1101
|
-
var buildColumnNode = (table, column) => {
|
|
1102
|
-
if (isColumnNode(column)) {
|
|
1103
|
-
return column;
|
|
1104
|
-
}
|
|
1105
|
-
const def = column;
|
|
1106
|
-
const baseTable = resolveTableName(def, table);
|
|
1107
|
-
return {
|
|
1108
|
-
type: "Column",
|
|
1109
|
-
table: baseTable,
|
|
1110
|
-
name: def.name
|
|
1111
|
-
};
|
|
1112
|
-
};
|
|
1113
|
-
var buildColumnNodes = (table, names) => names.map((name) => ({
|
|
1114
|
-
type: "Column",
|
|
1115
|
-
table: table.alias || table.name,
|
|
1116
|
-
name
|
|
1117
|
-
}));
|
|
1118
|
-
var createTableNode = (table) => ({
|
|
1119
|
-
type: "Table",
|
|
1120
|
-
name: table.name,
|
|
1121
|
-
schema: table.schema
|
|
1122
|
-
});
|
|
1123
|
-
var fnTable = (name, args = [], alias, opts) => ({
|
|
1124
|
-
type: "FunctionTable",
|
|
1125
|
-
name,
|
|
1126
|
-
args,
|
|
1127
|
-
alias,
|
|
1128
|
-
lateral: opts?.lateral,
|
|
1129
|
-
withOrdinality: opts?.withOrdinality,
|
|
1130
|
-
columnAliases: opts?.columnAliases,
|
|
1131
|
-
schema: opts?.schema
|
|
1132
|
-
});
|
|
1133
|
-
var derivedTable = (query, alias, columnAliases) => ({
|
|
1134
|
-
type: "DerivedTable",
|
|
1135
|
-
query,
|
|
1136
|
-
alias,
|
|
1137
|
-
columnAliases
|
|
1138
|
-
});
|
|
1139
|
-
|
|
1140
1098
|
// src/core/functions/function-registry.ts
|
|
1141
1099
|
var FunctionRegistry = class {
|
|
1142
|
-
|
|
1143
|
-
this.renderers = /* @__PURE__ */ new Map();
|
|
1144
|
-
}
|
|
1100
|
+
renderers = /* @__PURE__ */ new Map();
|
|
1145
1101
|
/**
|
|
1146
1102
|
* Registers or overrides a renderer for the given function name.
|
|
1147
1103
|
*/
|
|
@@ -1436,6 +1392,7 @@ function renderStandardGroupConcat(ctx) {
|
|
|
1436
1392
|
|
|
1437
1393
|
// src/core/functions/standard-strategy.ts
|
|
1438
1394
|
var StandardFunctionStrategy = class {
|
|
1395
|
+
registry;
|
|
1439
1396
|
/**
|
|
1440
1397
|
* Creates a new StandardFunctionStrategy and registers standard functions.
|
|
1441
1398
|
*/
|
|
@@ -1501,17 +1458,13 @@ var StandardFunctionStrategy = class {
|
|
|
1501
1458
|
getGroupConcatSeparatorOperand(ctx) {
|
|
1502
1459
|
return getGroupConcatSeparatorOperand(ctx);
|
|
1503
1460
|
}
|
|
1504
|
-
|
|
1505
|
-
|
|
1506
|
-
this.DEFAULT_GROUP_CONCAT_SEPARATOR = DEFAULT_GROUP_CONCAT_SEPARATOR;
|
|
1507
|
-
}
|
|
1461
|
+
/** Default separator for GROUP_CONCAT, a comma. */
|
|
1462
|
+
static DEFAULT_GROUP_CONCAT_SEPARATOR = DEFAULT_GROUP_CONCAT_SEPARATOR;
|
|
1508
1463
|
};
|
|
1509
1464
|
|
|
1510
1465
|
// src/core/functions/standard-table-strategy.ts
|
|
1511
1466
|
var StandardTableFunctionStrategy = class {
|
|
1512
|
-
|
|
1513
|
-
this.renderers = /* @__PURE__ */ new Map();
|
|
1514
|
-
}
|
|
1467
|
+
renderers = /* @__PURE__ */ new Map();
|
|
1515
1468
|
add(key, renderer) {
|
|
1516
1469
|
this.renderers.set(key, renderer);
|
|
1517
1470
|
}
|
|
@@ -1690,6 +1643,10 @@ var Dialect = class _Dialect {
|
|
|
1690
1643
|
const combinedCtes = [...normalized.ctes ?? [], ...hoistedCtes];
|
|
1691
1644
|
return combinedCtes.length ? { ...normalized, ctes: combinedCtes } : normalized;
|
|
1692
1645
|
}
|
|
1646
|
+
expressionCompilers;
|
|
1647
|
+
operandCompilers;
|
|
1648
|
+
functionStrategy;
|
|
1649
|
+
tableFunctionStrategy;
|
|
1693
1650
|
constructor(functionStrategy, tableFunctionStrategy) {
|
|
1694
1651
|
this.expressionCompilers = /* @__PURE__ */ new Map();
|
|
1695
1652
|
this.operandCompilers = /* @__PURE__ */ new Map();
|
|
@@ -1705,10 +1662,7 @@ var Dialect = class _Dialect {
|
|
|
1705
1662
|
*/
|
|
1706
1663
|
static create(functionStrategy, tableFunctionStrategy) {
|
|
1707
1664
|
class TestDialect extends _Dialect {
|
|
1708
|
-
|
|
1709
|
-
super(...arguments);
|
|
1710
|
-
this.dialect = "sqlite";
|
|
1711
|
-
}
|
|
1665
|
+
dialect = "sqlite";
|
|
1712
1666
|
quoteIdentifier(id) {
|
|
1713
1667
|
return `"${id}"`;
|
|
1714
1668
|
}
|
|
@@ -2148,11 +2102,8 @@ var OrderByCompiler = class {
|
|
|
2148
2102
|
|
|
2149
2103
|
// src/core/dialect/base/sql-dialect.ts
|
|
2150
2104
|
var SqlDialectBase = class extends Dialect {
|
|
2151
|
-
|
|
2152
|
-
|
|
2153
|
-
this.paginationStrategy = new StandardLimitOffsetPagination();
|
|
2154
|
-
this.returningStrategy = new NoReturningStrategy();
|
|
2155
|
-
}
|
|
2105
|
+
paginationStrategy = new StandardLimitOffsetPagination();
|
|
2106
|
+
returningStrategy = new NoReturningStrategy();
|
|
2156
2107
|
compileSelectAst(ast, ctx) {
|
|
2157
2108
|
const hasSetOps = !!(ast.setOps && ast.setOps.length);
|
|
2158
2109
|
const ctes = CteCompiler.compileCtes(
|
|
@@ -2540,12 +2491,12 @@ var PostgresTableFunctionStrategy = class extends StandardTableFunctionStrategy
|
|
|
2540
2491
|
|
|
2541
2492
|
// src/core/dialect/postgres/index.ts
|
|
2542
2493
|
var PostgresDialect = class extends SqlDialectBase {
|
|
2494
|
+
dialect = "postgres";
|
|
2543
2495
|
/**
|
|
2544
2496
|
* Creates a new PostgresDialect instance
|
|
2545
2497
|
*/
|
|
2546
2498
|
constructor() {
|
|
2547
2499
|
super(new PostgresFunctionStrategy(), new PostgresTableFunctionStrategy());
|
|
2548
|
-
this.dialect = "postgres";
|
|
2549
2500
|
this.registerExpressionCompiler("BitwiseExpression", (node, ctx) => {
|
|
2550
2501
|
const left2 = this.compileOperand(node.left, ctx);
|
|
2551
2502
|
const right2 = this.compileOperand(node.right, ctx);
|
|
@@ -2679,12 +2630,12 @@ var MysqlFunctionStrategy = class extends StandardFunctionStrategy {
|
|
|
2679
2630
|
|
|
2680
2631
|
// src/core/dialect/mysql/index.ts
|
|
2681
2632
|
var MySqlDialect = class extends SqlDialectBase {
|
|
2633
|
+
dialect = "mysql";
|
|
2682
2634
|
/**
|
|
2683
2635
|
* Creates a new MySqlDialect instance
|
|
2684
2636
|
*/
|
|
2685
2637
|
constructor() {
|
|
2686
2638
|
super(new MysqlFunctionStrategy());
|
|
2687
|
-
this.dialect = "mysql";
|
|
2688
2639
|
}
|
|
2689
2640
|
/**
|
|
2690
2641
|
* Quotes an identifier using MySQL backtick syntax
|
|
@@ -2835,12 +2786,12 @@ var SqliteFunctionStrategy = class extends StandardFunctionStrategy {
|
|
|
2835
2786
|
|
|
2836
2787
|
// src/core/dialect/sqlite/index.ts
|
|
2837
2788
|
var SqliteDialect = class extends SqlDialectBase {
|
|
2789
|
+
dialect = "sqlite";
|
|
2838
2790
|
/**
|
|
2839
2791
|
* Creates a new SqliteDialect instance
|
|
2840
2792
|
*/
|
|
2841
2793
|
constructor() {
|
|
2842
2794
|
super(new SqliteFunctionStrategy());
|
|
2843
|
-
this.dialect = "sqlite";
|
|
2844
2795
|
this.registerExpressionCompiler("BitwiseExpression", (node, ctx) => {
|
|
2845
2796
|
const left2 = this.compileOperand(node.left, ctx);
|
|
2846
2797
|
const right2 = this.compileOperand(node.right, ctx);
|
|
@@ -3013,12 +2964,12 @@ var MssqlFunctionStrategy = class extends StandardFunctionStrategy {
|
|
|
3013
2964
|
|
|
3014
2965
|
// src/core/dialect/mssql/index.ts
|
|
3015
2966
|
var SqlServerDialect = class extends SqlDialectBase {
|
|
2967
|
+
dialect = "mssql";
|
|
3016
2968
|
/**
|
|
3017
2969
|
* Creates a new SqlServerDialect instance
|
|
3018
2970
|
*/
|
|
3019
2971
|
constructor() {
|
|
3020
2972
|
super(new MssqlFunctionStrategy());
|
|
3021
|
-
this.dialect = "mssql";
|
|
3022
2973
|
}
|
|
3023
2974
|
/**
|
|
3024
2975
|
* Quotes an identifier using SQL Server bracket syntax
|
|
@@ -3145,12 +3096,8 @@ var SqlServerDialect = class extends SqlDialectBase {
|
|
|
3145
3096
|
|
|
3146
3097
|
// src/core/dialect/dialect-factory.ts
|
|
3147
3098
|
var DialectFactory = class {
|
|
3148
|
-
static
|
|
3149
|
-
|
|
3150
|
-
}
|
|
3151
|
-
static {
|
|
3152
|
-
this.defaultsInitialized = false;
|
|
3153
|
-
}
|
|
3099
|
+
static registry = /* @__PURE__ */ new Map();
|
|
3100
|
+
static defaultsInitialized = false;
|
|
3154
3101
|
static ensureDefaults() {
|
|
3155
3102
|
if (this.defaultsInitialized) return;
|
|
3156
3103
|
this.defaultsInitialized = true;
|
|
@@ -3209,8 +3156,66 @@ var resolveDialectInput = (dialect) => {
|
|
|
3209
3156
|
return dialect;
|
|
3210
3157
|
};
|
|
3211
3158
|
|
|
3159
|
+
// src/core/ast/builders.ts
|
|
3160
|
+
var isColumnNode = (col2) => "type" in col2 && col2.type === "Column";
|
|
3161
|
+
var resolveTableName = (def, table) => {
|
|
3162
|
+
if (!def.table) {
|
|
3163
|
+
return table.alias || table.name;
|
|
3164
|
+
}
|
|
3165
|
+
if (table.alias && def.table === table.name) {
|
|
3166
|
+
return table.alias;
|
|
3167
|
+
}
|
|
3168
|
+
return def.table;
|
|
3169
|
+
};
|
|
3170
|
+
var buildColumnNode = (table, column) => {
|
|
3171
|
+
if (isColumnNode(column)) {
|
|
3172
|
+
return column;
|
|
3173
|
+
}
|
|
3174
|
+
const def = column;
|
|
3175
|
+
const baseTable = resolveTableName(def, table);
|
|
3176
|
+
return {
|
|
3177
|
+
type: "Column",
|
|
3178
|
+
table: baseTable,
|
|
3179
|
+
name: def.name
|
|
3180
|
+
};
|
|
3181
|
+
};
|
|
3182
|
+
var buildColumnNodes = (table, names) => names.map((name) => ({
|
|
3183
|
+
type: "Column",
|
|
3184
|
+
table: table.alias || table.name,
|
|
3185
|
+
name
|
|
3186
|
+
}));
|
|
3187
|
+
var createTableNode = (table) => ({
|
|
3188
|
+
type: "Table",
|
|
3189
|
+
name: table.name,
|
|
3190
|
+
schema: table.schema
|
|
3191
|
+
});
|
|
3192
|
+
var fnTable = (name, args = [], alias, opts) => ({
|
|
3193
|
+
type: "FunctionTable",
|
|
3194
|
+
name,
|
|
3195
|
+
args,
|
|
3196
|
+
alias,
|
|
3197
|
+
lateral: opts?.lateral,
|
|
3198
|
+
withOrdinality: opts?.withOrdinality,
|
|
3199
|
+
columnAliases: opts?.columnAliases,
|
|
3200
|
+
schema: opts?.schema
|
|
3201
|
+
});
|
|
3202
|
+
var derivedTable = (query, alias, columnAliases) => ({
|
|
3203
|
+
type: "DerivedTable",
|
|
3204
|
+
query,
|
|
3205
|
+
alias,
|
|
3206
|
+
columnAliases
|
|
3207
|
+
});
|
|
3208
|
+
|
|
3212
3209
|
// src/query-builder/select-query-state.ts
|
|
3213
3210
|
var SelectQueryState = class _SelectQueryState {
|
|
3211
|
+
/**
|
|
3212
|
+
* Table definition for the query
|
|
3213
|
+
*/
|
|
3214
|
+
table;
|
|
3215
|
+
/**
|
|
3216
|
+
* Abstract Syntax Tree (AST) representation of the query
|
|
3217
|
+
*/
|
|
3218
|
+
ast;
|
|
3214
3219
|
/**
|
|
3215
3220
|
* Creates a new SelectQueryState instance
|
|
3216
3221
|
* @param table - Table definition
|
|
@@ -4180,199 +4185,150 @@ var buildRelationCorrelation = (root, relation, rootAlias, targetTableName) => {
|
|
|
4180
4185
|
// src/core/ast/join-metadata.ts
|
|
4181
4186
|
var getJoinRelationName = (join) => join.meta?.relationName;
|
|
4182
4187
|
|
|
4183
|
-
// src/query-builder/relation-
|
|
4184
|
-
var
|
|
4185
|
-
|
|
4186
|
-
|
|
4187
|
-
|
|
4188
|
-
|
|
4189
|
-
|
|
4190
|
-
|
|
4191
|
-
|
|
4192
|
-
|
|
4193
|
-
|
|
4194
|
-
this.state = state;
|
|
4195
|
-
this.hydration = hydration;
|
|
4196
|
-
this.createQueryAstService = createQueryAstService;
|
|
4197
|
-
this.projectionHelper = new RelationProjectionHelper(
|
|
4198
|
-
table,
|
|
4199
|
-
(state2, hydration2, columns) => this.selectColumns(state2, hydration2, columns)
|
|
4200
|
-
);
|
|
4201
|
-
}
|
|
4202
|
-
/**
|
|
4203
|
-
* Joins a relation to the query
|
|
4204
|
-
* @param relationName - Name of the relation to join
|
|
4205
|
-
* @param joinKind - Type of join to use
|
|
4206
|
-
* @param extraCondition - Additional join condition
|
|
4207
|
-
* @returns Relation result with updated state and hydration
|
|
4208
|
-
*/
|
|
4209
|
-
joinRelation(relationName, joinKind, extraCondition, tableSource) {
|
|
4210
|
-
const nextState = this.withJoin(this.state, relationName, joinKind, extraCondition, tableSource);
|
|
4211
|
-
return { state: nextState, hydration: this.hydration };
|
|
4188
|
+
// src/query-builder/relation-filter-utils.ts
|
|
4189
|
+
var splitFilterExpressions = (filter, allowedTables) => {
|
|
4190
|
+
const terms = flattenAnd(filter);
|
|
4191
|
+
const selfFilters = [];
|
|
4192
|
+
const crossFilters = [];
|
|
4193
|
+
for (const term of terms) {
|
|
4194
|
+
if (isExpressionSelfContained(term, allowedTables)) {
|
|
4195
|
+
selfFilters.push(term);
|
|
4196
|
+
} else {
|
|
4197
|
+
crossFilters.push(term);
|
|
4198
|
+
}
|
|
4212
4199
|
}
|
|
4213
|
-
|
|
4214
|
-
|
|
4215
|
-
|
|
4216
|
-
|
|
4217
|
-
|
|
4218
|
-
|
|
4219
|
-
match(relationName, predicate) {
|
|
4220
|
-
const joined = this.joinRelation(relationName, JOIN_KINDS.INNER, predicate);
|
|
4221
|
-
const pk = findPrimaryKey(this.table);
|
|
4222
|
-
const distinctCols = [{ type: "Column", table: this.rootTableName(), name: pk }];
|
|
4223
|
-
const existingDistinct = joined.state.ast.distinct ? joined.state.ast.distinct : [];
|
|
4224
|
-
const nextState = this.astService(joined.state).withDistinct([...existingDistinct, ...distinctCols]);
|
|
4225
|
-
return { state: nextState, hydration: joined.hydration };
|
|
4200
|
+
return { selfFilters, crossFilters };
|
|
4201
|
+
};
|
|
4202
|
+
var flattenAnd = (node) => {
|
|
4203
|
+
if (!node) return [];
|
|
4204
|
+
if (node.type === "LogicalExpression" && node.operator === "AND") {
|
|
4205
|
+
return node.operands.flatMap((operand) => flattenAnd(operand));
|
|
4226
4206
|
}
|
|
4227
|
-
|
|
4228
|
-
|
|
4229
|
-
|
|
4230
|
-
|
|
4231
|
-
|
|
4232
|
-
|
|
4233
|
-
|
|
4234
|
-
|
|
4235
|
-
|
|
4236
|
-
const relation = this.getRelation(relationName);
|
|
4237
|
-
const aliasPrefix = options?.aliasPrefix ?? relationName;
|
|
4238
|
-
const alreadyJoined = state.ast.joins.some((j) => getJoinRelationName(j) === relationName);
|
|
4239
|
-
const { selfFilters, crossFilters } = this.splitFilterExpressions(
|
|
4240
|
-
options?.filter,
|
|
4241
|
-
/* @__PURE__ */ new Set([relation.target.name])
|
|
4242
|
-
);
|
|
4243
|
-
const canUseCte = !alreadyJoined && selfFilters.length > 0;
|
|
4244
|
-
const joinFilters = [...crossFilters];
|
|
4245
|
-
if (!canUseCte) {
|
|
4246
|
-
joinFilters.push(...selfFilters);
|
|
4247
|
-
}
|
|
4248
|
-
const joinCondition = this.combineWithAnd(joinFilters);
|
|
4249
|
-
let tableSourceOverride;
|
|
4250
|
-
if (canUseCte) {
|
|
4251
|
-
const cteInfo = this.createFilteredRelationCte(state, relationName, relation, selfFilters);
|
|
4252
|
-
state = cteInfo.state;
|
|
4253
|
-
tableSourceOverride = cteInfo.table;
|
|
4254
|
-
}
|
|
4255
|
-
if (!alreadyJoined) {
|
|
4256
|
-
state = this.withJoin(
|
|
4257
|
-
state,
|
|
4258
|
-
relationName,
|
|
4259
|
-
options?.joinKind ?? JOIN_KINDS.LEFT,
|
|
4260
|
-
joinCondition,
|
|
4261
|
-
tableSourceOverride
|
|
4262
|
-
);
|
|
4207
|
+
return [node];
|
|
4208
|
+
};
|
|
4209
|
+
var isExpressionSelfContained = (expr, allowedTables) => {
|
|
4210
|
+
const collector = collectReferencedTables(expr);
|
|
4211
|
+
if (collector.hasSubquery) return false;
|
|
4212
|
+
if (collector.tables.size === 0) return true;
|
|
4213
|
+
for (const table of collector.tables) {
|
|
4214
|
+
if (!allowedTables.has(table)) {
|
|
4215
|
+
return false;
|
|
4263
4216
|
}
|
|
4264
|
-
|
|
4265
|
-
|
|
4266
|
-
|
|
4267
|
-
|
|
4268
|
-
|
|
4269
|
-
|
|
4270
|
-
|
|
4271
|
-
|
|
4272
|
-
|
|
4273
|
-
|
|
4274
|
-
|
|
4275
|
-
|
|
4276
|
-
|
|
4277
|
-
|
|
4278
|
-
|
|
4279
|
-
|
|
4280
|
-
|
|
4281
|
-
|
|
4282
|
-
|
|
4217
|
+
}
|
|
4218
|
+
return true;
|
|
4219
|
+
};
|
|
4220
|
+
var collectReferencedTables = (expr) => {
|
|
4221
|
+
const collector = {
|
|
4222
|
+
tables: /* @__PURE__ */ new Set(),
|
|
4223
|
+
hasSubquery: false
|
|
4224
|
+
};
|
|
4225
|
+
collectFromExpression(expr, collector);
|
|
4226
|
+
return collector;
|
|
4227
|
+
};
|
|
4228
|
+
var collectFromExpression = (expr, collector) => {
|
|
4229
|
+
switch (expr.type) {
|
|
4230
|
+
case "BinaryExpression":
|
|
4231
|
+
collectFromOperand(expr.left, collector);
|
|
4232
|
+
collectFromOperand(expr.right, collector);
|
|
4233
|
+
break;
|
|
4234
|
+
case "LogicalExpression":
|
|
4235
|
+
expr.operands.forEach((operand) => collectFromExpression(operand, collector));
|
|
4236
|
+
break;
|
|
4237
|
+
case "NullExpression":
|
|
4238
|
+
collectFromOperand(expr.left, collector);
|
|
4239
|
+
break;
|
|
4240
|
+
case "InExpression":
|
|
4241
|
+
collectFromOperand(expr.left, collector);
|
|
4242
|
+
if (Array.isArray(expr.right)) {
|
|
4243
|
+
expr.right.forEach((value) => collectFromOperand(value, collector));
|
|
4244
|
+
} else {
|
|
4245
|
+
collector.hasSubquery = true;
|
|
4283
4246
|
}
|
|
4284
|
-
|
|
4285
|
-
|
|
4286
|
-
|
|
4287
|
-
|
|
4288
|
-
|
|
4289
|
-
|
|
4290
|
-
|
|
4291
|
-
|
|
4292
|
-
|
|
4293
|
-
|
|
4294
|
-
|
|
4295
|
-
|
|
4296
|
-
|
|
4297
|
-
|
|
4298
|
-
|
|
4299
|
-
|
|
4300
|
-
};
|
|
4301
|
-
const targetSelection = buildTypedSelection(
|
|
4302
|
-
relation.target.columns,
|
|
4303
|
-
aliasPrefix,
|
|
4304
|
-
targetColumns,
|
|
4305
|
-
(key) => `Column '${key}' not found on relation '${relationName}'`
|
|
4306
|
-
);
|
|
4307
|
-
if (relation.type !== RelationKinds.BelongsToMany) {
|
|
4308
|
-
const relationSelectionResult2 = this.selectColumns(state, hydration, targetSelection);
|
|
4309
|
-
state = relationSelectionResult2.state;
|
|
4310
|
-
hydration = relationSelectionResult2.hydration;
|
|
4311
|
-
hydration = hydration.onRelationIncluded(
|
|
4312
|
-
state,
|
|
4313
|
-
relation,
|
|
4314
|
-
relationName,
|
|
4315
|
-
aliasPrefix,
|
|
4316
|
-
targetColumns
|
|
4317
|
-
);
|
|
4318
|
-
return { state, hydration };
|
|
4319
|
-
}
|
|
4320
|
-
const many = relation;
|
|
4321
|
-
const pivotAliasPrefix = options?.pivot?.aliasPrefix ?? `${aliasPrefix}_pivot`;
|
|
4322
|
-
const pivotPk = many.pivotPrimaryKey || findPrimaryKey(many.pivotTable);
|
|
4323
|
-
const pivotColumns = options?.pivot?.columns ?? many.defaultPivotColumns ?? buildDefaultPivotColumns(many, pivotPk);
|
|
4324
|
-
const pivotSelection = buildTypedSelection(
|
|
4325
|
-
many.pivotTable.columns,
|
|
4326
|
-
pivotAliasPrefix,
|
|
4327
|
-
pivotColumns,
|
|
4328
|
-
(key) => `Column '${key}' not found on pivot table '${many.pivotTable.name}'`
|
|
4329
|
-
);
|
|
4330
|
-
const combinedSelection = {
|
|
4331
|
-
...targetSelection,
|
|
4332
|
-
...pivotSelection
|
|
4333
|
-
};
|
|
4334
|
-
const relationSelectionResult = this.selectColumns(state, hydration, combinedSelection);
|
|
4335
|
-
state = relationSelectionResult.state;
|
|
4336
|
-
hydration = relationSelectionResult.hydration;
|
|
4337
|
-
hydration = hydration.onRelationIncluded(
|
|
4338
|
-
state,
|
|
4339
|
-
relation,
|
|
4340
|
-
relationName,
|
|
4341
|
-
aliasPrefix,
|
|
4342
|
-
targetColumns,
|
|
4343
|
-
{ aliasPrefix: pivotAliasPrefix, columns: pivotColumns }
|
|
4344
|
-
);
|
|
4345
|
-
return { state, hydration };
|
|
4247
|
+
break;
|
|
4248
|
+
case "ExistsExpression":
|
|
4249
|
+
collector.hasSubquery = true;
|
|
4250
|
+
break;
|
|
4251
|
+
case "BetweenExpression":
|
|
4252
|
+
collectFromOperand(expr.left, collector);
|
|
4253
|
+
collectFromOperand(expr.lower, collector);
|
|
4254
|
+
collectFromOperand(expr.upper, collector);
|
|
4255
|
+
break;
|
|
4256
|
+
case "ArithmeticExpression":
|
|
4257
|
+
case "BitwiseExpression":
|
|
4258
|
+
collectFromOperand(expr.left, collector);
|
|
4259
|
+
collectFromOperand(expr.right, collector);
|
|
4260
|
+
break;
|
|
4261
|
+
default:
|
|
4262
|
+
break;
|
|
4346
4263
|
}
|
|
4347
|
-
|
|
4348
|
-
|
|
4349
|
-
|
|
4350
|
-
|
|
4351
|
-
|
|
4352
|
-
|
|
4353
|
-
|
|
4354
|
-
|
|
4355
|
-
|
|
4356
|
-
|
|
4357
|
-
|
|
4358
|
-
|
|
4359
|
-
|
|
4360
|
-
|
|
4361
|
-
|
|
4362
|
-
|
|
4363
|
-
|
|
4364
|
-
|
|
4264
|
+
};
|
|
4265
|
+
var collectFromOperand = (node, collector) => {
|
|
4266
|
+
switch (node.type) {
|
|
4267
|
+
case "Column":
|
|
4268
|
+
collector.tables.add(node.table);
|
|
4269
|
+
break;
|
|
4270
|
+
case "Function":
|
|
4271
|
+
node.args.forEach((arg) => collectFromOperand(arg, collector));
|
|
4272
|
+
if (node.separator) {
|
|
4273
|
+
collectFromOperand(node.separator, collector);
|
|
4274
|
+
}
|
|
4275
|
+
if (node.orderBy) {
|
|
4276
|
+
node.orderBy.forEach((order) => collectFromOrderingTerm(order.term, collector));
|
|
4277
|
+
}
|
|
4278
|
+
break;
|
|
4279
|
+
case "JsonPath":
|
|
4280
|
+
collectFromOperand(node.column, collector);
|
|
4281
|
+
break;
|
|
4282
|
+
case "ScalarSubquery":
|
|
4283
|
+
collector.hasSubquery = true;
|
|
4284
|
+
break;
|
|
4285
|
+
case "CaseExpression":
|
|
4286
|
+
node.conditions.forEach(({ when, then }) => {
|
|
4287
|
+
collectFromExpression(when, collector);
|
|
4288
|
+
collectFromOperand(then, collector);
|
|
4289
|
+
});
|
|
4290
|
+
if (node.else) {
|
|
4291
|
+
collectFromOperand(node.else, collector);
|
|
4292
|
+
}
|
|
4293
|
+
break;
|
|
4294
|
+
case "Cast":
|
|
4295
|
+
collectFromOperand(node.expression, collector);
|
|
4296
|
+
break;
|
|
4297
|
+
case "WindowFunction":
|
|
4298
|
+
node.args.forEach((arg) => collectFromOperand(arg, collector));
|
|
4299
|
+
node.partitionBy?.forEach((part) => collectFromOperand(part, collector));
|
|
4300
|
+
node.orderBy?.forEach((order) => collectFromOrderingTerm(order.term, collector));
|
|
4301
|
+
break;
|
|
4302
|
+
case "Collate":
|
|
4303
|
+
collectFromOperand(node.expression, collector);
|
|
4304
|
+
break;
|
|
4305
|
+
case "ArithmeticExpression":
|
|
4306
|
+
case "BitwiseExpression":
|
|
4307
|
+
collectFromOperand(node.left, collector);
|
|
4308
|
+
collectFromOperand(node.right, collector);
|
|
4309
|
+
break;
|
|
4310
|
+
case "Literal":
|
|
4311
|
+
case "AliasRef":
|
|
4312
|
+
break;
|
|
4313
|
+
default:
|
|
4314
|
+
break;
|
|
4365
4315
|
}
|
|
4366
|
-
|
|
4367
|
-
|
|
4368
|
-
|
|
4369
|
-
|
|
4370
|
-
|
|
4371
|
-
|
|
4372
|
-
|
|
4373
|
-
|
|
4374
|
-
|
|
4375
|
-
|
|
4316
|
+
};
|
|
4317
|
+
var collectFromOrderingTerm = (term, collector) => {
|
|
4318
|
+
if (isOperandNode(term)) {
|
|
4319
|
+
collectFromOperand(term, collector);
|
|
4320
|
+
return;
|
|
4321
|
+
}
|
|
4322
|
+
collectFromExpression(term, collector);
|
|
4323
|
+
};
|
|
4324
|
+
|
|
4325
|
+
// src/query-builder/relation-join-planner.ts
|
|
4326
|
+
var RelationJoinPlanner = class {
|
|
4327
|
+
constructor(table, createQueryAstService) {
|
|
4328
|
+
this.table = table;
|
|
4329
|
+
this.createQueryAstService = createQueryAstService;
|
|
4330
|
+
}
|
|
4331
|
+
withJoin(state, relationName, relation, joinKind, extraCondition, tableSource) {
|
|
4376
4332
|
const rootAlias = state.ast.from.type === "Table" ? state.ast.from.alias : void 0;
|
|
4377
4333
|
if (relation.type === RelationKinds.BelongsToMany) {
|
|
4378
4334
|
const targetTableSource = tableSource ?? {
|
|
@@ -4409,167 +4365,31 @@ var RelationService = class {
|
|
|
4409
4365
|
const joinNode = createJoinNode(joinKind, targetTable, condition, relationName);
|
|
4410
4366
|
return this.astService(state).withJoin(joinNode);
|
|
4411
4367
|
}
|
|
4412
|
-
|
|
4413
|
-
|
|
4414
|
-
* @param state - Current query state
|
|
4415
|
-
* @param hydration - Hydration manager
|
|
4416
|
-
* @param columns - Columns to select
|
|
4417
|
-
* @returns Relation result with updated state and hydration
|
|
4418
|
-
*/
|
|
4419
|
-
selectColumns(state, hydration, columns) {
|
|
4420
|
-
const { state: nextState, addedColumns } = this.astService(state).select(columns);
|
|
4421
|
-
return {
|
|
4422
|
-
state: nextState,
|
|
4423
|
-
hydration: hydration.onColumnsSelected(nextState, addedColumns)
|
|
4424
|
-
};
|
|
4425
|
-
}
|
|
4426
|
-
combineWithAnd(expressions) {
|
|
4427
|
-
if (expressions.length === 0) return void 0;
|
|
4428
|
-
if (expressions.length === 1) return expressions[0];
|
|
4429
|
-
return {
|
|
4430
|
-
type: "LogicalExpression",
|
|
4431
|
-
operator: "AND",
|
|
4432
|
-
operands: expressions
|
|
4433
|
-
};
|
|
4434
|
-
}
|
|
4435
|
-
splitFilterExpressions(filter, allowedTables) {
|
|
4436
|
-
const terms = this.flattenAnd(filter);
|
|
4437
|
-
const selfFilters = [];
|
|
4438
|
-
const crossFilters = [];
|
|
4439
|
-
for (const term of terms) {
|
|
4440
|
-
if (this.isExpressionSelfContained(term, allowedTables)) {
|
|
4441
|
-
selfFilters.push(term);
|
|
4442
|
-
} else {
|
|
4443
|
-
crossFilters.push(term);
|
|
4444
|
-
}
|
|
4445
|
-
}
|
|
4446
|
-
return { selfFilters, crossFilters };
|
|
4447
|
-
}
|
|
4448
|
-
flattenAnd(node) {
|
|
4449
|
-
if (!node) return [];
|
|
4450
|
-
if (node.type === "LogicalExpression" && node.operator === "AND") {
|
|
4451
|
-
return node.operands.flatMap((operand) => this.flattenAnd(operand));
|
|
4452
|
-
}
|
|
4453
|
-
return [node];
|
|
4368
|
+
astService(state) {
|
|
4369
|
+
return this.createQueryAstService(this.table, state);
|
|
4454
4370
|
}
|
|
4455
|
-
|
|
4456
|
-
|
|
4457
|
-
|
|
4458
|
-
if (collector.tables.size === 0) return true;
|
|
4459
|
-
for (const table of collector.tables) {
|
|
4460
|
-
if (!allowedTables.has(table)) {
|
|
4461
|
-
return false;
|
|
4462
|
-
}
|
|
4371
|
+
resolveTargetTableName(target, relation) {
|
|
4372
|
+
if (target.type === "Table") {
|
|
4373
|
+
return target.alias ?? target.name;
|
|
4463
4374
|
}
|
|
4464
|
-
|
|
4465
|
-
|
|
4466
|
-
collectReferencedTables(expr) {
|
|
4467
|
-
const collector = {
|
|
4468
|
-
tables: /* @__PURE__ */ new Set(),
|
|
4469
|
-
hasSubquery: false
|
|
4470
|
-
};
|
|
4471
|
-
this.collectFromExpression(expr, collector);
|
|
4472
|
-
return collector;
|
|
4473
|
-
}
|
|
4474
|
-
collectFromExpression(expr, collector) {
|
|
4475
|
-
switch (expr.type) {
|
|
4476
|
-
case "BinaryExpression":
|
|
4477
|
-
this.collectFromOperand(expr.left, collector);
|
|
4478
|
-
this.collectFromOperand(expr.right, collector);
|
|
4479
|
-
break;
|
|
4480
|
-
case "LogicalExpression":
|
|
4481
|
-
expr.operands.forEach((operand) => this.collectFromExpression(operand, collector));
|
|
4482
|
-
break;
|
|
4483
|
-
case "NullExpression":
|
|
4484
|
-
this.collectFromOperand(expr.left, collector);
|
|
4485
|
-
break;
|
|
4486
|
-
case "InExpression":
|
|
4487
|
-
this.collectFromOperand(expr.left, collector);
|
|
4488
|
-
if (Array.isArray(expr.right)) {
|
|
4489
|
-
expr.right.forEach((value) => this.collectFromOperand(value, collector));
|
|
4490
|
-
} else {
|
|
4491
|
-
collector.hasSubquery = true;
|
|
4492
|
-
}
|
|
4493
|
-
break;
|
|
4494
|
-
case "ExistsExpression":
|
|
4495
|
-
collector.hasSubquery = true;
|
|
4496
|
-
break;
|
|
4497
|
-
case "BetweenExpression":
|
|
4498
|
-
this.collectFromOperand(expr.left, collector);
|
|
4499
|
-
this.collectFromOperand(expr.lower, collector);
|
|
4500
|
-
this.collectFromOperand(expr.upper, collector);
|
|
4501
|
-
break;
|
|
4502
|
-
case "ArithmeticExpression":
|
|
4503
|
-
case "BitwiseExpression":
|
|
4504
|
-
this.collectFromOperand(expr.left, collector);
|
|
4505
|
-
this.collectFromOperand(expr.right, collector);
|
|
4506
|
-
break;
|
|
4507
|
-
default:
|
|
4508
|
-
break;
|
|
4375
|
+
if (target.type === "DerivedTable") {
|
|
4376
|
+
return target.alias;
|
|
4509
4377
|
}
|
|
4510
|
-
|
|
4511
|
-
|
|
4512
|
-
switch (node.type) {
|
|
4513
|
-
case "Column":
|
|
4514
|
-
collector.tables.add(node.table);
|
|
4515
|
-
break;
|
|
4516
|
-
case "Function":
|
|
4517
|
-
node.args.forEach((arg) => this.collectFromOperand(arg, collector));
|
|
4518
|
-
if (node.separator) {
|
|
4519
|
-
this.collectFromOperand(node.separator, collector);
|
|
4520
|
-
}
|
|
4521
|
-
if (node.orderBy) {
|
|
4522
|
-
node.orderBy.forEach((order) => this.collectFromOrderingTerm(order.term, collector));
|
|
4523
|
-
}
|
|
4524
|
-
break;
|
|
4525
|
-
case "JsonPath":
|
|
4526
|
-
this.collectFromOperand(node.column, collector);
|
|
4527
|
-
break;
|
|
4528
|
-
case "ScalarSubquery":
|
|
4529
|
-
collector.hasSubquery = true;
|
|
4530
|
-
break;
|
|
4531
|
-
case "CaseExpression":
|
|
4532
|
-
node.conditions.forEach(({ when, then }) => {
|
|
4533
|
-
this.collectFromExpression(when, collector);
|
|
4534
|
-
this.collectFromOperand(then, collector);
|
|
4535
|
-
});
|
|
4536
|
-
if (node.else) {
|
|
4537
|
-
this.collectFromOperand(node.else, collector);
|
|
4538
|
-
}
|
|
4539
|
-
break;
|
|
4540
|
-
case "Cast":
|
|
4541
|
-
this.collectFromOperand(node.expression, collector);
|
|
4542
|
-
break;
|
|
4543
|
-
case "WindowFunction":
|
|
4544
|
-
node.args.forEach((arg) => this.collectFromOperand(arg, collector));
|
|
4545
|
-
node.partitionBy?.forEach((part) => this.collectFromOperand(part, collector));
|
|
4546
|
-
node.orderBy?.forEach((order) => this.collectFromOrderingTerm(order.term, collector));
|
|
4547
|
-
break;
|
|
4548
|
-
case "Collate":
|
|
4549
|
-
this.collectFromOperand(node.expression, collector);
|
|
4550
|
-
break;
|
|
4551
|
-
case "ArithmeticExpression":
|
|
4552
|
-
case "BitwiseExpression":
|
|
4553
|
-
this.collectFromOperand(node.left, collector);
|
|
4554
|
-
this.collectFromOperand(node.right, collector);
|
|
4555
|
-
break;
|
|
4556
|
-
case "Literal":
|
|
4557
|
-
case "AliasRef":
|
|
4558
|
-
break;
|
|
4559
|
-
default:
|
|
4560
|
-
break;
|
|
4378
|
+
if (target.type === "FunctionTable") {
|
|
4379
|
+
return target.alias ?? relation.target.name;
|
|
4561
4380
|
}
|
|
4381
|
+
return relation.target.name;
|
|
4562
4382
|
}
|
|
4563
|
-
|
|
4564
|
-
|
|
4565
|
-
|
|
4566
|
-
|
|
4567
|
-
|
|
4568
|
-
this.
|
|
4383
|
+
};
|
|
4384
|
+
|
|
4385
|
+
// src/query-builder/relation-cte-builder.ts
|
|
4386
|
+
var RelationCteBuilder = class {
|
|
4387
|
+
constructor(table, createQueryAstService) {
|
|
4388
|
+
this.table = table;
|
|
4389
|
+
this.createQueryAstService = createQueryAstService;
|
|
4569
4390
|
}
|
|
4570
|
-
createFilteredRelationCte(state, relationName, relation,
|
|
4391
|
+
createFilteredRelationCte(state, relationName, relation, predicate) {
|
|
4571
4392
|
const cteName = this.generateUniqueCteName(state, relationName);
|
|
4572
|
-
const predicate = this.combineWithAnd(filters);
|
|
4573
4393
|
if (!predicate) {
|
|
4574
4394
|
throw new Error("Unable to build filter CTE without predicates.");
|
|
4575
4395
|
}
|
|
@@ -4603,82 +4423,339 @@ var RelationService = class {
|
|
|
4603
4423
|
}
|
|
4604
4424
|
return candidate;
|
|
4605
4425
|
}
|
|
4606
|
-
|
|
4607
|
-
|
|
4608
|
-
return target.alias ?? target.name;
|
|
4609
|
-
}
|
|
4610
|
-
if (target.type === "DerivedTable") {
|
|
4611
|
-
return target.alias;
|
|
4612
|
-
}
|
|
4613
|
-
if (target.type === "FunctionTable") {
|
|
4614
|
-
return target.alias ?? relation.target.name;
|
|
4615
|
-
}
|
|
4616
|
-
return relation.target.name;
|
|
4426
|
+
astService(state) {
|
|
4427
|
+
return this.createQueryAstService(this.table, state);
|
|
4617
4428
|
}
|
|
4618
|
-
|
|
4619
|
-
|
|
4620
|
-
|
|
4621
|
-
|
|
4622
|
-
|
|
4623
|
-
|
|
4624
|
-
|
|
4625
|
-
|
|
4626
|
-
if (!relation) {
|
|
4627
|
-
throw new Error(`Relation '${relationName}' not found on table '${this.table.name}'`);
|
|
4429
|
+
};
|
|
4430
|
+
|
|
4431
|
+
// src/query-builder/relation-include-strategies.ts
|
|
4432
|
+
var buildTypedSelection = (columns, prefix, keys, missingMsg) => {
|
|
4433
|
+
return keys.reduce((acc, key) => {
|
|
4434
|
+
const def = columns[key];
|
|
4435
|
+
if (!def) {
|
|
4436
|
+
throw new Error(missingMsg(key));
|
|
4628
4437
|
}
|
|
4629
|
-
|
|
4438
|
+
acc[makeRelationAlias(prefix, key)] = def;
|
|
4439
|
+
return acc;
|
|
4440
|
+
}, {});
|
|
4441
|
+
};
|
|
4442
|
+
var resolveTargetColumns = (relation, options) => {
|
|
4443
|
+
const requestedColumns = options?.columns?.length ? [...options.columns] : Object.keys(relation.target.columns);
|
|
4444
|
+
const targetPrimaryKey = findPrimaryKey(relation.target);
|
|
4445
|
+
if (!requestedColumns.includes(targetPrimaryKey)) {
|
|
4446
|
+
requestedColumns.push(targetPrimaryKey);
|
|
4630
4447
|
}
|
|
4631
|
-
|
|
4632
|
-
|
|
4633
|
-
|
|
4634
|
-
|
|
4635
|
-
|
|
4636
|
-
|
|
4637
|
-
return this.createQueryAstService(this.table, state);
|
|
4448
|
+
return requestedColumns;
|
|
4449
|
+
};
|
|
4450
|
+
var ensureRootForeignKeySelected = (context, relation) => {
|
|
4451
|
+
const fkColumn = context.rootTable.columns[relation.foreignKey];
|
|
4452
|
+
if (!fkColumn) {
|
|
4453
|
+
return { state: context.state, hydration: context.hydration };
|
|
4638
4454
|
}
|
|
4639
|
-
|
|
4640
|
-
|
|
4641
|
-
|
|
4642
|
-
|
|
4455
|
+
const hasForeignKeySelected = context.state.ast.columns.some((col2) => {
|
|
4456
|
+
if (col2.type !== "Column") return false;
|
|
4457
|
+
const node = col2;
|
|
4458
|
+
const alias = node.alias ?? node.name;
|
|
4459
|
+
return alias === relation.foreignKey;
|
|
4460
|
+
});
|
|
4461
|
+
if (hasForeignKeySelected) {
|
|
4462
|
+
return { state: context.state, hydration: context.hydration };
|
|
4643
4463
|
}
|
|
4464
|
+
return context.selectColumns(context.state, context.hydration, {
|
|
4465
|
+
[relation.foreignKey]: fkColumn
|
|
4466
|
+
});
|
|
4467
|
+
};
|
|
4468
|
+
var standardIncludeStrategy = (context) => {
|
|
4469
|
+
const relation = context.relation;
|
|
4470
|
+
let { state, hydration } = context;
|
|
4471
|
+
const fkSelectionResult = ensureRootForeignKeySelected(context, relation);
|
|
4472
|
+
state = fkSelectionResult.state;
|
|
4473
|
+
hydration = fkSelectionResult.hydration;
|
|
4474
|
+
const targetColumns = resolveTargetColumns(relation, context.options);
|
|
4475
|
+
const targetSelection = buildTypedSelection(
|
|
4476
|
+
relation.target.columns,
|
|
4477
|
+
context.aliasPrefix,
|
|
4478
|
+
targetColumns,
|
|
4479
|
+
(key) => `Column '${key}' not found on relation '${context.relationName}'`
|
|
4480
|
+
);
|
|
4481
|
+
const relationSelectionResult = context.selectColumns(state, hydration, targetSelection);
|
|
4482
|
+
state = relationSelectionResult.state;
|
|
4483
|
+
hydration = relationSelectionResult.hydration;
|
|
4484
|
+
hydration = hydration.onRelationIncluded(
|
|
4485
|
+
state,
|
|
4486
|
+
relation,
|
|
4487
|
+
context.relationName,
|
|
4488
|
+
context.aliasPrefix,
|
|
4489
|
+
targetColumns
|
|
4490
|
+
);
|
|
4491
|
+
return { state, hydration };
|
|
4492
|
+
};
|
|
4493
|
+
var belongsToManyStrategy = (context) => {
|
|
4494
|
+
const relation = context.relation;
|
|
4495
|
+
let { state, hydration } = context;
|
|
4496
|
+
const targetColumns = resolveTargetColumns(relation, context.options);
|
|
4497
|
+
const targetSelection = buildTypedSelection(
|
|
4498
|
+
relation.target.columns,
|
|
4499
|
+
context.aliasPrefix,
|
|
4500
|
+
targetColumns,
|
|
4501
|
+
(key) => `Column '${key}' not found on relation '${context.relationName}'`
|
|
4502
|
+
);
|
|
4503
|
+
const pivotAliasPrefix = context.options?.pivot?.aliasPrefix ?? `${context.aliasPrefix}_pivot`;
|
|
4504
|
+
const pivotPk = relation.pivotPrimaryKey || findPrimaryKey(relation.pivotTable);
|
|
4505
|
+
const defaultPivotColumns = relation.defaultPivotColumns ?? buildDefaultPivotColumns(relation, pivotPk);
|
|
4506
|
+
const pivotColumns = context.options?.pivot?.columns ? [...context.options.pivot.columns] : [...defaultPivotColumns];
|
|
4507
|
+
const pivotSelection = buildTypedSelection(
|
|
4508
|
+
relation.pivotTable.columns,
|
|
4509
|
+
pivotAliasPrefix,
|
|
4510
|
+
pivotColumns,
|
|
4511
|
+
(key) => `Column '${key}' not found on pivot table '${relation.pivotTable.name}'`
|
|
4512
|
+
);
|
|
4513
|
+
const combinedSelection = {
|
|
4514
|
+
...targetSelection,
|
|
4515
|
+
...pivotSelection
|
|
4516
|
+
};
|
|
4517
|
+
const relationSelectionResult = context.selectColumns(state, hydration, combinedSelection);
|
|
4518
|
+
state = relationSelectionResult.state;
|
|
4519
|
+
hydration = relationSelectionResult.hydration;
|
|
4520
|
+
hydration = hydration.onRelationIncluded(
|
|
4521
|
+
state,
|
|
4522
|
+
relation,
|
|
4523
|
+
context.relationName,
|
|
4524
|
+
context.aliasPrefix,
|
|
4525
|
+
targetColumns,
|
|
4526
|
+
{ aliasPrefix: pivotAliasPrefix, columns: pivotColumns }
|
|
4527
|
+
);
|
|
4528
|
+
return { state, hydration };
|
|
4529
|
+
};
|
|
4530
|
+
var relationIncludeStrategies = {
|
|
4531
|
+
[RelationKinds.HasMany]: standardIncludeStrategy,
|
|
4532
|
+
[RelationKinds.HasOne]: standardIncludeStrategy,
|
|
4533
|
+
[RelationKinds.BelongsTo]: standardIncludeStrategy,
|
|
4534
|
+
[RelationKinds.BelongsToMany]: belongsToManyStrategy
|
|
4644
4535
|
};
|
|
4645
4536
|
|
|
4646
|
-
// src/query-builder/
|
|
4647
|
-
var
|
|
4537
|
+
// src/query-builder/relation-service.ts
|
|
4538
|
+
var RelationService = class {
|
|
4648
4539
|
/**
|
|
4649
|
-
* Creates a new
|
|
4650
|
-
* @param
|
|
4540
|
+
* Creates a new RelationService instance
|
|
4541
|
+
* @param table - Table definition
|
|
4542
|
+
* @param state - Current query state
|
|
4543
|
+
* @param hydration - Hydration manager
|
|
4651
4544
|
*/
|
|
4652
|
-
constructor(
|
|
4653
|
-
this.
|
|
4545
|
+
constructor(table, state, hydration, createQueryAstService) {
|
|
4546
|
+
this.table = table;
|
|
4547
|
+
this.state = state;
|
|
4548
|
+
this.hydration = hydration;
|
|
4549
|
+
this.createQueryAstService = createQueryAstService;
|
|
4550
|
+
this.projectionHelper = new RelationProjectionHelper(
|
|
4551
|
+
table,
|
|
4552
|
+
(state2, hydration2, columns) => this.selectColumns(state2, hydration2, columns)
|
|
4553
|
+
);
|
|
4554
|
+
this.joinPlanner = new RelationJoinPlanner(table, createQueryAstService);
|
|
4555
|
+
this.cteBuilder = new RelationCteBuilder(table, createQueryAstService);
|
|
4654
4556
|
}
|
|
4557
|
+
projectionHelper;
|
|
4558
|
+
joinPlanner;
|
|
4559
|
+
cteBuilder;
|
|
4655
4560
|
/**
|
|
4656
|
-
*
|
|
4657
|
-
* @param
|
|
4658
|
-
* @param
|
|
4659
|
-
* @
|
|
4561
|
+
* Joins a relation to the query
|
|
4562
|
+
* @param relationName - Name of the relation to join
|
|
4563
|
+
* @param joinKind - Type of join to use
|
|
4564
|
+
* @param extraCondition - Additional join condition
|
|
4565
|
+
* @returns Relation result with updated state and hydration
|
|
4660
4566
|
*/
|
|
4661
|
-
|
|
4662
|
-
const
|
|
4663
|
-
const
|
|
4664
|
-
|
|
4665
|
-
|
|
4666
|
-
|
|
4667
|
-
|
|
4567
|
+
joinRelation(relationName, joinKind, extraCondition, tableSource) {
|
|
4568
|
+
const relation = this.getRelation(relationName);
|
|
4569
|
+
const nextState = this.joinPlanner.withJoin(
|
|
4570
|
+
this.state,
|
|
4571
|
+
relationName,
|
|
4572
|
+
relation,
|
|
4573
|
+
joinKind,
|
|
4574
|
+
extraCondition,
|
|
4575
|
+
tableSource
|
|
4576
|
+
);
|
|
4577
|
+
return { state: nextState, hydration: this.hydration };
|
|
4668
4578
|
}
|
|
4669
4579
|
/**
|
|
4670
|
-
*
|
|
4671
|
-
* @param
|
|
4672
|
-
* @param
|
|
4673
|
-
* @returns
|
|
4580
|
+
* Matches records based on a relation with an optional predicate
|
|
4581
|
+
* @param relationName - Name of the relation to match
|
|
4582
|
+
* @param predicate - Optional predicate expression
|
|
4583
|
+
* @returns Relation result with updated state and hydration
|
|
4674
4584
|
*/
|
|
4675
|
-
|
|
4676
|
-
const
|
|
4677
|
-
const
|
|
4678
|
-
|
|
4585
|
+
match(relationName, predicate) {
|
|
4586
|
+
const joined = this.joinRelation(relationName, JOIN_KINDS.INNER, predicate);
|
|
4587
|
+
const pk = findPrimaryKey(this.table);
|
|
4588
|
+
const distinctCols = [{ type: "Column", table: this.rootTableName(), name: pk }];
|
|
4589
|
+
const existingDistinct = joined.state.ast.distinct ? joined.state.ast.distinct : [];
|
|
4590
|
+
const nextState = this.astService(joined.state).withDistinct([...existingDistinct, ...distinctCols]);
|
|
4591
|
+
return { state: nextState, hydration: joined.hydration };
|
|
4679
4592
|
}
|
|
4680
4593
|
/**
|
|
4681
|
-
*
|
|
4594
|
+
* Includes a relation in the query result
|
|
4595
|
+
* @param relationName - Name of the relation to include
|
|
4596
|
+
* @param options - Options for relation inclusion
|
|
4597
|
+
* @returns Relation result with updated state and hydration
|
|
4598
|
+
*/
|
|
4599
|
+
include(relationName, options) {
|
|
4600
|
+
let state = this.state;
|
|
4601
|
+
let hydration = this.hydration;
|
|
4602
|
+
const relation = this.getRelation(relationName);
|
|
4603
|
+
const aliasPrefix = options?.aliasPrefix ?? relationName;
|
|
4604
|
+
const alreadyJoined = state.ast.joins.some((j) => getJoinRelationName(j) === relationName);
|
|
4605
|
+
const { selfFilters, crossFilters } = splitFilterExpressions(
|
|
4606
|
+
options?.filter,
|
|
4607
|
+
/* @__PURE__ */ new Set([relation.target.name])
|
|
4608
|
+
);
|
|
4609
|
+
const canUseCte = !alreadyJoined && selfFilters.length > 0;
|
|
4610
|
+
const joinFilters = [...crossFilters];
|
|
4611
|
+
if (!canUseCte) {
|
|
4612
|
+
joinFilters.push(...selfFilters);
|
|
4613
|
+
}
|
|
4614
|
+
const joinCondition = this.combineWithAnd(joinFilters);
|
|
4615
|
+
let tableSourceOverride;
|
|
4616
|
+
if (canUseCte) {
|
|
4617
|
+
const predicate = this.combineWithAnd(selfFilters);
|
|
4618
|
+
const cteInfo = this.cteBuilder.createFilteredRelationCte(
|
|
4619
|
+
state,
|
|
4620
|
+
relationName,
|
|
4621
|
+
relation,
|
|
4622
|
+
predicate
|
|
4623
|
+
);
|
|
4624
|
+
state = cteInfo.state;
|
|
4625
|
+
tableSourceOverride = cteInfo.table;
|
|
4626
|
+
}
|
|
4627
|
+
if (!alreadyJoined) {
|
|
4628
|
+
state = this.joinPlanner.withJoin(
|
|
4629
|
+
state,
|
|
4630
|
+
relationName,
|
|
4631
|
+
relation,
|
|
4632
|
+
options?.joinKind ?? JOIN_KINDS.LEFT,
|
|
4633
|
+
joinCondition,
|
|
4634
|
+
tableSourceOverride
|
|
4635
|
+
);
|
|
4636
|
+
}
|
|
4637
|
+
const projectionResult = this.projectionHelper.ensureBaseProjection(state, hydration);
|
|
4638
|
+
state = projectionResult.state;
|
|
4639
|
+
hydration = projectionResult.hydration;
|
|
4640
|
+
const strategy = relationIncludeStrategies[relation.type];
|
|
4641
|
+
const result = strategy({
|
|
4642
|
+
rootTable: this.table,
|
|
4643
|
+
state,
|
|
4644
|
+
hydration,
|
|
4645
|
+
relation,
|
|
4646
|
+
relationName,
|
|
4647
|
+
aliasPrefix,
|
|
4648
|
+
options,
|
|
4649
|
+
selectColumns: (nextState, nextHydration, columns) => this.selectColumns(nextState, nextHydration, columns)
|
|
4650
|
+
});
|
|
4651
|
+
return { state: result.state, hydration: result.hydration };
|
|
4652
|
+
}
|
|
4653
|
+
/**
|
|
4654
|
+
* Applies relation correlation to a query AST
|
|
4655
|
+
* @param relationName - Name of the relation
|
|
4656
|
+
* @param ast - Query AST to modify
|
|
4657
|
+
* @returns Modified query AST with relation correlation
|
|
4658
|
+
*/
|
|
4659
|
+
applyRelationCorrelation(relationName, ast, additionalCorrelation) {
|
|
4660
|
+
const relation = this.getRelation(relationName);
|
|
4661
|
+
const rootAlias = this.state.ast.from.type === "Table" ? this.state.ast.from.alias : void 0;
|
|
4662
|
+
let correlation = buildRelationCorrelation(this.table, relation, rootAlias);
|
|
4663
|
+
if (additionalCorrelation) {
|
|
4664
|
+
correlation = and(correlation, additionalCorrelation);
|
|
4665
|
+
}
|
|
4666
|
+
const whereInSubquery = ast.where ? and(correlation, ast.where) : correlation;
|
|
4667
|
+
return {
|
|
4668
|
+
...ast,
|
|
4669
|
+
where: whereInSubquery
|
|
4670
|
+
};
|
|
4671
|
+
}
|
|
4672
|
+
/**
|
|
4673
|
+
* Selects columns for a relation
|
|
4674
|
+
* @param state - Current query state
|
|
4675
|
+
* @param hydration - Hydration manager
|
|
4676
|
+
* @param columns - Columns to select
|
|
4677
|
+
* @returns Relation result with updated state and hydration
|
|
4678
|
+
*/
|
|
4679
|
+
selectColumns(state, hydration, columns) {
|
|
4680
|
+
const { state: nextState, addedColumns } = this.astService(state).select(columns);
|
|
4681
|
+
return {
|
|
4682
|
+
state: nextState,
|
|
4683
|
+
hydration: hydration.onColumnsSelected(nextState, addedColumns)
|
|
4684
|
+
};
|
|
4685
|
+
}
|
|
4686
|
+
combineWithAnd(expressions) {
|
|
4687
|
+
if (expressions.length === 0) return void 0;
|
|
4688
|
+
if (expressions.length === 1) return expressions[0];
|
|
4689
|
+
return {
|
|
4690
|
+
type: "LogicalExpression",
|
|
4691
|
+
operator: "AND",
|
|
4692
|
+
operands: expressions
|
|
4693
|
+
};
|
|
4694
|
+
}
|
|
4695
|
+
/**
|
|
4696
|
+
* Gets a relation definition by name
|
|
4697
|
+
* @param relationName - Name of the relation
|
|
4698
|
+
* @returns Relation definition
|
|
4699
|
+
* @throws Error if relation is not found
|
|
4700
|
+
*/
|
|
4701
|
+
getRelation(relationName) {
|
|
4702
|
+
const relation = this.table.relations[relationName];
|
|
4703
|
+
if (!relation) {
|
|
4704
|
+
throw new Error(`Relation '${relationName}' not found on table '${this.table.name}'`);
|
|
4705
|
+
}
|
|
4706
|
+
return relation;
|
|
4707
|
+
}
|
|
4708
|
+
/**
|
|
4709
|
+
* Creates a QueryAstService instance
|
|
4710
|
+
* @param state - Current query state
|
|
4711
|
+
* @returns QueryAstService instance
|
|
4712
|
+
*/
|
|
4713
|
+
astService(state = this.state) {
|
|
4714
|
+
return this.createQueryAstService(this.table, state);
|
|
4715
|
+
}
|
|
4716
|
+
rootTableName() {
|
|
4717
|
+
const from = this.state.ast.from;
|
|
4718
|
+
if (from.type === "Table" && from.alias) return from.alias;
|
|
4719
|
+
return this.table.name;
|
|
4720
|
+
}
|
|
4721
|
+
};
|
|
4722
|
+
|
|
4723
|
+
// src/query-builder/column-selector.ts
|
|
4724
|
+
var ColumnSelector = class {
|
|
4725
|
+
/**
|
|
4726
|
+
* Creates a new ColumnSelector instance
|
|
4727
|
+
* @param env - Query builder environment
|
|
4728
|
+
*/
|
|
4729
|
+
constructor(env) {
|
|
4730
|
+
this.env = env;
|
|
4731
|
+
}
|
|
4732
|
+
/**
|
|
4733
|
+
* Selects columns for the query
|
|
4734
|
+
* @param context - Current query context
|
|
4735
|
+
* @param columns - Columns to select
|
|
4736
|
+
* @returns Updated query context with selected columns
|
|
4737
|
+
*/
|
|
4738
|
+
select(context, columns) {
|
|
4739
|
+
const astService = this.env.deps.createQueryAstService(this.env.table, context.state);
|
|
4740
|
+
const { state: nextState, addedColumns } = astService.select(columns);
|
|
4741
|
+
return {
|
|
4742
|
+
state: nextState,
|
|
4743
|
+
hydration: context.hydration.onColumnsSelected(nextState, addedColumns)
|
|
4744
|
+
};
|
|
4745
|
+
}
|
|
4746
|
+
/**
|
|
4747
|
+
* Selects raw column expressions
|
|
4748
|
+
* @param context - Current query context
|
|
4749
|
+
* @param columns - Raw column expressions
|
|
4750
|
+
* @returns Updated query context with raw column selections
|
|
4751
|
+
*/
|
|
4752
|
+
selectRaw(context, columns) {
|
|
4753
|
+
const astService = this.env.deps.createQueryAstService(this.env.table, context.state);
|
|
4754
|
+
const nextState = astService.selectRaw(columns).state;
|
|
4755
|
+
return { state: nextState, hydration: context.hydration };
|
|
4756
|
+
}
|
|
4757
|
+
/**
|
|
4758
|
+
* Selects a subquery as a column
|
|
4682
4759
|
* @param context - Current query context
|
|
4683
4760
|
* @param alias - Alias for the subquery
|
|
4684
4761
|
* @param query - Subquery to select
|
|
@@ -4903,8 +4980,52 @@ var hasEntityMeta = (entity) => {
|
|
|
4903
4980
|
return Boolean(getEntityMeta(entity));
|
|
4904
4981
|
};
|
|
4905
4982
|
|
|
4906
|
-
// src/orm/
|
|
4983
|
+
// src/orm/entity-hydration.ts
|
|
4907
4984
|
var toKey2 = (value) => value === null || value === void 0 ? "" : String(value);
|
|
4985
|
+
var populateHydrationCache = (entity, row, meta) => {
|
|
4986
|
+
for (const relationName of Object.keys(meta.table.relations)) {
|
|
4987
|
+
const relation = meta.table.relations[relationName];
|
|
4988
|
+
const data = row[relationName];
|
|
4989
|
+
if (relation.type === RelationKinds.HasOne) {
|
|
4990
|
+
const localKey = relation.localKey || findPrimaryKey(meta.table);
|
|
4991
|
+
const rootValue = entity[localKey];
|
|
4992
|
+
if (rootValue === void 0 || rootValue === null) continue;
|
|
4993
|
+
if (!data || typeof data !== "object") continue;
|
|
4994
|
+
const cache = /* @__PURE__ */ new Map();
|
|
4995
|
+
cache.set(toKey2(rootValue), data);
|
|
4996
|
+
meta.relationHydration.set(relationName, cache);
|
|
4997
|
+
meta.relationCache.set(relationName, Promise.resolve(cache));
|
|
4998
|
+
continue;
|
|
4999
|
+
}
|
|
5000
|
+
if (!Array.isArray(data)) continue;
|
|
5001
|
+
if (relation.type === RelationKinds.HasMany || relation.type === RelationKinds.BelongsToMany) {
|
|
5002
|
+
const localKey = relation.localKey || findPrimaryKey(meta.table);
|
|
5003
|
+
const rootValue = entity[localKey];
|
|
5004
|
+
if (rootValue === void 0 || rootValue === null) continue;
|
|
5005
|
+
const cache = /* @__PURE__ */ new Map();
|
|
5006
|
+
cache.set(toKey2(rootValue), data);
|
|
5007
|
+
meta.relationHydration.set(relationName, cache);
|
|
5008
|
+
meta.relationCache.set(relationName, Promise.resolve(cache));
|
|
5009
|
+
continue;
|
|
5010
|
+
}
|
|
5011
|
+
if (relation.type === RelationKinds.BelongsTo) {
|
|
5012
|
+
const targetKey = relation.localKey || findPrimaryKey(relation.target);
|
|
5013
|
+
const cache = /* @__PURE__ */ new Map();
|
|
5014
|
+
for (const item of data) {
|
|
5015
|
+
const pkValue = item[targetKey];
|
|
5016
|
+
if (pkValue === void 0 || pkValue === null) continue;
|
|
5017
|
+
cache.set(toKey2(pkValue), item);
|
|
5018
|
+
}
|
|
5019
|
+
if (cache.size) {
|
|
5020
|
+
meta.relationHydration.set(relationName, cache);
|
|
5021
|
+
meta.relationCache.set(relationName, Promise.resolve(cache));
|
|
5022
|
+
}
|
|
5023
|
+
}
|
|
5024
|
+
}
|
|
5025
|
+
};
|
|
5026
|
+
|
|
5027
|
+
// src/orm/relations/has-many.ts
|
|
5028
|
+
var toKey3 = (value) => value === null || value === void 0 ? "" : String(value);
|
|
4908
5029
|
var hideInternal = (obj, keys) => {
|
|
4909
5030
|
for (const key of keys) {
|
|
4910
5031
|
Object.defineProperty(obj, key, {
|
|
@@ -4938,13 +5059,13 @@ var DefaultHasManyCollection = class {
|
|
|
4938
5059
|
this.loader = loader;
|
|
4939
5060
|
this.createEntity = createEntity;
|
|
4940
5061
|
this.localKey = localKey;
|
|
4941
|
-
this.loaded = false;
|
|
4942
|
-
this.items = [];
|
|
4943
|
-
this.added = /* @__PURE__ */ new Set();
|
|
4944
|
-
this.removed = /* @__PURE__ */ new Set();
|
|
4945
5062
|
hideInternal(this, ["ctx", "meta", "root", "relationName", "relation", "rootTable", "loader", "createEntity", "localKey"]);
|
|
4946
5063
|
this.hydrateFromCache();
|
|
4947
5064
|
}
|
|
5065
|
+
loaded = false;
|
|
5066
|
+
items = [];
|
|
5067
|
+
added = /* @__PURE__ */ new Set();
|
|
5068
|
+
removed = /* @__PURE__ */ new Set();
|
|
4948
5069
|
/**
|
|
4949
5070
|
* Loads the related entities if not already loaded.
|
|
4950
5071
|
* @returns Promise resolving to the array of child entities
|
|
@@ -4952,7 +5073,7 @@ var DefaultHasManyCollection = class {
|
|
|
4952
5073
|
async load() {
|
|
4953
5074
|
if (this.loaded) return this.items;
|
|
4954
5075
|
const map = await this.loader();
|
|
4955
|
-
const key =
|
|
5076
|
+
const key = toKey3(this.root[this.localKey]);
|
|
4956
5077
|
const rows = map.get(key) ?? [];
|
|
4957
5078
|
this.items = rows.map((row) => this.createEntity(row));
|
|
4958
5079
|
this.loaded = true;
|
|
@@ -5064,7 +5185,7 @@ var DefaultHasManyCollection = class {
|
|
|
5064
5185
|
};
|
|
5065
5186
|
|
|
5066
5187
|
// src/orm/relations/has-one.ts
|
|
5067
|
-
var
|
|
5188
|
+
var toKey4 = (value) => value === null || value === void 0 ? "" : String(value);
|
|
5068
5189
|
var hideInternal2 = (obj, keys) => {
|
|
5069
5190
|
for (const key of keys) {
|
|
5070
5191
|
Object.defineProperty(obj, key, {
|
|
@@ -5097,8 +5218,6 @@ var DefaultHasOneReference = class {
|
|
|
5097
5218
|
this.loader = loader;
|
|
5098
5219
|
this.createEntity = createEntity;
|
|
5099
5220
|
this.localKey = localKey;
|
|
5100
|
-
this.loaded = false;
|
|
5101
|
-
this.current = null;
|
|
5102
5221
|
hideInternal2(this, [
|
|
5103
5222
|
"ctx",
|
|
5104
5223
|
"meta",
|
|
@@ -5112,6 +5231,8 @@ var DefaultHasOneReference = class {
|
|
|
5112
5231
|
]);
|
|
5113
5232
|
this.populateFromHydrationCache();
|
|
5114
5233
|
}
|
|
5234
|
+
loaded = false;
|
|
5235
|
+
current = null;
|
|
5115
5236
|
async load() {
|
|
5116
5237
|
if (this.loaded) return this.current;
|
|
5117
5238
|
const map = await this.loader();
|
|
@@ -5120,7 +5241,7 @@ var DefaultHasOneReference = class {
|
|
|
5120
5241
|
this.loaded = true;
|
|
5121
5242
|
return this.current;
|
|
5122
5243
|
}
|
|
5123
|
-
const row = map.get(
|
|
5244
|
+
const row = map.get(toKey4(keyValue));
|
|
5124
5245
|
this.current = row ? this.createEntity(row) : null;
|
|
5125
5246
|
this.loaded = true;
|
|
5126
5247
|
return this.current;
|
|
@@ -5192,7 +5313,7 @@ var DefaultHasOneReference = class {
|
|
|
5192
5313
|
};
|
|
5193
5314
|
|
|
5194
5315
|
// src/orm/relations/belongs-to.ts
|
|
5195
|
-
var
|
|
5316
|
+
var toKey5 = (value) => value === null || value === void 0 ? "" : String(value);
|
|
5196
5317
|
var hideInternal3 = (obj, keys) => {
|
|
5197
5318
|
for (const key of keys) {
|
|
5198
5319
|
Object.defineProperty(obj, key, {
|
|
@@ -5225,11 +5346,11 @@ var DefaultBelongsToReference = class {
|
|
|
5225
5346
|
this.loader = loader;
|
|
5226
5347
|
this.createEntity = createEntity;
|
|
5227
5348
|
this.targetKey = targetKey;
|
|
5228
|
-
this.loaded = false;
|
|
5229
|
-
this.current = null;
|
|
5230
5349
|
hideInternal3(this, ["ctx", "meta", "root", "relationName", "relation", "rootTable", "loader", "createEntity", "targetKey"]);
|
|
5231
5350
|
this.populateFromHydrationCache();
|
|
5232
5351
|
}
|
|
5352
|
+
loaded = false;
|
|
5353
|
+
current = null;
|
|
5233
5354
|
async load() {
|
|
5234
5355
|
if (this.loaded) return this.current;
|
|
5235
5356
|
const map = await this.loader();
|
|
@@ -5237,7 +5358,7 @@ var DefaultBelongsToReference = class {
|
|
|
5237
5358
|
if (fkValue === null || fkValue === void 0) {
|
|
5238
5359
|
this.current = null;
|
|
5239
5360
|
} else {
|
|
5240
|
-
const row = map.get(
|
|
5361
|
+
const row = map.get(toKey5(fkValue));
|
|
5241
5362
|
this.current = row ? this.createEntity(row) : null;
|
|
5242
5363
|
}
|
|
5243
5364
|
this.loaded = true;
|
|
@@ -5294,7 +5415,7 @@ var DefaultBelongsToReference = class {
|
|
|
5294
5415
|
};
|
|
5295
5416
|
|
|
5296
5417
|
// src/orm/relations/many-to-many.ts
|
|
5297
|
-
var
|
|
5418
|
+
var toKey6 = (value) => value === null || value === void 0 ? "" : String(value);
|
|
5298
5419
|
var hideInternal4 = (obj, keys) => {
|
|
5299
5420
|
for (const key of keys) {
|
|
5300
5421
|
Object.defineProperty(obj, key, {
|
|
@@ -5327,11 +5448,11 @@ var DefaultManyToManyCollection = class {
|
|
|
5327
5448
|
this.loader = loader;
|
|
5328
5449
|
this.createEntity = createEntity;
|
|
5329
5450
|
this.localKey = localKey;
|
|
5330
|
-
this.loaded = false;
|
|
5331
|
-
this.items = [];
|
|
5332
5451
|
hideInternal4(this, ["ctx", "meta", "root", "relationName", "relation", "rootTable", "loader", "createEntity", "localKey"]);
|
|
5333
5452
|
this.hydrateFromCache();
|
|
5334
5453
|
}
|
|
5454
|
+
loaded = false;
|
|
5455
|
+
items = [];
|
|
5335
5456
|
/**
|
|
5336
5457
|
* Loads the collection items if not already loaded.
|
|
5337
5458
|
* @returns A promise that resolves to the array of target entities.
|
|
@@ -5339,7 +5460,7 @@ var DefaultManyToManyCollection = class {
|
|
|
5339
5460
|
async load() {
|
|
5340
5461
|
if (this.loaded) return this.items;
|
|
5341
5462
|
const map = await this.loader();
|
|
5342
|
-
const key =
|
|
5463
|
+
const key = toKey6(this.root[this.localKey]);
|
|
5343
5464
|
const rows = map.get(key) ?? [];
|
|
5344
5465
|
this.items = rows.map((row) => {
|
|
5345
5466
|
const entity = this.createEntity(row);
|
|
@@ -5421,15 +5542,15 @@ var DefaultManyToManyCollection = class {
|
|
|
5421
5542
|
*/
|
|
5422
5543
|
async syncByIds(ids) {
|
|
5423
5544
|
await this.load();
|
|
5424
|
-
const normalized = new Set(ids.map((id) =>
|
|
5425
|
-
const currentIds = new Set(this.items.map((item) =>
|
|
5545
|
+
const normalized = new Set(ids.map((id) => toKey6(id)));
|
|
5546
|
+
const currentIds = new Set(this.items.map((item) => toKey6(this.extractId(item))));
|
|
5426
5547
|
for (const id of normalized) {
|
|
5427
5548
|
if (!currentIds.has(id)) {
|
|
5428
5549
|
this.attach(id);
|
|
5429
5550
|
}
|
|
5430
5551
|
}
|
|
5431
5552
|
for (const item of [...this.items]) {
|
|
5432
|
-
const itemId =
|
|
5553
|
+
const itemId = toKey6(this.extractId(item));
|
|
5433
5554
|
if (!normalized.has(itemId)) {
|
|
5434
5555
|
this.detach(item);
|
|
5435
5556
|
}
|
|
@@ -5476,7 +5597,7 @@ var DefaultManyToManyCollection = class {
|
|
|
5476
5597
|
}
|
|
5477
5598
|
};
|
|
5478
5599
|
|
|
5479
|
-
// src/orm/lazy-batch.ts
|
|
5600
|
+
// src/orm/lazy-batch/shared.ts
|
|
5480
5601
|
var hasColumns = (columns) => Boolean(columns && columns.length > 0);
|
|
5481
5602
|
var buildColumnSelection = (table, columns, missingMsg) => {
|
|
5482
5603
|
return columns.reduce((acc, column) => {
|
|
@@ -5517,7 +5638,7 @@ var executeQuery = async (ctx, qb) => {
|
|
|
5517
5638
|
const results = await ctx.executor.executeSql(compiled.sql, compiled.params);
|
|
5518
5639
|
return rowsFromResults(results);
|
|
5519
5640
|
};
|
|
5520
|
-
var
|
|
5641
|
+
var toKey7 = (value) => value === null || value === void 0 ? "" : String(value);
|
|
5521
5642
|
var collectKeysFromRoots = (roots, key) => {
|
|
5522
5643
|
const collected = /* @__PURE__ */ new Set();
|
|
5523
5644
|
for (const tracked of roots) {
|
|
@@ -5542,7 +5663,7 @@ var groupRowsByMany = (rows, keyColumn) => {
|
|
|
5542
5663
|
for (const row of rows) {
|
|
5543
5664
|
const value = row[keyColumn];
|
|
5544
5665
|
if (value === null || value === void 0) continue;
|
|
5545
|
-
const key =
|
|
5666
|
+
const key = toKey7(value);
|
|
5546
5667
|
const bucket = grouped.get(key) ?? [];
|
|
5547
5668
|
bucket.push(row);
|
|
5548
5669
|
grouped.set(key, bucket);
|
|
@@ -5554,13 +5675,15 @@ var groupRowsByUnique = (rows, keyColumn) => {
|
|
|
5554
5675
|
for (const row of rows) {
|
|
5555
5676
|
const value = row[keyColumn];
|
|
5556
5677
|
if (value === null || value === void 0) continue;
|
|
5557
|
-
const key =
|
|
5678
|
+
const key = toKey7(value);
|
|
5558
5679
|
if (!lookup.has(key)) {
|
|
5559
5680
|
lookup.set(key, row);
|
|
5560
5681
|
}
|
|
5561
5682
|
}
|
|
5562
5683
|
return lookup;
|
|
5563
5684
|
};
|
|
5685
|
+
|
|
5686
|
+
// src/orm/lazy-batch/has-many.ts
|
|
5564
5687
|
var loadHasManyRelation = async (ctx, rootTable, relationName, relation, options) => {
|
|
5565
5688
|
const localKey = relation.localKey || findPrimaryKey(rootTable);
|
|
5566
5689
|
const roots = ctx.getEntitiesForTable(rootTable);
|
|
@@ -5593,6 +5716,8 @@ var loadHasManyRelation = async (ctx, rootTable, relationName, relation, options
|
|
|
5593
5716
|
}
|
|
5594
5717
|
return filtered;
|
|
5595
5718
|
};
|
|
5719
|
+
|
|
5720
|
+
// src/orm/lazy-batch/has-one.ts
|
|
5596
5721
|
var loadHasOneRelation = async (ctx, rootTable, relationName, relation, options) => {
|
|
5597
5722
|
const localKey = relation.localKey || findPrimaryKey(rootTable);
|
|
5598
5723
|
const roots = ctx.getEntitiesForTable(rootTable);
|
|
@@ -5625,6 +5750,8 @@ var loadHasOneRelation = async (ctx, rootTable, relationName, relation, options)
|
|
|
5625
5750
|
}
|
|
5626
5751
|
return filtered;
|
|
5627
5752
|
};
|
|
5753
|
+
|
|
5754
|
+
// src/orm/lazy-batch/belongs-to.ts
|
|
5628
5755
|
var loadBelongsToRelation = async (ctx, rootTable, relationName, relation, options) => {
|
|
5629
5756
|
const roots = ctx.getEntitiesForTable(rootTable);
|
|
5630
5757
|
const getForeignKeys = () => collectKeysFromRoots(roots, relation.foreignKey);
|
|
@@ -5693,6 +5820,8 @@ var loadBelongsToRelation = async (ctx, rootTable, relationName, relation, optio
|
|
|
5693
5820
|
}
|
|
5694
5821
|
return filtered;
|
|
5695
5822
|
};
|
|
5823
|
+
|
|
5824
|
+
// src/orm/lazy-batch/belongs-to-many.ts
|
|
5696
5825
|
var loadBelongsToManyRelation = async (ctx, rootTable, relationName, relation, options) => {
|
|
5697
5826
|
const rootKey = relation.localKey || findPrimaryKey(rootTable);
|
|
5698
5827
|
const roots = ctx.getEntitiesForTable(rootTable);
|
|
@@ -5731,12 +5860,12 @@ var loadBelongsToManyRelation = async (ctx, rootTable, relationName, relation, o
|
|
|
5731
5860
|
if (rootValue === null || rootValue === void 0 || targetValue === null || targetValue === void 0) {
|
|
5732
5861
|
continue;
|
|
5733
5862
|
}
|
|
5734
|
-
const bucket = rootLookup.get(
|
|
5863
|
+
const bucket = rootLookup.get(toKey7(rootValue)) ?? [];
|
|
5735
5864
|
bucket.push({
|
|
5736
5865
|
targetId: targetValue,
|
|
5737
5866
|
pivot: pivotVisibleColumns.size ? filterRow(pivot, pivotVisibleColumns) : {}
|
|
5738
5867
|
});
|
|
5739
|
-
rootLookup.set(
|
|
5868
|
+
rootLookup.set(toKey7(rootValue), bucket);
|
|
5740
5869
|
targetIds.add(targetValue);
|
|
5741
5870
|
}
|
|
5742
5871
|
if (!targetIds.size) {
|
|
@@ -5755,14 +5884,21 @@ var loadBelongsToManyRelation = async (ctx, rootTable, relationName, relation, o
|
|
|
5755
5884
|
targetSelectedColumns,
|
|
5756
5885
|
(column) => `Column '${column}' not found on relation '${relationName}'`
|
|
5757
5886
|
);
|
|
5758
|
-
const targetRows = await fetchRowsForKeys(
|
|
5887
|
+
const targetRows = await fetchRowsForKeys(
|
|
5888
|
+
ctx,
|
|
5889
|
+
relation.target,
|
|
5890
|
+
targetPkColumn,
|
|
5891
|
+
targetIds,
|
|
5892
|
+
targetSelection,
|
|
5893
|
+
options?.filter
|
|
5894
|
+
);
|
|
5759
5895
|
const targetMap = groupRowsByUnique(targetRows, targetKey);
|
|
5760
5896
|
const targetVisibleColumns = new Set(targetSelectedColumns);
|
|
5761
5897
|
const result = /* @__PURE__ */ new Map();
|
|
5762
5898
|
for (const [rootId, entries] of rootLookup.entries()) {
|
|
5763
5899
|
const bucket = [];
|
|
5764
5900
|
for (const entry of entries) {
|
|
5765
|
-
const targetRow = targetMap.get(
|
|
5901
|
+
const targetRow = targetMap.get(toKey7(entry.targetId));
|
|
5766
5902
|
if (!targetRow) continue;
|
|
5767
5903
|
bucket.push({
|
|
5768
5904
|
...targetRequestedColumns ? filterRow(targetRow, targetVisibleColumns) : targetRow,
|
|
@@ -5774,7 +5910,7 @@ var loadBelongsToManyRelation = async (ctx, rootTable, relationName, relation, o
|
|
|
5774
5910
|
return result;
|
|
5775
5911
|
};
|
|
5776
5912
|
|
|
5777
|
-
// src/orm/entity.ts
|
|
5913
|
+
// src/orm/entity-relation-cache.ts
|
|
5778
5914
|
var relationLoaderCache = (meta, relationName, factory) => {
|
|
5779
5915
|
if (meta.relationCache.has(relationName)) {
|
|
5780
5916
|
return meta.relationCache.get(relationName);
|
|
@@ -5795,118 +5931,16 @@ var relationLoaderCache = (meta, relationName, factory) => {
|
|
|
5795
5931
|
}
|
|
5796
5932
|
return promise;
|
|
5797
5933
|
};
|
|
5798
|
-
|
|
5799
|
-
|
|
5800
|
-
|
|
5801
|
-
|
|
5802
|
-
|
|
5803
|
-
|
|
5804
|
-
|
|
5805
|
-
relationCache: /* @__PURE__ */ new Map(),
|
|
5806
|
-
relationHydration: /* @__PURE__ */ new Map(),
|
|
5807
|
-
relationWrappers: /* @__PURE__ */ new Map()
|
|
5808
|
-
};
|
|
5809
|
-
Object.defineProperty(target, ENTITY_META, {
|
|
5810
|
-
value: meta,
|
|
5811
|
-
enumerable: false,
|
|
5812
|
-
writable: false
|
|
5813
|
-
});
|
|
5814
|
-
const handler = {
|
|
5815
|
-
get(targetObj, prop, receiver) {
|
|
5816
|
-
if (prop === ENTITY_META) {
|
|
5817
|
-
return meta;
|
|
5818
|
-
}
|
|
5819
|
-
if (prop === "$load") {
|
|
5820
|
-
return async (relationName) => {
|
|
5821
|
-
const wrapper = getRelationWrapper(meta, relationName, receiver);
|
|
5822
|
-
if (wrapper && typeof wrapper.load === "function") {
|
|
5823
|
-
return wrapper.load();
|
|
5824
|
-
}
|
|
5825
|
-
return void 0;
|
|
5826
|
-
};
|
|
5934
|
+
|
|
5935
|
+
// src/orm/entity-relations.ts
|
|
5936
|
+
var proxifyRelationWrapper = (wrapper) => {
|
|
5937
|
+
return new Proxy(wrapper, {
|
|
5938
|
+
get(target, prop, receiver) {
|
|
5939
|
+
if (typeof prop === "symbol") {
|
|
5940
|
+
return Reflect.get(target, prop, receiver);
|
|
5827
5941
|
}
|
|
5828
|
-
if (
|
|
5829
|
-
return
|
|
5830
|
-
}
|
|
5831
|
-
return Reflect.get(targetObj, prop, receiver);
|
|
5832
|
-
},
|
|
5833
|
-
set(targetObj, prop, value, receiver) {
|
|
5834
|
-
const result = Reflect.set(targetObj, prop, value, receiver);
|
|
5835
|
-
if (typeof prop === "string" && table.columns[prop]) {
|
|
5836
|
-
ctx.markDirty(receiver);
|
|
5837
|
-
}
|
|
5838
|
-
return result;
|
|
5839
|
-
}
|
|
5840
|
-
};
|
|
5841
|
-
const proxy = new Proxy(target, handler);
|
|
5842
|
-
populateHydrationCache(proxy, row, meta);
|
|
5843
|
-
return proxy;
|
|
5844
|
-
};
|
|
5845
|
-
var createEntityFromRow = (ctx, table, row, lazyRelations = [], lazyRelationOptions = /* @__PURE__ */ new Map()) => {
|
|
5846
|
-
const pkName = findPrimaryKey(table);
|
|
5847
|
-
const pkValue = row[pkName];
|
|
5848
|
-
if (pkValue !== void 0 && pkValue !== null) {
|
|
5849
|
-
const tracked = ctx.getEntity(table, pkValue);
|
|
5850
|
-
if (tracked) return tracked;
|
|
5851
|
-
}
|
|
5852
|
-
const entity = createEntityProxy(ctx, table, row, lazyRelations, lazyRelationOptions);
|
|
5853
|
-
if (pkValue !== void 0 && pkValue !== null) {
|
|
5854
|
-
ctx.trackManaged(table, pkValue, entity);
|
|
5855
|
-
} else {
|
|
5856
|
-
ctx.trackNew(table, entity);
|
|
5857
|
-
}
|
|
5858
|
-
return entity;
|
|
5859
|
-
};
|
|
5860
|
-
var toKey7 = (value) => value === null || value === void 0 ? "" : String(value);
|
|
5861
|
-
var populateHydrationCache = (entity, row, meta) => {
|
|
5862
|
-
for (const relationName of Object.keys(meta.table.relations)) {
|
|
5863
|
-
const relation = meta.table.relations[relationName];
|
|
5864
|
-
const data = row[relationName];
|
|
5865
|
-
if (relation.type === RelationKinds.HasOne) {
|
|
5866
|
-
const localKey = relation.localKey || findPrimaryKey(meta.table);
|
|
5867
|
-
const rootValue = entity[localKey];
|
|
5868
|
-
if (rootValue === void 0 || rootValue === null) continue;
|
|
5869
|
-
if (!data || typeof data !== "object") continue;
|
|
5870
|
-
const cache = /* @__PURE__ */ new Map();
|
|
5871
|
-
cache.set(toKey7(rootValue), data);
|
|
5872
|
-
meta.relationHydration.set(relationName, cache);
|
|
5873
|
-
meta.relationCache.set(relationName, Promise.resolve(cache));
|
|
5874
|
-
continue;
|
|
5875
|
-
}
|
|
5876
|
-
if (!Array.isArray(data)) continue;
|
|
5877
|
-
if (relation.type === RelationKinds.HasMany || relation.type === RelationKinds.BelongsToMany) {
|
|
5878
|
-
const localKey = relation.localKey || findPrimaryKey(meta.table);
|
|
5879
|
-
const rootValue = entity[localKey];
|
|
5880
|
-
if (rootValue === void 0 || rootValue === null) continue;
|
|
5881
|
-
const cache = /* @__PURE__ */ new Map();
|
|
5882
|
-
cache.set(toKey7(rootValue), data);
|
|
5883
|
-
meta.relationHydration.set(relationName, cache);
|
|
5884
|
-
meta.relationCache.set(relationName, Promise.resolve(cache));
|
|
5885
|
-
continue;
|
|
5886
|
-
}
|
|
5887
|
-
if (relation.type === RelationKinds.BelongsTo) {
|
|
5888
|
-
const targetKey = relation.localKey || findPrimaryKey(relation.target);
|
|
5889
|
-
const cache = /* @__PURE__ */ new Map();
|
|
5890
|
-
for (const item of data) {
|
|
5891
|
-
const pkValue = item[targetKey];
|
|
5892
|
-
if (pkValue === void 0 || pkValue === null) continue;
|
|
5893
|
-
cache.set(toKey7(pkValue), item);
|
|
5894
|
-
}
|
|
5895
|
-
if (cache.size) {
|
|
5896
|
-
meta.relationHydration.set(relationName, cache);
|
|
5897
|
-
meta.relationCache.set(relationName, Promise.resolve(cache));
|
|
5898
|
-
}
|
|
5899
|
-
}
|
|
5900
|
-
}
|
|
5901
|
-
};
|
|
5902
|
-
var proxifyRelationWrapper = (wrapper) => {
|
|
5903
|
-
return new Proxy(wrapper, {
|
|
5904
|
-
get(target, prop, receiver) {
|
|
5905
|
-
if (typeof prop === "symbol") {
|
|
5906
|
-
return Reflect.get(target, prop, receiver);
|
|
5907
|
-
}
|
|
5908
|
-
if (prop in target) {
|
|
5909
|
-
return Reflect.get(target, prop, receiver);
|
|
5942
|
+
if (prop in target) {
|
|
5943
|
+
return Reflect.get(target, prop, receiver);
|
|
5910
5944
|
}
|
|
5911
5945
|
const getItems = target.getItems;
|
|
5912
5946
|
if (typeof getItems === "function") {
|
|
@@ -5951,98 +5985,93 @@ var proxifyRelationWrapper = (wrapper) => {
|
|
|
5951
5985
|
}
|
|
5952
5986
|
});
|
|
5953
5987
|
};
|
|
5954
|
-
var getRelationWrapper = (meta, relationName, owner) => {
|
|
5955
|
-
|
|
5956
|
-
|
|
5988
|
+
var getRelationWrapper = (meta, relationName, owner, createEntity) => {
|
|
5989
|
+
const relationKey = relationName;
|
|
5990
|
+
if (meta.relationWrappers.has(relationKey)) {
|
|
5991
|
+
return meta.relationWrappers.get(relationKey);
|
|
5957
5992
|
}
|
|
5958
|
-
const relation = meta.table.relations[
|
|
5993
|
+
const relation = meta.table.relations[relationKey];
|
|
5959
5994
|
if (!relation) return void 0;
|
|
5960
|
-
const wrapper = instantiateWrapper(meta,
|
|
5995
|
+
const wrapper = instantiateWrapper(meta, relationKey, relation, owner, createEntity);
|
|
5961
5996
|
if (!wrapper) return void 0;
|
|
5962
5997
|
const proxied = proxifyRelationWrapper(wrapper);
|
|
5963
|
-
meta.relationWrappers.set(
|
|
5998
|
+
meta.relationWrappers.set(relationKey, proxied);
|
|
5964
5999
|
return proxied;
|
|
5965
6000
|
};
|
|
5966
|
-
var instantiateWrapper = (meta, relationName, relation, owner) => {
|
|
6001
|
+
var instantiateWrapper = (meta, relationName, relation, owner, createEntity) => {
|
|
6002
|
+
const metaBase = meta;
|
|
5967
6003
|
const lazyOptions = meta.lazyRelationOptions.get(relationName);
|
|
6004
|
+
const loadCached = (factory) => relationLoaderCache(metaBase, relationName, factory);
|
|
5968
6005
|
switch (relation.type) {
|
|
5969
6006
|
case RelationKinds.HasOne: {
|
|
5970
6007
|
const hasOne2 = relation;
|
|
5971
6008
|
const localKey = hasOne2.localKey || findPrimaryKey(meta.table);
|
|
5972
|
-
const loader = () =>
|
|
5973
|
-
meta,
|
|
5974
|
-
relationName,
|
|
6009
|
+
const loader = () => loadCached(
|
|
5975
6010
|
() => loadHasOneRelation(meta.ctx, meta.table, relationName, hasOne2, lazyOptions)
|
|
5976
6011
|
);
|
|
5977
6012
|
return new DefaultHasOneReference(
|
|
5978
6013
|
meta.ctx,
|
|
5979
|
-
|
|
6014
|
+
metaBase,
|
|
5980
6015
|
owner,
|
|
5981
6016
|
relationName,
|
|
5982
6017
|
hasOne2,
|
|
5983
6018
|
meta.table,
|
|
5984
6019
|
loader,
|
|
5985
|
-
(row) =>
|
|
6020
|
+
(row) => createEntity(hasOne2.target, row),
|
|
5986
6021
|
localKey
|
|
5987
6022
|
);
|
|
5988
6023
|
}
|
|
5989
6024
|
case RelationKinds.HasMany: {
|
|
5990
6025
|
const hasMany2 = relation;
|
|
5991
6026
|
const localKey = hasMany2.localKey || findPrimaryKey(meta.table);
|
|
5992
|
-
const loader = () =>
|
|
5993
|
-
meta,
|
|
5994
|
-
relationName,
|
|
6027
|
+
const loader = () => loadCached(
|
|
5995
6028
|
() => loadHasManyRelation(meta.ctx, meta.table, relationName, hasMany2, lazyOptions)
|
|
5996
6029
|
);
|
|
5997
6030
|
return new DefaultHasManyCollection(
|
|
5998
6031
|
meta.ctx,
|
|
5999
|
-
|
|
6032
|
+
metaBase,
|
|
6000
6033
|
owner,
|
|
6001
6034
|
relationName,
|
|
6002
6035
|
hasMany2,
|
|
6003
6036
|
meta.table,
|
|
6004
6037
|
loader,
|
|
6005
|
-
(row) =>
|
|
6038
|
+
(row) => createEntity(relation.target, row),
|
|
6006
6039
|
localKey
|
|
6007
6040
|
);
|
|
6008
6041
|
}
|
|
6009
6042
|
case RelationKinds.BelongsTo: {
|
|
6010
6043
|
const belongsTo2 = relation;
|
|
6011
6044
|
const targetKey = belongsTo2.localKey || findPrimaryKey(belongsTo2.target);
|
|
6012
|
-
const loader = () =>
|
|
6013
|
-
meta,
|
|
6014
|
-
relationName,
|
|
6045
|
+
const loader = () => loadCached(
|
|
6015
6046
|
() => loadBelongsToRelation(meta.ctx, meta.table, relationName, belongsTo2, lazyOptions)
|
|
6016
6047
|
);
|
|
6017
6048
|
return new DefaultBelongsToReference(
|
|
6018
6049
|
meta.ctx,
|
|
6019
|
-
|
|
6050
|
+
metaBase,
|
|
6020
6051
|
owner,
|
|
6021
6052
|
relationName,
|
|
6022
6053
|
belongsTo2,
|
|
6023
6054
|
meta.table,
|
|
6024
6055
|
loader,
|
|
6025
|
-
(row) =>
|
|
6056
|
+
(row) => createEntity(relation.target, row),
|
|
6026
6057
|
targetKey
|
|
6027
6058
|
);
|
|
6028
6059
|
}
|
|
6029
6060
|
case RelationKinds.BelongsToMany: {
|
|
6030
6061
|
const many = relation;
|
|
6031
6062
|
const localKey = many.localKey || findPrimaryKey(meta.table);
|
|
6032
|
-
const loader = () =>
|
|
6033
|
-
meta,
|
|
6034
|
-
relationName,
|
|
6063
|
+
const loader = () => loadCached(
|
|
6035
6064
|
() => loadBelongsToManyRelation(meta.ctx, meta.table, relationName, many, lazyOptions)
|
|
6036
6065
|
);
|
|
6037
6066
|
return new DefaultManyToManyCollection(
|
|
6038
6067
|
meta.ctx,
|
|
6039
|
-
|
|
6068
|
+
metaBase,
|
|
6040
6069
|
owner,
|
|
6041
6070
|
relationName,
|
|
6042
6071
|
many,
|
|
6043
6072
|
meta.table,
|
|
6044
6073
|
loader,
|
|
6045
|
-
(row) =>
|
|
6074
|
+
(row) => createEntity(relation.target, row),
|
|
6046
6075
|
localKey
|
|
6047
6076
|
);
|
|
6048
6077
|
}
|
|
@@ -6051,103 +6080,570 @@ var instantiateWrapper = (meta, relationName, relation, owner) => {
|
|
|
6051
6080
|
}
|
|
6052
6081
|
};
|
|
6053
6082
|
|
|
6054
|
-
// src/orm/
|
|
6055
|
-
var
|
|
6056
|
-
const
|
|
6057
|
-
|
|
6058
|
-
|
|
6059
|
-
|
|
6060
|
-
|
|
6061
|
-
|
|
6062
|
-
|
|
6063
|
-
|
|
6064
|
-
|
|
6065
|
-
|
|
6083
|
+
// src/orm/entity.ts
|
|
6084
|
+
var createEntityProxy = (ctx, table, row, lazyRelations = [], lazyRelationOptions = /* @__PURE__ */ new Map()) => {
|
|
6085
|
+
const target = { ...row };
|
|
6086
|
+
const meta = {
|
|
6087
|
+
ctx,
|
|
6088
|
+
table,
|
|
6089
|
+
lazyRelations: [...lazyRelations],
|
|
6090
|
+
lazyRelationOptions: new Map(lazyRelationOptions),
|
|
6091
|
+
relationCache: /* @__PURE__ */ new Map(),
|
|
6092
|
+
relationHydration: /* @__PURE__ */ new Map(),
|
|
6093
|
+
relationWrappers: /* @__PURE__ */ new Map()
|
|
6094
|
+
};
|
|
6095
|
+
const createRelationEntity = (relationTable, relationRow) => createEntityFromRow(meta.ctx, relationTable, relationRow);
|
|
6096
|
+
Object.defineProperty(target, ENTITY_META, {
|
|
6097
|
+
value: meta,
|
|
6098
|
+
enumerable: false,
|
|
6099
|
+
writable: false
|
|
6100
|
+
});
|
|
6101
|
+
const handler = {
|
|
6102
|
+
get(targetObj, prop, receiver) {
|
|
6103
|
+
if (prop === ENTITY_META) {
|
|
6104
|
+
return meta;
|
|
6105
|
+
}
|
|
6106
|
+
if (prop === "$load") {
|
|
6107
|
+
return async (relationName) => {
|
|
6108
|
+
const wrapper = getRelationWrapper(meta, relationName, receiver, createRelationEntity);
|
|
6109
|
+
if (wrapper && typeof wrapper.load === "function") {
|
|
6110
|
+
return wrapper.load();
|
|
6111
|
+
}
|
|
6112
|
+
return void 0;
|
|
6113
|
+
};
|
|
6114
|
+
}
|
|
6115
|
+
if (typeof prop === "string" && table.relations[prop]) {
|
|
6116
|
+
return getRelationWrapper(meta, prop, receiver, createRelationEntity);
|
|
6117
|
+
}
|
|
6118
|
+
return Reflect.get(targetObj, prop, receiver);
|
|
6119
|
+
},
|
|
6120
|
+
set(targetObj, prop, value, receiver) {
|
|
6121
|
+
const result = Reflect.set(targetObj, prop, value, receiver);
|
|
6122
|
+
if (typeof prop === "string" && table.columns[prop]) {
|
|
6123
|
+
ctx.markDirty(receiver);
|
|
6124
|
+
}
|
|
6125
|
+
return result;
|
|
6126
|
+
}
|
|
6127
|
+
};
|
|
6128
|
+
const proxy = new Proxy(target, handler);
|
|
6129
|
+
populateHydrationCache(proxy, row, meta);
|
|
6130
|
+
return proxy;
|
|
6131
|
+
};
|
|
6132
|
+
var createEntityFromRow = (ctx, table, row, lazyRelations = [], lazyRelationOptions = /* @__PURE__ */ new Map()) => {
|
|
6133
|
+
const pkName = findPrimaryKey(table);
|
|
6134
|
+
const pkValue = row[pkName];
|
|
6135
|
+
if (pkValue !== void 0 && pkValue !== null) {
|
|
6136
|
+
const tracked = ctx.getEntity(table, pkValue);
|
|
6137
|
+
if (tracked) return tracked;
|
|
6138
|
+
}
|
|
6139
|
+
const entity = createEntityProxy(ctx, table, row, lazyRelations, lazyRelationOptions);
|
|
6140
|
+
if (pkValue !== void 0 && pkValue !== null) {
|
|
6141
|
+
ctx.trackManaged(table, pkValue, entity);
|
|
6142
|
+
} else {
|
|
6143
|
+
ctx.trackNew(table, entity);
|
|
6144
|
+
}
|
|
6145
|
+
return entity;
|
|
6146
|
+
};
|
|
6147
|
+
|
|
6148
|
+
// src/orm/execute.ts
|
|
6149
|
+
var flattenResults = (results) => {
|
|
6150
|
+
const rows = [];
|
|
6151
|
+
for (const result of results) {
|
|
6152
|
+
const { columns, values } = result;
|
|
6153
|
+
for (const valueRow of values) {
|
|
6154
|
+
const row = {};
|
|
6155
|
+
columns.forEach((column, idx) => {
|
|
6156
|
+
row[column] = valueRow[idx];
|
|
6157
|
+
});
|
|
6158
|
+
rows.push(row);
|
|
6159
|
+
}
|
|
6160
|
+
}
|
|
6161
|
+
return rows;
|
|
6162
|
+
};
|
|
6163
|
+
var executeWithContexts = async (execCtx, entityCtx, qb) => {
|
|
6164
|
+
const ast = qb.getAST();
|
|
6165
|
+
const compiled = execCtx.dialect.compileSelect(ast);
|
|
6166
|
+
const executed = await execCtx.interceptors.run({ sql: compiled.sql, params: compiled.params }, execCtx.executor);
|
|
6167
|
+
const rows = flattenResults(executed);
|
|
6168
|
+
const lazyRelations = qb.getLazyRelations();
|
|
6169
|
+
const lazyRelationOptions = qb.getLazyRelationOptions();
|
|
6170
|
+
if (ast.setOps && ast.setOps.length > 0) {
|
|
6171
|
+
const proxies = rows.map((row) => createEntityProxy(entityCtx, qb.getTable(), row, lazyRelations, lazyRelationOptions));
|
|
6172
|
+
await loadLazyRelationsForTable(entityCtx, qb.getTable(), lazyRelations, lazyRelationOptions);
|
|
6173
|
+
return proxies;
|
|
6174
|
+
}
|
|
6175
|
+
const hydrated = hydrateRows(rows, qb.getHydrationPlan());
|
|
6176
|
+
const entities = hydrated.map((row) => createEntityFromRow(entityCtx, qb.getTable(), row, lazyRelations, lazyRelationOptions));
|
|
6177
|
+
await loadLazyRelationsForTable(entityCtx, qb.getTable(), lazyRelations, lazyRelationOptions);
|
|
6178
|
+
return entities;
|
|
6179
|
+
};
|
|
6180
|
+
async function executeHydrated(session, qb) {
|
|
6181
|
+
return executeWithContexts(session.getExecutionContext(), session, qb);
|
|
6182
|
+
}
|
|
6183
|
+
async function executeHydratedWithContexts(execCtx, hydCtx, qb) {
|
|
6184
|
+
const entityCtx = hydCtx.entityContext;
|
|
6185
|
+
if (!entityCtx) {
|
|
6186
|
+
throw new Error("Hydration context is missing an EntityContext");
|
|
6187
|
+
}
|
|
6188
|
+
return executeWithContexts(execCtx, entityCtx, qb);
|
|
6189
|
+
}
|
|
6190
|
+
var loadLazyRelationsForTable = async (ctx, table, lazyRelations, lazyRelationOptions) => {
|
|
6191
|
+
if (!lazyRelations.length) return;
|
|
6192
|
+
const tracked = ctx.getEntitiesForTable(table);
|
|
6193
|
+
if (!tracked.length) return;
|
|
6194
|
+
const meta = getEntityMeta(tracked[0].entity);
|
|
6195
|
+
if (!meta) return;
|
|
6196
|
+
for (const relationName of lazyRelations) {
|
|
6197
|
+
const relation = table.relations[relationName];
|
|
6198
|
+
if (!relation) continue;
|
|
6199
|
+
const key = relationName;
|
|
6200
|
+
const options = lazyRelationOptions.get(key);
|
|
6201
|
+
if (!options) {
|
|
6202
|
+
continue;
|
|
6203
|
+
}
|
|
6204
|
+
switch (relation.type) {
|
|
6205
|
+
case RelationKinds.HasOne:
|
|
6206
|
+
await relationLoaderCache(
|
|
6207
|
+
meta,
|
|
6208
|
+
key,
|
|
6209
|
+
() => loadHasOneRelation(ctx, table, key, relation, options)
|
|
6210
|
+
);
|
|
6211
|
+
break;
|
|
6212
|
+
case RelationKinds.HasMany:
|
|
6213
|
+
await relationLoaderCache(
|
|
6214
|
+
meta,
|
|
6215
|
+
key,
|
|
6216
|
+
() => loadHasManyRelation(ctx, table, key, relation, options)
|
|
6217
|
+
);
|
|
6218
|
+
break;
|
|
6219
|
+
case RelationKinds.BelongsTo:
|
|
6220
|
+
await relationLoaderCache(
|
|
6221
|
+
meta,
|
|
6222
|
+
key,
|
|
6223
|
+
() => loadBelongsToRelation(ctx, table, key, relation, options)
|
|
6224
|
+
);
|
|
6225
|
+
break;
|
|
6226
|
+
case RelationKinds.BelongsToMany:
|
|
6227
|
+
await relationLoaderCache(
|
|
6228
|
+
meta,
|
|
6229
|
+
key,
|
|
6230
|
+
() => loadBelongsToManyRelation(ctx, table, key, relation, options)
|
|
6231
|
+
);
|
|
6232
|
+
break;
|
|
6233
|
+
}
|
|
6234
|
+
}
|
|
6235
|
+
};
|
|
6236
|
+
|
|
6237
|
+
// src/query-builder/query-resolution.ts
|
|
6238
|
+
function resolveSelectQuery(query) {
|
|
6239
|
+
const candidate = query;
|
|
6240
|
+
return typeof candidate.getAST === "function" && candidate.getAST ? candidate.getAST() : query;
|
|
6241
|
+
}
|
|
6242
|
+
|
|
6243
|
+
// src/query-builder/select/select-operations.ts
|
|
6244
|
+
function applyOrderBy(context, predicateFacet, term, directionOrOptions) {
|
|
6245
|
+
const options = typeof directionOrOptions === "string" ? { direction: directionOrOptions } : directionOrOptions;
|
|
6246
|
+
const dir = options.direction ?? ORDER_DIRECTIONS.ASC;
|
|
6247
|
+
return predicateFacet.orderBy(context, term, dir, options.nulls, options.collation);
|
|
6248
|
+
}
|
|
6249
|
+
async function executeCount(context, env, session) {
|
|
6250
|
+
const unpagedAst = {
|
|
6251
|
+
...context.state.ast,
|
|
6252
|
+
orderBy: void 0,
|
|
6253
|
+
limit: void 0,
|
|
6254
|
+
offset: void 0
|
|
6255
|
+
};
|
|
6256
|
+
const nextState = new SelectQueryState(env.table, unpagedAst);
|
|
6257
|
+
const nextContext = {
|
|
6258
|
+
...context,
|
|
6259
|
+
state: nextState
|
|
6260
|
+
};
|
|
6261
|
+
const subAst = nextContext.hydration.applyToAst(nextState.ast);
|
|
6262
|
+
const countQuery = {
|
|
6263
|
+
type: "SelectQuery",
|
|
6264
|
+
from: derivedTable(subAst, "__metal_count"),
|
|
6265
|
+
columns: [{ type: "Function", name: "COUNT", args: [], alias: "total" }],
|
|
6266
|
+
joins: []
|
|
6267
|
+
};
|
|
6268
|
+
const execCtx = session.getExecutionContext();
|
|
6269
|
+
const compiled = execCtx.dialect.compileSelect(countQuery);
|
|
6270
|
+
const results = await execCtx.interceptors.run({ sql: compiled.sql, params: compiled.params }, execCtx.executor);
|
|
6271
|
+
const value = results[0]?.values?.[0]?.[0];
|
|
6272
|
+
if (typeof value === "number") return value;
|
|
6273
|
+
if (typeof value === "bigint") return Number(value);
|
|
6274
|
+
if (typeof value === "string") return Number(value);
|
|
6275
|
+
return value === null || value === void 0 ? 0 : Number(value);
|
|
6276
|
+
}
|
|
6277
|
+
async function executePagedQuery(builder, session, options, countCallback) {
|
|
6278
|
+
const { page, pageSize } = options;
|
|
6279
|
+
if (!Number.isInteger(page) || page < 1) {
|
|
6280
|
+
throw new Error("executePaged: page must be an integer >= 1");
|
|
6281
|
+
}
|
|
6282
|
+
if (!Number.isInteger(pageSize) || pageSize < 1) {
|
|
6283
|
+
throw new Error("executePaged: pageSize must be an integer >= 1");
|
|
6284
|
+
}
|
|
6285
|
+
const offset = (page - 1) * pageSize;
|
|
6286
|
+
const [items, totalItems] = await Promise.all([
|
|
6287
|
+
builder.limit(pageSize).offset(offset).execute(session),
|
|
6288
|
+
countCallback(session)
|
|
6289
|
+
]);
|
|
6290
|
+
return { items, totalItems };
|
|
6291
|
+
}
|
|
6292
|
+
function buildWhereHasPredicate(env, context, relationFacet, createChildBuilder, relationName, callbackOrOptions, maybeOptions, negate = false) {
|
|
6293
|
+
const relation = env.table.relations[relationName];
|
|
6294
|
+
if (!relation) {
|
|
6295
|
+
throw new Error(`Relation '${relationName}' not found on table '${env.table.name}'`);
|
|
6296
|
+
}
|
|
6297
|
+
const callback = typeof callbackOrOptions === "function" ? callbackOrOptions : void 0;
|
|
6298
|
+
const options = typeof callbackOrOptions === "function" ? maybeOptions : callbackOrOptions;
|
|
6299
|
+
let subQb = createChildBuilder(relation.target);
|
|
6300
|
+
if (callback) {
|
|
6301
|
+
subQb = callback(subQb);
|
|
6302
|
+
}
|
|
6303
|
+
const subAst = subQb.getAST();
|
|
6304
|
+
const finalSubAst = relationFacet.applyRelationCorrelation(
|
|
6305
|
+
context,
|
|
6306
|
+
relationName,
|
|
6307
|
+
subAst,
|
|
6308
|
+
options?.correlate
|
|
6309
|
+
);
|
|
6310
|
+
return negate ? notExists(finalSubAst) : exists(finalSubAst);
|
|
6311
|
+
}
|
|
6312
|
+
|
|
6313
|
+
// src/query-builder/select/from-facet.ts
|
|
6314
|
+
var SelectFromFacet = class {
|
|
6315
|
+
/**
|
|
6316
|
+
* Creates a new SelectFromFacet instance
|
|
6317
|
+
* @param env - Query builder environment
|
|
6318
|
+
* @param createAstService - Function to create AST service
|
|
6319
|
+
*/
|
|
6320
|
+
constructor(env, createAstService) {
|
|
6321
|
+
this.env = env;
|
|
6322
|
+
this.createAstService = createAstService;
|
|
6323
|
+
}
|
|
6324
|
+
/**
|
|
6325
|
+
* Applies an alias to the FROM table
|
|
6326
|
+
* @param context - Current query context
|
|
6327
|
+
* @param alias - Alias to apply
|
|
6328
|
+
* @returns Updated query context with aliased FROM
|
|
6329
|
+
*/
|
|
6330
|
+
as(context, alias) {
|
|
6331
|
+
const from = context.state.ast.from;
|
|
6332
|
+
if (from.type !== "Table") {
|
|
6333
|
+
throw new Error("Cannot alias non-table FROM sources");
|
|
6334
|
+
}
|
|
6335
|
+
const nextFrom = { ...from, alias };
|
|
6336
|
+
const astService = this.createAstService(context.state);
|
|
6337
|
+
const nextState = astService.withFrom(nextFrom);
|
|
6338
|
+
return { state: nextState, hydration: context.hydration };
|
|
6339
|
+
}
|
|
6340
|
+
/**
|
|
6341
|
+
* Sets the FROM clause to a subquery
|
|
6342
|
+
* @param context - Current query context
|
|
6343
|
+
* @param subAst - Subquery AST
|
|
6344
|
+
* @param alias - Alias for the subquery
|
|
6345
|
+
* @param columnAliases - Optional column aliases
|
|
6346
|
+
* @returns Updated query context with subquery FROM
|
|
6347
|
+
*/
|
|
6348
|
+
fromSubquery(context, subAst, alias, columnAliases) {
|
|
6349
|
+
const fromNode = derivedTable(subAst, alias, columnAliases);
|
|
6350
|
+
const astService = this.createAstService(context.state);
|
|
6351
|
+
const nextState = astService.withFrom(fromNode);
|
|
6352
|
+
return { state: nextState, hydration: context.hydration };
|
|
6353
|
+
}
|
|
6354
|
+
/**
|
|
6355
|
+
* Sets the FROM clause to a function table
|
|
6356
|
+
* @param context - Current query context
|
|
6357
|
+
* @param name - Function name
|
|
6358
|
+
* @param args - Function arguments
|
|
6359
|
+
* @param alias - Optional alias for the function table
|
|
6360
|
+
* @param options - Optional function table options
|
|
6361
|
+
* @returns Updated query context with function table FROM
|
|
6362
|
+
*/
|
|
6363
|
+
fromFunctionTable(context, name, args, alias, options) {
|
|
6364
|
+
const functionTable = fnTable(name, args, alias, options);
|
|
6365
|
+
const astService = this.createAstService(context.state);
|
|
6366
|
+
const nextState = astService.withFrom(functionTable);
|
|
6367
|
+
return { state: nextState, hydration: context.hydration };
|
|
6368
|
+
}
|
|
6369
|
+
};
|
|
6370
|
+
|
|
6371
|
+
// src/query-builder/select/join-facet.ts
|
|
6372
|
+
var SelectJoinFacet = class {
|
|
6373
|
+
constructor(env, createAstService) {
|
|
6374
|
+
this.env = env;
|
|
6375
|
+
this.createAstService = createAstService;
|
|
6376
|
+
}
|
|
6377
|
+
applyJoin(context, table, condition, kind) {
|
|
6378
|
+
const joinNode = createJoinNode(kind, { type: "Table", name: table.name, schema: table.schema }, condition);
|
|
6379
|
+
const astService = this.createAstService(context.state);
|
|
6380
|
+
const nextState = astService.withJoin(joinNode);
|
|
6381
|
+
return { state: nextState, hydration: context.hydration };
|
|
6382
|
+
}
|
|
6383
|
+
joinSubquery(context, subAst, alias, condition, joinKind, columnAliases) {
|
|
6384
|
+
const joinNode = createJoinNode(joinKind, derivedTable(subAst, alias, columnAliases), condition);
|
|
6385
|
+
const astService = this.createAstService(context.state);
|
|
6386
|
+
const nextState = astService.withJoin(joinNode);
|
|
6387
|
+
return { state: nextState, hydration: context.hydration };
|
|
6388
|
+
}
|
|
6389
|
+
joinFunctionTable(context, name, args, alias, condition, joinKind, options) {
|
|
6390
|
+
const functionTable = fnTable(name, args, alias, options);
|
|
6391
|
+
const joinNode = createJoinNode(joinKind, functionTable, condition);
|
|
6392
|
+
const astService = this.createAstService(context.state);
|
|
6393
|
+
const nextState = astService.withJoin(joinNode);
|
|
6394
|
+
return { state: nextState, hydration: context.hydration };
|
|
6395
|
+
}
|
|
6396
|
+
};
|
|
6397
|
+
|
|
6398
|
+
// src/query-builder/select/projection-facet.ts
|
|
6399
|
+
var SelectProjectionFacet = class {
|
|
6400
|
+
/**
|
|
6401
|
+
* Creates a new SelectProjectionFacet instance
|
|
6402
|
+
* @param columnSelector - Column selector dependency
|
|
6403
|
+
*/
|
|
6404
|
+
constructor(columnSelector) {
|
|
6405
|
+
this.columnSelector = columnSelector;
|
|
6406
|
+
}
|
|
6407
|
+
/**
|
|
6408
|
+
* Selects columns for the query
|
|
6409
|
+
* @param context - Current query context
|
|
6410
|
+
* @param columns - Columns to select
|
|
6411
|
+
* @returns Updated query context with selected columns
|
|
6412
|
+
*/
|
|
6413
|
+
select(context, columns) {
|
|
6414
|
+
return this.columnSelector.select(context, columns);
|
|
6415
|
+
}
|
|
6416
|
+
/**
|
|
6417
|
+
* Selects raw column expressions
|
|
6418
|
+
* @param context - Current query context
|
|
6419
|
+
* @param cols - Raw column expressions
|
|
6420
|
+
* @returns Updated query context with raw column selections
|
|
6421
|
+
*/
|
|
6422
|
+
selectRaw(context, cols) {
|
|
6423
|
+
return this.columnSelector.selectRaw(context, cols);
|
|
6424
|
+
}
|
|
6425
|
+
/**
|
|
6426
|
+
* Selects a subquery as a column
|
|
6427
|
+
* @param context - Current query context
|
|
6428
|
+
* @param alias - Alias for the subquery
|
|
6429
|
+
* @param query - Subquery to select
|
|
6430
|
+
* @returns Updated query context with subquery selection
|
|
6431
|
+
*/
|
|
6432
|
+
selectSubquery(context, alias, query) {
|
|
6433
|
+
return this.columnSelector.selectSubquery(context, alias, query);
|
|
6434
|
+
}
|
|
6435
|
+
/**
|
|
6436
|
+
* Adds DISTINCT clause to the query
|
|
6437
|
+
* @param context - Current query context
|
|
6438
|
+
* @param cols - Columns to make distinct
|
|
6439
|
+
* @returns Updated query context with DISTINCT clause
|
|
6440
|
+
*/
|
|
6441
|
+
distinct(context, cols) {
|
|
6442
|
+
return this.columnSelector.distinct(context, cols);
|
|
6443
|
+
}
|
|
6444
|
+
};
|
|
6445
|
+
|
|
6446
|
+
// src/query-builder/select/predicate-facet.ts
|
|
6447
|
+
var SelectPredicateFacet = class {
|
|
6448
|
+
/**
|
|
6449
|
+
* Creates a new SelectPredicateFacet instance
|
|
6450
|
+
* @param env - Query builder environment
|
|
6451
|
+
* @param createAstService - Function to create AST service
|
|
6452
|
+
*/
|
|
6453
|
+
constructor(env, createAstService) {
|
|
6454
|
+
this.env = env;
|
|
6455
|
+
this.createAstService = createAstService;
|
|
6456
|
+
}
|
|
6457
|
+
/**
|
|
6458
|
+
* Adds a WHERE condition to the query
|
|
6459
|
+
* @param context - Current query context
|
|
6460
|
+
* @param expr - WHERE expression
|
|
6461
|
+
* @returns Updated query context with WHERE condition
|
|
6462
|
+
*/
|
|
6463
|
+
where(context, expr) {
|
|
6464
|
+
const astService = this.createAstService(context.state);
|
|
6465
|
+
const nextState = astService.withWhere(expr);
|
|
6466
|
+
return { state: nextState, hydration: context.hydration };
|
|
6467
|
+
}
|
|
6468
|
+
/**
|
|
6469
|
+
* Adds a GROUP BY clause to the query
|
|
6470
|
+
* @param context - Current query context
|
|
6471
|
+
* @param term - Column or ordering term to group by
|
|
6472
|
+
* @returns Updated query context with GROUP BY clause
|
|
6473
|
+
*/
|
|
6474
|
+
groupBy(context, term) {
|
|
6475
|
+
const astService = this.createAstService(context.state);
|
|
6476
|
+
const nextState = astService.withGroupBy(term);
|
|
6477
|
+
return { state: nextState, hydration: context.hydration };
|
|
6478
|
+
}
|
|
6479
|
+
/**
|
|
6480
|
+
* Adds a HAVING condition to the query
|
|
6481
|
+
* @param context - Current query context
|
|
6482
|
+
* @param expr - HAVING expression
|
|
6483
|
+
* @returns Updated query context with HAVING condition
|
|
6484
|
+
*/
|
|
6485
|
+
having(context, expr) {
|
|
6486
|
+
const astService = this.createAstService(context.state);
|
|
6487
|
+
const nextState = astService.withHaving(expr);
|
|
6488
|
+
return { state: nextState, hydration: context.hydration };
|
|
6489
|
+
}
|
|
6490
|
+
/**
|
|
6491
|
+
* Adds an ORDER BY clause to the query
|
|
6492
|
+
* @param context - Current query context
|
|
6493
|
+
* @param term - Column or ordering term to order by
|
|
6494
|
+
* @param direction - Order direction
|
|
6495
|
+
* @param nulls - Nulls ordering
|
|
6496
|
+
* @param collation - Collation
|
|
6497
|
+
* @returns Updated query context with ORDER BY clause
|
|
6498
|
+
*/
|
|
6499
|
+
orderBy(context, term, direction, nulls, collation) {
|
|
6500
|
+
const astService = this.createAstService(context.state);
|
|
6501
|
+
const nextState = astService.withOrderBy(term, direction, nulls, collation);
|
|
6502
|
+
return { state: nextState, hydration: context.hydration };
|
|
6503
|
+
}
|
|
6504
|
+
/**
|
|
6505
|
+
* Adds a LIMIT clause to the query
|
|
6506
|
+
* @param context - Current query context
|
|
6507
|
+
* @param n - Maximum number of rows
|
|
6508
|
+
* @returns Updated query context with LIMIT clause
|
|
6509
|
+
*/
|
|
6510
|
+
limit(context, n) {
|
|
6511
|
+
const astService = this.createAstService(context.state);
|
|
6512
|
+
const nextState = astService.withLimit(n);
|
|
6513
|
+
return { state: nextState, hydration: context.hydration };
|
|
6514
|
+
}
|
|
6515
|
+
/**
|
|
6516
|
+
* Adds an OFFSET clause to the query
|
|
6517
|
+
* @param context - Current query context
|
|
6518
|
+
* @param n - Number of rows to skip
|
|
6519
|
+
* @returns Updated query context with OFFSET clause
|
|
6520
|
+
*/
|
|
6521
|
+
offset(context, n) {
|
|
6522
|
+
const astService = this.createAstService(context.state);
|
|
6523
|
+
const nextState = astService.withOffset(n);
|
|
6524
|
+
return { state: nextState, hydration: context.hydration };
|
|
6525
|
+
}
|
|
6526
|
+
};
|
|
6527
|
+
|
|
6528
|
+
// src/query-builder/select/cte-facet.ts
|
|
6529
|
+
var SelectCTEFacet = class {
|
|
6530
|
+
/**
|
|
6531
|
+
* Creates a new SelectCTEFacet instance
|
|
6532
|
+
* @param env - Query builder environment
|
|
6533
|
+
* @param createAstService - Function to create AST service
|
|
6534
|
+
*/
|
|
6535
|
+
constructor(env, createAstService) {
|
|
6536
|
+
this.env = env;
|
|
6537
|
+
this.createAstService = createAstService;
|
|
6538
|
+
}
|
|
6539
|
+
/**
|
|
6540
|
+
* Adds a Common Table Expression to the query
|
|
6541
|
+
* @param context - Current query context
|
|
6542
|
+
* @param name - CTE name
|
|
6543
|
+
* @param subAst - CTE query AST
|
|
6544
|
+
* @param columns - Optional column names
|
|
6545
|
+
* @param recursive - Whether the CTE is recursive
|
|
6546
|
+
* @returns Updated query context with CTE
|
|
6547
|
+
*/
|
|
6548
|
+
withCTE(context, name, subAst, columns, recursive) {
|
|
6549
|
+
const astService = this.createAstService(context.state);
|
|
6550
|
+
const nextState = astService.withCte(name, subAst, columns, recursive);
|
|
6551
|
+
return { state: nextState, hydration: context.hydration };
|
|
6552
|
+
}
|
|
6553
|
+
};
|
|
6554
|
+
|
|
6555
|
+
// src/query-builder/select/setop-facet.ts
|
|
6556
|
+
var SelectSetOpFacet = class {
|
|
6557
|
+
/**
|
|
6558
|
+
* Creates a new SelectSetOpFacet instance
|
|
6559
|
+
* @param env - Query builder environment
|
|
6560
|
+
* @param createAstService - Function to create AST service
|
|
6561
|
+
*/
|
|
6562
|
+
constructor(env, createAstService) {
|
|
6563
|
+
this.env = env;
|
|
6564
|
+
this.createAstService = createAstService;
|
|
6066
6565
|
}
|
|
6067
|
-
|
|
6068
|
-
|
|
6069
|
-
|
|
6070
|
-
|
|
6071
|
-
|
|
6072
|
-
|
|
6073
|
-
|
|
6074
|
-
|
|
6075
|
-
|
|
6076
|
-
|
|
6077
|
-
|
|
6078
|
-
await loadLazyRelationsForTable(entityCtx, qb.getTable(), lazyRelations, lazyRelationOptions);
|
|
6079
|
-
return proxies;
|
|
6566
|
+
/**
|
|
6567
|
+
* Applies a set operation to the query
|
|
6568
|
+
* @param context - Current query context
|
|
6569
|
+
* @param operator - Set operation kind
|
|
6570
|
+
* @param subAst - Subquery AST to combine
|
|
6571
|
+
* @returns Updated query context with set operation
|
|
6572
|
+
*/
|
|
6573
|
+
applySetOperation(context, operator, subAst) {
|
|
6574
|
+
const astService = this.createAstService(context.state);
|
|
6575
|
+
const nextState = astService.withSetOperation(operator, subAst);
|
|
6576
|
+
return { state: nextState, hydration: context.hydration };
|
|
6080
6577
|
}
|
|
6081
|
-
const hydrated = hydrateRows(rows, qb.getHydrationPlan());
|
|
6082
|
-
const entities = hydrated.map((row) => createEntityFromRow(entityCtx, qb.getTable(), row, lazyRelations, lazyRelationOptions));
|
|
6083
|
-
await loadLazyRelationsForTable(entityCtx, qb.getTable(), lazyRelations, lazyRelationOptions);
|
|
6084
|
-
return entities;
|
|
6085
6578
|
};
|
|
6086
|
-
|
|
6087
|
-
|
|
6088
|
-
|
|
6089
|
-
|
|
6090
|
-
|
|
6091
|
-
|
|
6092
|
-
|
|
6579
|
+
|
|
6580
|
+
// src/query-builder/select/relation-facet.ts
|
|
6581
|
+
var SelectRelationFacet = class {
|
|
6582
|
+
/**
|
|
6583
|
+
* Creates a new SelectRelationFacet instance
|
|
6584
|
+
* @param relationManager - Relation manager dependency
|
|
6585
|
+
*/
|
|
6586
|
+
constructor(relationManager) {
|
|
6587
|
+
this.relationManager = relationManager;
|
|
6093
6588
|
}
|
|
6094
|
-
|
|
6095
|
-
|
|
6096
|
-
|
|
6097
|
-
|
|
6098
|
-
|
|
6099
|
-
|
|
6100
|
-
|
|
6101
|
-
|
|
6102
|
-
|
|
6103
|
-
|
|
6104
|
-
|
|
6105
|
-
|
|
6106
|
-
|
|
6107
|
-
|
|
6108
|
-
|
|
6109
|
-
|
|
6110
|
-
|
|
6111
|
-
|
|
6112
|
-
|
|
6113
|
-
|
|
6114
|
-
|
|
6115
|
-
|
|
6116
|
-
|
|
6117
|
-
|
|
6118
|
-
|
|
6119
|
-
|
|
6120
|
-
|
|
6121
|
-
|
|
6122
|
-
|
|
6123
|
-
|
|
6124
|
-
|
|
6125
|
-
|
|
6126
|
-
|
|
6127
|
-
|
|
6128
|
-
|
|
6129
|
-
|
|
6130
|
-
|
|
6131
|
-
|
|
6132
|
-
|
|
6133
|
-
|
|
6134
|
-
|
|
6135
|
-
key,
|
|
6136
|
-
() => loadBelongsToManyRelation(ctx, table, key, relation, options)
|
|
6137
|
-
);
|
|
6138
|
-
break;
|
|
6139
|
-
}
|
|
6589
|
+
/**
|
|
6590
|
+
* Matches records based on a relationship
|
|
6591
|
+
* @param context - Current query context
|
|
6592
|
+
* @param relationName - Name of the relationship
|
|
6593
|
+
* @param predicate - Optional predicate
|
|
6594
|
+
* @returns Updated query context with relation match
|
|
6595
|
+
*/
|
|
6596
|
+
match(context, relationName, predicate) {
|
|
6597
|
+
return this.relationManager.match(context, relationName, predicate);
|
|
6598
|
+
}
|
|
6599
|
+
/**
|
|
6600
|
+
* Joins a related table
|
|
6601
|
+
* @param context - Current query context
|
|
6602
|
+
* @param relationName - Name of the relationship
|
|
6603
|
+
* @param joinKind - Type of join
|
|
6604
|
+
* @param extraCondition - Optional additional condition
|
|
6605
|
+
* @returns Updated query context with relation join
|
|
6606
|
+
*/
|
|
6607
|
+
joinRelation(context, relationName, joinKind, extraCondition) {
|
|
6608
|
+
return this.relationManager.joinRelation(context, relationName, joinKind, extraCondition);
|
|
6609
|
+
}
|
|
6610
|
+
/**
|
|
6611
|
+
* Includes related data in the query results
|
|
6612
|
+
* @param context - Current query context
|
|
6613
|
+
* @param relationName - Name of the relationship to include
|
|
6614
|
+
* @param options - Optional include options
|
|
6615
|
+
* @returns Updated query context with relation inclusion
|
|
6616
|
+
*/
|
|
6617
|
+
include(context, relationName, options) {
|
|
6618
|
+
return this.relationManager.include(context, relationName, options);
|
|
6619
|
+
}
|
|
6620
|
+
/**
|
|
6621
|
+
* Applies correlation for relation-based subqueries
|
|
6622
|
+
* @param context - Current query context
|
|
6623
|
+
* @param relationName - Name of the relationship
|
|
6624
|
+
* @param subAst - Subquery AST
|
|
6625
|
+
* @param extraCorrelate - Optional additional correlation
|
|
6626
|
+
* @returns Modified subquery AST with correlation
|
|
6627
|
+
*/
|
|
6628
|
+
applyRelationCorrelation(context, relationName, subAst, extraCorrelate) {
|
|
6629
|
+
return this.relationManager.applyRelationCorrelation(context, relationName, subAst, extraCorrelate);
|
|
6140
6630
|
}
|
|
6141
6631
|
};
|
|
6142
6632
|
|
|
6143
|
-
// src/query-builder/query-resolution.ts
|
|
6144
|
-
function resolveSelectQuery(query) {
|
|
6145
|
-
const candidate = query;
|
|
6146
|
-
return typeof candidate.getAST === "function" && candidate.getAST ? candidate.getAST() : query;
|
|
6147
|
-
}
|
|
6148
|
-
|
|
6149
6633
|
// src/query-builder/select.ts
|
|
6150
6634
|
var SelectQueryBuilder = class _SelectQueryBuilder {
|
|
6635
|
+
env;
|
|
6636
|
+
context;
|
|
6637
|
+
columnSelector;
|
|
6638
|
+
fromFacet;
|
|
6639
|
+
joinFacet;
|
|
6640
|
+
projectionFacet;
|
|
6641
|
+
predicateFacet;
|
|
6642
|
+
cteFacet;
|
|
6643
|
+
setOpFacet;
|
|
6644
|
+
relationFacet;
|
|
6645
|
+
lazyRelations;
|
|
6646
|
+
lazyRelationOptions;
|
|
6151
6647
|
/**
|
|
6152
6648
|
* Creates a new SelectQueryBuilder instance
|
|
6153
6649
|
* @param table - Table definition to query
|
|
@@ -6158,6 +6654,7 @@ var SelectQueryBuilder = class _SelectQueryBuilder {
|
|
|
6158
6654
|
constructor(table, state, hydration, dependencies, lazyRelations, lazyRelationOptions) {
|
|
6159
6655
|
const deps = resolveSelectQueryBuilderDependencies(dependencies);
|
|
6160
6656
|
this.env = { table, deps };
|
|
6657
|
+
const createAstService = (nextState) => deps.createQueryAstService(table, nextState);
|
|
6161
6658
|
const initialState = state ?? deps.createState(table);
|
|
6162
6659
|
const initialHydration = hydration ?? deps.createHydration(table);
|
|
6163
6660
|
this.context = {
|
|
@@ -6167,7 +6664,14 @@ var SelectQueryBuilder = class _SelectQueryBuilder {
|
|
|
6167
6664
|
this.lazyRelations = new Set(lazyRelations ?? []);
|
|
6168
6665
|
this.lazyRelationOptions = new Map(lazyRelationOptions ?? []);
|
|
6169
6666
|
this.columnSelector = deps.createColumnSelector(this.env);
|
|
6170
|
-
|
|
6667
|
+
const relationManager = deps.createRelationManager(this.env);
|
|
6668
|
+
this.fromFacet = new SelectFromFacet(this.env, createAstService);
|
|
6669
|
+
this.joinFacet = new SelectJoinFacet(this.env, createAstService);
|
|
6670
|
+
this.projectionFacet = new SelectProjectionFacet(this.columnSelector);
|
|
6671
|
+
this.predicateFacet = new SelectPredicateFacet(this.env, createAstService);
|
|
6672
|
+
this.cteFacet = new SelectCTEFacet(this.env, createAstService);
|
|
6673
|
+
this.setOpFacet = new SelectSetOpFacet(this.env, createAstService);
|
|
6674
|
+
this.relationFacet = new SelectRelationFacet(relationManager);
|
|
6171
6675
|
}
|
|
6172
6676
|
/**
|
|
6173
6677
|
* Creates a new SelectQueryBuilder instance with updated context and lazy relations
|
|
@@ -6190,12 +6694,7 @@ var SelectQueryBuilder = class _SelectQueryBuilder {
|
|
|
6190
6694
|
* @param alias - Alias to apply
|
|
6191
6695
|
*/
|
|
6192
6696
|
as(alias) {
|
|
6193
|
-
const
|
|
6194
|
-
if (from.type !== "Table") {
|
|
6195
|
-
throw new Error("Cannot alias non-table FROM sources");
|
|
6196
|
-
}
|
|
6197
|
-
const nextFrom = { ...from, alias };
|
|
6198
|
-
const nextContext = this.applyAst(this.context, (service) => service.withFrom(nextFrom));
|
|
6697
|
+
const nextContext = this.fromFacet.as(this.context, alias);
|
|
6199
6698
|
return this.clone(nextContext);
|
|
6200
6699
|
}
|
|
6201
6700
|
/**
|
|
@@ -6220,29 +6719,6 @@ var SelectQueryBuilder = class _SelectQueryBuilder {
|
|
|
6220
6719
|
createChildBuilder(table) {
|
|
6221
6720
|
return new _SelectQueryBuilder(table, void 0, void 0, this.env.deps);
|
|
6222
6721
|
}
|
|
6223
|
-
/**
|
|
6224
|
-
* Applies an AST mutation using the query AST service
|
|
6225
|
-
* @param context - Current query context
|
|
6226
|
-
* @param mutator - Function that mutates the AST
|
|
6227
|
-
* @returns Updated query context
|
|
6228
|
-
*/
|
|
6229
|
-
applyAst(context, mutator) {
|
|
6230
|
-
const astService = this.env.deps.createQueryAstService(this.env.table, context.state);
|
|
6231
|
-
const nextState = mutator(astService);
|
|
6232
|
-
return { state: nextState, hydration: context.hydration };
|
|
6233
|
-
}
|
|
6234
|
-
/**
|
|
6235
|
-
* Applies a join to the query context
|
|
6236
|
-
* @param context - Current query context
|
|
6237
|
-
* @param table - Table to join
|
|
6238
|
-
* @param condition - Join condition
|
|
6239
|
-
* @param kind - Join kind
|
|
6240
|
-
* @returns Updated query context with join applied
|
|
6241
|
-
*/
|
|
6242
|
-
applyJoin(context, table, condition, kind) {
|
|
6243
|
-
const joinNode = createJoinNode(kind, { type: "Table", name: table.name, schema: table.schema }, condition);
|
|
6244
|
-
return this.applyAst(context, (service) => service.withJoin(joinNode));
|
|
6245
|
-
}
|
|
6246
6722
|
/**
|
|
6247
6723
|
* Applies a set operation to the query
|
|
6248
6724
|
* @param operator - Set operation kind
|
|
@@ -6251,12 +6727,12 @@ var SelectQueryBuilder = class _SelectQueryBuilder {
|
|
|
6251
6727
|
*/
|
|
6252
6728
|
applySetOperation(operator, query) {
|
|
6253
6729
|
const subAst = resolveSelectQuery(query);
|
|
6254
|
-
return this.
|
|
6730
|
+
return this.setOpFacet.applySetOperation(this.context, operator, subAst);
|
|
6255
6731
|
}
|
|
6256
6732
|
select(...args) {
|
|
6257
6733
|
if (args.length === 1 && typeof args[0] === "object" && args[0] !== null && typeof args[0] !== "string") {
|
|
6258
6734
|
const columns = args[0];
|
|
6259
|
-
return this.clone(this.
|
|
6735
|
+
return this.clone(this.projectionFacet.select(this.context, columns));
|
|
6260
6736
|
}
|
|
6261
6737
|
const cols = args;
|
|
6262
6738
|
const selection = {};
|
|
@@ -6267,7 +6743,7 @@ var SelectQueryBuilder = class _SelectQueryBuilder {
|
|
|
6267
6743
|
}
|
|
6268
6744
|
selection[key] = col2;
|
|
6269
6745
|
}
|
|
6270
|
-
return this.clone(this.
|
|
6746
|
+
return this.clone(this.projectionFacet.select(this.context, selection));
|
|
6271
6747
|
}
|
|
6272
6748
|
/**
|
|
6273
6749
|
* Selects raw column expressions
|
|
@@ -6275,7 +6751,7 @@ var SelectQueryBuilder = class _SelectQueryBuilder {
|
|
|
6275
6751
|
* @returns New query builder instance with raw column selections
|
|
6276
6752
|
*/
|
|
6277
6753
|
selectRaw(...cols) {
|
|
6278
|
-
return this.clone(this.
|
|
6754
|
+
return this.clone(this.projectionFacet.selectRaw(this.context, cols));
|
|
6279
6755
|
}
|
|
6280
6756
|
/**
|
|
6281
6757
|
* Adds a Common Table Expression (CTE) to the query
|
|
@@ -6286,7 +6762,7 @@ var SelectQueryBuilder = class _SelectQueryBuilder {
|
|
|
6286
6762
|
*/
|
|
6287
6763
|
with(name, query, columns) {
|
|
6288
6764
|
const subAst = resolveSelectQuery(query);
|
|
6289
|
-
const nextContext = this.
|
|
6765
|
+
const nextContext = this.cteFacet.withCTE(this.context, name, subAst, columns, false);
|
|
6290
6766
|
return this.clone(nextContext);
|
|
6291
6767
|
}
|
|
6292
6768
|
/**
|
|
@@ -6298,7 +6774,7 @@ var SelectQueryBuilder = class _SelectQueryBuilder {
|
|
|
6298
6774
|
*/
|
|
6299
6775
|
withRecursive(name, query, columns) {
|
|
6300
6776
|
const subAst = resolveSelectQuery(query);
|
|
6301
|
-
const nextContext = this.
|
|
6777
|
+
const nextContext = this.cteFacet.withCTE(this.context, name, subAst, columns, true);
|
|
6302
6778
|
return this.clone(nextContext);
|
|
6303
6779
|
}
|
|
6304
6780
|
/**
|
|
@@ -6310,8 +6786,7 @@ var SelectQueryBuilder = class _SelectQueryBuilder {
|
|
|
6310
6786
|
*/
|
|
6311
6787
|
fromSubquery(subquery, alias, columnAliases) {
|
|
6312
6788
|
const subAst = resolveSelectQuery(subquery);
|
|
6313
|
-
const
|
|
6314
|
-
const nextContext = this.applyAst(this.context, (service) => service.withFrom(fromNode));
|
|
6789
|
+
const nextContext = this.fromFacet.fromSubquery(this.context, subAst, alias, columnAliases);
|
|
6315
6790
|
return this.clone(nextContext);
|
|
6316
6791
|
}
|
|
6317
6792
|
/**
|
|
@@ -6322,8 +6797,7 @@ var SelectQueryBuilder = class _SelectQueryBuilder {
|
|
|
6322
6797
|
* @param options - Optional function-table metadata (lateral, ordinality, column aliases, schema)
|
|
6323
6798
|
*/
|
|
6324
6799
|
fromFunctionTable(name, args = [], alias, options) {
|
|
6325
|
-
const
|
|
6326
|
-
const nextContext = this.applyAst(this.context, (service) => service.withFrom(functionTable));
|
|
6800
|
+
const nextContext = this.fromFacet.fromFunctionTable(this.context, name, args, alias, options);
|
|
6327
6801
|
return this.clone(nextContext);
|
|
6328
6802
|
}
|
|
6329
6803
|
/**
|
|
@@ -6334,7 +6808,7 @@ var SelectQueryBuilder = class _SelectQueryBuilder {
|
|
|
6334
6808
|
*/
|
|
6335
6809
|
selectSubquery(alias, sub2) {
|
|
6336
6810
|
const query = resolveSelectQuery(sub2);
|
|
6337
|
-
return this.clone(this.
|
|
6811
|
+
return this.clone(this.projectionFacet.selectSubquery(this.context, alias, query));
|
|
6338
6812
|
}
|
|
6339
6813
|
/**
|
|
6340
6814
|
* Adds a JOIN against a derived table (subquery with alias)
|
|
@@ -6347,8 +6821,7 @@ var SelectQueryBuilder = class _SelectQueryBuilder {
|
|
|
6347
6821
|
*/
|
|
6348
6822
|
joinSubquery(subquery, alias, condition, joinKind = JOIN_KINDS.INNER, columnAliases) {
|
|
6349
6823
|
const subAst = resolveSelectQuery(subquery);
|
|
6350
|
-
const
|
|
6351
|
-
const nextContext = this.applyAst(this.context, (service) => service.withJoin(joinNode));
|
|
6824
|
+
const nextContext = this.joinFacet.joinSubquery(this.context, subAst, alias, condition, joinKind, columnAliases);
|
|
6352
6825
|
return this.clone(nextContext);
|
|
6353
6826
|
}
|
|
6354
6827
|
/**
|
|
@@ -6361,9 +6834,7 @@ var SelectQueryBuilder = class _SelectQueryBuilder {
|
|
|
6361
6834
|
* @param options - Optional metadata (lateral, ordinality, column aliases, schema)
|
|
6362
6835
|
*/
|
|
6363
6836
|
joinFunctionTable(name, args = [], alias, condition, joinKind = JOIN_KINDS.INNER, options) {
|
|
6364
|
-
const
|
|
6365
|
-
const joinNode = createJoinNode(joinKind, functionTable, condition);
|
|
6366
|
-
const nextContext = this.applyAst(this.context, (service) => service.withJoin(joinNode));
|
|
6837
|
+
const nextContext = this.joinFacet.joinFunctionTable(this.context, name, args, alias, condition, joinKind, options);
|
|
6367
6838
|
return this.clone(nextContext);
|
|
6368
6839
|
}
|
|
6369
6840
|
/**
|
|
@@ -6373,7 +6844,7 @@ var SelectQueryBuilder = class _SelectQueryBuilder {
|
|
|
6373
6844
|
* @returns New query builder instance with the INNER JOIN
|
|
6374
6845
|
*/
|
|
6375
6846
|
innerJoin(table, condition) {
|
|
6376
|
-
const nextContext = this.applyJoin(this.context, table, condition, JOIN_KINDS.INNER);
|
|
6847
|
+
const nextContext = this.joinFacet.applyJoin(this.context, table, condition, JOIN_KINDS.INNER);
|
|
6377
6848
|
return this.clone(nextContext);
|
|
6378
6849
|
}
|
|
6379
6850
|
/**
|
|
@@ -6383,7 +6854,7 @@ var SelectQueryBuilder = class _SelectQueryBuilder {
|
|
|
6383
6854
|
* @returns New query builder instance with the LEFT JOIN
|
|
6384
6855
|
*/
|
|
6385
6856
|
leftJoin(table, condition) {
|
|
6386
|
-
const nextContext = this.applyJoin(this.context, table, condition, JOIN_KINDS.LEFT);
|
|
6857
|
+
const nextContext = this.joinFacet.applyJoin(this.context, table, condition, JOIN_KINDS.LEFT);
|
|
6387
6858
|
return this.clone(nextContext);
|
|
6388
6859
|
}
|
|
6389
6860
|
/**
|
|
@@ -6393,7 +6864,7 @@ var SelectQueryBuilder = class _SelectQueryBuilder {
|
|
|
6393
6864
|
* @returns New query builder instance with the RIGHT JOIN
|
|
6394
6865
|
*/
|
|
6395
6866
|
rightJoin(table, condition) {
|
|
6396
|
-
const nextContext = this.applyJoin(this.context, table, condition, JOIN_KINDS.RIGHT);
|
|
6867
|
+
const nextContext = this.joinFacet.applyJoin(this.context, table, condition, JOIN_KINDS.RIGHT);
|
|
6397
6868
|
return this.clone(nextContext);
|
|
6398
6869
|
}
|
|
6399
6870
|
/**
|
|
@@ -6403,7 +6874,7 @@ var SelectQueryBuilder = class _SelectQueryBuilder {
|
|
|
6403
6874
|
* @returns New query builder instance with the relationship match
|
|
6404
6875
|
*/
|
|
6405
6876
|
match(relationName, predicate) {
|
|
6406
|
-
const nextContext = this.
|
|
6877
|
+
const nextContext = this.relationFacet.match(this.context, relationName, predicate);
|
|
6407
6878
|
return this.clone(nextContext);
|
|
6408
6879
|
}
|
|
6409
6880
|
/**
|
|
@@ -6414,7 +6885,7 @@ var SelectQueryBuilder = class _SelectQueryBuilder {
|
|
|
6414
6885
|
* @returns New query builder instance with the relationship join
|
|
6415
6886
|
*/
|
|
6416
6887
|
joinRelation(relationName, joinKind = JOIN_KINDS.INNER, extraCondition) {
|
|
6417
|
-
const nextContext = this.
|
|
6888
|
+
const nextContext = this.relationFacet.joinRelation(this.context, relationName, joinKind, extraCondition);
|
|
6418
6889
|
return this.clone(nextContext);
|
|
6419
6890
|
}
|
|
6420
6891
|
/**
|
|
@@ -6424,7 +6895,7 @@ var SelectQueryBuilder = class _SelectQueryBuilder {
|
|
|
6424
6895
|
* @returns New query builder instance with the relationship inclusion
|
|
6425
6896
|
*/
|
|
6426
6897
|
include(relationName, options) {
|
|
6427
|
-
const nextContext = this.
|
|
6898
|
+
const nextContext = this.relationFacet.include(this.context, relationName, options);
|
|
6428
6899
|
return this.clone(nextContext);
|
|
6429
6900
|
}
|
|
6430
6901
|
/**
|
|
@@ -6463,7 +6934,8 @@ var SelectQueryBuilder = class _SelectQueryBuilder {
|
|
|
6463
6934
|
* Convenience alias for including only specific columns from a relation.
|
|
6464
6935
|
*/
|
|
6465
6936
|
includePick(relationName, cols) {
|
|
6466
|
-
|
|
6937
|
+
const options = { columns: cols };
|
|
6938
|
+
return this.include(relationName, options);
|
|
6467
6939
|
}
|
|
6468
6940
|
/**
|
|
6469
6941
|
* Selects columns for the root table and relations from an array of entries
|
|
@@ -6476,7 +6948,8 @@ var SelectQueryBuilder = class _SelectQueryBuilder {
|
|
|
6476
6948
|
if (entry.type === "root") {
|
|
6477
6949
|
currBuilder = currBuilder.select(...entry.columns);
|
|
6478
6950
|
} else {
|
|
6479
|
-
|
|
6951
|
+
const options = { columns: entry.columns };
|
|
6952
|
+
currBuilder = currBuilder.include(entry.relationName, options);
|
|
6480
6953
|
}
|
|
6481
6954
|
}
|
|
6482
6955
|
return currBuilder;
|
|
@@ -6510,51 +6983,23 @@ var SelectQueryBuilder = class _SelectQueryBuilder {
|
|
|
6510
6983
|
async execute(ctx) {
|
|
6511
6984
|
return executeHydrated(ctx, this);
|
|
6512
6985
|
}
|
|
6513
|
-
|
|
6514
|
-
|
|
6515
|
-
|
|
6516
|
-
|
|
6517
|
-
|
|
6518
|
-
|
|
6519
|
-
return this.clone(nextContext);
|
|
6520
|
-
}
|
|
6986
|
+
/**
|
|
6987
|
+
* Executes a count query for the current builder without LIMIT/OFFSET clauses.
|
|
6988
|
+
*
|
|
6989
|
+
* @example
|
|
6990
|
+
* const total = await qb.count(session);
|
|
6991
|
+
*/
|
|
6521
6992
|
async count(session) {
|
|
6522
|
-
|
|
6523
|
-
...this.context.state.ast,
|
|
6524
|
-
orderBy: void 0,
|
|
6525
|
-
limit: void 0,
|
|
6526
|
-
offset: void 0
|
|
6527
|
-
};
|
|
6528
|
-
const subAst = this.withAst(unpagedAst).getAST();
|
|
6529
|
-
const countQuery = {
|
|
6530
|
-
type: "SelectQuery",
|
|
6531
|
-
from: derivedTable(subAst, "__metal_count"),
|
|
6532
|
-
columns: [{ type: "Function", name: "COUNT", args: [], alias: "total" }],
|
|
6533
|
-
joins: []
|
|
6534
|
-
};
|
|
6535
|
-
const execCtx = session.getExecutionContext();
|
|
6536
|
-
const compiled = execCtx.dialect.compileSelect(countQuery);
|
|
6537
|
-
const results = await execCtx.interceptors.run({ sql: compiled.sql, params: compiled.params }, execCtx.executor);
|
|
6538
|
-
const value = results[0]?.values?.[0]?.[0];
|
|
6539
|
-
if (typeof value === "number") return value;
|
|
6540
|
-
if (typeof value === "bigint") return Number(value);
|
|
6541
|
-
if (typeof value === "string") return Number(value);
|
|
6542
|
-
return value === null || value === void 0 ? 0 : Number(value);
|
|
6993
|
+
return executeCount(this.context, this.env, session);
|
|
6543
6994
|
}
|
|
6995
|
+
/**
|
|
6996
|
+
* Executes the query and returns both the paged items and the total.
|
|
6997
|
+
*
|
|
6998
|
+
* @example
|
|
6999
|
+
* const { items, totalItems } = await qb.executePaged(session, { page: 1, pageSize: 20 });
|
|
7000
|
+
*/
|
|
6544
7001
|
async executePaged(session, options) {
|
|
6545
|
-
|
|
6546
|
-
if (!Number.isInteger(page) || page < 1) {
|
|
6547
|
-
throw new Error("executePaged: page must be an integer >= 1");
|
|
6548
|
-
}
|
|
6549
|
-
if (!Number.isInteger(pageSize) || pageSize < 1) {
|
|
6550
|
-
throw new Error("executePaged: pageSize must be an integer >= 1");
|
|
6551
|
-
}
|
|
6552
|
-
const offset = (page - 1) * pageSize;
|
|
6553
|
-
const [items, totalItems] = await Promise.all([
|
|
6554
|
-
this.limit(pageSize).offset(offset).execute(session),
|
|
6555
|
-
this.count(session)
|
|
6556
|
-
]);
|
|
6557
|
-
return { items, totalItems };
|
|
7002
|
+
return executePagedQuery(this, session, options, (sess) => this.count(sess));
|
|
6558
7003
|
}
|
|
6559
7004
|
/**
|
|
6560
7005
|
* Executes the query with provided execution and hydration contexts
|
|
@@ -6571,7 +7016,7 @@ var SelectQueryBuilder = class _SelectQueryBuilder {
|
|
|
6571
7016
|
* @returns New query builder instance with the WHERE condition
|
|
6572
7017
|
*/
|
|
6573
7018
|
where(expr) {
|
|
6574
|
-
const nextContext = this.
|
|
7019
|
+
const nextContext = this.predicateFacet.where(this.context, expr);
|
|
6575
7020
|
return this.clone(nextContext);
|
|
6576
7021
|
}
|
|
6577
7022
|
/**
|
|
@@ -6580,7 +7025,7 @@ var SelectQueryBuilder = class _SelectQueryBuilder {
|
|
|
6580
7025
|
* @returns New query builder instance with the GROUP BY clause
|
|
6581
7026
|
*/
|
|
6582
7027
|
groupBy(term) {
|
|
6583
|
-
const nextContext = this.
|
|
7028
|
+
const nextContext = this.predicateFacet.groupBy(this.context, term);
|
|
6584
7029
|
return this.clone(nextContext);
|
|
6585
7030
|
}
|
|
6586
7031
|
/**
|
|
@@ -6589,7 +7034,7 @@ var SelectQueryBuilder = class _SelectQueryBuilder {
|
|
|
6589
7034
|
* @returns New query builder instance with the HAVING condition
|
|
6590
7035
|
*/
|
|
6591
7036
|
having(expr) {
|
|
6592
|
-
const nextContext = this.
|
|
7037
|
+
const nextContext = this.predicateFacet.having(this.context, expr);
|
|
6593
7038
|
return this.clone(nextContext);
|
|
6594
7039
|
}
|
|
6595
7040
|
/**
|
|
@@ -6597,14 +7042,12 @@ var SelectQueryBuilder = class _SelectQueryBuilder {
|
|
|
6597
7042
|
* @param term - Column definition or ordering term to order by
|
|
6598
7043
|
* @param directionOrOptions - Order direction or options (defaults to ASC)
|
|
6599
7044
|
* @returns New query builder instance with the ORDER BY clause
|
|
7045
|
+
*
|
|
7046
|
+
* @example
|
|
7047
|
+
* qb.orderBy(userTable.columns.createdAt, 'DESC');
|
|
6600
7048
|
*/
|
|
6601
7049
|
orderBy(term, directionOrOptions = ORDER_DIRECTIONS.ASC) {
|
|
6602
|
-
const
|
|
6603
|
-
const dir = options.direction ?? ORDER_DIRECTIONS.ASC;
|
|
6604
|
-
const nextContext = this.applyAst(
|
|
6605
|
-
this.context,
|
|
6606
|
-
(service) => service.withOrderBy(term, dir, options.nulls, options.collation)
|
|
6607
|
-
);
|
|
7050
|
+
const nextContext = applyOrderBy(this.context, this.predicateFacet, term, directionOrOptions);
|
|
6608
7051
|
return this.clone(nextContext);
|
|
6609
7052
|
}
|
|
6610
7053
|
/**
|
|
@@ -6613,7 +7056,7 @@ var SelectQueryBuilder = class _SelectQueryBuilder {
|
|
|
6613
7056
|
* @returns New query builder instance with the DISTINCT clause
|
|
6614
7057
|
*/
|
|
6615
7058
|
distinct(...cols) {
|
|
6616
|
-
return this.clone(this.
|
|
7059
|
+
return this.clone(this.projectionFacet.distinct(this.context, cols));
|
|
6617
7060
|
}
|
|
6618
7061
|
/**
|
|
6619
7062
|
* Adds a LIMIT clause to the query
|
|
@@ -6621,7 +7064,7 @@ var SelectQueryBuilder = class _SelectQueryBuilder {
|
|
|
6621
7064
|
* @returns New query builder instance with the LIMIT clause
|
|
6622
7065
|
*/
|
|
6623
7066
|
limit(n) {
|
|
6624
|
-
const nextContext = this.
|
|
7067
|
+
const nextContext = this.predicateFacet.limit(this.context, n);
|
|
6625
7068
|
return this.clone(nextContext);
|
|
6626
7069
|
}
|
|
6627
7070
|
/**
|
|
@@ -6630,7 +7073,7 @@ var SelectQueryBuilder = class _SelectQueryBuilder {
|
|
|
6630
7073
|
* @returns New query builder instance with the OFFSET clause
|
|
6631
7074
|
*/
|
|
6632
7075
|
offset(n) {
|
|
6633
|
-
const nextContext = this.
|
|
7076
|
+
const nextContext = this.predicateFacet.offset(this.context, n);
|
|
6634
7077
|
return this.clone(nextContext);
|
|
6635
7078
|
}
|
|
6636
7079
|
/**
|
|
@@ -6690,42 +7133,44 @@ var SelectQueryBuilder = class _SelectQueryBuilder {
|
|
|
6690
7133
|
* @param relationName - Name of the relationship to check
|
|
6691
7134
|
* @param callback - Optional callback to modify the relationship query
|
|
6692
7135
|
* @returns New query builder instance with the relationship existence check
|
|
7136
|
+
*
|
|
7137
|
+
* @example
|
|
7138
|
+
* qb.whereHas('posts', postQb => postQb.where(eq(postTable.columns.published, true)));
|
|
6693
7139
|
*/
|
|
6694
7140
|
whereHas(relationName, callbackOrOptions, maybeOptions) {
|
|
6695
|
-
const
|
|
6696
|
-
|
|
6697
|
-
|
|
6698
|
-
|
|
6699
|
-
|
|
6700
|
-
|
|
6701
|
-
|
|
6702
|
-
|
|
6703
|
-
|
|
6704
|
-
|
|
6705
|
-
|
|
6706
|
-
const finalSubAst = this.relationManager.applyRelationCorrelation(this.context, relationName, subAst, options?.correlate);
|
|
6707
|
-
return this.where(exists(finalSubAst));
|
|
7141
|
+
const predicate = buildWhereHasPredicate(
|
|
7142
|
+
this.env,
|
|
7143
|
+
this.context,
|
|
7144
|
+
this.relationFacet,
|
|
7145
|
+
(table) => this.createChildBuilder(table),
|
|
7146
|
+
relationName,
|
|
7147
|
+
callbackOrOptions,
|
|
7148
|
+
maybeOptions,
|
|
7149
|
+
false
|
|
7150
|
+
);
|
|
7151
|
+
return this.where(predicate);
|
|
6708
7152
|
}
|
|
6709
7153
|
/**
|
|
6710
7154
|
* Adds a WHERE NOT EXISTS condition based on a relationship
|
|
6711
7155
|
* @param relationName - Name of the relationship to check
|
|
6712
7156
|
* @param callback - Optional callback to modify the relationship query
|
|
6713
7157
|
* @returns New query builder instance with the relationship non-existence check
|
|
7158
|
+
*
|
|
7159
|
+
* @example
|
|
7160
|
+
* qb.whereHasNot('posts', postQb => postQb.where(eq(postTable.columns.published, true)));
|
|
6714
7161
|
*/
|
|
6715
7162
|
whereHasNot(relationName, callbackOrOptions, maybeOptions) {
|
|
6716
|
-
const
|
|
6717
|
-
|
|
6718
|
-
|
|
6719
|
-
|
|
6720
|
-
|
|
6721
|
-
|
|
6722
|
-
|
|
6723
|
-
|
|
6724
|
-
|
|
6725
|
-
|
|
6726
|
-
|
|
6727
|
-
const finalSubAst = this.relationManager.applyRelationCorrelation(this.context, relationName, subAst, options?.correlate);
|
|
6728
|
-
return this.where(notExists(finalSubAst));
|
|
7163
|
+
const predicate = buildWhereHasPredicate(
|
|
7164
|
+
this.env,
|
|
7165
|
+
this.context,
|
|
7166
|
+
this.relationFacet,
|
|
7167
|
+
(table) => this.createChildBuilder(table),
|
|
7168
|
+
relationName,
|
|
7169
|
+
callbackOrOptions,
|
|
7170
|
+
maybeOptions,
|
|
7171
|
+
true
|
|
7172
|
+
);
|
|
7173
|
+
return this.where(predicate);
|
|
6729
7174
|
}
|
|
6730
7175
|
/**
|
|
6731
7176
|
* Compiles the query to SQL for a specific dialect
|
|
@@ -6857,23 +7302,44 @@ var resolveTableTarget = (target, tableMap) => {
|
|
|
6857
7302
|
}
|
|
6858
7303
|
return table;
|
|
6859
7304
|
};
|
|
7305
|
+
var toSnakeCase = (value) => {
|
|
7306
|
+
return value.replace(/([a-z0-9])([A-Z])/g, "$1_$2").replace(/[^a-z0-9_]+/gi, "_").replace(/__+/g, "_").replace(/^_|_$/g, "").toLowerCase();
|
|
7307
|
+
};
|
|
7308
|
+
var normalizeEntityName = (value) => {
|
|
7309
|
+
const stripped = value.replace(/Entity$/i, "");
|
|
7310
|
+
const normalized = toSnakeCase(stripped || value);
|
|
7311
|
+
return normalized || "unknown";
|
|
7312
|
+
};
|
|
7313
|
+
var getPivotKeyBaseFromTarget = (target) => {
|
|
7314
|
+
const resolved = unwrapTarget(target);
|
|
7315
|
+
if (isTableDef(resolved)) {
|
|
7316
|
+
return toSnakeCase(resolved.name || "unknown");
|
|
7317
|
+
}
|
|
7318
|
+
const ctor = resolved;
|
|
7319
|
+
return normalizeEntityName(ctor.name || "unknown");
|
|
7320
|
+
};
|
|
7321
|
+
var getPivotKeyBaseFromRoot = (meta) => {
|
|
7322
|
+
return normalizeEntityName(meta.target.name || meta.tableName || "unknown");
|
|
7323
|
+
};
|
|
6860
7324
|
var buildRelationDefinitions = (meta, tableMap) => {
|
|
6861
7325
|
const relations = {};
|
|
6862
7326
|
for (const [name, relation] of Object.entries(meta.relations)) {
|
|
6863
7327
|
switch (relation.kind) {
|
|
6864
7328
|
case RelationKinds.HasOne: {
|
|
7329
|
+
const foreignKey = relation.foreignKey ?? `${getPivotKeyBaseFromRoot(meta)}_id`;
|
|
6865
7330
|
relations[name] = hasOne(
|
|
6866
7331
|
resolveTableTarget(relation.target, tableMap),
|
|
6867
|
-
|
|
7332
|
+
foreignKey,
|
|
6868
7333
|
relation.localKey,
|
|
6869
7334
|
relation.cascade
|
|
6870
7335
|
);
|
|
6871
7336
|
break;
|
|
6872
7337
|
}
|
|
6873
7338
|
case RelationKinds.HasMany: {
|
|
7339
|
+
const foreignKey = relation.foreignKey ?? `${getPivotKeyBaseFromRoot(meta)}_id`;
|
|
6874
7340
|
relations[name] = hasMany(
|
|
6875
7341
|
resolveTableTarget(relation.target, tableMap),
|
|
6876
|
-
|
|
7342
|
+
foreignKey,
|
|
6877
7343
|
relation.localKey,
|
|
6878
7344
|
relation.cascade
|
|
6879
7345
|
);
|
|
@@ -6889,12 +7355,14 @@ var buildRelationDefinitions = (meta, tableMap) => {
|
|
|
6889
7355
|
break;
|
|
6890
7356
|
}
|
|
6891
7357
|
case RelationKinds.BelongsToMany: {
|
|
7358
|
+
const pivotForeignKeyToRoot = relation.pivotForeignKeyToRoot ?? `${getPivotKeyBaseFromRoot(meta)}_id`;
|
|
7359
|
+
const pivotForeignKeyToTarget = relation.pivotForeignKeyToTarget ?? `${getPivotKeyBaseFromTarget(relation.target)}_id`;
|
|
6892
7360
|
relations[name] = belongsToMany(
|
|
6893
7361
|
resolveTableTarget(relation.target, tableMap),
|
|
6894
7362
|
resolveTableTarget(relation.pivotTable, tableMap),
|
|
6895
7363
|
{
|
|
6896
|
-
pivotForeignKeyToRoot
|
|
6897
|
-
pivotForeignKeyToTarget
|
|
7364
|
+
pivotForeignKeyToRoot,
|
|
7365
|
+
pivotForeignKeyToTarget,
|
|
6898
7366
|
localKey: relation.localKey,
|
|
6899
7367
|
targetKey: relation.targetKey,
|
|
6900
7368
|
pivotPrimaryKey: relation.pivotPrimaryKey,
|
|
@@ -6975,6 +7443,8 @@ function esel(entity, ...props) {
|
|
|
6975
7443
|
|
|
6976
7444
|
// src/query-builder/insert-query-state.ts
|
|
6977
7445
|
var InsertQueryState = class _InsertQueryState {
|
|
7446
|
+
table;
|
|
7447
|
+
ast;
|
|
6978
7448
|
/**
|
|
6979
7449
|
* Creates a new InsertQueryState instance
|
|
6980
7450
|
* @param table - The table definition for the INSERT query
|
|
@@ -7095,6 +7565,8 @@ var InsertQueryState = class _InsertQueryState {
|
|
|
7095
7565
|
|
|
7096
7566
|
// src/query-builder/insert.ts
|
|
7097
7567
|
var InsertQueryBuilder = class _InsertQueryBuilder {
|
|
7568
|
+
table;
|
|
7569
|
+
state;
|
|
7098
7570
|
/**
|
|
7099
7571
|
* Creates a new InsertQueryBuilder instance
|
|
7100
7572
|
* @param table - The table definition for the INSERT query
|
|
@@ -7194,6 +7666,8 @@ var isUpdateValue = (value) => {
|
|
|
7194
7666
|
}
|
|
7195
7667
|
};
|
|
7196
7668
|
var UpdateQueryState = class _UpdateQueryState {
|
|
7669
|
+
table;
|
|
7670
|
+
ast;
|
|
7197
7671
|
/**
|
|
7198
7672
|
* Creates a new UpdateQueryState instance
|
|
7199
7673
|
* @param table - Table definition for the update
|
|
@@ -7304,6 +7778,8 @@ var UpdateQueryState = class _UpdateQueryState {
|
|
|
7304
7778
|
|
|
7305
7779
|
// src/query-builder/update.ts
|
|
7306
7780
|
var UpdateQueryBuilder = class _UpdateQueryBuilder {
|
|
7781
|
+
table;
|
|
7782
|
+
state;
|
|
7307
7783
|
/**
|
|
7308
7784
|
* Creates a new UpdateQueryBuilder instance
|
|
7309
7785
|
* @param table - The table definition for the UPDATE query
|
|
@@ -7421,6 +7897,8 @@ var isTableSourceNode = (source) => typeof source.type === "string";
|
|
|
7421
7897
|
|
|
7422
7898
|
// src/query-builder/delete-query-state.ts
|
|
7423
7899
|
var DeleteQueryState = class _DeleteQueryState {
|
|
7900
|
+
table;
|
|
7901
|
+
ast;
|
|
7424
7902
|
/**
|
|
7425
7903
|
* Creates a new DeleteQueryState instance
|
|
7426
7904
|
* @param table - The table definition for the DELETE query
|
|
@@ -7499,6 +7977,8 @@ var DeleteQueryState = class _DeleteQueryState {
|
|
|
7499
7977
|
|
|
7500
7978
|
// src/query-builder/delete.ts
|
|
7501
7979
|
var DeleteQueryBuilder = class _DeleteQueryBuilder {
|
|
7980
|
+
table;
|
|
7981
|
+
state;
|
|
7502
7982
|
/**
|
|
7503
7983
|
* Creates a new DeleteQueryBuilder instance
|
|
7504
7984
|
* @param table - The table definition for the DELETE query
|
|
@@ -7626,7 +8106,8 @@ var renderColumnDefinition = (table, col2, dialect, options = {}) => {
|
|
|
7626
8106
|
if (col2.default !== void 0) {
|
|
7627
8107
|
parts.push(`DEFAULT ${dialect.renderDefault(col2.default, col2)}`);
|
|
7628
8108
|
}
|
|
7629
|
-
|
|
8109
|
+
const autoIncIncludesPrimary = typeof autoInc === "string" && /\bPRIMARY\s+KEY\b/i.test(autoInc);
|
|
8110
|
+
if (options.includePrimary && col2.primary && !autoIncIncludesPrimary) {
|
|
7630
8111
|
parts.push("PRIMARY KEY");
|
|
7631
8112
|
}
|
|
7632
8113
|
if (col2.check) {
|
|
@@ -7684,6 +8165,16 @@ var generateSchemaSql = (tables, dialect) => {
|
|
|
7684
8165
|
});
|
|
7685
8166
|
return statements;
|
|
7686
8167
|
};
|
|
8168
|
+
var generateSchemaSqlFor = (dialect, ...tables) => generateSchemaSql(tables, dialect);
|
|
8169
|
+
var executeSchemaSql = async (executor, tables, dialect) => {
|
|
8170
|
+
const statements = generateSchemaSql(tables, dialect);
|
|
8171
|
+
for (const sql of statements) {
|
|
8172
|
+
await executor.executeSql(sql);
|
|
8173
|
+
}
|
|
8174
|
+
};
|
|
8175
|
+
var executeSchemaSqlFor = async (executor, dialect, ...tables) => {
|
|
8176
|
+
await executeSchemaSql(executor, tables, dialect);
|
|
8177
|
+
};
|
|
7687
8178
|
var orderTablesByDependencies = (tables) => {
|
|
7688
8179
|
const map = /* @__PURE__ */ new Map();
|
|
7689
8180
|
tables.forEach((t) => map.set(t.name, t));
|
|
@@ -9590,6 +10081,7 @@ var arrayAppend = (array, value) => fn7("ARRAY_APPEND", [array, value]);
|
|
|
9590
10081
|
|
|
9591
10082
|
// src/orm/als.ts
|
|
9592
10083
|
var AsyncLocalStorage = class {
|
|
10084
|
+
store;
|
|
9593
10085
|
/**
|
|
9594
10086
|
* Executes a callback function within a context containing the specified store value.
|
|
9595
10087
|
* The store value is only available during the callback's execution and is automatically
|
|
@@ -10086,9 +10578,7 @@ var TypeScriptGenerator = class {
|
|
|
10086
10578
|
|
|
10087
10579
|
// src/orm/identity-map.ts
|
|
10088
10580
|
var IdentityMap = class {
|
|
10089
|
-
|
|
10090
|
-
this.buckets = /* @__PURE__ */ new Map();
|
|
10091
|
-
}
|
|
10581
|
+
buckets = /* @__PURE__ */ new Map();
|
|
10092
10582
|
get bucketsMap() {
|
|
10093
10583
|
return this.buckets;
|
|
10094
10584
|
}
|
|
@@ -10158,8 +10648,8 @@ var UnitOfWork = class {
|
|
|
10158
10648
|
this.executor = executor;
|
|
10159
10649
|
this.identityMap = identityMap;
|
|
10160
10650
|
this.hookContext = hookContext;
|
|
10161
|
-
this.trackedEntities = /* @__PURE__ */ new Map();
|
|
10162
10651
|
}
|
|
10652
|
+
trackedEntities = /* @__PURE__ */ new Map();
|
|
10163
10653
|
/**
|
|
10164
10654
|
* Gets the identity buckets map.
|
|
10165
10655
|
*/
|
|
@@ -10489,12 +10979,12 @@ var UnitOfWork = class {
|
|
|
10489
10979
|
|
|
10490
10980
|
// src/orm/domain-event-bus.ts
|
|
10491
10981
|
var DomainEventBus = class {
|
|
10982
|
+
handlers = /* @__PURE__ */ new Map();
|
|
10492
10983
|
/**
|
|
10493
10984
|
* Creates a new DomainEventBus instance.
|
|
10494
10985
|
* @param initialHandlers - Optional initial event handlers
|
|
10495
10986
|
*/
|
|
10496
10987
|
constructor(initialHandlers) {
|
|
10497
|
-
this.handlers = /* @__PURE__ */ new Map();
|
|
10498
10988
|
if (initialHandlers) {
|
|
10499
10989
|
for (const key in initialHandlers) {
|
|
10500
10990
|
const type = key;
|
|
@@ -10563,8 +11053,8 @@ var RelationChangeProcessor = class {
|
|
|
10563
11053
|
this.unitOfWork = unitOfWork;
|
|
10564
11054
|
this.dialect = dialect;
|
|
10565
11055
|
this.executor = executor;
|
|
10566
|
-
this.relationChanges = [];
|
|
10567
11056
|
}
|
|
11057
|
+
relationChanges = [];
|
|
10568
11058
|
/**
|
|
10569
11059
|
* Registers a relation change for processing.
|
|
10570
11060
|
* @param entry - The relation change entry
|
|
@@ -10998,25 +11488,24 @@ var saveGraphInternal = async (session, entityClass, payload, options = {}) => {
|
|
|
10998
11488
|
|
|
10999
11489
|
// src/orm/orm-session.ts
|
|
11000
11490
|
var OrmSession = class {
|
|
11491
|
+
/** The ORM instance */
|
|
11492
|
+
orm;
|
|
11493
|
+
/** The database executor */
|
|
11494
|
+
executor;
|
|
11495
|
+
/** The identity map for tracking entity instances */
|
|
11496
|
+
identityMap;
|
|
11497
|
+
/** The unit of work for tracking entity changes */
|
|
11498
|
+
unitOfWork;
|
|
11499
|
+
/** The domain event bus */
|
|
11500
|
+
domainEvents;
|
|
11501
|
+
/** The relation change processor */
|
|
11502
|
+
relationChanges;
|
|
11503
|
+
interceptors;
|
|
11001
11504
|
/**
|
|
11002
11505
|
* Creates a new OrmSession instance.
|
|
11003
11506
|
* @param opts - Session options
|
|
11004
11507
|
*/
|
|
11005
11508
|
constructor(opts) {
|
|
11006
|
-
/**
|
|
11007
|
-
* Registers a relation change.
|
|
11008
|
-
* @param root - The root entity
|
|
11009
|
-
* @param relationKey - The relation key
|
|
11010
|
-
* @param rootTable - The root table definition
|
|
11011
|
-
* @param relationName - The relation name
|
|
11012
|
-
* @param relation - The relation definition
|
|
11013
|
-
* @param change - The relation change
|
|
11014
|
-
*/
|
|
11015
|
-
this.registerRelationChange = (root, relationKey, rootTable, relationName, relation, change) => {
|
|
11016
|
-
this.relationChanges.registerChange(
|
|
11017
|
-
buildRelationChangeEntry(root, relationKey, rootTable, relationName, relation, change)
|
|
11018
|
-
);
|
|
11019
|
-
};
|
|
11020
11509
|
this.orm = opts.orm;
|
|
11021
11510
|
this.executor = createQueryLoggingExecutor(opts.executor, opts.queryLogger);
|
|
11022
11511
|
this.interceptors = [...opts.interceptors ?? []];
|
|
@@ -11105,6 +11594,20 @@ var OrmSession = class {
|
|
|
11105
11594
|
markRemoved(entity) {
|
|
11106
11595
|
this.unitOfWork.markRemoved(entity);
|
|
11107
11596
|
}
|
|
11597
|
+
/**
|
|
11598
|
+
* Registers a relation change.
|
|
11599
|
+
* @param root - The root entity
|
|
11600
|
+
* @param relationKey - The relation key
|
|
11601
|
+
* @param rootTable - The root table definition
|
|
11602
|
+
* @param relationName - The relation name
|
|
11603
|
+
* @param relation - The relation definition
|
|
11604
|
+
* @param change - The relation change
|
|
11605
|
+
*/
|
|
11606
|
+
registerRelationChange = (root, relationKey, rootTable, relationName, relation, change) => {
|
|
11607
|
+
this.relationChanges.registerChange(
|
|
11608
|
+
buildRelationChangeEntry(root, relationKey, rootTable, relationName, relation, change)
|
|
11609
|
+
);
|
|
11610
|
+
};
|
|
11108
11611
|
/**
|
|
11109
11612
|
* Gets all tracked entities for a specific table.
|
|
11110
11613
|
* @param table - The table definition
|
|
@@ -11310,9 +11813,7 @@ var buildRelationChangeEntry = (root, relationKey, rootTable, relationName, rela
|
|
|
11310
11813
|
|
|
11311
11814
|
// src/orm/interceptor-pipeline.ts
|
|
11312
11815
|
var InterceptorPipeline = class {
|
|
11313
|
-
|
|
11314
|
-
this.interceptors = [];
|
|
11315
|
-
}
|
|
11816
|
+
interceptors = [];
|
|
11316
11817
|
use(interceptor) {
|
|
11317
11818
|
this.interceptors.push(interceptor);
|
|
11318
11819
|
}
|
|
@@ -11331,6 +11832,13 @@ var InterceptorPipeline = class {
|
|
|
11331
11832
|
|
|
11332
11833
|
// src/orm/orm.ts
|
|
11333
11834
|
var Orm = class {
|
|
11835
|
+
/** The database dialect */
|
|
11836
|
+
dialect;
|
|
11837
|
+
/** The interceptors pipeline */
|
|
11838
|
+
interceptors;
|
|
11839
|
+
/** The naming strategy */
|
|
11840
|
+
namingStrategy;
|
|
11841
|
+
executorFactory;
|
|
11334
11842
|
/**
|
|
11335
11843
|
* Creates a new ORM instance.
|
|
11336
11844
|
* @param opts - ORM options
|
|
@@ -11387,17 +11895,13 @@ var jsonify = (value) => {
|
|
|
11387
11895
|
|
|
11388
11896
|
// src/decorators/decorator-metadata.ts
|
|
11389
11897
|
var METADATA_KEY = "metal-orm:decorators";
|
|
11390
|
-
var isStandardDecoratorContext = (value) => {
|
|
11391
|
-
return typeof value === "object" && value !== null && "kind" in value;
|
|
11392
|
-
};
|
|
11393
11898
|
var getOrCreateMetadataBag = (context) => {
|
|
11394
11899
|
const metadata = context.metadata || (context.metadata = {});
|
|
11395
|
-
|
|
11396
|
-
if (
|
|
11397
|
-
|
|
11900
|
+
let bag = metadata[METADATA_KEY];
|
|
11901
|
+
if (!bag) {
|
|
11902
|
+
bag = { columns: [], relations: [] };
|
|
11903
|
+
metadata[METADATA_KEY] = bag;
|
|
11398
11904
|
}
|
|
11399
|
-
const bag = { columns: [], relations: [] };
|
|
11400
|
-
metadata[METADATA_KEY] = bag;
|
|
11401
11905
|
return bag;
|
|
11402
11906
|
};
|
|
11403
11907
|
var readMetadataBag = (context) => {
|
|
@@ -11412,57 +11916,50 @@ var readMetadataBagFromConstructor = (ctor) => {
|
|
|
11412
11916
|
var getDecoratorMetadata = (ctor) => readMetadataBagFromConstructor(ctor);
|
|
11413
11917
|
|
|
11414
11918
|
// src/decorators/entity.ts
|
|
11415
|
-
var
|
|
11919
|
+
var toSnakeCase2 = (value) => {
|
|
11416
11920
|
return value.replace(/([a-z0-9])([A-Z])/g, "$1_$2").replace(/[^a-z0-9_]+/gi, "_").replace(/__+/g, "_").replace(/^_|_$/g, "").toLowerCase();
|
|
11417
11921
|
};
|
|
11418
11922
|
var deriveTableNameFromConstructor = (ctor) => {
|
|
11419
11923
|
const fallback = "unknown";
|
|
11420
11924
|
const rawName = ctor.name || fallback;
|
|
11421
11925
|
const strippedName = rawName.replace(/Entity$/i, "");
|
|
11422
|
-
const normalized =
|
|
11926
|
+
const normalized = toSnakeCase2(strippedName || rawName);
|
|
11423
11927
|
if (!normalized) {
|
|
11424
11928
|
return fallback;
|
|
11425
11929
|
}
|
|
11426
11930
|
return normalized.endsWith("s") ? normalized : `${normalized}s`;
|
|
11427
11931
|
};
|
|
11428
11932
|
function Entity(options = {}) {
|
|
11429
|
-
|
|
11430
|
-
const tableName = options.tableName ?? deriveTableNameFromConstructor(value);
|
|
11431
|
-
setEntityTableName(value, tableName, options.hooks);
|
|
11432
|
-
return value;
|
|
11433
|
-
};
|
|
11434
|
-
const decoratorWithContext = (value, context) => {
|
|
11933
|
+
return function(value, context) {
|
|
11435
11934
|
const ctor = value;
|
|
11436
|
-
|
|
11437
|
-
|
|
11438
|
-
|
|
11439
|
-
|
|
11440
|
-
|
|
11441
|
-
|
|
11442
|
-
|
|
11443
|
-
|
|
11444
|
-
|
|
11445
|
-
|
|
11446
|
-
}
|
|
11447
|
-
addColumnMetadata(ctor, entry.propertyName, { ...entry.column });
|
|
11935
|
+
const tableName = options.tableName ?? deriveTableNameFromConstructor(ctor);
|
|
11936
|
+
setEntityTableName(ctor, tableName, options.hooks);
|
|
11937
|
+
const bag = readMetadataBag(context);
|
|
11938
|
+
if (bag) {
|
|
11939
|
+
const meta = ensureEntityMetadata(ctor);
|
|
11940
|
+
for (const entry of bag.columns) {
|
|
11941
|
+
if (meta.columns[entry.propertyName]) {
|
|
11942
|
+
throw new Error(
|
|
11943
|
+
`Column '${entry.propertyName}' is already defined on entity '${ctor.name}'.`
|
|
11944
|
+
);
|
|
11448
11945
|
}
|
|
11449
|
-
|
|
11450
|
-
|
|
11451
|
-
|
|
11452
|
-
|
|
11453
|
-
|
|
11454
|
-
|
|
11455
|
-
|
|
11456
|
-
...entry.relation,
|
|
11457
|
-
defaultPivotColumns: entry.relation.defaultPivotColumns ? [...entry.relation.defaultPivotColumns] : void 0
|
|
11458
|
-
} : { ...entry.relation };
|
|
11459
|
-
addRelationMetadata(ctor, entry.propertyName, relationCopy);
|
|
11946
|
+
addColumnMetadata(ctor, entry.propertyName, { ...entry.column });
|
|
11947
|
+
}
|
|
11948
|
+
for (const entry of bag.relations) {
|
|
11949
|
+
if (meta.relations[entry.propertyName]) {
|
|
11950
|
+
throw new Error(
|
|
11951
|
+
`Relation '${entry.propertyName}' is already defined on entity '${ctor.name}'.`
|
|
11952
|
+
);
|
|
11460
11953
|
}
|
|
11954
|
+
const relationCopy = entry.relation.kind === RelationKinds.BelongsToMany ? {
|
|
11955
|
+
...entry.relation,
|
|
11956
|
+
defaultPivotColumns: entry.relation.defaultPivotColumns ? [...entry.relation.defaultPivotColumns] : void 0
|
|
11957
|
+
} : { ...entry.relation };
|
|
11958
|
+
addRelationMetadata(ctor, entry.propertyName, relationCopy);
|
|
11461
11959
|
}
|
|
11462
11960
|
}
|
|
11463
11961
|
return ctor;
|
|
11464
11962
|
};
|
|
11465
|
-
return decoratorWithContext;
|
|
11466
11963
|
}
|
|
11467
11964
|
|
|
11468
11965
|
// src/decorators/column-decorator.ts
|
|
@@ -11495,26 +11992,13 @@ var normalizePropertyName = (name) => {
|
|
|
11495
11992
|
}
|
|
11496
11993
|
return name;
|
|
11497
11994
|
};
|
|
11498
|
-
var resolveConstructor = (target) => {
|
|
11499
|
-
if (typeof target === "function") {
|
|
11500
|
-
return target;
|
|
11501
|
-
}
|
|
11502
|
-
if (target && typeof target.constructor === "function") {
|
|
11503
|
-
return target.constructor;
|
|
11504
|
-
}
|
|
11505
|
-
return void 0;
|
|
11506
|
-
};
|
|
11507
|
-
var registerColumn = (ctor, propertyName, column) => {
|
|
11508
|
-
const meta = ensureEntityMetadata(ctor);
|
|
11509
|
-
if (meta.columns[propertyName]) {
|
|
11510
|
-
return;
|
|
11511
|
-
}
|
|
11512
|
-
addColumnMetadata(ctor, propertyName, column);
|
|
11513
|
-
};
|
|
11514
11995
|
var registerColumnFromContext = (context, column) => {
|
|
11515
11996
|
if (!context.name) {
|
|
11516
11997
|
throw new Error("Column decorator requires a property name");
|
|
11517
11998
|
}
|
|
11999
|
+
if (context.private) {
|
|
12000
|
+
throw new Error("Column decorator does not support private fields");
|
|
12001
|
+
}
|
|
11518
12002
|
const propertyName = normalizePropertyName(context.name);
|
|
11519
12003
|
const bag = getOrCreateMetadataBag(context);
|
|
11520
12004
|
if (!bag.columns.some((entry) => entry.propertyName === propertyName)) {
|
|
@@ -11523,19 +12007,9 @@ var registerColumnFromContext = (context, column) => {
|
|
|
11523
12007
|
};
|
|
11524
12008
|
function Column(definition) {
|
|
11525
12009
|
const normalized = normalizeColumnInput(definition);
|
|
11526
|
-
|
|
11527
|
-
|
|
11528
|
-
registerColumnFromContext(propertyKeyOrContext, normalized);
|
|
11529
|
-
return;
|
|
11530
|
-
}
|
|
11531
|
-
const propertyName = normalizePropertyName(propertyKeyOrContext);
|
|
11532
|
-
const ctor = resolveConstructor(targetOrValue);
|
|
11533
|
-
if (!ctor) {
|
|
11534
|
-
throw new Error("Unable to resolve constructor when registering column metadata");
|
|
11535
|
-
}
|
|
11536
|
-
registerColumn(ctor, propertyName, { ...normalized });
|
|
12010
|
+
return function(_value, context) {
|
|
12011
|
+
registerColumnFromContext(context, normalized);
|
|
11537
12012
|
};
|
|
11538
|
-
return decorator;
|
|
11539
12013
|
}
|
|
11540
12014
|
function PrimaryKey(definition) {
|
|
11541
12015
|
const normalized = normalizeColumnInput(definition);
|
|
@@ -11550,41 +12024,21 @@ var normalizePropertyName2 = (name) => {
|
|
|
11550
12024
|
}
|
|
11551
12025
|
return name;
|
|
11552
12026
|
};
|
|
11553
|
-
var resolveConstructor2 = (instanceOrCtor) => {
|
|
11554
|
-
if (typeof instanceOrCtor === "function") {
|
|
11555
|
-
return instanceOrCtor;
|
|
11556
|
-
}
|
|
11557
|
-
if (instanceOrCtor && typeof instanceOrCtor.constructor === "function") {
|
|
11558
|
-
return instanceOrCtor.constructor;
|
|
11559
|
-
}
|
|
11560
|
-
return void 0;
|
|
11561
|
-
};
|
|
11562
|
-
var registerRelation = (ctor, propertyName, metadata) => {
|
|
11563
|
-
addRelationMetadata(ctor, propertyName, metadata);
|
|
11564
|
-
};
|
|
11565
12027
|
var createFieldDecorator = (metadataFactory) => {
|
|
11566
|
-
|
|
11567
|
-
if (
|
|
11568
|
-
|
|
11569
|
-
if (!ctx.name) {
|
|
11570
|
-
throw new Error("Relation decorator requires a property name");
|
|
11571
|
-
}
|
|
11572
|
-
const propertyName2 = normalizePropertyName2(ctx.name);
|
|
11573
|
-
const bag = getOrCreateMetadataBag(ctx);
|
|
11574
|
-
const relationMetadata = metadataFactory(propertyName2);
|
|
11575
|
-
if (!bag.relations.some((entry) => entry.propertyName === propertyName2)) {
|
|
11576
|
-
bag.relations.push({ propertyName: propertyName2, relation: relationMetadata });
|
|
11577
|
-
}
|
|
11578
|
-
return;
|
|
12028
|
+
return function(_value, context) {
|
|
12029
|
+
if (!context.name) {
|
|
12030
|
+
throw new Error("Relation decorator requires a property name");
|
|
11579
12031
|
}
|
|
11580
|
-
|
|
11581
|
-
|
|
11582
|
-
|
|
11583
|
-
|
|
12032
|
+
if (context.private) {
|
|
12033
|
+
throw new Error("Relation decorator does not support private fields");
|
|
12034
|
+
}
|
|
12035
|
+
const propertyName = normalizePropertyName2(context.name);
|
|
12036
|
+
const bag = getOrCreateMetadataBag(context);
|
|
12037
|
+
const relationMetadata = metadataFactory(propertyName);
|
|
12038
|
+
if (!bag.relations.some((entry) => entry.propertyName === propertyName)) {
|
|
12039
|
+
bag.relations.push({ propertyName, relation: relationMetadata });
|
|
11584
12040
|
}
|
|
11585
|
-
registerRelation(ctor, propertyName, metadataFactory(propertyName));
|
|
11586
12041
|
};
|
|
11587
|
-
return decorator;
|
|
11588
12042
|
};
|
|
11589
12043
|
function HasMany(options) {
|
|
11590
12044
|
return createFieldDecorator((propertyName) => ({
|
|
@@ -11611,7 +12065,7 @@ function BelongsTo(options) {
|
|
|
11611
12065
|
kind: RelationKinds.BelongsTo,
|
|
11612
12066
|
propertyKey: propertyName,
|
|
11613
12067
|
target: options.target,
|
|
11614
|
-
foreignKey: options.foreignKey
|
|
12068
|
+
foreignKey: options.foreignKey ?? `${propertyName}_id`,
|
|
11615
12069
|
localKey: options.localKey,
|
|
11616
12070
|
cascade: options.cascade
|
|
11617
12071
|
}));
|
|
@@ -11687,13 +12141,15 @@ var deferred = () => {
|
|
|
11687
12141
|
return { promise, resolve, reject };
|
|
11688
12142
|
};
|
|
11689
12143
|
var Pool = class {
|
|
12144
|
+
adapter;
|
|
12145
|
+
options;
|
|
12146
|
+
destroyed = false;
|
|
12147
|
+
creating = 0;
|
|
12148
|
+
leased = 0;
|
|
12149
|
+
idle = [];
|
|
12150
|
+
waiters = [];
|
|
12151
|
+
reapTimer = null;
|
|
11690
12152
|
constructor(adapter, options) {
|
|
11691
|
-
this.destroyed = false;
|
|
11692
|
-
this.creating = 0;
|
|
11693
|
-
this.leased = 0;
|
|
11694
|
-
this.idle = [];
|
|
11695
|
-
this.waiters = [];
|
|
11696
|
-
this.reapTimer = null;
|
|
11697
12153
|
if (!Number.isFinite(options.max) || options.max <= 0) {
|
|
11698
12154
|
throw new Error("Pool options.max must be a positive number");
|
|
11699
12155
|
}
|
|
@@ -12256,6 +12712,8 @@ function createPooledExecutorFactory(opts) {
|
|
|
12256
12712
|
esel,
|
|
12257
12713
|
executeHydrated,
|
|
12258
12714
|
executeHydratedWithContexts,
|
|
12715
|
+
executeSchemaSql,
|
|
12716
|
+
executeSchemaSqlFor,
|
|
12259
12717
|
exists,
|
|
12260
12718
|
exp,
|
|
12261
12719
|
extract,
|
|
@@ -12264,6 +12722,7 @@ function createPooledExecutorFactory(opts) {
|
|
|
12264
12722
|
fromUnixTime,
|
|
12265
12723
|
generateCreateTableSql,
|
|
12266
12724
|
generateSchemaSql,
|
|
12725
|
+
generateSchemaSqlFor,
|
|
12267
12726
|
getColumn,
|
|
12268
12727
|
getDecoratorMetadata,
|
|
12269
12728
|
getSchemaIntrospector,
|
|
@@ -12369,6 +12828,7 @@ function createPooledExecutorFactory(opts) {
|
|
|
12369
12828
|
second,
|
|
12370
12829
|
sel,
|
|
12371
12830
|
selectFromEntity,
|
|
12831
|
+
setRelations,
|
|
12372
12832
|
sha1,
|
|
12373
12833
|
sha2,
|
|
12374
12834
|
shiftLeft,
|