mythix-orm-sql-base 1.9.2 → 1.9.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.
|
@@ -661,18 +661,18 @@ class SQLConnectionBase extends ConnectionBase {
|
|
|
661
661
|
queryEngine = await this.finalizeQuery('read', queryEngine, options);
|
|
662
662
|
queryEngine = queryEngine.clone();
|
|
663
663
|
|
|
664
|
-
let queryContext = queryEngine.getOperationContext();
|
|
665
|
-
let distinct = queryContext.distinct;
|
|
666
|
-
if (distinct) {
|
|
667
|
-
|
|
668
|
-
|
|
669
|
-
|
|
670
|
-
|
|
671
|
-
|
|
672
|
-
|
|
673
|
-
|
|
674
|
-
|
|
675
|
-
}
|
|
664
|
+
// let queryContext = queryEngine.getOperationContext();
|
|
665
|
+
// let distinct = queryContext.distinct;
|
|
666
|
+
// if (distinct) {
|
|
667
|
+
// let fullyQualifiedFieldName = distinct.getFullyQualifiedFieldName();
|
|
668
|
+
|
|
669
|
+
// if (fullyQualifiedFieldName) {
|
|
670
|
+
// let LiteralConstructor = literal.constructor;
|
|
671
|
+
// literal = new LiteralConstructor(fullyQualifiedFieldName);
|
|
672
|
+
|
|
673
|
+
// queryEngine = queryEngine.DISTINCT(false).PROJECT(literal);
|
|
674
|
+
// }
|
|
675
|
+
// }
|
|
676
676
|
|
|
677
677
|
let literalStr = literal.toString(this);
|
|
678
678
|
let queryGenerator = this.getQueryGenerator();
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { Field,
|
|
1
|
+
import { Field, Model, ModelClass, PreparedModels, QueryEngine, QueryGeneratorBase } from 'mythix-orm';
|
|
2
2
|
import { LiteralBase } from 'mythix-orm/lib/connection/literals';
|
|
3
3
|
import { GenericObject } from 'mythix-orm/lib/interfaces/common';
|
|
4
4
|
import { Type } from 'mythix-orm/lib/types';
|
|
@@ -11,7 +11,61 @@ export declare interface QueryConditionContext {
|
|
|
11
11
|
value: any;
|
|
12
12
|
}
|
|
13
13
|
|
|
14
|
+
export declare interface GetEscapedFieldNameOptions {
|
|
15
|
+
fieldNameOnly?: boolean;
|
|
16
|
+
}
|
|
17
|
+
|
|
18
|
+
export declare interface GetEscapedTableNameNameOptions {
|
|
19
|
+
tableNamePrefix?: string;
|
|
20
|
+
}
|
|
21
|
+
|
|
22
|
+
export declare interface GetEscapedColumnNameOptions extends GetEscapedTableNameNameOptions {
|
|
23
|
+
columnNamePrefix?: string
|
|
24
|
+
columnNameOnly?: boolean;
|
|
25
|
+
}
|
|
26
|
+
|
|
27
|
+
export declare interface GetEscapedProjectionNameOptions extends GetEscapedColumnNameOptions, GetEscapedFieldNameOptions {
|
|
28
|
+
noProjectionAliases?: boolean;
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
export declare interface GetEscapedModelFieldsOptions extends GetEscapedProjectionNameOptions {
|
|
32
|
+
asProjection?: boolean;
|
|
33
|
+
asColumn?: boolean;
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
export declare interface JoinTableInfo {
|
|
37
|
+
operator: string;
|
|
38
|
+
joinType: string | LiteralBase;
|
|
39
|
+
rootModelName: string;
|
|
40
|
+
joinModel: ModelClass;
|
|
41
|
+
joinModelName: string;
|
|
42
|
+
leftSideModel: ModelClass;
|
|
43
|
+
leftSideModelName: string;
|
|
44
|
+
leftQueryContext: GenericObject;
|
|
45
|
+
leftSideField: Field;
|
|
46
|
+
rightSideModel: ModelClass;
|
|
47
|
+
rightSideModelName: string;
|
|
48
|
+
rightQueryContext: GenericObject;
|
|
49
|
+
rightSideField: Field;
|
|
50
|
+
}
|
|
51
|
+
|
|
14
52
|
declare class SQLQueryGeneratorBase extends QueryGeneratorBase {
|
|
53
|
+
public getEscapedFieldName(Model: ModelClass | null | undefined, field: Field, options?: GetEscapedFieldNameOptions): string;
|
|
54
|
+
public getEscapedColumnName(Model: ModelClass | null | undefined, field: Field, options?: GetEscapedColumnNameOptions): string;
|
|
55
|
+
public getEscapedTableName(modelOrField: ModelClass | Field, options?: GetEscapedTableNameNameOptions): string;
|
|
56
|
+
public getEscapedProjectionName(Model: ModelClass | null | undefined, field: Field, options?: GetEscapedProjectionNameOptions): string;
|
|
57
|
+
public getEscapedModelFields(Model: ModelClass, options?: GetEscapedModelFieldsOptions): { [key: string]: string };
|
|
58
|
+
public isFieldIdentifier(value: string): boolean;
|
|
59
|
+
public getProjectedFields(queryEngine: QueryEngine, options?: GenericObject, asMap?: false | undefined): Array<string>;
|
|
60
|
+
public getProjectedFields(queryEngine: QueryEngine, options?: GenericObject, asMap?: true): Map<string, string>;
|
|
61
|
+
|
|
62
|
+
public getJoinTableInfoFromQueryContexts(
|
|
63
|
+
leftQueryContext: GenericObject,
|
|
64
|
+
rightQueryContext: GenericObject,
|
|
65
|
+
joinType: string | LiteralBase,
|
|
66
|
+
options?: GenericObject
|
|
67
|
+
): JoinTableInfo;
|
|
68
|
+
|
|
15
69
|
public prepareArrayValuesForSQL(array: Array<any>): Array<any>;
|
|
16
70
|
public parseFieldProjection(value: string, getRawField: boolean): string | Field | undefined;
|
|
17
71
|
public parseFieldProjectionToFieldMap(selectStatement: string): Map<string, Field | string>;
|
|
@@ -15,6 +15,296 @@ const DefaultHelpers = Types.DefaultHelpers;
|
|
|
15
15
|
const LiteralBase = Literals.LiteralBase;
|
|
16
16
|
|
|
17
17
|
class SQLQueryGeneratorBase extends QueryGeneratorBase {
|
|
18
|
+
getEscapedFieldName(_Model, field, options) {
|
|
19
|
+
let isString = Nife.instanceOf(field, 'string');
|
|
20
|
+
let fieldName = (isString) ? field : field.fieldName;
|
|
21
|
+
let Model = _Model;
|
|
22
|
+
|
|
23
|
+
if (!Model && field && !isString)
|
|
24
|
+
Model = field.Model;
|
|
25
|
+
|
|
26
|
+
if (!Model || (options && options.fieldNameOnly === true))
|
|
27
|
+
return this.escapeID(fieldName);
|
|
28
|
+
else
|
|
29
|
+
return `"${field.Model.getModelName()}:${fieldName}"`;
|
|
30
|
+
}
|
|
31
|
+
|
|
32
|
+
getEscapedColumnName(_Model, field, options) {
|
|
33
|
+
let isString = Nife.instanceOf(field, 'string');
|
|
34
|
+
let columnName = (isString) ? field : (field.columnName || field.fieldName);
|
|
35
|
+
let Model = _Model;
|
|
36
|
+
|
|
37
|
+
if (!Model && field && !isString)
|
|
38
|
+
Model = field.Model;
|
|
39
|
+
|
|
40
|
+
if (options && options.columnNamePrefix)
|
|
41
|
+
columnName = `${options.columnNamePrefix}${columnName}`;
|
|
42
|
+
|
|
43
|
+
if (!Model || (options && options.columnNameOnly === true))
|
|
44
|
+
return this.escapeID(columnName);
|
|
45
|
+
else
|
|
46
|
+
return `${this.getEscapedTableName(Model)}.${this.escapeID(columnName)}`;
|
|
47
|
+
}
|
|
48
|
+
|
|
49
|
+
getEscapedTableName(_modelOrField, options) {
|
|
50
|
+
let Model = (_modelOrField.Model) ? _modelOrField.Model : _modelOrField;
|
|
51
|
+
let tableName = Model.getTableName(this.connection);
|
|
52
|
+
|
|
53
|
+
if (options && options.tableNamePrefix)
|
|
54
|
+
tableName = `${options.tableNamePrefix}${tableName}`;
|
|
55
|
+
|
|
56
|
+
return this.escapeID(tableName);
|
|
57
|
+
}
|
|
58
|
+
|
|
59
|
+
// eslint-disable-next-line no-unused-vars
|
|
60
|
+
getEscapedProjectionName(Model, field, options) {
|
|
61
|
+
if (options && options.noProjectionAliases)
|
|
62
|
+
return this.getEscapedColumnName(Model, field, options);
|
|
63
|
+
else
|
|
64
|
+
return `${this.getEscapedColumnName(Model, field, options)} AS ${(options && options.as) ? this.escapeID(options.as) : this.getEscapedFieldName(Model, field, options)}`;
|
|
65
|
+
}
|
|
66
|
+
|
|
67
|
+
// eslint-disable-next-line no-unused-vars
|
|
68
|
+
getEscapedModelFields(Model, options) {
|
|
69
|
+
let fields = {};
|
|
70
|
+
let modelName = Model.getModelName();
|
|
71
|
+
|
|
72
|
+
Model.iterateFields(({ field, fieldName }) => {
|
|
73
|
+
if (field.type.isVirtual())
|
|
74
|
+
return;
|
|
75
|
+
|
|
76
|
+
let result;
|
|
77
|
+
|
|
78
|
+
if (options && options.asProjection)
|
|
79
|
+
result = this.getEscapedProjectionName(Model, field, options);
|
|
80
|
+
else if (options && options.asColumn)
|
|
81
|
+
result = this.getEscapedColumnName(Model, field, options);
|
|
82
|
+
else
|
|
83
|
+
result = this.getEscapedFieldName(Model, field, options);
|
|
84
|
+
|
|
85
|
+
fields[`${modelName}:${fieldName}`] = result;
|
|
86
|
+
}, (options && options.fields));
|
|
87
|
+
|
|
88
|
+
return fields;
|
|
89
|
+
}
|
|
90
|
+
|
|
91
|
+
isFieldIdentifier(str) {
|
|
92
|
+
return (/^"[^"]+"."[^"]+"|"\w+:[\w.]+"/i).test(str);
|
|
93
|
+
}
|
|
94
|
+
|
|
95
|
+
getQueryEngineOrder(queryEngine, _options) {
|
|
96
|
+
let options = _options || {};
|
|
97
|
+
let context = queryEngine.getOperationContext();
|
|
98
|
+
let order = context.order;
|
|
99
|
+
|
|
100
|
+
return (order && order.size) ? order : this.connection.getDefaultOrder(context.rootModel, options);
|
|
101
|
+
}
|
|
102
|
+
|
|
103
|
+
getProjectedFields(queryEngine, _options, asMap) {
|
|
104
|
+
let options = this.stackAssign(_options || {}, { isProjection: true });
|
|
105
|
+
let context = queryEngine.getOperationContext();
|
|
106
|
+
let queryProjection = new Map(context.projection);
|
|
107
|
+
let order = this.getQueryEngineOrder(queryEngine, options);
|
|
108
|
+
let allProjectionFields = new Map();
|
|
109
|
+
let allModelsUsedInQuery = queryEngine.getAllModelsUsedInQuery();
|
|
110
|
+
|
|
111
|
+
if (!options.isSubQuery && order && order.size) {
|
|
112
|
+
let contextOrderSupport = this.connection.isOrderSupportedInContext(options);
|
|
113
|
+
if (contextOrderSupport) {
|
|
114
|
+
for (let [ fullyQualifiedFieldName, orderScope ] of order) {
|
|
115
|
+
if (!queryProjection.has(fullyQualifiedFieldName))
|
|
116
|
+
queryProjection.set(fullyQualifiedFieldName, orderScope);
|
|
117
|
+
}
|
|
118
|
+
}
|
|
119
|
+
}
|
|
120
|
+
|
|
121
|
+
for (let [ fullyQualifiedName, projectedScope ] of queryProjection) {
|
|
122
|
+
let { value } = projectedScope;
|
|
123
|
+
|
|
124
|
+
if (Nife.instanceOf(value, 'string')) {
|
|
125
|
+
// Raw string is treated as a literal
|
|
126
|
+
allProjectionFields.set(fullyQualifiedName, value);
|
|
127
|
+
continue;
|
|
128
|
+
} else if (LiteralBase.isLiteral(value)) {
|
|
129
|
+
let result = value.toString(this.connection, options);
|
|
130
|
+
allProjectionFields.set(result || fullyQualifiedName, result || fullyQualifiedName);
|
|
131
|
+
|
|
132
|
+
continue;
|
|
133
|
+
}
|
|
134
|
+
|
|
135
|
+
if (allModelsUsedInQuery.indexOf(value.Model) < 0)
|
|
136
|
+
continue;
|
|
137
|
+
|
|
138
|
+
let escapedFieldName = this.getEscapedProjectionName(value.Model, value, options);
|
|
139
|
+
allProjectionFields.set(`${value.Model.getModelName()}:${value.fieldName}`, escapedFieldName);
|
|
140
|
+
}
|
|
141
|
+
|
|
142
|
+
if (asMap === true)
|
|
143
|
+
return allProjectionFields;
|
|
144
|
+
else
|
|
145
|
+
return Array.from(allProjectionFields.values());
|
|
146
|
+
}
|
|
147
|
+
|
|
148
|
+
// eslint-disable-next-line no-unused-vars
|
|
149
|
+
getJoinTableInfoFromQueryContexts(leftQueryContext, rightQueryContext, joinType, options) {
|
|
150
|
+
let rootModel = leftQueryContext.rootModel;
|
|
151
|
+
let rootModelName = rootModel.getModelName();
|
|
152
|
+
let leftSideModel = leftQueryContext.Model;
|
|
153
|
+
let leftSideModelName = leftQueryContext.modelName;
|
|
154
|
+
if (!leftSideModel)
|
|
155
|
+
throw new Error(`${this.constructor.name}::getJoinTableInfoFromQueryEngine: Invalid operation: No model found for left-side of join statement.`);
|
|
156
|
+
|
|
157
|
+
let leftSideField = leftQueryContext.Field;
|
|
158
|
+
if (!leftSideField)
|
|
159
|
+
throw new Error(`${this.constructor.name}::getJoinTableInfoFromQueryEngine: Invalid operation: No left-side field found to match on for table join statement.`);
|
|
160
|
+
|
|
161
|
+
let isNot = leftQueryContext.not;
|
|
162
|
+
let operator = (isNot) ? leftQueryContext.inverseOperator : leftQueryContext.operator;
|
|
163
|
+
let rightSideModel = rightQueryContext.Model;
|
|
164
|
+
let rightSideModelName = rightQueryContext.modelName;
|
|
165
|
+
if (!rightSideModel)
|
|
166
|
+
throw new Error(`${this.constructor.name}::getJoinTableInfoFromQueryEngine: Invalid operation: No model found for right-side of join statement.`);
|
|
167
|
+
|
|
168
|
+
let rightSideField = rightQueryContext.Field;
|
|
169
|
+
if (!rightSideField)
|
|
170
|
+
throw new Error(`${this.constructor.name}::getJoinTableInfoFromQueryEngine: Invalid operation: No right-side field found to match on for table join statement.`);
|
|
171
|
+
|
|
172
|
+
let swapJoinRelation = (rightSideModelName === rootModelName);
|
|
173
|
+
let joinModel = (swapJoinRelation) ? leftSideModel : rightSideModel;
|
|
174
|
+
let joinModelName = (swapJoinRelation) ? leftSideModelName : rightSideModelName;
|
|
175
|
+
|
|
176
|
+
return {
|
|
177
|
+
operator,
|
|
178
|
+
joinType,
|
|
179
|
+
rootModelName,
|
|
180
|
+
|
|
181
|
+
joinModel,
|
|
182
|
+
joinModelName,
|
|
183
|
+
|
|
184
|
+
leftSideModel,
|
|
185
|
+
leftSideModelName,
|
|
186
|
+
leftQueryContext,
|
|
187
|
+
leftSideField,
|
|
188
|
+
|
|
189
|
+
rightSideModel,
|
|
190
|
+
rightSideModelName,
|
|
191
|
+
rightQueryContext,
|
|
192
|
+
rightSideField,
|
|
193
|
+
};
|
|
194
|
+
}
|
|
195
|
+
|
|
196
|
+
_getLiteralAlias(literal, options) {
|
|
197
|
+
let as = (literal.options && literal.options.as) || (options && options.as);
|
|
198
|
+
if (Nife.isEmpty(as))
|
|
199
|
+
return '';
|
|
200
|
+
|
|
201
|
+
return ` AS ${this.escapeID(as)}`;
|
|
202
|
+
}
|
|
203
|
+
|
|
204
|
+
_averageLiteralToString(literal, options) {
|
|
205
|
+
if (!literal || !LiteralBase.isLiteral(literal))
|
|
206
|
+
return;
|
|
207
|
+
|
|
208
|
+
let field = literal.getField(this.connection);
|
|
209
|
+
let escapedFieldName;
|
|
210
|
+
|
|
211
|
+
if (LiteralBase.isLiteral(field))
|
|
212
|
+
escapedFieldName = field.toString(this.connection, options);
|
|
213
|
+
else
|
|
214
|
+
escapedFieldName = this.getEscapedColumnName(field.Model, field, this.stackAssign(options, literal.options));
|
|
215
|
+
|
|
216
|
+
return `AVG(${escapedFieldName})${this._getLiteralAlias(literal, options)}`;
|
|
217
|
+
}
|
|
218
|
+
|
|
219
|
+
_countLiteralToString(literal, options) {
|
|
220
|
+
if (!literal || !LiteralBase.isLiteral(literal))
|
|
221
|
+
return;
|
|
222
|
+
|
|
223
|
+
let field = literal.getField(this.connection);
|
|
224
|
+
let escapedFieldName;
|
|
225
|
+
|
|
226
|
+
if (field) {
|
|
227
|
+
if (LiteralBase.isLiteral(field))
|
|
228
|
+
escapedFieldName = field.toString(this.connection, options);
|
|
229
|
+
else
|
|
230
|
+
escapedFieldName = this.getEscapedColumnName(field.Model, field, this.stackAssign(options, literal.options));
|
|
231
|
+
} else {
|
|
232
|
+
escapedFieldName = '*';
|
|
233
|
+
}
|
|
234
|
+
|
|
235
|
+
return `COUNT(${escapedFieldName})${this._getLiteralAlias(literal, options)}`;
|
|
236
|
+
}
|
|
237
|
+
|
|
238
|
+
_distinctLiteralToString(literal, options) {
|
|
239
|
+
if (!literal || !LiteralBase.isLiteral(literal))
|
|
240
|
+
return;
|
|
241
|
+
|
|
242
|
+
let field = literal.getField(this.connection);
|
|
243
|
+
if (!field)
|
|
244
|
+
return 'DISTINCT';
|
|
245
|
+
|
|
246
|
+
if (LiteralBase.isLiteral(field))
|
|
247
|
+
return `DISTINCT ON(${field.toString(this.connection, this.stackAssign(options, { noProjectionAliases: true }))})`;
|
|
248
|
+
|
|
249
|
+
return `DISTINCT ON(${this.getEscapedColumnName(field.Model, field, this.stackAssign(options, literal.options, { noProjectionAliases: true }))})`;
|
|
250
|
+
}
|
|
251
|
+
|
|
252
|
+
_fieldLiteralToString(literal, options) {
|
|
253
|
+
if (!literal || !LiteralBase.isLiteral(literal))
|
|
254
|
+
return;
|
|
255
|
+
|
|
256
|
+
let field = literal.getField(this.connection);
|
|
257
|
+
if (LiteralBase.isLiteral(field))
|
|
258
|
+
return field.toString(this.connection, options);
|
|
259
|
+
|
|
260
|
+
return this.getEscapedProjectionName(field.Model, field, this.stackAssign(options, { noProjectionAliases: (options && !options.isProjection) }, literal.options));
|
|
261
|
+
}
|
|
262
|
+
|
|
263
|
+
_maxLiteralToString(literal, options) {
|
|
264
|
+
if (!literal || !LiteralBase.isLiteral(literal))
|
|
265
|
+
return;
|
|
266
|
+
|
|
267
|
+
let field = literal.getField(this.connection);
|
|
268
|
+
let escapedFieldName;
|
|
269
|
+
|
|
270
|
+
if (LiteralBase.isLiteral(field))
|
|
271
|
+
escapedFieldName = field.toString(this.connection, options);
|
|
272
|
+
else
|
|
273
|
+
escapedFieldName = this.getEscapedColumnName(field.Model, field, this.stackAssign(options, literal.options));
|
|
274
|
+
|
|
275
|
+
return `MAX(${escapedFieldName})${this._getLiteralAlias(literal, options)}`;
|
|
276
|
+
}
|
|
277
|
+
|
|
278
|
+
_minLiteralToString(literal, options) {
|
|
279
|
+
if (!literal || !LiteralBase.isLiteral(literal))
|
|
280
|
+
return;
|
|
281
|
+
|
|
282
|
+
let field = literal.getField(this.connection);
|
|
283
|
+
let escapedFieldName;
|
|
284
|
+
|
|
285
|
+
if (LiteralBase.isLiteral(field))
|
|
286
|
+
escapedFieldName = field.toString(this.connection, options);
|
|
287
|
+
else
|
|
288
|
+
escapedFieldName = this.getEscapedColumnName(field.Model, field, this.stackAssign(options, literal.options));
|
|
289
|
+
|
|
290
|
+
return `MIN(${escapedFieldName})${this._getLiteralAlias(literal, options)}`;
|
|
291
|
+
}
|
|
292
|
+
|
|
293
|
+
_sumLiteralToString(literal, options) {
|
|
294
|
+
if (!literal || !LiteralBase.isLiteral(literal))
|
|
295
|
+
return;
|
|
296
|
+
|
|
297
|
+
let field = literal.getField(this.connection);
|
|
298
|
+
let escapedFieldName;
|
|
299
|
+
|
|
300
|
+
if (LiteralBase.isLiteral(field))
|
|
301
|
+
escapedFieldName = field.toString(this.connection, options);
|
|
302
|
+
else
|
|
303
|
+
escapedFieldName = this.getEscapedColumnName(field.Model, field, this.stackAssign(options, literal.options));
|
|
304
|
+
|
|
305
|
+
return `SUM(${escapedFieldName})${this._getLiteralAlias(literal, options)}`;
|
|
306
|
+
}
|
|
307
|
+
|
|
18
308
|
prepareArrayValuesForSQL(array) {
|
|
19
309
|
return this.connection.prepareArrayValuesForSQL(array);
|
|
20
310
|
}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "mythix-orm-sql-base",
|
|
3
|
-
"version": "1.9.
|
|
3
|
+
"version": "1.9.3",
|
|
4
4
|
"description": "SQL base support for Mythix ORM",
|
|
5
5
|
"main": "lib/index",
|
|
6
6
|
"type": "commonjs",
|
|
@@ -34,7 +34,7 @@
|
|
|
34
34
|
},
|
|
35
35
|
"homepage": "https://github.com/th317erd/mythix-orm-sql-base#readme",
|
|
36
36
|
"peerDependencies": {
|
|
37
|
-
"mythix-orm": "^1.11.
|
|
37
|
+
"mythix-orm": "^1.11.4"
|
|
38
38
|
},
|
|
39
39
|
"dependencies": {
|
|
40
40
|
"luxon": "^3.1.0",
|