@mikro-orm/sql 7.3.0-dev.1 → 7.3.0-dev.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.
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@mikro-orm/sql",
|
|
3
|
-
"version": "7.3.0-dev.
|
|
3
|
+
"version": "7.3.0-dev.3",
|
|
4
4
|
"description": "TypeScript ORM for Node.js based on Data Mapper, Unit of Work and Identity Map patterns. Supports MongoDB, MySQL, PostgreSQL and SQLite databases as well as usage with vanilla JavaScript.",
|
|
5
5
|
"keywords": [
|
|
6
6
|
"data-mapper",
|
|
@@ -53,7 +53,7 @@
|
|
|
53
53
|
"@mikro-orm/core": "^7.2.1"
|
|
54
54
|
},
|
|
55
55
|
"peerDependencies": {
|
|
56
|
-
"@mikro-orm/core": "7.3.0-dev.
|
|
56
|
+
"@mikro-orm/core": "7.3.0-dev.3"
|
|
57
57
|
},
|
|
58
58
|
"engines": {
|
|
59
59
|
"node": ">= 22.17.0"
|
package/query/CriteriaNode.d.ts
CHANGED
|
@@ -17,6 +17,8 @@ export declare class CriteriaNode<T extends object> implements ICriteriaNode<T>
|
|
|
17
17
|
index?: number;
|
|
18
18
|
constructor(metadata: MetadataStorage, entityName: EntityName<T>, parent?: ICriteriaNode<T> | undefined, key?: EntityKey<T> | RawQueryFragmentSymbol | undefined, validate?: boolean, strict?: boolean);
|
|
19
19
|
process(qb: IQueryBuilder<T>, options?: ICriteriaNodeProcessOptions): any;
|
|
20
|
+
/** Whether this node holds the condition for a single target of a polymorphic relation (e.g. `imageable[Article]`). */
|
|
21
|
+
isPolymorphicBranch(): boolean;
|
|
20
22
|
unwrap(): any;
|
|
21
23
|
shouldInline(payload: any): boolean;
|
|
22
24
|
willAutoJoin(qb: IQueryBuilder<T>, alias?: string, options?: ICriteriaNodeProcessOptions): boolean;
|
package/query/CriteriaNode.js
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { RawQueryFragment, ReferenceKind, Utils, inspect, } from '@mikro-orm/core';
|
|
1
|
+
import { QueryHelper, RawQueryFragment, ReferenceKind, Utils, inspect, } from '@mikro-orm/core';
|
|
2
2
|
/**
|
|
3
3
|
* Helper for working with deeply nested where/orderBy/having criteria. Uses composite pattern to build tree from the payload.
|
|
4
4
|
* Auto-joins relations and converts payload from { books: { publisher: { name: '...' } } } to { 'publisher_alias.name': '...' }
|
|
@@ -28,7 +28,9 @@ export class CriteriaNode {
|
|
|
28
28
|
return;
|
|
29
29
|
}
|
|
30
30
|
for (const k of pks) {
|
|
31
|
-
|
|
31
|
+
const [name, target] = QueryHelper.splitPolymorphicKey(k);
|
|
32
|
+
this.prop = meta.props.find(prop => (prop.name === name && (!target || !!prop.polymorphTargets?.some(t => t.className === target))) ||
|
|
33
|
+
(prop.fieldNames?.length === 1 && prop.fieldNames[0] === k && prop.persist !== false));
|
|
32
34
|
const isProp = this.prop || meta.props.find(prop => (prop.fieldNames || []).includes(k));
|
|
33
35
|
// do not validate if the key is prefixed or type casted (e.g. `k::text`)
|
|
34
36
|
if (validate && !isProp && !k.includes('.') && !k.includes('::') && !Utils.isOperator(k)) {
|
|
@@ -40,6 +42,10 @@ export class CriteriaNode {
|
|
|
40
42
|
process(qb, options) {
|
|
41
43
|
return this.payload;
|
|
42
44
|
}
|
|
45
|
+
/** Whether this node holds the condition for a single target of a polymorphic relation (e.g. `imageable[Article]`). */
|
|
46
|
+
isPolymorphicBranch() {
|
|
47
|
+
return !!this.prop?.polymorphic && typeof this.key === 'string' && this.key.endsWith(']');
|
|
48
|
+
}
|
|
43
49
|
unwrap() {
|
|
44
50
|
return this.payload;
|
|
45
51
|
}
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { GroupOperator, isRaw, JsonType, RawQueryFragment, ReferenceKind, Utils, ValidationError, } from '@mikro-orm/core';
|
|
1
|
+
import { GroupOperator, isRaw, JsonType, QueryHelper, RawQueryFragment, ReferenceKind, Utils, ValidationError, } from '@mikro-orm/core';
|
|
2
2
|
import { ObjectCriteriaNode } from './ObjectCriteriaNode.js';
|
|
3
3
|
import { ArrayCriteriaNode } from './ArrayCriteriaNode.js';
|
|
4
4
|
import { ScalarCriteriaNode } from './ScalarCriteriaNode.js';
|
|
@@ -50,8 +50,9 @@ export class CriteriaNodeFactory {
|
|
|
50
50
|
}
|
|
51
51
|
static createObjectItemNode(metadata, entityName, node, payload, key, meta, validate = true) {
|
|
52
52
|
const rawField = RawQueryFragment.isKnownFragmentSymbol(key);
|
|
53
|
-
const prop = rawField ? null : meta?.properties[key];
|
|
54
|
-
const
|
|
53
|
+
const prop = rawField ? null : meta?.properties[QueryHelper.splitPolymorphicKey(key)[0]];
|
|
54
|
+
const target = rawField ? undefined : QueryHelper.findTargetMeta(prop, key);
|
|
55
|
+
const childEntity = prop && prop.kind !== ReferenceKind.SCALAR ? (target ?? prop.targetMeta).class : entityName;
|
|
55
56
|
const isNotEmbedded = rawField || prop?.kind !== ReferenceKind.EMBEDDED;
|
|
56
57
|
const val = payload[key];
|
|
57
58
|
if (isNotEmbedded && prop?.customType instanceof JsonType) {
|
|
@@ -99,7 +99,7 @@ export class ObjectCriteriaNode extends CriteriaNode {
|
|
|
99
99
|
// with an exclusive condition on the join columns:
|
|
100
100
|
// - if the owning column is null, the row is missing, we don't apply the filter
|
|
101
101
|
// - if the target column is not null, the row is matched, we apply the filter
|
|
102
|
-
if (toOneProperty && this.prop.nullable && this.isStrict()) {
|
|
102
|
+
if (toOneProperty && this.prop.nullable && this.isStrict() && !this.isPolymorphicBranch()) {
|
|
103
103
|
const key = this.prop.owner ? this.prop.name : this.prop.referencedPKs;
|
|
104
104
|
qb.andWhere({
|
|
105
105
|
$or: [
|
|
@@ -109,7 +109,7 @@ export class ObjectCriteriaNode extends CriteriaNode {
|
|
|
109
109
|
});
|
|
110
110
|
}
|
|
111
111
|
}
|
|
112
|
-
|
|
112
|
+
const ret = keys.reduce((o, field) => {
|
|
113
113
|
const childNode = this.payload[field];
|
|
114
114
|
const payload = childNode.process(qb, { ...options, alias: this.prop ? alias : ownerAlias });
|
|
115
115
|
const operator = Utils.isOperator(field);
|
|
@@ -149,6 +149,12 @@ export class ObjectCriteriaNode extends CriteriaNode {
|
|
|
149
149
|
}
|
|
150
150
|
return o;
|
|
151
151
|
}, {});
|
|
152
|
+
// the target is left joined, so its condition must only match rows that point to it
|
|
153
|
+
if (this.isPolymorphicBranch() && alias) {
|
|
154
|
+
const pk = this.metadata.find(this.entityName).primaryKeys[0];
|
|
155
|
+
this.inlineCondition(`${alias}.${pk}`, ret, { $ne: null });
|
|
156
|
+
}
|
|
157
|
+
return ret;
|
|
152
158
|
}
|
|
153
159
|
isStrict() {
|
|
154
160
|
return (this.strict ||
|
|
@@ -211,7 +217,7 @@ export class ObjectCriteriaNode extends CriteriaNode {
|
|
|
211
217
|
this.inlineCondition(key, obj, value);
|
|
212
218
|
}
|
|
213
219
|
inlineChildPayload(o, payload, field, alias, childAlias) {
|
|
214
|
-
const prop = this.
|
|
220
|
+
const prop = this.payload[field].prop;
|
|
215
221
|
for (const k of Utils.getObjectQueryKeys(payload)) {
|
|
216
222
|
if (RawQueryFragment.isKnownFragmentSymbol(k)) {
|
|
217
223
|
o[k] = payload[k];
|
|
@@ -273,6 +279,10 @@ export class ObjectCriteriaNode extends CriteriaNode {
|
|
|
273
279
|
if (keys.some(k => this.isCollectionOperator(k))) {
|
|
274
280
|
return true;
|
|
275
281
|
}
|
|
282
|
+
// the target's discriminator is checked in the join condition, so it is needed even for PK conditions
|
|
283
|
+
if (this.isPolymorphicBranch()) {
|
|
284
|
+
return !nestedAlias;
|
|
285
|
+
}
|
|
276
286
|
const meta = this.metadata.find(this.entityName);
|
|
277
287
|
const embeddable = this.prop.kind === ReferenceKind.EMBEDDED;
|
|
278
288
|
const knownKey = [ReferenceKind.SCALAR, ReferenceKind.MANY_TO_ONE, ReferenceKind.EMBEDDED].includes(this.prop.kind) ||
|
|
@@ -317,6 +327,10 @@ export class ObjectCriteriaNode extends CriteriaNode {
|
|
|
317
327
|
if (this.prop.kind === ReferenceKind.MANY_TO_MANY && (scalar || operator)) {
|
|
318
328
|
qb.join(field, nestedAlias, undefined, JoinType.pivotJoin, path);
|
|
319
329
|
}
|
|
330
|
+
else if (this.isPolymorphicBranch()) {
|
|
331
|
+
const targetMeta = this.metadata.find(this.entityName);
|
|
332
|
+
qb.addPolymorphicJoin(this.prop, targetMeta, alias, nestedAlias, JoinType.leftJoin, path);
|
|
333
|
+
}
|
|
320
334
|
else {
|
|
321
335
|
const prev = qb.state.fields?.slice();
|
|
322
336
|
const toOneProperty = [ReferenceKind.MANY_TO_ONE, ReferenceKind.ONE_TO_ONE].includes(this.prop.kind);
|
package/typings.d.ts
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import type { Generated, Kysely } from 'kysely';
|
|
2
|
-
import type { CheckCallback, DeferMode, Dictionary, EntityName, EntityProperty, EntitySchemaWithMeta, ExtractDefineEntityProperties, FilterQuery, GroupOperator, IndexColumnOptions, InferEntityName, Opt, Primary, PrimaryProperty, QueryFlag, QueryOrderMap, RawQueryFragment, RoutineIgnoreField, Scalar, Type } from '@mikro-orm/core';
|
|
2
|
+
import type { CheckCallback, DeferMode, Dictionary, EntityName, EntityMetadata, EntityProperty, EntitySchemaWithMeta, ExtractDefineEntityProperties, FilterQuery, GroupOperator, IndexColumnOptions, InferEntityName, Opt, Primary, PrimaryProperty, QueryFlag, QueryOrderMap, RawQueryFragment, RoutineIgnoreField, Scalar, Type } from '@mikro-orm/core';
|
|
3
3
|
import type { JoinType, QueryType } from './query/enums.js';
|
|
4
4
|
import type { DatabaseSchema } from './schema/DatabaseSchema.js';
|
|
5
5
|
import type { DatabaseTable } from './schema/DatabaseTable.js';
|
|
@@ -295,6 +295,8 @@ export interface IQueryBuilder<T> {
|
|
|
295
295
|
scheduleFilterCheck(path: string): void;
|
|
296
296
|
/** @internal */
|
|
297
297
|
ensureTPTJoins(): void;
|
|
298
|
+
/** @internal */
|
|
299
|
+
addPolymorphicJoin(prop: EntityProperty, targetMeta: EntityMetadata, ownerAlias: string, alias: string, type: JoinType, path: string, schema?: string): void;
|
|
298
300
|
withSchema(schema: string): this;
|
|
299
301
|
}
|
|
300
302
|
export interface ICriteriaNodeProcessOptions {
|