@mikro-orm/knex 6.0.0-dev.2 → 6.0.0-dev.200
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/{dist/AbstractSqlConnection.d.ts → AbstractSqlConnection.d.ts} +8 -4
- package/{dist/AbstractSqlConnection.js → AbstractSqlConnection.js} +35 -18
- package/AbstractSqlDriver.d.ts +73 -0
- package/AbstractSqlDriver.js +1085 -0
- package/AbstractSqlPlatform.d.ts +22 -0
- package/{dist/AbstractSqlPlatform.js → AbstractSqlPlatform.js} +46 -19
- package/{dist/MonkeyPatchable.d.ts → MonkeyPatchable.d.ts} +1 -0
- package/{dist/MonkeyPatchable.js → MonkeyPatchable.js} +3 -0
- package/PivotCollectionPersister.d.ts +17 -0
- package/PivotCollectionPersister.js +128 -0
- package/{dist/README.md → README.md} +66 -109
- package/{dist/SqlEntityManager.d.ts → SqlEntityManager.d.ts} +6 -10
- package/{dist/SqlEntityManager.js → SqlEntityManager.js} +5 -10
- package/SqlEntityRepository.d.ts +24 -0
- package/{dist/SqlEntityRepository.js → SqlEntityRepository.js} +11 -8
- package/{dist/index.d.ts → index.d.ts} +1 -0
- package/{dist/index.js → index.js} +6 -1
- package/index.mjs +211 -0
- package/package.json +20 -49
- package/query/ArrayCriteriaNode.d.ts +10 -0
- package/{dist/query → query}/ArrayCriteriaNode.js +7 -2
- package/{dist/query → query}/CriteriaNode.d.ts +11 -9
- package/{dist/query → query}/CriteriaNode.js +31 -15
- package/query/CriteriaNodeFactory.d.ts +12 -0
- package/{dist/query → query}/CriteriaNodeFactory.js +32 -15
- package/query/ObjectCriteriaNode.d.ts +15 -0
- package/{dist/query → query}/ObjectCriteriaNode.js +68 -21
- package/query/QueryBuilder.d.ts +284 -0
- package/query/QueryBuilder.js +1218 -0
- package/{dist/query → query}/QueryBuilderHelper.d.ts +26 -23
- package/query/QueryBuilderHelper.js +661 -0
- package/query/ScalarCriteriaNode.d.ts +10 -0
- package/{dist/query → query}/ScalarCriteriaNode.js +12 -8
- package/query/enums.d.ts +15 -0
- package/query/enums.js +20 -0
- package/{dist/query → query}/index.js +5 -1
- package/{dist/schema → schema}/DatabaseSchema.d.ts +6 -3
- package/{dist/schema → schema}/DatabaseSchema.js +35 -25
- package/{dist/schema → schema}/DatabaseTable.d.ts +21 -13
- package/schema/DatabaseTable.js +645 -0
- package/{dist/schema → schema}/SchemaComparator.d.ts +9 -7
- package/{dist/schema → schema}/SchemaComparator.js +99 -25
- package/{dist/schema → schema}/SchemaHelper.d.ts +20 -13
- package/{dist/schema → schema}/SchemaHelper.js +70 -18
- package/{dist/schema/SchemaGenerator.d.ts → schema/SqlSchemaGenerator.d.ts} +11 -14
- package/{dist/schema/SchemaGenerator.js → schema/SqlSchemaGenerator.js} +149 -63
- package/{dist/schema → schema}/index.d.ts +1 -1
- package/{dist/schema → schema}/index.js +6 -2
- package/{dist/typings.d.ts → typings.d.ts} +45 -22
- package/CHANGELOG.md +0 -661
- package/dist/AbstractSqlDriver.d.ts +0 -55
- package/dist/AbstractSqlDriver.js +0 -644
- package/dist/AbstractSqlPlatform.d.ts +0 -21
- package/dist/LICENSE +0 -21
- package/dist/SqlEntityRepository.d.ts +0 -23
- package/dist/index.mjs +0 -26
- package/dist/package.json +0 -99
- package/dist/query/ArrayCriteriaNode.d.ts +0 -9
- package/dist/query/CriteriaNodeFactory.d.ts +0 -12
- package/dist/query/ObjectCriteriaNode.d.ts +0 -14
- package/dist/query/QueryBuilder.d.ts +0 -211
- package/dist/query/QueryBuilder.js +0 -688
- package/dist/query/QueryBuilderHelper.js +0 -523
- package/dist/query/ScalarCriteriaNode.d.ts +0 -9
- package/dist/query/enums.d.ts +0 -8
- package/dist/query/enums.js +0 -12
- package/dist/schema/DatabaseTable.js +0 -319
- /package/{dist/query → query}/index.d.ts +0 -0
- /package/{dist/typings.js → typings.js} +0 -0
|
@@ -12,7 +12,7 @@ const CriteriaNode_1 = require("./CriteriaNode");
|
|
|
12
12
|
class CriteriaNodeFactory {
|
|
13
13
|
static createNode(metadata, entityName, payload, parent, key) {
|
|
14
14
|
const customExpression = CriteriaNode_1.CriteriaNode.isCustomExpression(key || '');
|
|
15
|
-
const scalar = core_1.Utils.isPrimaryKey(payload) || payload instanceof RegExp || payload instanceof Date || customExpression;
|
|
15
|
+
const scalar = core_1.Utils.isPrimaryKey(payload) || core_1.Utils.isRawSql(payload) || payload instanceof RegExp || payload instanceof Date || customExpression;
|
|
16
16
|
if (Array.isArray(payload) && !scalar) {
|
|
17
17
|
return this.createArrayNode(metadata, entityName, payload, parent, key);
|
|
18
18
|
}
|
|
@@ -30,16 +30,16 @@ class CriteriaNodeFactory {
|
|
|
30
30
|
const node = new ArrayCriteriaNode_1.ArrayCriteriaNode(metadata, entityName, parent, key);
|
|
31
31
|
node.payload = payload.map((item, index) => {
|
|
32
32
|
const n = this.createNode(metadata, entityName, item, node);
|
|
33
|
-
|
|
33
|
+
// we care about branching only for $and
|
|
34
|
+
if (key === '$and' && payload.length > 1) {
|
|
35
|
+
n.index = index;
|
|
36
|
+
}
|
|
34
37
|
return n;
|
|
35
38
|
});
|
|
36
39
|
return node;
|
|
37
40
|
}
|
|
38
41
|
static createObjectNode(metadata, entityName, payload, parent, key) {
|
|
39
42
|
const meta = metadata.find(entityName);
|
|
40
|
-
if (!parent && Object.keys(payload).every(k => meta?.properties[k]?.reference === core_1.ReferenceType.SCALAR)) {
|
|
41
|
-
return this.createScalarNode(metadata, entityName, payload, parent, key);
|
|
42
|
-
}
|
|
43
43
|
const node = new ObjectCriteriaNode_1.ObjectCriteriaNode(metadata, entityName, parent, key);
|
|
44
44
|
node.payload = Object.keys(payload).reduce((o, item) => {
|
|
45
45
|
o[item] = this.createObjectItemNode(metadata, entityName, node, payload, item, meta);
|
|
@@ -47,24 +47,41 @@ class CriteriaNodeFactory {
|
|
|
47
47
|
}, {});
|
|
48
48
|
return node;
|
|
49
49
|
}
|
|
50
|
-
static createObjectItemNode(metadata, entityName, node, payload,
|
|
51
|
-
const prop = meta?.properties[
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
return this.createNode(metadata, childEntity, payload[
|
|
50
|
+
static createObjectItemNode(metadata, entityName, node, payload, key, meta) {
|
|
51
|
+
const prop = meta?.properties[key];
|
|
52
|
+
const childEntity = prop && prop.kind !== core_1.ReferenceKind.SCALAR ? prop.type : entityName;
|
|
53
|
+
if (prop?.kind !== core_1.ReferenceKind.EMBEDDED) {
|
|
54
|
+
return this.createNode(metadata, childEntity, payload[key], node, key);
|
|
55
|
+
}
|
|
56
|
+
if (payload[key] == null) {
|
|
57
|
+
const map = Object.keys(prop.embeddedProps).reduce((oo, k) => {
|
|
58
|
+
oo[prop.embeddedProps[k].name] = null;
|
|
59
|
+
return oo;
|
|
60
|
+
}, {});
|
|
61
|
+
return this.createNode(metadata, entityName, map, node, key);
|
|
55
62
|
}
|
|
56
|
-
|
|
63
|
+
// array operators can be used on embedded properties
|
|
64
|
+
const allowedOperators = ['$contains', '$contained', '$overlap'];
|
|
65
|
+
const operator = Object.keys(payload[key]).some(f => core_1.Utils.isOperator(f) && !allowedOperators.includes(f));
|
|
57
66
|
if (operator) {
|
|
58
67
|
throw core_1.ValidationError.cannotUseOperatorsInsideEmbeddables(entityName, prop.name, payload);
|
|
59
68
|
}
|
|
60
|
-
const map = Object.keys(payload[
|
|
61
|
-
if (!prop.embeddedProps[k]) {
|
|
69
|
+
const map = Object.keys(payload[key]).reduce((oo, k) => {
|
|
70
|
+
if (!prop.embeddedProps[k] && !allowedOperators.includes(k)) {
|
|
62
71
|
throw core_1.ValidationError.invalidEmbeddableQuery(entityName, k, prop.type);
|
|
63
72
|
}
|
|
64
|
-
|
|
73
|
+
if (prop.embeddedProps[k]) {
|
|
74
|
+
oo[prop.embeddedProps[k].name] = payload[key][k];
|
|
75
|
+
}
|
|
76
|
+
else if (typeof payload[key][k] === 'object') {
|
|
77
|
+
oo[k] = JSON.stringify(payload[key][k]);
|
|
78
|
+
}
|
|
79
|
+
else {
|
|
80
|
+
oo[k] = payload[key][k];
|
|
81
|
+
}
|
|
65
82
|
return oo;
|
|
66
83
|
}, {});
|
|
67
|
-
return this.createNode(metadata, entityName, map, node,
|
|
84
|
+
return this.createNode(metadata, entityName, map, node, key);
|
|
68
85
|
}
|
|
69
86
|
}
|
|
70
87
|
exports.CriteriaNodeFactory = CriteriaNodeFactory;
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
import { CriteriaNode } from './CriteriaNode';
|
|
2
|
+
import type { IQueryBuilder, ICriteriaNodeProcessOptions } from '../typings';
|
|
3
|
+
/**
|
|
4
|
+
* @internal
|
|
5
|
+
*/
|
|
6
|
+
export declare class ObjectCriteriaNode<T extends object> extends CriteriaNode<T> {
|
|
7
|
+
process(qb: IQueryBuilder<T>, options?: ICriteriaNodeProcessOptions): any;
|
|
8
|
+
unwrap(): any;
|
|
9
|
+
willAutoJoin(qb: IQueryBuilder<T>, alias?: string): boolean;
|
|
10
|
+
shouldInline(payload: any): boolean;
|
|
11
|
+
private inlineChildPayload;
|
|
12
|
+
private shouldAutoJoin;
|
|
13
|
+
private autoJoin;
|
|
14
|
+
private isPrefixed;
|
|
15
|
+
}
|
|
@@ -8,32 +8,59 @@ const enums_1 = require("./enums");
|
|
|
8
8
|
* @internal
|
|
9
9
|
*/
|
|
10
10
|
class ObjectCriteriaNode extends CriteriaNode_1.CriteriaNode {
|
|
11
|
-
process(qb,
|
|
12
|
-
const nestedAlias = qb.getAliasForJoinPath(this.getPath());
|
|
13
|
-
const ownerAlias = alias || qb.alias;
|
|
11
|
+
process(qb, options) {
|
|
12
|
+
const nestedAlias = qb.getAliasForJoinPath(this.getPath(), options);
|
|
13
|
+
const ownerAlias = options?.alias || qb.alias;
|
|
14
|
+
const keys = Object.keys(this.payload);
|
|
15
|
+
let alias = options?.alias;
|
|
14
16
|
if (nestedAlias) {
|
|
15
17
|
alias = nestedAlias;
|
|
16
18
|
}
|
|
17
19
|
if (this.shouldAutoJoin(nestedAlias)) {
|
|
20
|
+
if (keys.some(k => ['$some', '$none', '$every'].includes(k))) {
|
|
21
|
+
const $and = [];
|
|
22
|
+
const primaryKeys = this.metadata.find(this.entityName).primaryKeys.map(pk => `${alias}.${pk}`);
|
|
23
|
+
for (const key of keys) {
|
|
24
|
+
const payload = this.payload[key].unwrap();
|
|
25
|
+
const sub = qb.clone(true).innerJoin(this.key, qb.getNextAlias(this.prop.type));
|
|
26
|
+
sub.select(this.prop.targetMeta.primaryKeys);
|
|
27
|
+
if (key === '$every') {
|
|
28
|
+
sub.where({ $not: { [this.key]: payload } });
|
|
29
|
+
}
|
|
30
|
+
else {
|
|
31
|
+
sub.where({ [this.key]: payload });
|
|
32
|
+
}
|
|
33
|
+
const op = key === '$some' ? '$in' : '$nin';
|
|
34
|
+
$and.push({
|
|
35
|
+
[core_1.Utils.getPrimaryKeyHash(primaryKeys)]: { [op]: sub.getKnexQuery() },
|
|
36
|
+
});
|
|
37
|
+
}
|
|
38
|
+
return { $and };
|
|
39
|
+
}
|
|
18
40
|
alias = this.autoJoin(qb, ownerAlias);
|
|
19
41
|
}
|
|
20
|
-
return
|
|
42
|
+
return keys.reduce((o, field) => {
|
|
21
43
|
const childNode = this.payload[field];
|
|
22
|
-
const payload = childNode.process(qb, this.prop ? alias : ownerAlias);
|
|
44
|
+
const payload = childNode.process(qb, { ...options, alias: this.prop ? alias : ownerAlias });
|
|
23
45
|
const operator = core_1.Utils.isOperator(field);
|
|
24
|
-
const
|
|
25
|
-
|
|
46
|
+
const isRawField = core_1.RawQueryFragment.isKnownFragment(field);
|
|
47
|
+
// we need to keep the prefixing for formulas otherwise we would lose aliasing context when nesting inside group operators
|
|
48
|
+
const virtual = childNode.prop?.persist === false && !childNode.prop?.formula;
|
|
26
49
|
// if key is missing, we are inside group operator and we need to prefix with alias
|
|
27
50
|
const primaryKey = this.key && this.metadata.find(this.entityName).primaryKeys.includes(field);
|
|
28
51
|
if (childNode.shouldInline(payload)) {
|
|
29
|
-
const childAlias = qb.getAliasForJoinPath(childNode.getPath());
|
|
52
|
+
const childAlias = qb.getAliasForJoinPath(childNode.getPath(), options);
|
|
30
53
|
this.inlineChildPayload(o, payload, field, alias, childAlias);
|
|
31
54
|
}
|
|
32
55
|
else if (childNode.shouldRename(payload)) {
|
|
33
56
|
o[childNode.renameFieldToPK(qb)] = payload;
|
|
34
57
|
}
|
|
35
|
-
else if (
|
|
36
|
-
|
|
58
|
+
else if (isRawField) {
|
|
59
|
+
const rawField = core_1.RawQueryFragment.getKnownFragment(field);
|
|
60
|
+
o[(0, core_1.raw)(rawField.sql.replaceAll(core_1.ALIAS_REPLACEMENT, alias), rawField.params)] = payload;
|
|
61
|
+
}
|
|
62
|
+
else if (primaryKey || virtual || operator || field.includes('.') || ![enums_1.QueryType.SELECT, enums_1.QueryType.COUNT].includes(qb.type ?? enums_1.QueryType.SELECT)) {
|
|
63
|
+
o[field.replaceAll(core_1.ALIAS_REPLACEMENT, alias)] = payload;
|
|
37
64
|
}
|
|
38
65
|
else {
|
|
39
66
|
o[`${alias}.${field}`] = payload;
|
|
@@ -41,16 +68,23 @@ class ObjectCriteriaNode extends CriteriaNode_1.CriteriaNode {
|
|
|
41
68
|
return o;
|
|
42
69
|
}, {});
|
|
43
70
|
}
|
|
71
|
+
unwrap() {
|
|
72
|
+
return Object.keys(this.payload).reduce((o, field) => {
|
|
73
|
+
o[field] = this.payload[field].unwrap();
|
|
74
|
+
return o;
|
|
75
|
+
}, {});
|
|
76
|
+
}
|
|
44
77
|
willAutoJoin(qb, alias) {
|
|
45
78
|
const nestedAlias = qb.getAliasForJoinPath(this.getPath());
|
|
46
79
|
const ownerAlias = alias || qb.alias;
|
|
80
|
+
const keys = Object.keys(this.payload);
|
|
47
81
|
if (nestedAlias) {
|
|
48
82
|
alias = nestedAlias;
|
|
49
83
|
}
|
|
50
84
|
if (this.shouldAutoJoin(nestedAlias)) {
|
|
51
|
-
return
|
|
85
|
+
return !keys.some(k => ['$some', '$none', '$every'].includes(k));
|
|
52
86
|
}
|
|
53
|
-
return
|
|
87
|
+
return keys.some(field => {
|
|
54
88
|
const childNode = this.payload[field];
|
|
55
89
|
return childNode.willAutoJoin(qb, this.prop ? alias : ownerAlias);
|
|
56
90
|
});
|
|
@@ -59,7 +93,7 @@ class ObjectCriteriaNode extends CriteriaNode_1.CriteriaNode {
|
|
|
59
93
|
const customExpression = ObjectCriteriaNode.isCustomExpression(this.key);
|
|
60
94
|
const scalar = core_1.Utils.isPrimaryKey(payload) || payload instanceof RegExp || payload instanceof Date || customExpression;
|
|
61
95
|
const operator = core_1.Utils.isObject(payload) && Object.keys(payload).every(k => core_1.Utils.isOperator(k, false));
|
|
62
|
-
return !!this.prop && this.prop.
|
|
96
|
+
return !!this.prop && this.prop.kind !== core_1.ReferenceKind.SCALAR && !scalar && !operator;
|
|
63
97
|
}
|
|
64
98
|
inlineChildPayload(o, payload, field, alias, childAlias) {
|
|
65
99
|
const prop = this.metadata.find(this.entityName).properties[field];
|
|
@@ -71,17 +105,27 @@ class ObjectCriteriaNode extends CriteriaNode_1.CriteriaNode {
|
|
|
71
105
|
}
|
|
72
106
|
else if (this.isPrefixed(k) || core_1.Utils.isOperator(k) || !childAlias) {
|
|
73
107
|
const idx = prop.referencedPKs.indexOf(k);
|
|
74
|
-
const key = idx !== -1 && !childAlias ? prop.joinColumns[idx] : k;
|
|
108
|
+
const key = idx !== -1 && !childAlias && ![core_1.ReferenceKind.ONE_TO_MANY, core_1.ReferenceKind.MANY_TO_MANY].includes(prop.kind) ? prop.joinColumns[idx] : k;
|
|
75
109
|
if (key in o) {
|
|
76
110
|
const $and = o.$and ?? [];
|
|
77
111
|
$and.push({ [key]: o[key] }, { [key]: payload[k] });
|
|
78
112
|
delete o[key];
|
|
79
113
|
o.$and = $and;
|
|
80
114
|
}
|
|
115
|
+
else if (core_1.Utils.isOperator(k) && Array.isArray(payload[k])) {
|
|
116
|
+
o[key] = payload[k].map((child) => Object.keys(child).reduce((o, childKey) => {
|
|
117
|
+
const key = (this.isPrefixed(childKey) || core_1.Utils.isOperator(childKey)) ? childKey : `${childAlias}.${childKey}`;
|
|
118
|
+
o[key] = child[childKey];
|
|
119
|
+
return o;
|
|
120
|
+
}, {}));
|
|
121
|
+
}
|
|
81
122
|
else {
|
|
82
123
|
o[key] = payload[k];
|
|
83
124
|
}
|
|
84
125
|
}
|
|
126
|
+
else if (ObjectCriteriaNode.isCustomExpression(k)) {
|
|
127
|
+
o[k] = payload[k];
|
|
128
|
+
}
|
|
85
129
|
else {
|
|
86
130
|
o[`${childAlias}.${k}`] = payload[k];
|
|
87
131
|
}
|
|
@@ -91,15 +135,15 @@ class ObjectCriteriaNode extends CriteriaNode_1.CriteriaNode {
|
|
|
91
135
|
if (!this.prop || !this.parent) {
|
|
92
136
|
return false;
|
|
93
137
|
}
|
|
94
|
-
const embeddable = this.prop.
|
|
95
|
-
const knownKey = [core_1.
|
|
138
|
+
const embeddable = this.prop.kind === core_1.ReferenceKind.EMBEDDED;
|
|
139
|
+
const knownKey = [core_1.ReferenceKind.SCALAR, core_1.ReferenceKind.MANY_TO_ONE, core_1.ReferenceKind.EMBEDDED].includes(this.prop.kind) || (this.prop.kind === core_1.ReferenceKind.ONE_TO_ONE && this.prop.owner);
|
|
96
140
|
const operatorKeys = knownKey && Object.keys(this.payload).every(key => core_1.Utils.isOperator(key, false));
|
|
97
141
|
const primaryKeys = knownKey && Object.keys(this.payload).every(key => {
|
|
98
142
|
const meta = this.metadata.find(this.entityName);
|
|
99
143
|
if (!meta.primaryKeys.includes(key)) {
|
|
100
144
|
return false;
|
|
101
145
|
}
|
|
102
|
-
if (!core_1.Utils.isPlainObject(this.payload[key].payload) || ![core_1.
|
|
146
|
+
if (!core_1.Utils.isPlainObject(this.payload[key].payload) || ![core_1.ReferenceKind.ONE_TO_ONE, core_1.ReferenceKind.MANY_TO_ONE].includes(meta.properties[key].kind)) {
|
|
103
147
|
return true;
|
|
104
148
|
}
|
|
105
149
|
return Object.keys(this.payload[key].payload).every(k => meta.properties[key].targetMeta.primaryKeys.includes(k));
|
|
@@ -112,13 +156,16 @@ class ObjectCriteriaNode extends CriteriaNode_1.CriteriaNode {
|
|
|
112
156
|
const scalar = core_1.Utils.isPrimaryKey(this.payload) || this.payload instanceof RegExp || this.payload instanceof Date || customExpression;
|
|
113
157
|
const operator = core_1.Utils.isPlainObject(this.payload) && Object.keys(this.payload).every(k => core_1.Utils.isOperator(k, false));
|
|
114
158
|
const field = `${alias}.${this.prop.name}`;
|
|
115
|
-
|
|
116
|
-
|
|
159
|
+
const method = qb.hasFlag(core_1.QueryFlag.INFER_POPULATE) ? 'joinAndSelect' : 'join';
|
|
160
|
+
if (this.prop.kind === core_1.ReferenceKind.MANY_TO_MANY && (scalar || operator)) {
|
|
161
|
+
qb.join(field, nestedAlias, undefined, enums_1.JoinType.pivotJoin, this.getPath());
|
|
117
162
|
}
|
|
118
163
|
else {
|
|
119
164
|
const prev = qb._fields?.slice();
|
|
120
|
-
qb
|
|
121
|
-
qb.
|
|
165
|
+
qb[method](field, nestedAlias, undefined, enums_1.JoinType.leftJoin, this.getPath());
|
|
166
|
+
if (!qb.hasFlag(core_1.QueryFlag.INFER_POPULATE)) {
|
|
167
|
+
qb._fields = prev;
|
|
168
|
+
}
|
|
122
169
|
}
|
|
123
170
|
return nestedAlias;
|
|
124
171
|
}
|
|
@@ -0,0 +1,284 @@
|
|
|
1
|
+
/// <reference types="node" />
|
|
2
|
+
import { inspect } from 'util';
|
|
3
|
+
import type { Knex } from 'knex';
|
|
4
|
+
import { type AnyEntity, type ConnectionType, type Dictionary, type EntityData, type EntityName, type EntityProperty, type FlushMode, type GroupOperator, LockMode, type LoggingOptions, type MetadataStorage, type ObjectQuery, PopulateHint, type PopulateOptions, type QBFilterQuery, type QBQueryOrderMap, QueryFlag, type QueryResult, type RequiredEntityData } from '@mikro-orm/core';
|
|
5
|
+
import { QueryType, JoinType } from './enums';
|
|
6
|
+
import type { AbstractSqlDriver } from '../AbstractSqlDriver';
|
|
7
|
+
import { type Alias, QueryBuilderHelper } from './QueryBuilderHelper';
|
|
8
|
+
import type { SqlEntityManager } from '../SqlEntityManager';
|
|
9
|
+
import type { Field, ICriteriaNodeProcessOptions, JoinOptions } from '../typings';
|
|
10
|
+
import type { AbstractSqlPlatform } from '../AbstractSqlPlatform';
|
|
11
|
+
export interface ExecuteOptions {
|
|
12
|
+
mapResults?: boolean;
|
|
13
|
+
mergeResults?: boolean;
|
|
14
|
+
}
|
|
15
|
+
/**
|
|
16
|
+
* SQL query builder with fluent interface.
|
|
17
|
+
*
|
|
18
|
+
* ```ts
|
|
19
|
+
* const qb = orm.em.createQueryBuilder(Publisher);
|
|
20
|
+
* qb.select('*')
|
|
21
|
+
* .where({
|
|
22
|
+
* name: 'test 123',
|
|
23
|
+
* type: PublisherType.GLOBAL,
|
|
24
|
+
* })
|
|
25
|
+
* .orderBy({
|
|
26
|
+
* name: QueryOrder.DESC,
|
|
27
|
+
* type: QueryOrder.ASC,
|
|
28
|
+
* })
|
|
29
|
+
* .limit(2, 1);
|
|
30
|
+
*
|
|
31
|
+
* const publisher = await qb.getSingleResult();
|
|
32
|
+
* ```
|
|
33
|
+
*/
|
|
34
|
+
export declare class QueryBuilder<T extends object = AnyEntity> {
|
|
35
|
+
#private;
|
|
36
|
+
private readonly metadata;
|
|
37
|
+
private readonly driver;
|
|
38
|
+
private readonly context?;
|
|
39
|
+
private connectionType?;
|
|
40
|
+
private readonly em?;
|
|
41
|
+
private readonly logging?;
|
|
42
|
+
get mainAlias(): Alias<T>;
|
|
43
|
+
get alias(): string;
|
|
44
|
+
get helper(): QueryBuilderHelper;
|
|
45
|
+
/** @internal */
|
|
46
|
+
type?: QueryType;
|
|
47
|
+
/** @internal */
|
|
48
|
+
_fields?: Field<T>[];
|
|
49
|
+
/** @internal */
|
|
50
|
+
_populate: PopulateOptions<T>[];
|
|
51
|
+
/** @internal */
|
|
52
|
+
_populateWhere?: ObjectQuery<T> | PopulateHint | `${PopulateHint}`;
|
|
53
|
+
/** @internal */
|
|
54
|
+
__populateWhere?: ObjectQuery<T> | PopulateHint | `${PopulateHint}`;
|
|
55
|
+
/** @internal */
|
|
56
|
+
_populateMap: Dictionary<string>;
|
|
57
|
+
private aliasCounter;
|
|
58
|
+
private flags;
|
|
59
|
+
private finalized;
|
|
60
|
+
private _joins;
|
|
61
|
+
private _explicitAlias;
|
|
62
|
+
private _schema?;
|
|
63
|
+
private _cond;
|
|
64
|
+
private _data;
|
|
65
|
+
private _orderBy;
|
|
66
|
+
private _groupBy;
|
|
67
|
+
private _having;
|
|
68
|
+
private _returning?;
|
|
69
|
+
private _onConflict?;
|
|
70
|
+
private _limit?;
|
|
71
|
+
private _offset?;
|
|
72
|
+
private _distinctOn?;
|
|
73
|
+
private _joinedProps;
|
|
74
|
+
private _cache?;
|
|
75
|
+
private _indexHint?;
|
|
76
|
+
private _comments;
|
|
77
|
+
private _hintComments;
|
|
78
|
+
private flushMode?;
|
|
79
|
+
private lockMode?;
|
|
80
|
+
private lockTables?;
|
|
81
|
+
private subQueries;
|
|
82
|
+
private _mainAlias?;
|
|
83
|
+
private _aliases;
|
|
84
|
+
private _helper?;
|
|
85
|
+
private readonly platform;
|
|
86
|
+
private readonly knex;
|
|
87
|
+
/**
|
|
88
|
+
* @internal
|
|
89
|
+
*/
|
|
90
|
+
constructor(entityName: EntityName<T> | QueryBuilder<T>, metadata: MetadataStorage, driver: AbstractSqlDriver, context?: Knex.Transaction<any, any[]> | undefined, alias?: string, connectionType?: ConnectionType | undefined, em?: SqlEntityManager<AbstractSqlDriver<import("..").AbstractSqlConnection, AbstractSqlPlatform>> | undefined, logging?: LoggingOptions | undefined);
|
|
91
|
+
select(fields: Field<T> | Field<T>[], distinct?: boolean): SelectQueryBuilder<T>;
|
|
92
|
+
addSelect(fields: Field<T> | Field<T>[]): SelectQueryBuilder<T>;
|
|
93
|
+
distinct(): SelectQueryBuilder<T>;
|
|
94
|
+
/** postgres only */
|
|
95
|
+
distinctOn(fields: string | string[]): SelectQueryBuilder<T>;
|
|
96
|
+
insert(data: RequiredEntityData<T> | RequiredEntityData<T>[]): InsertQueryBuilder<T>;
|
|
97
|
+
update(data: EntityData<T>): UpdateQueryBuilder<T>;
|
|
98
|
+
delete(cond?: QBFilterQuery): DeleteQueryBuilder<T>;
|
|
99
|
+
truncate(): TruncateQueryBuilder<T>;
|
|
100
|
+
count(field?: string | string[], distinct?: boolean): CountQueryBuilder<T>;
|
|
101
|
+
join(field: string | Knex.QueryBuilder | QueryBuilder<any>, alias: string, cond?: QBFilterQuery, type?: JoinType, path?: string, schema?: string): this;
|
|
102
|
+
innerJoin(field: string | Knex.QueryBuilder | QueryBuilder<any>, alias: string, cond?: QBFilterQuery, schema?: string): this;
|
|
103
|
+
innerJoinLateral(field: string | Knex.QueryBuilder | QueryBuilder<any>, alias: string, cond?: QBFilterQuery, schema?: string): this;
|
|
104
|
+
leftJoin(field: string | Knex.QueryBuilder | QueryBuilder<any>, alias: string, cond?: QBFilterQuery, schema?: string): this;
|
|
105
|
+
leftJoinLateral(field: string | Knex.QueryBuilder | QueryBuilder<any>, alias: string, cond?: QBFilterQuery, schema?: string): this;
|
|
106
|
+
joinAndSelect(field: string | [field: string, qb: Knex.QueryBuilder | QueryBuilder<any>], alias: string, cond?: QBFilterQuery, type?: JoinType, path?: string, fields?: string[], schema?: string): SelectQueryBuilder<T>;
|
|
107
|
+
leftJoinAndSelect(field: string | [field: string, qb: Knex.QueryBuilder | QueryBuilder<any>], alias: string, cond?: QBFilterQuery, fields?: string[], schema?: string): SelectQueryBuilder<T>;
|
|
108
|
+
leftJoinLateralAndSelect(field: string | [field: string, qb: Knex.QueryBuilder | QueryBuilder<any>], alias: string, cond?: QBFilterQuery, fields?: string[], schema?: string): SelectQueryBuilder<T>;
|
|
109
|
+
innerJoinAndSelect(field: string | [field: string, qb: Knex.QueryBuilder | QueryBuilder<any>], alias: string, cond?: QBFilterQuery, fields?: string[], schema?: string): SelectQueryBuilder<T>;
|
|
110
|
+
innerJoinLateralAndSelect(field: string | [field: string, qb: Knex.QueryBuilder | QueryBuilder<any>], alias: string, cond?: QBFilterQuery, fields?: string[], schema?: string): SelectQueryBuilder<T>;
|
|
111
|
+
protected getFieldsForJoinedLoad(prop: EntityProperty<T>, alias: string, explicitFields?: string[]): Field<T>[];
|
|
112
|
+
withSubQuery(subQuery: Knex.QueryBuilder, alias: string): this;
|
|
113
|
+
where(cond: QBFilterQuery<T>, operator?: keyof typeof GroupOperator): this;
|
|
114
|
+
where(cond: string, params?: any[], operator?: keyof typeof GroupOperator): this;
|
|
115
|
+
andWhere(cond: QBFilterQuery<T>): this;
|
|
116
|
+
andWhere(cond: string, params?: any[]): this;
|
|
117
|
+
orWhere(cond: QBFilterQuery<T>): this;
|
|
118
|
+
orWhere(cond: string, params?: any[]): this;
|
|
119
|
+
orderBy(orderBy: QBQueryOrderMap<T> | QBQueryOrderMap<T>[]): this;
|
|
120
|
+
groupBy(fields: (string | keyof T) | readonly (string | keyof T)[]): this;
|
|
121
|
+
having(cond?: QBFilterQuery | string, params?: any[]): this;
|
|
122
|
+
onConflict(fields?: Field<T> | Field<T>[]): this;
|
|
123
|
+
ignore(): this;
|
|
124
|
+
merge(data?: EntityData<T> | Field<T>[]): this;
|
|
125
|
+
returning(fields?: Field<T> | Field<T>[]): this;
|
|
126
|
+
/**
|
|
127
|
+
* @internal
|
|
128
|
+
*/
|
|
129
|
+
populate(populate: PopulateOptions<T>[], populateWhere?: ObjectQuery<T> | PopulateHint | `${PopulateHint}`): this;
|
|
130
|
+
limit(limit?: number, offset?: number): this;
|
|
131
|
+
offset(offset?: number): this;
|
|
132
|
+
withSchema(schema?: string): this;
|
|
133
|
+
setLockMode(mode?: LockMode, tables?: string[]): this;
|
|
134
|
+
setFlushMode(flushMode?: FlushMode): this;
|
|
135
|
+
setFlag(flag: QueryFlag): this;
|
|
136
|
+
unsetFlag(flag: QueryFlag): this;
|
|
137
|
+
hasFlag(flag: QueryFlag): boolean;
|
|
138
|
+
cache(config?: boolean | number | [string, number]): this;
|
|
139
|
+
/**
|
|
140
|
+
* Adds index hint to the FROM clause.
|
|
141
|
+
*/
|
|
142
|
+
indexHint(sql: string): this;
|
|
143
|
+
/**
|
|
144
|
+
* Prepend comment to the sql query using the syntax `/* ... *‍/`. Some characters are forbidden such as `/*, *‍/` and `?`.
|
|
145
|
+
*/
|
|
146
|
+
comment(comment: string | string[]): this;
|
|
147
|
+
/**
|
|
148
|
+
* Add hints to the query using comment-like syntax `/*+ ... *‍/`. MySQL and Oracle use this syntax for optimizer hints.
|
|
149
|
+
* Also various DB proxies and routers use this syntax to pass hints to alter their behavior. In other dialects the hints
|
|
150
|
+
* are ignored as simple comments.
|
|
151
|
+
*/
|
|
152
|
+
hintComment(comment: string | string[]): this;
|
|
153
|
+
/**
|
|
154
|
+
* Specifies FROM which entity's table select/update/delete will be executed, removing all previously set FROM-s.
|
|
155
|
+
* Allows setting a main string alias of the selection data.
|
|
156
|
+
*/
|
|
157
|
+
from<T extends AnyEntity<T> = AnyEntity>(target: QueryBuilder<T>, aliasName?: string): QueryBuilder<T>;
|
|
158
|
+
from<T extends AnyEntity<T> = AnyEntity>(target: EntityName<T>): QueryBuilder<T>;
|
|
159
|
+
getKnexQuery(): Knex.QueryBuilder;
|
|
160
|
+
/**
|
|
161
|
+
* Returns the query with parameters as wildcards.
|
|
162
|
+
*/
|
|
163
|
+
getQuery(): string;
|
|
164
|
+
toQuery(): {
|
|
165
|
+
sql: string;
|
|
166
|
+
_sql: Knex.Sql;
|
|
167
|
+
params: readonly unknown[];
|
|
168
|
+
};
|
|
169
|
+
/**
|
|
170
|
+
* Returns the list of all parameters for this query.
|
|
171
|
+
*/
|
|
172
|
+
getParams(): readonly Knex.Value[];
|
|
173
|
+
/**
|
|
174
|
+
* Returns raw interpolated query string with all the parameters inlined.
|
|
175
|
+
*/
|
|
176
|
+
getFormattedQuery(): string;
|
|
177
|
+
/**
|
|
178
|
+
* @internal
|
|
179
|
+
*/
|
|
180
|
+
getAliasForJoinPath(path?: string | JoinOptions, options?: ICriteriaNodeProcessOptions): string | undefined;
|
|
181
|
+
/**
|
|
182
|
+
* @internal
|
|
183
|
+
*/
|
|
184
|
+
getJoinForPath(path: string, options?: ICriteriaNodeProcessOptions): JoinOptions | undefined;
|
|
185
|
+
/**
|
|
186
|
+
* @internal
|
|
187
|
+
*/
|
|
188
|
+
getNextAlias(entityName?: string): string;
|
|
189
|
+
/**
|
|
190
|
+
* @internal
|
|
191
|
+
*/
|
|
192
|
+
getAliasMap(): Dictionary<string>;
|
|
193
|
+
/**
|
|
194
|
+
* Executes this QB and returns the raw results, mapped to the property names (unless disabled via last parameter).
|
|
195
|
+
* Use `method` to specify what kind of result you want to get (array/single/meta).
|
|
196
|
+
*/
|
|
197
|
+
execute<U = any>(method?: 'all' | 'get' | 'run', options?: ExecuteOptions | boolean): Promise<U>;
|
|
198
|
+
/**
|
|
199
|
+
* Alias for `qb.getResultList()`
|
|
200
|
+
*/
|
|
201
|
+
getResult(): Promise<T[]>;
|
|
202
|
+
/**
|
|
203
|
+
* Executes the query, returning array of results
|
|
204
|
+
*/
|
|
205
|
+
getResultList(): Promise<T[]>;
|
|
206
|
+
/**
|
|
207
|
+
* Executes the query, returning the first result or null
|
|
208
|
+
*/
|
|
209
|
+
getSingleResult(): Promise<T | null>;
|
|
210
|
+
/**
|
|
211
|
+
* Executes count query (without offset and limit), returning total count of results
|
|
212
|
+
*/
|
|
213
|
+
getCount(field?: string | string[], distinct?: boolean): Promise<number>;
|
|
214
|
+
/**
|
|
215
|
+
* Executes the query, returning both array of results and total count query (without offset and limit).
|
|
216
|
+
*/
|
|
217
|
+
getResultAndCount(): Promise<[T[], number]>;
|
|
218
|
+
/**
|
|
219
|
+
* Provides promise-like interface so we can await the QB instance.
|
|
220
|
+
*/
|
|
221
|
+
then<TResult1 = any, TResult2 = never>(onfulfilled?: ((value: any) => TResult1 | PromiseLike<TResult1>) | undefined | null, onrejected?: ((reason: any) => TResult2 | PromiseLike<TResult2>) | undefined | null): Promise<T[] | number | QueryResult<T>>;
|
|
222
|
+
/**
|
|
223
|
+
* Returns knex instance with sub-query aliased with given alias.
|
|
224
|
+
* You can provide `EntityName.propName` as alias, then the field name will be used based on the metadata
|
|
225
|
+
*/
|
|
226
|
+
as(alias: string): Knex.QueryBuilder;
|
|
227
|
+
clone(reset?: boolean): QueryBuilder<T>;
|
|
228
|
+
getKnex(): Knex.QueryBuilder;
|
|
229
|
+
private joinReference;
|
|
230
|
+
private prepareFields;
|
|
231
|
+
private init;
|
|
232
|
+
private getQueryBase;
|
|
233
|
+
private applyDiscriminatorCondition;
|
|
234
|
+
private finalize;
|
|
235
|
+
private processPopulateWhere;
|
|
236
|
+
private hasToManyJoins;
|
|
237
|
+
private wrapPaginateSubQuery;
|
|
238
|
+
private wrapModifySubQuery;
|
|
239
|
+
private getSchema;
|
|
240
|
+
private createAlias;
|
|
241
|
+
private createMainAlias;
|
|
242
|
+
private fromSubQuery;
|
|
243
|
+
private fromEntityName;
|
|
244
|
+
private createQueryBuilderHelper;
|
|
245
|
+
private ensureFromClause;
|
|
246
|
+
private ensureNotFinalized;
|
|
247
|
+
/** @ignore */
|
|
248
|
+
[inspect.custom](depth: number): string;
|
|
249
|
+
}
|
|
250
|
+
export interface RunQueryBuilder<T extends object> extends Omit<QueryBuilder<T>, 'getResult' | 'getSingleResult' | 'getResultList' | 'where'> {
|
|
251
|
+
where(cond: QBFilterQuery<T> | string, params?: keyof typeof GroupOperator | any[], operator?: keyof typeof GroupOperator): this;
|
|
252
|
+
execute<U = QueryResult<T>>(method?: 'all' | 'get' | 'run', mapResults?: boolean): Promise<U>;
|
|
253
|
+
then<TResult1 = QueryResult<T>, TResult2 = never>(onfulfilled?: ((value: QueryResult<T>) => TResult1 | PromiseLike<TResult1>) | undefined | null, onrejected?: ((reason: any) => TResult2 | PromiseLike<TResult2>) | undefined | null): Promise<QueryResult<T>>;
|
|
254
|
+
}
|
|
255
|
+
export interface SelectQueryBuilder<T extends object> extends QueryBuilder<T> {
|
|
256
|
+
execute<U = T[]>(method?: 'all' | 'get' | 'run', mapResults?: boolean): Promise<U>;
|
|
257
|
+
execute<U = T[]>(method: 'all', mapResults?: boolean): Promise<U>;
|
|
258
|
+
execute<U = T>(method: 'get', mapResults?: boolean): Promise<U>;
|
|
259
|
+
execute<U = QueryResult<T>>(method: 'run', mapResults?: boolean): Promise<U>;
|
|
260
|
+
then<TResult1 = T[], TResult2 = never>(onfulfilled?: ((value: T[]) => TResult1 | PromiseLike<TResult1>) | undefined | null, onrejected?: ((reason: any) => TResult2 | PromiseLike<TResult2>) | undefined | null): Promise<T[]>;
|
|
261
|
+
}
|
|
262
|
+
export interface CountQueryBuilder<T extends object> extends QueryBuilder<T> {
|
|
263
|
+
execute<U = {
|
|
264
|
+
count: number;
|
|
265
|
+
}[]>(method?: 'all' | 'get' | 'run', mapResults?: boolean): Promise<U>;
|
|
266
|
+
execute<U = {
|
|
267
|
+
count: number;
|
|
268
|
+
}[]>(method: 'all', mapResults?: boolean): Promise<U>;
|
|
269
|
+
execute<U = {
|
|
270
|
+
count: number;
|
|
271
|
+
}>(method: 'get', mapResults?: boolean): Promise<U>;
|
|
272
|
+
execute<U = QueryResult<{
|
|
273
|
+
count: number;
|
|
274
|
+
}>>(method: 'run', mapResults?: boolean): Promise<U>;
|
|
275
|
+
then<TResult1 = number, TResult2 = never>(onfulfilled?: ((value: number) => TResult1 | PromiseLike<TResult1>) | undefined | null, onrejected?: ((reason: any) => TResult2 | PromiseLike<TResult2>) | undefined | null): Promise<number>;
|
|
276
|
+
}
|
|
277
|
+
export interface InsertQueryBuilder<T extends object> extends RunQueryBuilder<T> {
|
|
278
|
+
}
|
|
279
|
+
export interface UpdateQueryBuilder<T extends object> extends RunQueryBuilder<T> {
|
|
280
|
+
}
|
|
281
|
+
export interface DeleteQueryBuilder<T extends object> extends RunQueryBuilder<T> {
|
|
282
|
+
}
|
|
283
|
+
export interface TruncateQueryBuilder<T extends object> extends RunQueryBuilder<T> {
|
|
284
|
+
}
|