@mikro-orm/sql 7.1.13-dev.1 → 7.1.13-dev.10
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 +2 -2
- package/query/QueryBuilder.d.ts +14 -0
- package/query/QueryBuilder.js +64 -0
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@mikro-orm/sql",
|
|
3
|
-
"version": "7.1.13-dev.
|
|
3
|
+
"version": "7.1.13-dev.10",
|
|
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.1.12"
|
|
54
54
|
},
|
|
55
55
|
"peerDependencies": {
|
|
56
|
-
"@mikro-orm/core": "7.1.13-dev.
|
|
56
|
+
"@mikro-orm/core": "7.1.13-dev.10"
|
|
57
57
|
},
|
|
58
58
|
"engines": {
|
|
59
59
|
"node": ">= 22.17.0"
|
package/query/QueryBuilder.d.ts
CHANGED
|
@@ -994,6 +994,20 @@ export declare class QueryBuilder<Entity extends object = AnyEntity, RootAlias e
|
|
|
994
994
|
processPopulateHint(): void;
|
|
995
995
|
private processPopulateWhere;
|
|
996
996
|
private mergeOnConditions;
|
|
997
|
+
/**
|
|
998
|
+
* `$or` branches can be moved to a join's `on` clause only when they all target that same join
|
|
999
|
+
* and stay flat — a partial `$or` in the `on` clause would drop rows matching a sibling branch,
|
|
1000
|
+
* and nested operators cannot be preserved inside a distributed disjunction, as `mergeOnConditions`
|
|
1001
|
+
* would flatten them into `and` conjuncts.
|
|
1002
|
+
*/
|
|
1003
|
+
private canDistributeOrBranches;
|
|
1004
|
+
private getOrBranchAliases;
|
|
1005
|
+
/**
|
|
1006
|
+
* An entity filter's `$or` that cannot be distributed is applied intact to the `on` clause of the
|
|
1007
|
+
* outermost join common to all targeted joins, nesting the targeted joins under it so the clause
|
|
1008
|
+
* can reference their aliases.
|
|
1009
|
+
*/
|
|
1010
|
+
private mergeFilterOrCondition;
|
|
997
1011
|
/**
|
|
998
1012
|
* When adding an inner join on a left joined relation, we need to nest them,
|
|
999
1013
|
* otherwise the inner join could discard rows of the root table.
|
package/query/QueryBuilder.js
CHANGED
|
@@ -2038,6 +2038,13 @@ export class QueryBuilder {
|
|
|
2038
2038
|
for (const k of Object.keys(cond)) {
|
|
2039
2039
|
if (Utils.isOperator(k)) {
|
|
2040
2040
|
if (Array.isArray(cond[k])) {
|
|
2041
|
+
if (k === '$or' && !this.canDistributeOrBranches(cond[k], joins)) {
|
|
2042
|
+
// entity filters have no other sink, so their `$or` is kept intact on the outermost targeted join instead
|
|
2043
|
+
if (filter) {
|
|
2044
|
+
this.mergeFilterOrCondition(cond[k], joins);
|
|
2045
|
+
}
|
|
2046
|
+
continue;
|
|
2047
|
+
}
|
|
2041
2048
|
cond[k].forEach((c) => this.mergeOnConditions(joins, c, filter, k));
|
|
2042
2049
|
}
|
|
2043
2050
|
/* v8 ignore next */
|
|
@@ -2071,6 +2078,63 @@ export class QueryBuilder {
|
|
|
2071
2078
|
}
|
|
2072
2079
|
}
|
|
2073
2080
|
}
|
|
2081
|
+
/**
|
|
2082
|
+
* `$or` branches can be moved to a join's `on` clause only when they all target that same join
|
|
2083
|
+
* and stay flat — a partial `$or` in the `on` clause would drop rows matching a sibling branch,
|
|
2084
|
+
* and nested operators cannot be preserved inside a distributed disjunction, as `mergeOnConditions`
|
|
2085
|
+
* would flatten them into `and` conjuncts.
|
|
2086
|
+
*/
|
|
2087
|
+
canDistributeOrBranches(branches, joins) {
|
|
2088
|
+
const aliases = this.getOrBranchAliases(branches);
|
|
2089
|
+
const targeted = joins.filter(j => aliases.has(j.alias));
|
|
2090
|
+
const flat = branches.every(branch => Object.keys(branch).every(k => !Utils.isOperator(k)));
|
|
2091
|
+
return aliases.size === 1 && targeted.length === 1 && flat;
|
|
2092
|
+
}
|
|
2093
|
+
getOrBranchAliases(branches) {
|
|
2094
|
+
const aliases = new Set();
|
|
2095
|
+
const collectAliases = (cond) => {
|
|
2096
|
+
for (const k of Object.keys(cond)) {
|
|
2097
|
+
if (Utils.isOperator(k)) {
|
|
2098
|
+
Utils.asArray(cond[k]).forEach((c) => collectAliases(c));
|
|
2099
|
+
}
|
|
2100
|
+
else {
|
|
2101
|
+
aliases.add(this.helper.splitField(k)[0]);
|
|
2102
|
+
}
|
|
2103
|
+
}
|
|
2104
|
+
};
|
|
2105
|
+
branches.forEach(collectAliases);
|
|
2106
|
+
return aliases;
|
|
2107
|
+
}
|
|
2108
|
+
/**
|
|
2109
|
+
* An entity filter's `$or` that cannot be distributed is applied intact to the `on` clause of the
|
|
2110
|
+
* outermost join common to all targeted joins, nesting the targeted joins under it so the clause
|
|
2111
|
+
* can reference their aliases.
|
|
2112
|
+
*/
|
|
2113
|
+
mergeFilterOrCondition(branches, joins) {
|
|
2114
|
+
const aliases = this.getOrBranchAliases(branches);
|
|
2115
|
+
const chainOf = (join) => {
|
|
2116
|
+
const parent = joins.find(j => j.alias === join.ownerAlias);
|
|
2117
|
+
return parent ? [join, ...chainOf(parent)] : [join];
|
|
2118
|
+
};
|
|
2119
|
+
// chains go from each targeted join up to its root, so the first join present in all of them is the outermost common one
|
|
2120
|
+
const chains = joins.filter(j => aliases.has(j.alias)).map(chainOf);
|
|
2121
|
+
const anchor = chains[0]?.find(a => chains.every(chain => chain.includes(a)));
|
|
2122
|
+
/* v8 ignore next 3 */
|
|
2123
|
+
if (!anchor) {
|
|
2124
|
+
return;
|
|
2125
|
+
}
|
|
2126
|
+
for (const chain of chains) {
|
|
2127
|
+
// nest the chain below the anchor, so the anchor's `on` clause can reference the nested aliases
|
|
2128
|
+
for (let i = 0; chain[i] !== anchor; i++) {
|
|
2129
|
+
const nested = (chain[i + 1].nested ??= new Set());
|
|
2130
|
+
if (!nested.has(chain[i])) {
|
|
2131
|
+
chain[i].type = chain[i].type === JoinType.innerJoin ? JoinType.nestedInnerJoin : JoinType.nestedLeftJoin;
|
|
2132
|
+
nested.add(chain[i]);
|
|
2133
|
+
}
|
|
2134
|
+
}
|
|
2135
|
+
}
|
|
2136
|
+
anchor.cond = anchor.cond.$or ? { $and: [anchor.cond, { $or: branches }] } : { ...anchor.cond, $or: branches };
|
|
2137
|
+
}
|
|
2074
2138
|
/**
|
|
2075
2139
|
* When adding an inner join on a left joined relation, we need to nest them,
|
|
2076
2140
|
* otherwise the inner join could discard rows of the root table.
|