@mikro-orm/sql 7.0.0-dev.99 → 7.0.0-rc.0
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/AbstractSqlConnection.d.ts +2 -4
- package/AbstractSqlConnection.js +3 -7
- package/AbstractSqlDriver.d.ts +82 -23
- package/AbstractSqlDriver.js +584 -184
- package/AbstractSqlPlatform.d.ts +3 -4
- package/AbstractSqlPlatform.js +0 -4
- package/PivotCollectionPersister.d.ts +5 -0
- package/PivotCollectionPersister.js +30 -12
- package/SqlEntityManager.d.ts +2 -2
- package/dialects/mysql/{MySqlPlatform.d.ts → BaseMySqlPlatform.d.ts} +3 -2
- package/dialects/mysql/{MySqlPlatform.js → BaseMySqlPlatform.js} +5 -1
- package/dialects/mysql/MySqlSchemaHelper.d.ts +12 -1
- package/dialects/mysql/MySqlSchemaHelper.js +97 -6
- package/dialects/mysql/index.d.ts +1 -2
- package/dialects/mysql/index.js +1 -2
- package/dialects/postgresql/BasePostgreSqlPlatform.d.ts +106 -0
- package/dialects/postgresql/BasePostgreSqlPlatform.js +350 -0
- package/dialects/postgresql/FullTextType.d.ts +14 -0
- package/dialects/postgresql/FullTextType.js +59 -0
- package/dialects/postgresql/PostgreSqlExceptionConverter.d.ts +8 -0
- package/dialects/postgresql/PostgreSqlExceptionConverter.js +47 -0
- package/dialects/postgresql/PostgreSqlSchemaHelper.d.ts +90 -0
- package/dialects/postgresql/PostgreSqlSchemaHelper.js +732 -0
- package/dialects/postgresql/index.d.ts +3 -0
- package/dialects/postgresql/index.js +3 -0
- package/dialects/sqlite/BaseSqliteConnection.d.ts +1 -0
- package/dialects/sqlite/BaseSqliteConnection.js +13 -0
- package/dialects/sqlite/BaseSqlitePlatform.d.ts +6 -0
- package/dialects/sqlite/BaseSqlitePlatform.js +12 -0
- package/dialects/sqlite/SqliteSchemaHelper.d.ts +25 -0
- package/dialects/sqlite/SqliteSchemaHelper.js +145 -19
- package/dialects/sqlite/index.d.ts +0 -1
- package/dialects/sqlite/index.js +0 -1
- package/package.json +5 -6
- package/plugin/transformer.d.ts +1 -1
- package/plugin/transformer.js +1 -1
- package/query/CriteriaNode.d.ts +9 -5
- package/query/CriteriaNode.js +16 -15
- package/query/CriteriaNodeFactory.d.ts +6 -6
- package/query/CriteriaNodeFactory.js +33 -31
- package/query/NativeQueryBuilder.d.ts +3 -2
- package/query/NativeQueryBuilder.js +1 -2
- package/query/ObjectCriteriaNode.js +50 -35
- package/query/QueryBuilder.d.ts +548 -79
- package/query/QueryBuilder.js +537 -159
- package/query/QueryBuilderHelper.d.ts +22 -14
- package/query/QueryBuilderHelper.js +158 -69
- package/query/ScalarCriteriaNode.js +2 -2
- package/query/raw.d.ts +11 -3
- package/query/raw.js +1 -2
- package/schema/DatabaseSchema.d.ts +15 -2
- package/schema/DatabaseSchema.js +143 -15
- package/schema/DatabaseTable.d.ts +12 -0
- package/schema/DatabaseTable.js +91 -31
- package/schema/SchemaComparator.d.ts +8 -0
- package/schema/SchemaComparator.js +126 -3
- package/schema/SchemaHelper.d.ts +26 -3
- package/schema/SchemaHelper.js +98 -11
- package/schema/SqlSchemaGenerator.d.ts +10 -0
- package/schema/SqlSchemaGenerator.js +137 -9
- package/tsconfig.build.tsbuildinfo +1 -0
- package/typings.d.ts +74 -36
- package/dialects/postgresql/PostgreSqlTableCompiler.d.ts +0 -1
- package/dialects/postgresql/PostgreSqlTableCompiler.js +0 -1
|
@@ -6,26 +6,26 @@ import { ScalarCriteriaNode } from './ScalarCriteriaNode.js';
|
|
|
6
6
|
* @internal
|
|
7
7
|
*/
|
|
8
8
|
export class CriteriaNodeFactory {
|
|
9
|
-
static createNode(metadata, entityName, payload, parent, key) {
|
|
10
|
-
const
|
|
11
|
-
const scalar = Utils.isPrimaryKey(payload) || isRaw(payload) || payload instanceof RegExp || payload instanceof Date ||
|
|
9
|
+
static createNode(metadata, entityName, payload, parent, key, validate = true) {
|
|
10
|
+
const rawField = RawQueryFragment.isKnownFragmentSymbol(key);
|
|
11
|
+
const scalar = Utils.isPrimaryKey(payload) || isRaw(payload) || payload instanceof RegExp || payload instanceof Date || rawField;
|
|
12
12
|
if (Array.isArray(payload) && !scalar) {
|
|
13
|
-
return this.createArrayNode(metadata, entityName, payload, parent, key);
|
|
13
|
+
return this.createArrayNode(metadata, entityName, payload, parent, key, validate);
|
|
14
14
|
}
|
|
15
15
|
if (Utils.isPlainObject(payload) && !scalar) {
|
|
16
|
-
return this.createObjectNode(metadata, entityName, payload, parent, key);
|
|
16
|
+
return this.createObjectNode(metadata, entityName, payload, parent, key, validate);
|
|
17
17
|
}
|
|
18
|
-
return this.createScalarNode(metadata, entityName, payload, parent, key);
|
|
18
|
+
return this.createScalarNode(metadata, entityName, payload, parent, key, validate);
|
|
19
19
|
}
|
|
20
|
-
static createScalarNode(metadata, entityName, payload, parent, key) {
|
|
21
|
-
const node = new ScalarCriteriaNode(metadata, entityName, parent, key);
|
|
20
|
+
static createScalarNode(metadata, entityName, payload, parent, key, validate = true) {
|
|
21
|
+
const node = new ScalarCriteriaNode(metadata, entityName, parent, key, validate);
|
|
22
22
|
node.payload = payload;
|
|
23
23
|
return node;
|
|
24
24
|
}
|
|
25
|
-
static createArrayNode(metadata, entityName, payload, parent, key) {
|
|
26
|
-
const node = new ArrayCriteriaNode(metadata, entityName, parent, key);
|
|
25
|
+
static createArrayNode(metadata, entityName, payload, parent, key, validate = true) {
|
|
26
|
+
const node = new ArrayCriteriaNode(metadata, entityName, parent, key, validate);
|
|
27
27
|
node.payload = payload.map((item, index) => {
|
|
28
|
-
const n = this.createNode(metadata, entityName, item, node);
|
|
28
|
+
const n = this.createNode(metadata, entityName, item, node, undefined, validate);
|
|
29
29
|
// we care about branching only for $and
|
|
30
30
|
if (key === '$and' && payload.length > 1) {
|
|
31
31
|
n.index = index;
|
|
@@ -34,57 +34,59 @@ export class CriteriaNodeFactory {
|
|
|
34
34
|
});
|
|
35
35
|
return node;
|
|
36
36
|
}
|
|
37
|
-
static createObjectNode(metadata, entityName, payload, parent, key) {
|
|
37
|
+
static createObjectNode(metadata, entityName, payload, parent, key, validate = true) {
|
|
38
38
|
const meta = metadata.find(entityName);
|
|
39
|
-
const node = new ObjectCriteriaNode(metadata, entityName, parent, key,
|
|
39
|
+
const node = new ObjectCriteriaNode(metadata, entityName, parent, key, validate, payload.__strict);
|
|
40
40
|
node.payload = {};
|
|
41
|
-
for (const
|
|
42
|
-
node.payload[
|
|
41
|
+
for (const k of Utils.getObjectQueryKeys(payload)) {
|
|
42
|
+
node.payload[k] = this.createObjectItemNode(metadata, entityName, node, payload, k, meta, validate);
|
|
43
43
|
}
|
|
44
44
|
return node;
|
|
45
45
|
}
|
|
46
|
-
static createObjectItemNode(metadata, entityName, node, payload, key, meta) {
|
|
47
|
-
const
|
|
48
|
-
const
|
|
49
|
-
const
|
|
46
|
+
static createObjectItemNode(metadata, entityName, node, payload, key, meta, validate = true) {
|
|
47
|
+
const rawField = RawQueryFragment.isKnownFragmentSymbol(key);
|
|
48
|
+
const prop = rawField ? null : meta?.properties[key];
|
|
49
|
+
const childEntity = prop && prop.kind !== ReferenceKind.SCALAR ? prop.targetMeta.class : entityName;
|
|
50
|
+
const isNotEmbedded = rawField || prop?.kind !== ReferenceKind.EMBEDDED;
|
|
51
|
+
const val = payload[key];
|
|
50
52
|
if (isNotEmbedded && prop?.customType instanceof JsonType) {
|
|
51
|
-
return this.createScalarNode(metadata, childEntity,
|
|
53
|
+
return this.createScalarNode(metadata, childEntity, val, node, key, validate);
|
|
52
54
|
}
|
|
53
|
-
if (prop?.kind === ReferenceKind.SCALAR &&
|
|
55
|
+
if (prop?.kind === ReferenceKind.SCALAR && val != null && Object.keys(val).some(f => f in GroupOperator)) {
|
|
54
56
|
throw ValidationError.cannotUseGroupOperatorsInsideScalars(entityName, prop.name, payload);
|
|
55
57
|
}
|
|
56
58
|
if (isNotEmbedded) {
|
|
57
|
-
return this.createNode(metadata, childEntity,
|
|
59
|
+
return this.createNode(metadata, childEntity, val, node, key, validate);
|
|
58
60
|
}
|
|
59
|
-
if (
|
|
61
|
+
if (val == null) {
|
|
60
62
|
const map = Object.keys(prop.embeddedProps).reduce((oo, k) => {
|
|
61
63
|
oo[prop.embeddedProps[k].name] = null;
|
|
62
64
|
return oo;
|
|
63
65
|
}, {});
|
|
64
|
-
return this.createNode(metadata, entityName, map, node, key);
|
|
66
|
+
return this.createNode(metadata, entityName, map, node, key, validate);
|
|
65
67
|
}
|
|
66
68
|
// array operators can be used on embedded properties
|
|
67
69
|
const allowedOperators = ['$contains', '$contained', '$overlap'];
|
|
68
|
-
const operator = Object.keys(
|
|
70
|
+
const operator = Object.keys(val).some(f => Utils.isOperator(f) && !allowedOperators.includes(f));
|
|
69
71
|
if (operator) {
|
|
70
72
|
throw ValidationError.cannotUseOperatorsInsideEmbeddables(entityName, prop.name, payload);
|
|
71
73
|
}
|
|
72
|
-
const map = Object.keys(
|
|
74
|
+
const map = Object.keys(val).reduce((oo, k) => {
|
|
73
75
|
const embeddedProp = prop.embeddedProps[k] ?? Object.values(prop.embeddedProps).find(p => p.name === k);
|
|
74
76
|
if (!embeddedProp && !allowedOperators.includes(k)) {
|
|
75
77
|
throw ValidationError.invalidEmbeddableQuery(entityName, k, prop.type);
|
|
76
78
|
}
|
|
77
79
|
if (embeddedProp) {
|
|
78
|
-
oo[embeddedProp.name] =
|
|
80
|
+
oo[embeddedProp.name] = val[k];
|
|
79
81
|
}
|
|
80
|
-
else if (typeof
|
|
81
|
-
oo[k] = JSON.stringify(
|
|
82
|
+
else if (typeof val[k] === 'object') {
|
|
83
|
+
oo[k] = JSON.stringify(val[k]);
|
|
82
84
|
}
|
|
83
85
|
else {
|
|
84
|
-
oo[k] =
|
|
86
|
+
oo[k] = val[k];
|
|
85
87
|
}
|
|
86
88
|
return oo;
|
|
87
89
|
}, {});
|
|
88
|
-
return this.createNode(metadata, entityName, map, node, key);
|
|
90
|
+
return this.createNode(metadata, entityName, map, node, key, validate);
|
|
89
91
|
}
|
|
90
92
|
}
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { type Dictionary, LockMode, type QueryFlag, RawQueryFragment } from '@mikro-orm/core';
|
|
1
|
+
import { type Dictionary, LockMode, type QueryFlag, RawQueryFragment, type Subquery } from '@mikro-orm/core';
|
|
2
2
|
import { QueryType } from './enums.js';
|
|
3
3
|
import type { AbstractSqlPlatform } from '../AbstractSqlPlatform.js';
|
|
4
4
|
interface Options {
|
|
@@ -48,8 +48,9 @@ interface OnConflictClause {
|
|
|
48
48
|
};
|
|
49
49
|
}
|
|
50
50
|
/** @internal */
|
|
51
|
-
export declare class NativeQueryBuilder {
|
|
51
|
+
export declare class NativeQueryBuilder implements Subquery {
|
|
52
52
|
protected readonly platform: AbstractSqlPlatform;
|
|
53
|
+
readonly __subquery: true;
|
|
53
54
|
protected type?: QueryType;
|
|
54
55
|
protected parts: string[];
|
|
55
56
|
protected params: unknown[];
|
|
@@ -27,8 +27,7 @@ export class NativeQueryBuilder {
|
|
|
27
27
|
}
|
|
28
28
|
from(tableName, options) {
|
|
29
29
|
if (tableName instanceof NativeQueryBuilder) {
|
|
30
|
-
|
|
31
|
-
tableName = raw(sql, params);
|
|
30
|
+
tableName = tableName.toRaw();
|
|
32
31
|
}
|
|
33
32
|
if (typeof tableName === 'string') {
|
|
34
33
|
const alias = options?.alias ? ` as ${this.platform.quoteIdentifier(options.alias)}` : '';
|
|
@@ -1,21 +1,22 @@
|
|
|
1
1
|
import { ALIAS_REPLACEMENT, GroupOperator, QueryFlag, raw, RawQueryFragment, ReferenceKind, Utils, } from '@mikro-orm/core';
|
|
2
2
|
import { CriteriaNode } from './CriteriaNode.js';
|
|
3
3
|
import { JoinType, QueryType } from './enums.js';
|
|
4
|
+
const COLLECTION_OPERATORS = ['$some', '$none', '$every', '$size'];
|
|
4
5
|
/**
|
|
5
6
|
* @internal
|
|
6
7
|
*/
|
|
7
8
|
export class ObjectCriteriaNode extends CriteriaNode {
|
|
8
9
|
process(qb, options) {
|
|
9
10
|
const matchPopulateJoins = options?.matchPopulateJoins || (this.prop && [ReferenceKind.MANY_TO_ONE, ReferenceKind.ONE_TO_ONE].includes(this.prop.kind));
|
|
10
|
-
const nestedAlias = qb.getAliasForJoinPath(this.getPath(), { ...options, matchPopulateJoins });
|
|
11
|
+
const nestedAlias = qb.getAliasForJoinPath(this.getPath(options), { ...options, matchPopulateJoins });
|
|
11
12
|
const ownerAlias = options?.alias || qb.alias;
|
|
12
|
-
const keys =
|
|
13
|
+
const keys = Utils.getObjectQueryKeys(this.payload);
|
|
13
14
|
let alias = options?.alias;
|
|
14
15
|
if (nestedAlias) {
|
|
15
16
|
alias = nestedAlias;
|
|
16
17
|
}
|
|
17
18
|
if (this.shouldAutoJoin(qb, nestedAlias)) {
|
|
18
|
-
if (keys.some(k =>
|
|
19
|
+
if (keys.some(k => COLLECTION_OPERATORS.includes(k))) {
|
|
19
20
|
if (![ReferenceKind.MANY_TO_MANY, ReferenceKind.ONE_TO_MANY].includes(this.prop.kind)) {
|
|
20
21
|
// ignore collection operators when used on a non-relational property - this can happen when they get into
|
|
21
22
|
// populateWhere via `infer` on m:n properties with select-in strategy
|
|
@@ -31,22 +32,31 @@ export class ObjectCriteriaNode extends CriteriaNode {
|
|
|
31
32
|
return [QueryType.SELECT, QueryType.COUNT].includes(qb.type) ? `${knownKey ? alias : ownerAlias}.${pk}` : pk;
|
|
32
33
|
});
|
|
33
34
|
for (const key of keys) {
|
|
34
|
-
if (
|
|
35
|
+
if (typeof key !== 'string' || !COLLECTION_OPERATORS.includes(key)) {
|
|
35
36
|
throw new Error('Mixing collection operators with other filters is not allowed.');
|
|
36
37
|
}
|
|
37
38
|
const payload = this.payload[key].unwrap();
|
|
38
|
-
const qb2 = qb.clone(true);
|
|
39
|
+
const qb2 = qb.clone(true, ['_schema']);
|
|
40
|
+
const joinAlias = qb2.getNextAlias(this.prop.targetMeta.class);
|
|
39
41
|
const sub = qb2
|
|
40
|
-
.from(parentMeta.
|
|
41
|
-
|
|
42
|
+
.from(parentMeta.class)
|
|
43
|
+
// eslint-disable-next-line no-unexpected-multiline
|
|
44
|
+
[key === '$size' ? 'leftJoin' : 'innerJoin'](this.key, joinAlias)
|
|
42
45
|
.select(parentMeta.primaryKeys);
|
|
43
|
-
if (key === '$
|
|
46
|
+
if (key === '$size') {
|
|
47
|
+
const sizeCondition = typeof payload === 'number' ? { $eq: payload } : payload;
|
|
48
|
+
const pks = this.prop.referencedColumnNames;
|
|
49
|
+
const countExpr = raw(`count(${pks.map(() => '??').join(', ')})`, pks.map(pk => `${joinAlias}.${pk}`));
|
|
50
|
+
sub.groupBy(parentMeta.primaryKeys);
|
|
51
|
+
sub.having({ $and: Object.keys(sizeCondition).map(op => ({ [countExpr]: { [op]: sizeCondition[op] } })) });
|
|
52
|
+
}
|
|
53
|
+
else if (key === '$every') {
|
|
44
54
|
sub.where({ $not: { [this.key]: payload } });
|
|
45
55
|
}
|
|
46
56
|
else {
|
|
47
57
|
sub.where({ [this.key]: payload });
|
|
48
58
|
}
|
|
49
|
-
const op =
|
|
59
|
+
const op = ['$size', '$some'].includes(key) ? '$in' : '$nin';
|
|
50
60
|
$and.push({
|
|
51
61
|
[Utils.getPrimaryKeyHash(primaryKeys)]: { [op]: sub.getNativeQuery().toRaw() },
|
|
52
62
|
});
|
|
@@ -78,7 +88,7 @@ export class ObjectCriteriaNode extends CriteriaNode {
|
|
|
78
88
|
const childNode = this.payload[field];
|
|
79
89
|
const payload = childNode.process(qb, { ...options, alias: this.prop ? alias : ownerAlias });
|
|
80
90
|
const operator = Utils.isOperator(field);
|
|
81
|
-
const isRawField = RawQueryFragment.
|
|
91
|
+
const isRawField = RawQueryFragment.isKnownFragmentSymbol(field);
|
|
82
92
|
// we need to keep the prefixing for formulas otherwise we would lose aliasing context when nesting inside group operators
|
|
83
93
|
const virtual = childNode.prop?.persist === false && !childNode.prop?.formula;
|
|
84
94
|
// if key is missing, we are inside group operator and we need to prefix with alias
|
|
@@ -96,35 +106,40 @@ export class ObjectCriteriaNode extends CriteriaNode {
|
|
|
96
106
|
const rawField = RawQueryFragment.getKnownFragment(field);
|
|
97
107
|
o[raw(rawField.sql.replaceAll(ALIAS_REPLACEMENT, alias), rawField.params)] = payload;
|
|
98
108
|
}
|
|
109
|
+
else if (!childNode.validate && !childNode.prop && !field.includes('.') && !operator) {
|
|
110
|
+
// wrap unknown fields in raw() to prevent alias prefixing (e.g. raw SQL aliases in HAVING)
|
|
111
|
+
// use '??' placeholder to properly quote the identifier
|
|
112
|
+
o[raw('??', [field])] = payload;
|
|
113
|
+
}
|
|
99
114
|
else if (primaryKey || virtual || operator || field.includes('.') || ![QueryType.SELECT, QueryType.COUNT].includes(qb.type)) {
|
|
100
115
|
this.inlineCondition(field.replaceAll(ALIAS_REPLACEMENT, alias), o, payload);
|
|
101
116
|
}
|
|
102
117
|
else {
|
|
103
|
-
this.inlineCondition(`${alias}.${field}`, o, payload);
|
|
118
|
+
this.inlineCondition(`${alias ?? qb.alias}.${field}`, o, payload);
|
|
104
119
|
}
|
|
105
120
|
return o;
|
|
106
121
|
}, {});
|
|
107
122
|
}
|
|
108
123
|
isStrict() {
|
|
109
|
-
return this.strict ||
|
|
124
|
+
return this.strict || Utils.getObjectQueryKeys(this.payload).some(key => {
|
|
110
125
|
return this.payload[key].isStrict();
|
|
111
126
|
});
|
|
112
127
|
}
|
|
113
128
|
unwrap() {
|
|
114
|
-
return
|
|
129
|
+
return Utils.getObjectQueryKeys(this.payload).reduce((o, field) => {
|
|
115
130
|
o[field] = this.payload[field].unwrap();
|
|
116
131
|
return o;
|
|
117
132
|
}, {});
|
|
118
133
|
}
|
|
119
134
|
willAutoJoin(qb, alias, options) {
|
|
120
|
-
const nestedAlias = qb.getAliasForJoinPath(this.getPath(), options);
|
|
135
|
+
const nestedAlias = qb.getAliasForJoinPath(this.getPath(options), options);
|
|
121
136
|
const ownerAlias = alias || qb.alias;
|
|
122
|
-
const keys =
|
|
137
|
+
const keys = Utils.getObjectQueryKeys(this.payload);
|
|
123
138
|
if (nestedAlias) {
|
|
124
139
|
alias = nestedAlias;
|
|
125
140
|
}
|
|
126
141
|
if (this.shouldAutoJoin(qb, nestedAlias)) {
|
|
127
|
-
return !keys.some(k =>
|
|
142
|
+
return !keys.some(k => COLLECTION_OPERATORS.includes(k));
|
|
128
143
|
}
|
|
129
144
|
return keys.some(field => {
|
|
130
145
|
const childNode = this.payload[field];
|
|
@@ -132,9 +147,9 @@ export class ObjectCriteriaNode extends CriteriaNode {
|
|
|
132
147
|
});
|
|
133
148
|
}
|
|
134
149
|
shouldInline(payload) {
|
|
135
|
-
const
|
|
136
|
-
const scalar = Utils.isPrimaryKey(payload) || payload instanceof RegExp || payload instanceof Date ||
|
|
137
|
-
const operator = Utils.isObject(payload) &&
|
|
150
|
+
const rawField = RawQueryFragment.isKnownFragmentSymbol(this.key);
|
|
151
|
+
const scalar = Utils.isPrimaryKey(payload) || payload instanceof RegExp || payload instanceof Date || rawField;
|
|
152
|
+
const operator = Utils.isObject(payload) && Utils.getObjectQueryKeys(payload).every(k => Utils.isOperator(k, false));
|
|
138
153
|
return !!this.prop && this.prop.kind !== ReferenceKind.SCALAR && !scalar && !operator;
|
|
139
154
|
}
|
|
140
155
|
getChildKey(k, prop, childAlias, alias) {
|
|
@@ -145,8 +160,8 @@ export class ObjectCriteriaNode extends CriteriaNode {
|
|
|
145
160
|
}
|
|
146
161
|
inlineArrayChildPayload(obj, payload, k, prop, childAlias, alias) {
|
|
147
162
|
const key = this.getChildKey(k, prop, childAlias);
|
|
148
|
-
const value = payload.map((child) =>
|
|
149
|
-
const key = (this.isPrefixed(childKey) || Utils.isOperator(childKey)) ? childKey : this.aliased(childKey, childAlias);
|
|
163
|
+
const value = payload.map((child) => Utils.getObjectQueryKeys(child).reduce((inner, childKey) => {
|
|
164
|
+
const key = (RawQueryFragment.isKnownFragmentSymbol(childKey) || this.isPrefixed(childKey) || Utils.isOperator(childKey)) ? childKey : this.aliased(childKey, childAlias);
|
|
150
165
|
inner[key] = child[childKey];
|
|
151
166
|
return inner;
|
|
152
167
|
}, {}));
|
|
@@ -154,8 +169,11 @@ export class ObjectCriteriaNode extends CriteriaNode {
|
|
|
154
169
|
}
|
|
155
170
|
inlineChildPayload(o, payload, field, alias, childAlias) {
|
|
156
171
|
const prop = this.metadata.find(this.entityName).properties[field];
|
|
157
|
-
for (const k of
|
|
158
|
-
if (
|
|
172
|
+
for (const k of Utils.getObjectQueryKeys(payload)) {
|
|
173
|
+
if (RawQueryFragment.isKnownFragmentSymbol(k)) {
|
|
174
|
+
o[k] = payload[k];
|
|
175
|
+
}
|
|
176
|
+
else if (Utils.isOperator(k, false)) {
|
|
159
177
|
const tmp = payload[k];
|
|
160
178
|
delete payload[k];
|
|
161
179
|
o[this.aliased(field, alias)] = { [k]: tmp, ...o[this.aliased(field, alias)] };
|
|
@@ -167,9 +185,6 @@ export class ObjectCriteriaNode extends CriteriaNode {
|
|
|
167
185
|
const key = this.getChildKey(k, prop, childAlias, alias);
|
|
168
186
|
this.inlineCondition(key, o, payload[k]);
|
|
169
187
|
}
|
|
170
|
-
else if (RawQueryFragment.isKnownFragment(k)) {
|
|
171
|
-
o[k] = payload[k];
|
|
172
|
-
}
|
|
173
188
|
else {
|
|
174
189
|
o[this.aliased(k, childAlias)] = payload[k];
|
|
175
190
|
}
|
|
@@ -194,11 +209,11 @@ export class ObjectCriteriaNode extends CriteriaNode {
|
|
|
194
209
|
if (!this.prop || !this.parent) {
|
|
195
210
|
return false;
|
|
196
211
|
}
|
|
197
|
-
const keys =
|
|
198
|
-
if (keys.every(k => k.includes('.') && k.startsWith(`${qb.alias}.`))) {
|
|
212
|
+
const keys = Utils.getObjectQueryKeys(this.payload);
|
|
213
|
+
if (keys.every(k => typeof k === 'string' && k.includes('.') && k.startsWith(`${qb.alias}.`))) {
|
|
199
214
|
return false;
|
|
200
215
|
}
|
|
201
|
-
if (keys.some(k =>
|
|
216
|
+
if (keys.some(k => COLLECTION_OPERATORS.includes(k))) {
|
|
202
217
|
return true;
|
|
203
218
|
}
|
|
204
219
|
const meta = this.metadata.find(this.entityName);
|
|
@@ -206,21 +221,21 @@ export class ObjectCriteriaNode extends CriteriaNode {
|
|
|
206
221
|
const knownKey = [ReferenceKind.SCALAR, ReferenceKind.MANY_TO_ONE, ReferenceKind.EMBEDDED].includes(this.prop.kind) || (this.prop.kind === ReferenceKind.ONE_TO_ONE && this.prop.owner);
|
|
207
222
|
const operatorKeys = knownKey && keys.every(key => Utils.isOperator(key, false));
|
|
208
223
|
const primaryKeys = knownKey && keys.every(key => {
|
|
209
|
-
if (!meta.primaryKeys.includes(key)) {
|
|
224
|
+
if (typeof key !== 'string' || !meta.primaryKeys.includes(key)) {
|
|
210
225
|
return false;
|
|
211
226
|
}
|
|
212
227
|
if (!Utils.isPlainObject(this.payload[key].payload) || ![ReferenceKind.ONE_TO_ONE, ReferenceKind.MANY_TO_ONE].includes(meta.properties[key].kind)) {
|
|
213
228
|
return true;
|
|
214
229
|
}
|
|
215
|
-
return
|
|
230
|
+
return Utils.getObjectQueryKeys(this.payload[key].payload).every(k => typeof k === 'string' && meta.properties[key].targetMeta.primaryKeys.includes(k));
|
|
216
231
|
});
|
|
217
232
|
return !primaryKeys && !nestedAlias && !operatorKeys && !embeddable;
|
|
218
233
|
}
|
|
219
234
|
autoJoin(qb, alias, options) {
|
|
220
|
-
const nestedAlias = qb.getNextAlias(this.prop?.
|
|
221
|
-
const
|
|
222
|
-
const scalar = Utils.isPrimaryKey(this.payload) || this.payload instanceof RegExp || this.payload instanceof Date ||
|
|
223
|
-
const operator = Utils.isPlainObject(this.payload) &&
|
|
235
|
+
const nestedAlias = qb.getNextAlias(this.prop?.pivotEntity ?? this.entityName);
|
|
236
|
+
const rawField = RawQueryFragment.isKnownFragmentSymbol(this.key);
|
|
237
|
+
const scalar = Utils.isPrimaryKey(this.payload) || this.payload instanceof RegExp || this.payload instanceof Date || rawField;
|
|
238
|
+
const operator = Utils.isPlainObject(this.payload) && Utils.getObjectQueryKeys(this.payload).every(k => Utils.isOperator(k, false));
|
|
224
239
|
const field = `${alias}.${this.prop.name}`;
|
|
225
240
|
const method = qb.hasFlag(QueryFlag.INFER_POPULATE) ? 'joinAndSelect' : 'join';
|
|
226
241
|
const path = this.getPath();
|