@mikro-orm/sql 7.0.10 → 7.0.11-dev.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 +58 -94
- package/AbstractSqlConnection.js +238 -235
- package/AbstractSqlDriver.d.ts +155 -410
- package/AbstractSqlDriver.js +1968 -2096
- package/AbstractSqlPlatform.d.ts +75 -85
- package/AbstractSqlPlatform.js +162 -166
- package/PivotCollectionPersister.d.ts +15 -33
- package/PivotCollectionPersister.js +160 -158
- package/README.md +1 -1
- package/SqlEntityManager.d.ts +22 -67
- package/SqlEntityManager.js +38 -54
- package/SqlEntityRepository.d.ts +14 -14
- package/SqlEntityRepository.js +23 -23
- package/dialects/mssql/MsSqlNativeQueryBuilder.d.ts +12 -12
- package/dialects/mssql/MsSqlNativeQueryBuilder.js +201 -199
- package/dialects/mysql/BaseMySqlPlatform.d.ts +46 -65
- package/dialects/mysql/BaseMySqlPlatform.js +134 -137
- package/dialects/mysql/MySqlExceptionConverter.d.ts +6 -6
- package/dialects/mysql/MySqlExceptionConverter.js +77 -91
- package/dialects/mysql/MySqlNativeQueryBuilder.d.ts +3 -3
- package/dialects/mysql/MySqlNativeQueryBuilder.js +69 -66
- package/dialects/mysql/MySqlSchemaHelper.d.ts +39 -58
- package/dialects/mysql/MySqlSchemaHelper.js +319 -327
- package/dialects/oracledb/OracleDialect.d.ts +52 -81
- package/dialects/oracledb/OracleDialect.js +149 -155
- package/dialects/oracledb/OracleNativeQueryBuilder.d.ts +12 -12
- package/dialects/oracledb/OracleNativeQueryBuilder.js +243 -239
- package/dialects/postgresql/BasePostgreSqlPlatform.d.ts +106 -109
- package/dialects/postgresql/BasePostgreSqlPlatform.js +353 -354
- package/dialects/postgresql/FullTextType.d.ts +6 -10
- package/dialects/postgresql/FullTextType.js +51 -51
- package/dialects/postgresql/PostgreSqlExceptionConverter.d.ts +5 -5
- package/dialects/postgresql/PostgreSqlExceptionConverter.js +43 -55
- package/dialects/postgresql/PostgreSqlNativeQueryBuilder.d.ts +1 -1
- package/dialects/postgresql/PostgreSqlNativeQueryBuilder.js +4 -4
- package/dialects/postgresql/PostgreSqlSchemaHelper.d.ts +82 -117
- package/dialects/postgresql/PostgreSqlSchemaHelper.js +711 -747
- package/dialects/sqlite/BaseSqliteConnection.d.ts +5 -3
- package/dialects/sqlite/BaseSqliteConnection.js +19 -21
- package/dialects/sqlite/NodeSqliteDialect.d.ts +1 -1
- package/dialects/sqlite/NodeSqliteDialect.js +23 -23
- package/dialects/sqlite/SqliteDriver.d.ts +1 -1
- package/dialects/sqlite/SqliteDriver.js +3 -3
- package/dialects/sqlite/SqliteExceptionConverter.d.ts +6 -6
- package/dialects/sqlite/SqliteExceptionConverter.js +51 -67
- package/dialects/sqlite/SqliteNativeQueryBuilder.d.ts +2 -2
- package/dialects/sqlite/SqliteNativeQueryBuilder.js +7 -7
- package/dialects/sqlite/SqlitePlatform.d.ts +72 -63
- package/dialects/sqlite/SqlitePlatform.js +139 -139
- package/dialects/sqlite/SqliteSchemaHelper.d.ts +60 -77
- package/dialects/sqlite/SqliteSchemaHelper.js +522 -541
- package/package.json +2 -2
- package/plugin/index.d.ts +35 -42
- package/plugin/index.js +36 -43
- package/plugin/transformer.d.ts +94 -117
- package/plugin/transformer.js +881 -890
- package/query/ArrayCriteriaNode.d.ts +4 -4
- package/query/ArrayCriteriaNode.js +18 -18
- package/query/CriteriaNode.d.ts +25 -35
- package/query/CriteriaNode.js +123 -133
- package/query/CriteriaNodeFactory.d.ts +6 -49
- package/query/CriteriaNodeFactory.js +94 -97
- package/query/NativeQueryBuilder.d.ts +120 -120
- package/query/NativeQueryBuilder.js +501 -507
- package/query/ObjectCriteriaNode.d.ts +12 -12
- package/query/ObjectCriteriaNode.js +282 -298
- package/query/QueryBuilder.d.ts +906 -1558
- package/query/QueryBuilder.js +2202 -2331
- package/query/QueryBuilderHelper.d.ts +72 -153
- package/query/QueryBuilderHelper.js +1032 -1084
- package/query/ScalarCriteriaNode.d.ts +3 -3
- package/query/ScalarCriteriaNode.js +46 -53
- package/query/enums.d.ts +14 -14
- package/query/enums.js +14 -14
- package/query/raw.d.ts +6 -16
- package/query/raw.js +10 -10
- package/schema/DatabaseSchema.d.ts +50 -74
- package/schema/DatabaseSchema.js +327 -355
- package/schema/DatabaseTable.d.ts +73 -96
- package/schema/DatabaseTable.js +927 -1002
- package/schema/SchemaComparator.d.ts +66 -70
- package/schema/SchemaComparator.js +764 -790
- package/schema/SchemaHelper.d.ts +97 -128
- package/schema/SchemaHelper.js +668 -683
- package/schema/SqlSchemaGenerator.d.ts +59 -79
- package/schema/SqlSchemaGenerator.js +495 -525
- package/typings.d.ts +275 -405
|
@@ -3,253 +3,257 @@ import { QueryType } from '../../query/enums.js';
|
|
|
3
3
|
import { NativeQueryBuilder } from '../../query/NativeQueryBuilder.js';
|
|
4
4
|
/** @internal */
|
|
5
5
|
export function markOutBindings(obj) {
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
6
|
+
Object.defineProperty(obj, '__outBindings', {
|
|
7
|
+
value: true,
|
|
8
|
+
writable: true,
|
|
9
|
+
configurable: true,
|
|
10
|
+
enumerable: false,
|
|
11
|
+
});
|
|
12
12
|
}
|
|
13
13
|
/** @internal */
|
|
14
14
|
export class OracleNativeQueryBuilder extends NativeQueryBuilder {
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
}
|
|
19
|
-
compile() {
|
|
20
|
-
if (!this.type) {
|
|
21
|
-
throw new Error('No query type provided');
|
|
22
|
-
}
|
|
23
|
-
this.parts.length = 0;
|
|
24
|
-
this.params.length = 0;
|
|
25
|
-
/* v8 ignore next 3: query comment branch */
|
|
26
|
-
if (this.options.comment) {
|
|
27
|
-
this.parts.push(...this.options.comment.map(comment => `/* ${comment} */`));
|
|
28
|
-
}
|
|
29
|
-
let copy;
|
|
30
|
-
if (this.options.onConflict && !Utils.isEmpty(Utils.asArray(this.options.data)[0])) {
|
|
31
|
-
this.compileUpsert();
|
|
32
|
-
} else {
|
|
33
|
-
if (this.options.returning && Array.isArray(this.options.data) && this.options.data.length > 1) {
|
|
34
|
-
copy = [...this.options.data];
|
|
35
|
-
this.options.data.length = 1;
|
|
36
|
-
}
|
|
37
|
-
switch (this.type) {
|
|
38
|
-
case QueryType.SELECT:
|
|
39
|
-
case QueryType.COUNT:
|
|
40
|
-
this.compileSelect();
|
|
41
|
-
break;
|
|
42
|
-
case QueryType.INSERT:
|
|
43
|
-
this.compileInsert();
|
|
44
|
-
break;
|
|
45
|
-
case QueryType.UPDATE:
|
|
46
|
-
this.compileUpdate();
|
|
47
|
-
break;
|
|
48
|
-
case QueryType.DELETE:
|
|
49
|
-
this.compileDelete();
|
|
50
|
-
break;
|
|
51
|
-
case QueryType.TRUNCATE:
|
|
52
|
-
this.compileTruncate();
|
|
53
|
-
break;
|
|
54
|
-
}
|
|
55
|
-
this.addOnConflictClause();
|
|
56
|
-
}
|
|
57
|
-
if (this.options.returning) {
|
|
58
|
-
const isUpsert = this.options.onConflict && !Utils.isEmpty(Utils.asArray(this.options.data)[0]);
|
|
59
|
-
const prefix = isUpsert ? `${this.getTableName()}.` : '';
|
|
60
|
-
const fields = this.options.returning.map(field => prefix + this.quote(Array.isArray(field) ? field[0] : field));
|
|
61
|
-
const into = this.options.returning.map(field => ':out_' + (Array.isArray(field) ? field[0] : field));
|
|
62
|
-
const outBindings = this.options.returning.map(field => {
|
|
63
|
-
const name = 'out_' + (Array.isArray(field) ? field[0] : field);
|
|
64
|
-
const type = Array.isArray(field) ? field[1] : 'string';
|
|
65
|
-
return [name, type];
|
|
66
|
-
});
|
|
67
|
-
markOutBindings(outBindings);
|
|
68
|
-
this.parts.push(`returning ${fields.join(', ')}`);
|
|
69
|
-
this.parts.push(`into ${into.join(', ')}`);
|
|
70
|
-
this.params.push(outBindings);
|
|
71
|
-
}
|
|
72
|
-
this.addLockClause();
|
|
73
|
-
if (!copy) {
|
|
74
|
-
return this.combineParts();
|
|
75
|
-
}
|
|
76
|
-
// multi insert with returning
|
|
77
|
-
const sql = this.parts.join(' ');
|
|
78
|
-
const blockLines = [];
|
|
79
|
-
const block2Lines = [];
|
|
80
|
-
const keys = Object.keys(copy[0]);
|
|
81
|
-
const last = this.params[this.params.length - 1];
|
|
82
|
-
/* v8 ignore next 3: defensive check — output bindings are always set by compile() */
|
|
83
|
-
if (!Array.isArray(last) || !('__outBindings' in last) || !last.__outBindings) {
|
|
84
|
-
throw new Error('Output bindings are required for multi insert with returning');
|
|
85
|
-
}
|
|
86
|
-
const outBindings = {};
|
|
87
|
-
markOutBindings(outBindings);
|
|
88
|
-
for (let i = 0; i < copy.length; i++) {
|
|
89
|
-
const params = [];
|
|
90
|
-
for (const key of keys) {
|
|
91
|
-
/* v8 ignore next 3: undefined value branch in multi-insert */
|
|
92
|
-
if (typeof copy[i][key] === 'undefined') {
|
|
93
|
-
params.push(this.platform.usesDefaultKeyword() ? raw('default') : null);
|
|
94
|
-
} else {
|
|
95
|
-
params.push(copy[i][key]);
|
|
96
|
-
}
|
|
97
|
-
}
|
|
98
|
-
// we need to interpolate to allow proper escaping
|
|
99
|
-
const formatted = this.platform.formatQuery(sql, params).replaceAll(`'`, `''`);
|
|
100
|
-
/* v8 ignore next 3: returning field type branches */
|
|
101
|
-
const using = this.options.returning.map(field => {
|
|
102
|
-
const name = Array.isArray(field) ? field[0] : field;
|
|
103
|
-
const type = Array.isArray(field) ? field[1] : 'string';
|
|
104
|
-
outBindings[`out_${name}__${i}`] = {
|
|
105
|
-
dir: this.platform.mapToBindType('out'),
|
|
106
|
-
type: this.platform.mapToBindType(type),
|
|
107
|
-
};
|
|
108
|
-
return `out :out_${name}__${i}`;
|
|
109
|
-
});
|
|
110
|
-
blockLines.push(` execute immediate '${formatted}' using ${using.join(', ')};`);
|
|
111
|
-
block2Lines.push(` execute immediate '${sql}' using ${using.join(', ')};`);
|
|
112
|
-
}
|
|
113
|
-
const block = `begin\n${blockLines.join('\n')}\n end;`;
|
|
114
|
-
const block2 = `begin\n${block2Lines.join('\n')}\n end;`;
|
|
115
|
-
// save raw query without interpolation for logging,
|
|
116
|
-
Object.defineProperty(outBindings, '__rawQuery', {
|
|
117
|
-
value: block2,
|
|
118
|
-
writable: true,
|
|
119
|
-
configurable: true,
|
|
120
|
-
enumerable: false,
|
|
121
|
-
});
|
|
122
|
-
this.options.data = copy;
|
|
123
|
-
return { sql: block, params: [outBindings] };
|
|
124
|
-
}
|
|
125
|
-
compileTruncate() {
|
|
126
|
-
super.compileTruncate();
|
|
127
|
-
this.parts.push('drop all storage cascade');
|
|
128
|
-
}
|
|
129
|
-
combineParts() {
|
|
130
|
-
let sql = this.parts.join(' ');
|
|
131
|
-
const last = this.params[this.params.length - 1];
|
|
132
|
-
if (this.options.wrap) {
|
|
133
|
-
const [a, b] = this.options.wrap;
|
|
134
|
-
sql = `${a}${sql}${b}`;
|
|
135
|
-
}
|
|
136
|
-
if (!(Array.isArray(last) && '__outBindings' in last && last.__outBindings)) {
|
|
137
|
-
return { sql, params: this.params };
|
|
15
|
+
as(alias) {
|
|
16
|
+
this.wrap('(', `) ${this.platform.quoteIdentifier(alias)}`);
|
|
17
|
+
return this;
|
|
138
18
|
}
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
|
|
162
|
-
|
|
163
|
-
|
|
164
|
-
|
|
165
|
-
|
|
166
|
-
|
|
167
|
-
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
|
|
172
|
-
|
|
173
|
-
|
|
174
|
-
|
|
175
|
-
|
|
176
|
-
|
|
177
|
-
|
|
178
|
-
|
|
179
|
-
|
|
180
|
-
|
|
181
|
-
|
|
182
|
-
|
|
183
|
-
|
|
184
|
-
|
|
185
|
-
|
|
186
|
-
|
|
187
|
-
|
|
188
|
-
|
|
189
|
-
this.parts.push(`
|
|
190
|
-
this.
|
|
191
|
-
|
|
192
|
-
|
|
193
|
-
|
|
194
|
-
|
|
195
|
-
|
|
196
|
-
|
|
197
|
-
|
|
198
|
-
|
|
199
|
-
|
|
200
|
-
|
|
201
|
-
|
|
202
|
-
const
|
|
203
|
-
|
|
204
|
-
|
|
19
|
+
compile() {
|
|
20
|
+
if (!this.type) {
|
|
21
|
+
throw new Error('No query type provided');
|
|
22
|
+
}
|
|
23
|
+
this.parts.length = 0;
|
|
24
|
+
this.params.length = 0;
|
|
25
|
+
/* v8 ignore next 3: query comment branch */
|
|
26
|
+
if (this.options.comment) {
|
|
27
|
+
this.parts.push(...this.options.comment.map(comment => `/* ${comment} */`));
|
|
28
|
+
}
|
|
29
|
+
let copy;
|
|
30
|
+
if (this.options.onConflict && !Utils.isEmpty(Utils.asArray(this.options.data)[0])) {
|
|
31
|
+
this.compileUpsert();
|
|
32
|
+
}
|
|
33
|
+
else {
|
|
34
|
+
if (this.options.returning && Array.isArray(this.options.data) && this.options.data.length > 1) {
|
|
35
|
+
copy = [...this.options.data];
|
|
36
|
+
this.options.data.length = 1;
|
|
37
|
+
}
|
|
38
|
+
switch (this.type) {
|
|
39
|
+
case QueryType.SELECT:
|
|
40
|
+
case QueryType.COUNT:
|
|
41
|
+
this.compileSelect();
|
|
42
|
+
break;
|
|
43
|
+
case QueryType.INSERT:
|
|
44
|
+
this.compileInsert();
|
|
45
|
+
break;
|
|
46
|
+
case QueryType.UPDATE:
|
|
47
|
+
this.compileUpdate();
|
|
48
|
+
break;
|
|
49
|
+
case QueryType.DELETE:
|
|
50
|
+
this.compileDelete();
|
|
51
|
+
break;
|
|
52
|
+
case QueryType.TRUNCATE:
|
|
53
|
+
this.compileTruncate();
|
|
54
|
+
break;
|
|
55
|
+
}
|
|
56
|
+
this.addOnConflictClause();
|
|
57
|
+
}
|
|
58
|
+
if (this.options.returning) {
|
|
59
|
+
const isUpsert = this.options.onConflict && !Utils.isEmpty(Utils.asArray(this.options.data)[0]);
|
|
60
|
+
const prefix = isUpsert ? `${this.getTableName()}.` : '';
|
|
61
|
+
const fields = this.options.returning.map(field => prefix + this.quote(Array.isArray(field) ? field[0] : field));
|
|
62
|
+
const into = this.options.returning.map(field => ':out_' + (Array.isArray(field) ? field[0] : field));
|
|
63
|
+
const outBindings = this.options.returning.map(field => {
|
|
64
|
+
const name = 'out_' + (Array.isArray(field) ? field[0] : field);
|
|
65
|
+
const type = Array.isArray(field) ? field[1] : 'string';
|
|
66
|
+
return [name, type];
|
|
67
|
+
});
|
|
68
|
+
markOutBindings(outBindings);
|
|
69
|
+
this.parts.push(`returning ${fields.join(', ')}`);
|
|
70
|
+
this.parts.push(`into ${into.join(', ')}`);
|
|
71
|
+
this.params.push(outBindings);
|
|
72
|
+
}
|
|
73
|
+
this.addLockClause();
|
|
74
|
+
if (!copy) {
|
|
75
|
+
return this.combineParts();
|
|
76
|
+
}
|
|
77
|
+
// multi insert with returning
|
|
78
|
+
const sql = this.parts.join(' ');
|
|
79
|
+
const blockLines = [];
|
|
80
|
+
const block2Lines = [];
|
|
81
|
+
const keys = Object.keys(copy[0]);
|
|
82
|
+
const last = this.params[this.params.length - 1];
|
|
83
|
+
/* v8 ignore next 3: defensive check — output bindings are always set by compile() */
|
|
84
|
+
if (!Array.isArray(last) || !('__outBindings' in last) || !last.__outBindings) {
|
|
85
|
+
throw new Error('Output bindings are required for multi insert with returning');
|
|
86
|
+
}
|
|
87
|
+
const outBindings = {};
|
|
88
|
+
markOutBindings(outBindings);
|
|
89
|
+
for (let i = 0; i < copy.length; i++) {
|
|
90
|
+
const params = [];
|
|
91
|
+
for (const key of keys) {
|
|
92
|
+
/* v8 ignore next 3: undefined value branch in multi-insert */
|
|
93
|
+
if (typeof copy[i][key] === 'undefined') {
|
|
94
|
+
params.push(this.platform.usesDefaultKeyword() ? raw('default') : null);
|
|
95
|
+
}
|
|
96
|
+
else {
|
|
97
|
+
params.push(copy[i][key]);
|
|
98
|
+
}
|
|
99
|
+
}
|
|
100
|
+
// we need to interpolate to allow proper escaping
|
|
101
|
+
const formatted = this.platform.formatQuery(sql, params).replaceAll(`'`, `''`);
|
|
102
|
+
/* v8 ignore next 3: returning field type branches */
|
|
103
|
+
const using = this.options.returning.map(field => {
|
|
104
|
+
const name = Array.isArray(field) ? field[0] : field;
|
|
105
|
+
const type = Array.isArray(field) ? field[1] : 'string';
|
|
106
|
+
outBindings[`out_${name}__${i}`] = {
|
|
107
|
+
dir: this.platform.mapToBindType('out'),
|
|
108
|
+
type: this.platform.mapToBindType(type),
|
|
109
|
+
};
|
|
110
|
+
return `out :out_${name}__${i}`;
|
|
111
|
+
});
|
|
112
|
+
blockLines.push(` execute immediate '${formatted}' using ${using.join(', ')};`);
|
|
113
|
+
block2Lines.push(` execute immediate '${sql}' using ${using.join(', ')};`);
|
|
114
|
+
}
|
|
115
|
+
const block = `begin\n${blockLines.join('\n')}\n end;`;
|
|
116
|
+
const block2 = `begin\n${block2Lines.join('\n')}\n end;`;
|
|
117
|
+
// save raw query without interpolation for logging,
|
|
118
|
+
Object.defineProperty(outBindings, '__rawQuery', {
|
|
119
|
+
value: block2,
|
|
120
|
+
writable: true,
|
|
121
|
+
configurable: true,
|
|
122
|
+
enumerable: false,
|
|
205
123
|
});
|
|
206
|
-
this.
|
|
207
|
-
|
|
208
|
-
/* v8 ignore stop */
|
|
209
|
-
}
|
|
210
|
-
}
|
|
211
|
-
compileSelect() {
|
|
212
|
-
const wrapCountSubquery = this.needsCountSubquery();
|
|
213
|
-
if (wrapCountSubquery) {
|
|
214
|
-
this.parts.push(`select count(*) as ${this.quote('count')} from (`);
|
|
215
|
-
}
|
|
216
|
-
this.parts.push('select');
|
|
217
|
-
this.addHintComment();
|
|
218
|
-
this.parts.push(`${this.getFields(wrapCountSubquery)} from ${this.getTableName()}`);
|
|
219
|
-
if (this.options.joins) {
|
|
220
|
-
for (const join of this.options.joins) {
|
|
221
|
-
this.parts.push(join.sql);
|
|
222
|
-
this.params.push(...join.params);
|
|
223
|
-
}
|
|
224
|
-
}
|
|
225
|
-
if (this.options.where?.sql.trim()) {
|
|
226
|
-
this.parts.push(`where ${this.options.where.sql}`);
|
|
227
|
-
this.params.push(...this.options.where.params);
|
|
124
|
+
this.options.data = copy;
|
|
125
|
+
return { sql: block, params: [outBindings] };
|
|
228
126
|
}
|
|
229
|
-
|
|
230
|
-
|
|
231
|
-
|
|
127
|
+
compileTruncate() {
|
|
128
|
+
super.compileTruncate();
|
|
129
|
+
this.parts.push('drop all storage cascade');
|
|
232
130
|
}
|
|
233
|
-
|
|
234
|
-
|
|
235
|
-
|
|
131
|
+
combineParts() {
|
|
132
|
+
let sql = this.parts.join(' ');
|
|
133
|
+
const last = this.params[this.params.length - 1];
|
|
134
|
+
if (this.options.wrap) {
|
|
135
|
+
const [a, b] = this.options.wrap;
|
|
136
|
+
sql = `${a}${sql}${b}`;
|
|
137
|
+
}
|
|
138
|
+
if (!(Array.isArray(last) && '__outBindings' in last && last.__outBindings)) {
|
|
139
|
+
return { sql, params: this.params };
|
|
140
|
+
}
|
|
141
|
+
const out = this.params.pop();
|
|
142
|
+
const outBindings = {};
|
|
143
|
+
markOutBindings(outBindings);
|
|
144
|
+
this.params.push(outBindings);
|
|
145
|
+
for (const item of out) {
|
|
146
|
+
outBindings[item[0]] = {
|
|
147
|
+
dir: this.platform.mapToBindType('out'),
|
|
148
|
+
type: this.platform.mapToBindType(item[1]),
|
|
149
|
+
};
|
|
150
|
+
}
|
|
151
|
+
return { sql, params: this.params };
|
|
236
152
|
}
|
|
237
|
-
|
|
238
|
-
|
|
239
|
-
|
|
240
|
-
|
|
241
|
-
|
|
242
|
-
|
|
243
|
-
|
|
244
|
-
|
|
245
|
-
|
|
246
|
-
|
|
247
|
-
|
|
248
|
-
|
|
153
|
+
compileUpsert() {
|
|
154
|
+
const clause = this.options.onConflict;
|
|
155
|
+
const dataAsArray = Utils.asArray(this.options.data);
|
|
156
|
+
const keys = Object.keys(dataAsArray[0]);
|
|
157
|
+
const parts = [];
|
|
158
|
+
for (const data of dataAsArray) {
|
|
159
|
+
for (const key of keys) {
|
|
160
|
+
this.params.push(data[key]);
|
|
161
|
+
}
|
|
162
|
+
parts.push(`select ${keys.map(k => `? as ${this.quote(k)}`).join(', ')} from dual`);
|
|
163
|
+
}
|
|
164
|
+
this.parts.push(`merge into ${this.getTableName()}`);
|
|
165
|
+
this.parts.push(`using (${parts.join(' union all ')}) tsource`);
|
|
166
|
+
/* v8 ignore next 4: RawQueryFragment conflict fields branch */
|
|
167
|
+
if (isRaw(clause.fields)) {
|
|
168
|
+
this.parts.push(clause.fields.sql);
|
|
169
|
+
this.params.push(...clause.fields.params);
|
|
170
|
+
}
|
|
171
|
+
else if (clause.fields.length > 0) {
|
|
172
|
+
const fields = clause.fields.map(field => {
|
|
173
|
+
const col = this.quote(field);
|
|
174
|
+
return `${this.getTableName()}.${col} = tsource.${col}`;
|
|
175
|
+
});
|
|
176
|
+
this.parts.push(`on (${fields.join(' and ')})`);
|
|
177
|
+
}
|
|
178
|
+
const sourceColumns = keys.map(field => `tsource.${this.quote(field)}`).join(', ');
|
|
179
|
+
const destinationColumns = keys.map(field => this.quote(field)).join(', ');
|
|
180
|
+
this.parts.push(`when not matched then insert (${destinationColumns}) values (${sourceColumns})`);
|
|
181
|
+
if (!clause.ignore) {
|
|
182
|
+
/* v8 ignore next: merge type branch */
|
|
183
|
+
if (!clause.merge || Array.isArray(clause.merge)) {
|
|
184
|
+
const mergeParts = (clause.merge || keys)
|
|
185
|
+
.filter(field => !Array.isArray(clause.fields) || !clause.fields.includes(field))
|
|
186
|
+
.filter((field) => keys.includes(field)) // only reference columns present in the source data
|
|
187
|
+
.map((column) => `${this.quote(column)} = tsource.${this.quote(column)}`);
|
|
188
|
+
/* v8 ignore next 10: empty mergeParts branch */
|
|
189
|
+
if (mergeParts.length > 0) {
|
|
190
|
+
this.parts.push('when matched');
|
|
191
|
+
if (clause.where) {
|
|
192
|
+
this.parts.push(`and ${clause.where.sql}`);
|
|
193
|
+
this.params.push(...clause.where.params);
|
|
194
|
+
}
|
|
195
|
+
this.parts.push('then update set');
|
|
196
|
+
this.parts.push(mergeParts.join(', '));
|
|
197
|
+
}
|
|
198
|
+
} /* v8 ignore start: object-form merge branch */
|
|
199
|
+
else if (typeof clause.merge === 'object') {
|
|
200
|
+
this.parts.push('when matched');
|
|
201
|
+
if (clause.where) {
|
|
202
|
+
this.parts.push(`and ${clause.where.sql}`);
|
|
203
|
+
this.params.push(...clause.where.params);
|
|
204
|
+
}
|
|
205
|
+
this.parts.push('then update set');
|
|
206
|
+
const parts = Object.entries(clause.merge).map(([key, value]) => {
|
|
207
|
+
this.params.push(value);
|
|
208
|
+
return `${this.getTableName()}.${this.quote(key)} = ?`;
|
|
209
|
+
});
|
|
210
|
+
this.parts.push(parts.join(', '));
|
|
211
|
+
}
|
|
212
|
+
/* v8 ignore stop */
|
|
213
|
+
}
|
|
249
214
|
}
|
|
250
|
-
|
|
251
|
-
|
|
252
|
-
|
|
215
|
+
compileSelect() {
|
|
216
|
+
const wrapCountSubquery = this.needsCountSubquery();
|
|
217
|
+
if (wrapCountSubquery) {
|
|
218
|
+
this.parts.push(`select count(*) as ${this.quote('count')} from (`);
|
|
219
|
+
}
|
|
220
|
+
this.parts.push('select');
|
|
221
|
+
this.addHintComment();
|
|
222
|
+
this.parts.push(`${this.getFields(wrapCountSubquery)} from ${this.getTableName()}`);
|
|
223
|
+
if (this.options.joins) {
|
|
224
|
+
for (const join of this.options.joins) {
|
|
225
|
+
this.parts.push(join.sql);
|
|
226
|
+
this.params.push(...join.params);
|
|
227
|
+
}
|
|
228
|
+
}
|
|
229
|
+
if (this.options.where?.sql.trim()) {
|
|
230
|
+
this.parts.push(`where ${this.options.where.sql}`);
|
|
231
|
+
this.params.push(...this.options.where.params);
|
|
232
|
+
}
|
|
233
|
+
if (this.options.groupBy) {
|
|
234
|
+
const fields = this.options.groupBy.map(field => this.quote(field));
|
|
235
|
+
this.parts.push(`group by ${fields.join(', ')}`);
|
|
236
|
+
}
|
|
237
|
+
if (this.options.having) {
|
|
238
|
+
this.parts.push(`having ${this.options.having.sql}`);
|
|
239
|
+
this.params.push(...this.options.having.params);
|
|
240
|
+
}
|
|
241
|
+
if (!wrapCountSubquery) {
|
|
242
|
+
if (this.options.orderBy) {
|
|
243
|
+
this.parts.push(`order by ${this.options.orderBy}`);
|
|
244
|
+
}
|
|
245
|
+
if (this.options.offset != null) {
|
|
246
|
+
this.parts.push(`offset ? rows`);
|
|
247
|
+
this.params.push(this.options.offset);
|
|
248
|
+
}
|
|
249
|
+
if (this.options.limit != null) {
|
|
250
|
+
this.parts.push(`fetch next ? rows only`);
|
|
251
|
+
this.params.push(this.options.limit);
|
|
252
|
+
}
|
|
253
|
+
}
|
|
254
|
+
if (wrapCountSubquery) {
|
|
255
|
+
const asKeyword = this.platform.usesAsKeyword() ? ' as ' : ' ';
|
|
256
|
+
this.parts.push(`)${asKeyword}${this.quote('dcnt')}`);
|
|
257
|
+
}
|
|
253
258
|
}
|
|
254
|
-
}
|
|
255
259
|
}
|