typeorm-extensions 2.2.0-rc.1 → 2.2.0-rc.3
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
|
@@ -1,8 +1,8 @@
|
|
|
1
1
|
export type TypedGroupByOptions = {
|
|
2
2
|
/**
|
|
3
3
|
* Group by the quoted database column (`"ticket"."ticket_status"`) instead of `ticket.status`,
|
|
4
|
-
* which TypeORM maps to the column itself.
|
|
5
|
-
*
|
|
4
|
+
* which TypeORM maps to the column itself. Keys of an alias without metadata (a subquery in FROM)
|
|
5
|
+
* are quoted unless this is `false`: PostgreSQL folds an unquoted `sub.firstName` to `firstname`.
|
|
6
6
|
*/
|
|
7
7
|
useQuotes?: boolean;
|
|
8
8
|
};
|
|
@@ -47,10 +47,13 @@ export declare function isTypedJsonPath<Type extends ObjectLiteral>(builder: Whe
|
|
|
47
47
|
*/
|
|
48
48
|
export declare function getTypedSingleColumnKey<Type extends ObjectLiteral>(builder: WhereExpressionBuilder, callback: KeyProxyCallback<Type>, methodName: string, jsonOptions?: JsonPathSqlOptions): string;
|
|
49
49
|
/**
|
|
50
|
-
* Key for typed select / order / distinct on a SelectQueryBuilder.
|
|
50
|
+
* Key for typed select / order / distinct / group by on a SelectQueryBuilder.
|
|
51
51
|
*
|
|
52
52
|
* Without quotes it is `alias.propertyPath` (`user.name`, `images.url`, `p.address.city`),
|
|
53
53
|
* which TypeORM maps to the column itself. With `useQuotes` it is the quoted database column
|
|
54
|
-
* (`"t"."ticket_status"`), since TypeORM doesn't map quoted keys.
|
|
54
|
+
* (`"t"."ticket_status"`), since TypeORM doesn't map quoted keys. An alias of the query without
|
|
55
|
+
* metadata (a subquery or a CTE in FROM or a join) is quoted unless `useQuotes` is `false`:
|
|
56
|
+
* TypeORM leaves its keys as written, and PostgreSQL folds an unquoted `cte.firstName` to `firstname`.
|
|
57
|
+
* Strings are kept as is.
|
|
55
58
|
*/
|
|
56
59
|
export declare function getTypedSelectionKey<Type extends ObjectLiteral>(builder: WhereExpressionBuilder, selection: KeyProxyCallback<Type> | string, useQuotes?: boolean): string | string[];
|
|
@@ -30,12 +30,29 @@ function requireMainAliasName(queryBuilder, key) {
|
|
|
30
30
|
}
|
|
31
31
|
return mainAlias.name;
|
|
32
32
|
}
|
|
33
|
+
/**
|
|
34
|
+
* An alias of the query by name, or of a query it is part of. The builder of a `Brackets` callback has the
|
|
35
|
+
* outer query's main alias but an empty alias list: the aliases, joins included, are on its parent. A subquery
|
|
36
|
+
* sees the aliases of the outer query too, its own first.
|
|
37
|
+
*/
|
|
38
|
+
function findQueryAlias(queryBuilder, aliasName) {
|
|
39
|
+
var _a, _b;
|
|
40
|
+
// parentQueryBuilder is protected in TypeORM's types
|
|
41
|
+
for (let query = queryBuilder; query; query = query.parentQueryBuilder) {
|
|
42
|
+
const { aliases = [], mainAlias } = (_a = query.expressionMap) !== null && _a !== void 0 ? _a : {};
|
|
43
|
+
const alias = (_b = aliases.find((candidate) => candidate.name === aliasName)) !== null && _b !== void 0 ? _b : ((mainAlias === null || mainAlias === void 0 ? void 0 : mainAlias.name) === aliasName ? mainAlias : undefined);
|
|
44
|
+
if (alias) {
|
|
45
|
+
return alias;
|
|
46
|
+
}
|
|
47
|
+
}
|
|
48
|
+
return undefined;
|
|
49
|
+
}
|
|
33
50
|
/** Entity metadata of a query alias (the main alias when `aliasName` is undefined), if it has any. */
|
|
34
51
|
function getAliasMetadata(queryBuilder, aliasName) {
|
|
35
|
-
|
|
52
|
+
var _a;
|
|
36
53
|
const alias = aliasName === undefined
|
|
37
|
-
? expressionMap === null ||
|
|
38
|
-
:
|
|
54
|
+
? (_a = queryBuilder.expressionMap) === null || _a === void 0 ? void 0 : _a.mainAlias
|
|
55
|
+
: findQueryAlias(queryBuilder, aliasName);
|
|
39
56
|
return (alias === null || alias === void 0 ? void 0 : alias.hasMetadata) ? alias.metadata : undefined;
|
|
40
57
|
}
|
|
41
58
|
/**
|
|
@@ -85,14 +102,11 @@ exports.findFieldColumn = findFieldColumn;
|
|
|
85
102
|
* `stringToSQLIdentifier` does, in the driver's quotes.
|
|
86
103
|
*/
|
|
87
104
|
function toFieldSql(builder, field) {
|
|
88
|
-
var _a;
|
|
89
105
|
const queryBuilder = builder;
|
|
90
106
|
const dot = field.indexOf('.');
|
|
91
107
|
if (dot > 0) {
|
|
92
108
|
const aliasName = field.slice(0, dot);
|
|
93
|
-
const metadata = (
|
|
94
|
-
? getAliasMetadata(queryBuilder, aliasName)
|
|
95
|
-
: undefined;
|
|
109
|
+
const metadata = getAliasMetadata(queryBuilder, aliasName);
|
|
96
110
|
const column = metadata && findColumn(metadata, field.slice(dot + 1));
|
|
97
111
|
if (column) {
|
|
98
112
|
const columnSql = queryBuilder.escape(column.databaseName);
|
|
@@ -182,7 +196,7 @@ function resolveTypedKeyPath(queryBuilder, keys) {
|
|
|
182
196
|
...findColumnPath(metadata, restKeys),
|
|
183
197
|
};
|
|
184
198
|
}
|
|
185
|
-
const queryAlias =
|
|
199
|
+
const queryAlias = findQueryAlias(queryBuilder, firstKey);
|
|
186
200
|
if (!queryAlias && mainAlias) {
|
|
187
201
|
const mainMetadata = getAliasMetadata(queryBuilder, undefined);
|
|
188
202
|
const columnPath = findColumnPath(mainMetadata, keys);
|
|
@@ -254,12 +268,20 @@ function getTypedSingleColumnKey(builder, callback, methodName, jsonOptions) {
|
|
|
254
268
|
return key;
|
|
255
269
|
}
|
|
256
270
|
exports.getTypedSingleColumnKey = getTypedSingleColumnKey;
|
|
271
|
+
// an alias the query doesn't know yet may still get metadata (a join added later), so it stays unquoted
|
|
272
|
+
function isAliasWithoutMetadata(queryBuilder, aliasName) {
|
|
273
|
+
const alias = aliasName === undefined ? undefined : findQueryAlias(queryBuilder, aliasName);
|
|
274
|
+
return alias !== undefined && !alias.hasMetadata;
|
|
275
|
+
}
|
|
257
276
|
/**
|
|
258
|
-
* Key for typed select / order / distinct on a SelectQueryBuilder.
|
|
277
|
+
* Key for typed select / order / distinct / group by on a SelectQueryBuilder.
|
|
259
278
|
*
|
|
260
279
|
* Without quotes it is `alias.propertyPath` (`user.name`, `images.url`, `p.address.city`),
|
|
261
280
|
* which TypeORM maps to the column itself. With `useQuotes` it is the quoted database column
|
|
262
|
-
* (`"t"."ticket_status"`), since TypeORM doesn't map quoted keys.
|
|
281
|
+
* (`"t"."ticket_status"`), since TypeORM doesn't map quoted keys. An alias of the query without
|
|
282
|
+
* metadata (a subquery or a CTE in FROM or a join) is quoted unless `useQuotes` is `false`:
|
|
283
|
+
* TypeORM leaves its keys as written, and PostgreSQL folds an unquoted `cte.firstName` to `firstname`.
|
|
284
|
+
* Strings are kept as is.
|
|
263
285
|
*/
|
|
264
286
|
function getTypedSelectionKey(builder, selection, useQuotes) {
|
|
265
287
|
if (typeof selection === 'string') {
|
|
@@ -272,7 +294,7 @@ function getTypedSelectionKey(builder, selection, useQuotes) {
|
|
|
272
294
|
throw new TypeError(`Typed key "${keyHolder.getKeys().join('.')}" points into the JSON column "${resolved.propertyPath}": ` +
|
|
273
295
|
`select, order, distinct and group by take columns only. For an expression use tableHelper().jsonColumn()`);
|
|
274
296
|
}
|
|
275
|
-
if (useQuotes) {
|
|
297
|
+
if (useQuotes !== null && useQuotes !== void 0 ? useQuotes : isAliasWithoutMetadata(queryBuilder, resolved.aliasName)) {
|
|
276
298
|
return toQuotedColumnKey(queryBuilder, resolved);
|
|
277
299
|
}
|
|
278
300
|
return resolved.aliasName === undefined
|