@spinajs/orm-sql 2.0.480 → 2.0.482
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/README.md +61 -3
- package/lib/cjs/compilers.d.ts +67 -3
- package/lib/cjs/compilers.d.ts.map +1 -1
- package/lib/cjs/compilers.js +225 -105
- package/lib/cjs/compilers.js.map +1 -1
- package/lib/cjs/converters.d.ts.map +1 -1
- package/lib/cjs/converters.js +1 -4
- package/lib/cjs/converters.js.map +1 -1
- package/lib/cjs/index.d.ts.map +1 -1
- package/lib/cjs/index.js +10 -2
- package/lib/cjs/index.js.map +1 -1
- package/lib/cjs/statements.d.ts.map +1 -1
- package/lib/cjs/statements.js +84 -24
- package/lib/cjs/statements.js.map +1 -1
- package/lib/mjs/compilers.d.ts +67 -3
- package/lib/mjs/compilers.d.ts.map +1 -1
- package/lib/mjs/compilers.js +224 -106
- package/lib/mjs/compilers.js.map +1 -1
- package/lib/mjs/converters.d.ts.map +1 -1
- package/lib/mjs/converters.js +1 -4
- package/lib/mjs/converters.js.map +1 -1
- package/lib/mjs/index.d.ts.map +1 -1
- package/lib/mjs/index.js +10 -2
- package/lib/mjs/index.js.map +1 -1
- package/lib/mjs/statements.d.ts.map +1 -1
- package/lib/mjs/statements.js +85 -25
- package/lib/mjs/statements.js.map +1 -1
- package/lib/tsconfig.cjs.tsbuildinfo +1 -1
- package/lib/tsconfig.mjs.tsbuildinfo +1 -1
- package/package.json +13 -14
package/lib/cjs/compilers.js
CHANGED
|
@@ -13,6 +13,8 @@ var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
|
13
13
|
};
|
|
14
14
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
15
15
|
exports.SqlRawSchemaQueryCompiler = exports.SqlDropEventQueryCompiler = exports.SqlEventQueryCompiler = exports.SqlAlterColumnQueryCompiler = exports.SqlColumnQueryCompiler = exports.SqlTableQueryCompiler = exports.SqlTableHistoryQueryCompiler = exports.SqlTruncateTableQueryCompiler = exports.SqlTableCloneQueryCompiler = exports.SqlAlterTableQueryCompiler = exports.SqlDropViewQueryCompiler = exports.SqlDropTableQueryCompiler = exports.SqlInsertQueryCompiler = exports.SqlIndexQueryCompiler = exports.SqlOnDuplicateQueryCompiler = exports.SqlDeleteQueryCompiler = exports.SqlUpdateQueryCompiler = exports.SqlSelectQueryCompiler = exports.SqlJoinCompiler = exports.SqlHavingCompiler = exports.SqlWhereCompiler = exports.SqlColumnsCompiler = exports.SqlGroupByCompiler = exports.SqlLimitQueryCompiler = exports.SqlForeignKeyQueryCompiler = exports.SqlWithRecursiveCompiler = exports.SqlOrderByQueryCompiler = exports.SqlQueryCompiler = exports.SqlTableAliasCompiler = void 0;
|
|
16
|
+
exports.escapeIdentifier = escapeIdentifier;
|
|
17
|
+
exports.escapeStringLiteral = escapeStringLiteral;
|
|
16
18
|
/* eslint-disable @typescript-eslint/no-unsafe-call */
|
|
17
19
|
/* eslint-disable @typescript-eslint/no-unsafe-member-access */
|
|
18
20
|
/* eslint-disable @typescript-eslint/no-empty-interface */
|
|
@@ -22,15 +24,41 @@ const orm_1 = require("@spinajs/orm");
|
|
|
22
24
|
const typescript_mix_1 = require("typescript-mix");
|
|
23
25
|
const di_1 = require("@spinajs/di");
|
|
24
26
|
const lodash_1 = __importDefault(require("lodash"));
|
|
27
|
+
/**
|
|
28
|
+
* Central identifier escaping for the MySQL-flavoured dialect.
|
|
29
|
+
*
|
|
30
|
+
* Wraps a table/column/alias/schema name in backticks and escapes any embedded
|
|
31
|
+
* backtick by doubling it (the MySQL rule). For a normal identifier (no special
|
|
32
|
+
* characters) the output is byte-identical to the previous raw interpolation
|
|
33
|
+
* (`` `${name}` ``), so existing generated SQL is unchanged; only names that
|
|
34
|
+
* actually contain a backtick produce different — and now safe — output.
|
|
35
|
+
*
|
|
36
|
+
* Dialects that quote differently (e.g. `[name]` with `]`-doubling) override
|
|
37
|
+
* this by shadowing the relevant compiler/statement, the same way
|
|
38
|
+
* {@link SqlTableAliasCompiler} is already overridden per driver.
|
|
39
|
+
*/
|
|
40
|
+
function escapeIdentifier(name) {
|
|
41
|
+
return '`' + String(name).replace(/`/g, '``') + '`';
|
|
42
|
+
}
|
|
43
|
+
/**
|
|
44
|
+
* Escapes a DDL string *literal* (SET/ENUM member, COMMENT, CHARACTER SET,
|
|
45
|
+
* COLLATE, string DEFAULT). These are single-quoted string literals, NOT
|
|
46
|
+
* identifiers, so the correct escaping is doubling embedded single quotes.
|
|
47
|
+
* Returns the value WITHOUT the surrounding quotes so callers keep their exact
|
|
48
|
+
* quoting; for a value with no quote the output is byte-identical.
|
|
49
|
+
*/
|
|
50
|
+
function escapeStringLiteral(value) {
|
|
51
|
+
return String(value).replace(/'/g, "''");
|
|
52
|
+
}
|
|
25
53
|
let SqlTableAliasCompiler = class SqlTableAliasCompiler {
|
|
26
54
|
compile(builder, tbl) {
|
|
27
55
|
let table = '';
|
|
28
56
|
if (builder.Database) {
|
|
29
|
-
table +=
|
|
57
|
+
table += `${escapeIdentifier(builder.Database)}.`;
|
|
30
58
|
}
|
|
31
|
-
table +=
|
|
59
|
+
table += escapeIdentifier(tbl ? tbl : builder.Table);
|
|
32
60
|
if (builder.TableAlias) {
|
|
33
|
-
table += ` as
|
|
61
|
+
table += ` as ${escapeIdentifier(builder.TableAlias)}`;
|
|
34
62
|
}
|
|
35
63
|
return table;
|
|
36
64
|
}
|
|
@@ -44,7 +72,7 @@ let SqlQueryCompiler = class SqlQueryCompiler extends orm_1.SelectQueryCompiler
|
|
|
44
72
|
super();
|
|
45
73
|
this._builder = _builder;
|
|
46
74
|
this._container = _container;
|
|
47
|
-
if (_builder === null
|
|
75
|
+
if (_builder === null || _builder === undefined) {
|
|
48
76
|
throw new exceptions_1.InvalidArgument('builder cannot be null or undefined');
|
|
49
77
|
}
|
|
50
78
|
}
|
|
@@ -72,11 +100,11 @@ let SqlOrderByQueryCompiler = class SqlOrderByQueryCompiler extends orm_1.OrderB
|
|
|
72
100
|
this._builder = builder;
|
|
73
101
|
}
|
|
74
102
|
compile() {
|
|
75
|
-
const
|
|
103
|
+
const sorts = this._builder.getSorts();
|
|
76
104
|
let stmt = '';
|
|
77
105
|
const bindings = [];
|
|
78
|
-
if (
|
|
79
|
-
stmt = ` ORDER BY
|
|
106
|
+
if (sorts.length > 0) {
|
|
107
|
+
stmt = ` ORDER BY ${sorts.map((s) => `${escapeIdentifier(s.column)} ${s.order}`).join(', ')}`;
|
|
80
108
|
}
|
|
81
109
|
return {
|
|
82
110
|
bindings,
|
|
@@ -117,7 +145,7 @@ let SqlForeignKeyQueryCompiler = class SqlForeignKeyQueryCompiler {
|
|
|
117
145
|
}
|
|
118
146
|
}
|
|
119
147
|
compile() {
|
|
120
|
-
const exprr = `FOREIGN KEY (${this._builder.ForeignKeyField}) REFERENCES ${this._builder.Table}(${this._builder.PrimaryKey}) ON DELETE ${this._builder.OnDeleteAction} ON UPDATE ${this._builder.OnUpdateAction}`;
|
|
148
|
+
const exprr = `FOREIGN KEY (${escapeIdentifier(this._builder.ForeignKeyField)}) REFERENCES ${escapeIdentifier(this._builder.Table)}(${escapeIdentifier(this._builder.PrimaryKey)}) ON DELETE ${this._builder.OnDeleteAction} ON UPDATE ${this._builder.OnUpdateAction}`;
|
|
121
149
|
return {
|
|
122
150
|
bindings: [],
|
|
123
151
|
expression: exprr,
|
|
@@ -200,23 +228,24 @@ exports.SqlColumnsCompiler = SqlColumnsCompiler = __decorate([
|
|
|
200
228
|
], SqlColumnsCompiler);
|
|
201
229
|
let SqlWhereCompiler = class SqlWhereCompiler {
|
|
202
230
|
where(builder) {
|
|
203
|
-
const where = [];
|
|
204
231
|
const bindings = [];
|
|
205
|
-
|
|
206
|
-
builder
|
|
207
|
-
|
|
208
|
-
|
|
209
|
-
|
|
210
|
-
|
|
211
|
-
|
|
212
|
-
|
|
213
|
-
|
|
214
|
-
|
|
215
|
-
|
|
216
|
-
|
|
232
|
+
// Lazy statements must be built FIRST: their build() may have side effects
|
|
233
|
+
// that append further statements to the builder (e.g. a correlated EXISTS
|
|
234
|
+
// sub-query registers its correlation predicate lazily). Building them now and
|
|
235
|
+
// reusing the result guarantees the side effect runs exactly once, and lets the
|
|
236
|
+
// non-lazy pass below pick up any statements the lazy build appended. The lazy
|
|
237
|
+
// results are then emitted after the non-lazy ones (preserving legacy ordering).
|
|
238
|
+
const lazyEntries = builder.Statements.filter((x) => x instanceof orm_1.LazyQueryStatement).map((stmt) => ({
|
|
239
|
+
boolean: stmt.Boolean,
|
|
240
|
+
result: stmt.build(),
|
|
241
|
+
}));
|
|
242
|
+
const nonLazyEntries = builder.Statements
|
|
243
|
+
.filter((x) => !x.IsAggregate)
|
|
244
|
+
.filter((x) => !(x instanceof orm_1.LazyQueryStatement))
|
|
245
|
+
.map((stmt) => ({ boolean: stmt.Boolean, result: stmt.build() }));
|
|
217
246
|
return {
|
|
218
247
|
bindings,
|
|
219
|
-
expression:
|
|
248
|
+
expression: joinBuiltStatements(nonLazyEntries.concat(lazyEntries), bindings),
|
|
220
249
|
};
|
|
221
250
|
}
|
|
222
251
|
};
|
|
@@ -224,23 +253,41 @@ exports.SqlWhereCompiler = SqlWhereCompiler;
|
|
|
224
253
|
exports.SqlWhereCompiler = SqlWhereCompiler = __decorate([
|
|
225
254
|
(0, di_1.NewInstance)()
|
|
226
255
|
], SqlWhereCompiler);
|
|
256
|
+
/**
|
|
257
|
+
* Joins a list of already-built where/having statements into a single SQL
|
|
258
|
+
* expression, prefixing every statement after the first with its OWN boolean
|
|
259
|
+
* connector. This yields correct mixed grouping such as
|
|
260
|
+
* `a AND b OR c` for `where(a).where(b).orWhere(c)`, instead of applying a single
|
|
261
|
+
* builder-level connector uniformly. Bindings are collected in statement order.
|
|
262
|
+
*/
|
|
263
|
+
function joinBuiltStatements(statements, bindings) {
|
|
264
|
+
const parts = [];
|
|
265
|
+
statements.forEach(({ boolean, result }) => {
|
|
266
|
+
if (Array.isArray(result.Bindings)) {
|
|
267
|
+
bindings.push(...result.Bindings);
|
|
268
|
+
}
|
|
269
|
+
// A single statement always builds to one fragment; guard multi-fragment
|
|
270
|
+
// statements by joining them with AND (they carry no per-fragment connector).
|
|
271
|
+
const fragment = result.Statements.join(' AND ');
|
|
272
|
+
if (fragment === '') {
|
|
273
|
+
return;
|
|
274
|
+
}
|
|
275
|
+
if (parts.length === 0) {
|
|
276
|
+
parts.push(fragment);
|
|
277
|
+
}
|
|
278
|
+
else {
|
|
279
|
+
parts.push(`${(boolean ?? orm_1.WhereBoolean.AND).toUpperCase()} ${fragment}`);
|
|
280
|
+
}
|
|
281
|
+
});
|
|
282
|
+
return parts.join(' ');
|
|
283
|
+
}
|
|
227
284
|
let SqlHavingCompiler = class SqlHavingCompiler {
|
|
228
285
|
having(builder) {
|
|
229
|
-
const where = [];
|
|
230
286
|
const bindings = [];
|
|
231
|
-
builder.Statements.filter((x) => x.IsAggregate)
|
|
232
|
-
.map((x) => {
|
|
233
|
-
return x.build();
|
|
234
|
-
})
|
|
235
|
-
.forEach((r) => {
|
|
236
|
-
where.push(...r.Statements);
|
|
237
|
-
if (Array.isArray(r.Bindings)) {
|
|
238
|
-
bindings.push(...r.Bindings);
|
|
239
|
-
}
|
|
240
|
-
});
|
|
287
|
+
const aggregates = builder.Statements.filter((x) => x.IsAggregate).map((stmt) => ({ boolean: stmt.Boolean, result: stmt.build() }));
|
|
241
288
|
return {
|
|
242
289
|
bindings,
|
|
243
|
-
expression:
|
|
290
|
+
expression: joinBuiltStatements(aggregates, bindings),
|
|
244
291
|
};
|
|
245
292
|
}
|
|
246
293
|
};
|
|
@@ -348,7 +395,7 @@ let SqlUpdateQueryCompiler = class SqlUpdateQueryCompiler extends SqlQueryCompil
|
|
|
348
395
|
const exprr = [];
|
|
349
396
|
for (const prop of Object.keys(this._builder.Value)) {
|
|
350
397
|
const v = this._builder.Value[`${prop}`];
|
|
351
|
-
exprr.push(
|
|
398
|
+
exprr.push(`${escapeIdentifier(prop)} = ?`);
|
|
352
399
|
bindings = bindings.concat(this.tryConvertValue(v));
|
|
353
400
|
}
|
|
354
401
|
return {
|
|
@@ -415,22 +462,22 @@ let SqlOnDuplicateQueryCompiler = class SqlOnDuplicateQueryCompiler {
|
|
|
415
462
|
.getColumnsToUpdate()
|
|
416
463
|
.map((c) => {
|
|
417
464
|
if (lodash_1.default.isString(c)) {
|
|
418
|
-
|
|
465
|
+
// Reference the row being inserted via VALUES(col) instead of
|
|
466
|
+
// re-binding one specific row's value. Binding `parent.Values[0]`
|
|
467
|
+
// applied the FIRST row's values to every conflicting row in a
|
|
468
|
+
// multi row upsert.
|
|
469
|
+
return `${escapeIdentifier(c)} = VALUES(${escapeIdentifier(c)})`;
|
|
419
470
|
}
|
|
420
471
|
else {
|
|
421
472
|
return c.Query;
|
|
422
473
|
}
|
|
423
474
|
})
|
|
424
475
|
.join(',');
|
|
425
|
-
|
|
426
|
-
|
|
427
|
-
|
|
428
|
-
|
|
429
|
-
|
|
430
|
-
}
|
|
431
|
-
else {
|
|
432
|
-
return c.Bindings;
|
|
433
|
-
}
|
|
476
|
+
// Only RawQuery update columns contribute bindings - VALUES(col) needs
|
|
477
|
+
// none. flatMap keeps raw bindings flat; returning the array itself
|
|
478
|
+
// nested them and shifted every following placeholder.
|
|
479
|
+
const bindings = lodash_1.default.flatMap(this._builder.getColumnsToUpdate(), (c) => {
|
|
480
|
+
return lodash_1.default.isString(c) ? [] : c.Bindings ?? [];
|
|
434
481
|
});
|
|
435
482
|
return {
|
|
436
483
|
bindings,
|
|
@@ -451,7 +498,7 @@ let SqlIndexQueryCompiler = class SqlIndexQueryCompiler extends orm_1.IndexQuery
|
|
|
451
498
|
compile() {
|
|
452
499
|
return {
|
|
453
500
|
bindings: [],
|
|
454
|
-
expression: `CREATE ${this._builder.Unique ? 'UNIQUE ' : ''}INDEX
|
|
501
|
+
expression: `CREATE ${this._builder.Unique ? 'UNIQUE ' : ''}INDEX ${escapeIdentifier(this._builder.Name)} ON ${escapeIdentifier(this._builder.Table)} (${this._builder.Columns.map((c) => escapeIdentifier(c)).join(',')});`,
|
|
455
502
|
};
|
|
456
503
|
}
|
|
457
504
|
};
|
|
@@ -483,31 +530,54 @@ let SqlInsertQueryCompiler = class SqlInsertQueryCompiler extends SqlQueryCompil
|
|
|
483
530
|
expression: '',
|
|
484
531
|
};
|
|
485
532
|
}
|
|
533
|
+
/**
|
|
534
|
+
* Indices of the columns that take part in this INSERT.
|
|
535
|
+
*
|
|
536
|
+
* An auto increment primary key is omitted only when NO row supplies a value
|
|
537
|
+
* for it. If at least one row supplies one the column stays, and the rows
|
|
538
|
+
* that don't emit NULL so the engine assigns the value.
|
|
539
|
+
*
|
|
540
|
+
* Both {@link columns} and {@link values} MUST derive their shape from this
|
|
541
|
+
* single decision - deciding per-row in one place and per-batch in the other
|
|
542
|
+
* produced value tuples whose arity did not match the column list.
|
|
543
|
+
*/
|
|
544
|
+
keptColumnIndices() {
|
|
545
|
+
return this._builder
|
|
546
|
+
.getColumns()
|
|
547
|
+
.map((c, i) => ({ c, i }))
|
|
548
|
+
.filter(({ c, i }) => {
|
|
549
|
+
const descriptor = c.Descriptor;
|
|
550
|
+
if (descriptor && descriptor.AutoIncrement && descriptor.PrimaryKey) {
|
|
551
|
+
return this._builder.Values.some((x) => x[i] !== undefined && x[i] !== null);
|
|
552
|
+
}
|
|
553
|
+
return true;
|
|
554
|
+
})
|
|
555
|
+
.map(({ i }) => i);
|
|
556
|
+
}
|
|
486
557
|
values() {
|
|
487
558
|
if (this._builder.Values.length === 0) {
|
|
488
559
|
throw new exceptions_1.InvalidArgument('values count invalid');
|
|
489
560
|
}
|
|
561
|
+
const kept = this.keptColumnIndices();
|
|
490
562
|
const bindings = [];
|
|
491
563
|
let data = 'VALUES ';
|
|
492
564
|
data += this._builder.Values.map((val) => {
|
|
493
|
-
const toInsert =
|
|
494
|
-
|
|
565
|
+
const toInsert = kept.map((i) => {
|
|
566
|
+
// eslint-disable-next-line security/detect-object-injection
|
|
567
|
+
const v = val[i];
|
|
495
568
|
// eslint-disable-next-line security/detect-object-injection
|
|
496
569
|
const descriptor = this._builder.getColumns()[i].Descriptor;
|
|
497
570
|
if (descriptor) {
|
|
498
571
|
if (!descriptor.Nullable && (v === null || v === undefined) && !descriptor.AutoIncrement) {
|
|
499
572
|
throw new exceptions_1.InvalidArgument(`value column ${descriptor.Name} cannot be null`);
|
|
500
573
|
}
|
|
501
|
-
|
|
502
|
-
|
|
503
|
-
|
|
504
|
-
|
|
505
|
-
return
|
|
574
|
+
// Auto increment PK this row does not supply. NULL (not DEFAULT) lets
|
|
575
|
+
// the engine assign it and is portable - sqlite does not accept the
|
|
576
|
+
// DEFAULT keyword inside a VALUES tuple.
|
|
577
|
+
if (descriptor.AutoIncrement && descriptor.PrimaryKey && (v === undefined || v === null)) {
|
|
578
|
+
return 'NULL';
|
|
506
579
|
}
|
|
507
580
|
}
|
|
508
|
-
return true;
|
|
509
|
-
})
|
|
510
|
-
.map((v) => {
|
|
511
581
|
if (v === undefined) {
|
|
512
582
|
return 'DEFAULT';
|
|
513
583
|
}
|
|
@@ -525,23 +595,15 @@ let SqlInsertQueryCompiler = class SqlInsertQueryCompiler extends SqlQueryCompil
|
|
|
525
595
|
};
|
|
526
596
|
}
|
|
527
597
|
columns() {
|
|
528
|
-
const columns = this.
|
|
529
|
-
.
|
|
530
|
-
|
|
531
|
-
|
|
532
|
-
if (descriptor && descriptor.AutoIncrement && descriptor.PrimaryKey) {
|
|
533
|
-
if (this._builder.Values.every((x) => x[i] !== undefined && x[i] !== null)) {
|
|
534
|
-
return true;
|
|
535
|
-
}
|
|
536
|
-
return false;
|
|
537
|
-
}
|
|
538
|
-
return true;
|
|
539
|
-
})
|
|
540
|
-
.map((c) => {
|
|
541
|
-
return c.Column;
|
|
598
|
+
const columns = this.keptColumnIndices()
|
|
599
|
+
.map((i) => {
|
|
600
|
+
// eslint-disable-next-line security/detect-object-injection
|
|
601
|
+
return this._builder.getColumns()[i].Column;
|
|
542
602
|
})
|
|
543
603
|
.map((c) => {
|
|
544
|
-
|
|
604
|
+
// RawQuery columns carry raw SQL - preserve the existing (unescaped)
|
|
605
|
+
// backtick wrapping. String columns go through the identifier escaper.
|
|
606
|
+
return c instanceof orm_1.RawQuery ? `\`${c.Query}\`` : escapeIdentifier(c);
|
|
545
607
|
});
|
|
546
608
|
if (columns.length === 0) {
|
|
547
609
|
throw new exceptions_1.InvalidArgument('invalid column count');
|
|
@@ -629,10 +691,22 @@ let SqlAlterTableQueryCompiler = class SqlAlterTableQueryCompiler extends orm_1.
|
|
|
629
691
|
}
|
|
630
692
|
if (this.builder.Columns.length !== 0) {
|
|
631
693
|
_outputs = _outputs.concat(this.builder.Columns.map((c) => {
|
|
632
|
-
|
|
694
|
+
// keep the compiler instance around - it carries the dialect's answer to
|
|
695
|
+
// "is my expression already a complete statement ?" (see IsStandaloneStatement)
|
|
696
|
+
const compiler = this.container.resolve(orm_1.AlterColumnQueryCompiler, [c]);
|
|
697
|
+
return { compiler, output: compiler.compile() };
|
|
698
|
+
})
|
|
699
|
+
// a driver may legitimately skip an alteration by compiling it to nothing.
|
|
700
|
+
// emitting it anyway would yield a dangling `ALTER TABLE \`x\`` - invalid SQL.
|
|
701
|
+
.filter(({ output }) => (output.expression ?? '').trim().length !== 0)
|
|
702
|
+
.map(({ compiler, output }) => {
|
|
703
|
+
// some dialects cannot express an alteration as a suffix of `ALTER TABLE x`
|
|
704
|
+
// eg. MSSQL renames a column with `EXEC sp_rename '[t].[old]', 'new', 'COLUMN'`,
|
|
705
|
+
// which is a complete statement and must be emitted verbatim.
|
|
706
|
+
const standalone = compiler.IsStandaloneStatement === true;
|
|
633
707
|
return {
|
|
634
|
-
bindings:
|
|
635
|
-
expression: `${_table} ${
|
|
708
|
+
bindings: output.bindings,
|
|
709
|
+
expression: standalone ? output.expression : `${_table} ${output.expression}`,
|
|
636
710
|
};
|
|
637
711
|
}));
|
|
638
712
|
}
|
|
@@ -669,7 +743,7 @@ let SqlTableCloneQueryCompiler = class SqlTableCloneQueryCompiler extends orm_1.
|
|
|
669
743
|
// if no filter is provided, copy all the data
|
|
670
744
|
expression: `SELECT * FROM ${_tblName}`,
|
|
671
745
|
};
|
|
672
|
-
const fExprr = `INSERT INTO
|
|
746
|
+
const fExprr = `INSERT INTO ${escapeIdentifier(this.builder.Table)} ${fOut.expression}`;
|
|
673
747
|
return [
|
|
674
748
|
out1,
|
|
675
749
|
{
|
|
@@ -851,7 +925,7 @@ let SqlTableQueryCompiler = class SqlTableQueryCompiler extends orm_1.TableQuery
|
|
|
851
925
|
}
|
|
852
926
|
_primaryKeys() {
|
|
853
927
|
const _keys = this.builder.Columns.filter((x) => x.PrimaryKey)
|
|
854
|
-
.map((c) =>
|
|
928
|
+
.map((c) => escapeIdentifier(c.Name))
|
|
855
929
|
.join(',');
|
|
856
930
|
if (!lodash_1.default.isEmpty(_keys)) {
|
|
857
931
|
return `PRIMARY KEY (${_keys})`;
|
|
@@ -872,7 +946,7 @@ let SqlColumnQueryCompiler = class SqlColumnQueryCompiler {
|
|
|
872
946
|
constructor(builder) {
|
|
873
947
|
this.builder = builder;
|
|
874
948
|
this._statementsMappings = {
|
|
875
|
-
set: (builder) => `SET(${builder.Args[0].map((a) => `'${a}
|
|
949
|
+
set: (builder) => `SET(${builder.Args[0].map((a) => `'${escapeStringLiteral(a)}'`).join(',')})`,
|
|
876
950
|
string: (builder) => `VARCHAR(${builder.Args[0] ? builder.Args[0] : 255})`,
|
|
877
951
|
boolean: () => `BOOLEAN`,
|
|
878
952
|
float: (builder) => {
|
|
@@ -882,8 +956,8 @@ let SqlColumnQueryCompiler = class SqlColumnQueryCompiler {
|
|
|
882
956
|
},
|
|
883
957
|
double: (builder) => this._statementsMappings.float(builder),
|
|
884
958
|
decimal: (builder) => this._statementsMappings.float(builder),
|
|
885
|
-
enum: (builder) => `${builder.Type.toUpperCase()}(${builder.Args[0].map((a) => `'${a}'`).join(',')})`,
|
|
886
|
-
binary: (builder) => `BINARY(${builder.Args[0] ?? 255}`,
|
|
959
|
+
enum: (builder) => `${builder.Type.toUpperCase()}(${builder.Args[0].map((a) => `'${escapeStringLiteral(a)}'`).join(',')})`,
|
|
960
|
+
binary: (builder) => `BINARY(${builder.Args[0] ?? 255})`,
|
|
887
961
|
smallint: (builder) => builder.Type.toUpperCase(),
|
|
888
962
|
tinyint: (builder) => builder.Type.toUpperCase(),
|
|
889
963
|
mediumint: (builder) => builder.Type.toUpperCase(),
|
|
@@ -904,12 +978,12 @@ let SqlColumnQueryCompiler = class SqlColumnQueryCompiler {
|
|
|
904
978
|
longblob: (builder) => builder.Type.toUpperCase(),
|
|
905
979
|
// COLUMN ADDITIONA PROPS
|
|
906
980
|
unsigned: () => 'UNSIGNED',
|
|
907
|
-
charset: (builder) => `CHARACTER SET '${builder.Charset}'`,
|
|
908
|
-
collation: (builder) => `COLLATE '${builder.Collation}'`,
|
|
981
|
+
charset: (builder) => `CHARACTER SET '${escapeStringLiteral(builder.Charset)}'`,
|
|
982
|
+
collation: (builder) => `COLLATE '${escapeStringLiteral(builder.Collation)}'`,
|
|
909
983
|
notnull: () => `NOT NULL`,
|
|
910
984
|
default: () => this._defaultCompiler(),
|
|
911
985
|
autoincrement: () => `AUTO_INCREMENT`,
|
|
912
|
-
comment: (builder) => `COMMENT '${builder.Comment}'`,
|
|
986
|
+
comment: (builder) => `COMMENT '${escapeStringLiteral(builder.Comment)}'`,
|
|
913
987
|
};
|
|
914
988
|
if (!builder) {
|
|
915
989
|
throw new Error('column query builder cannot be null');
|
|
@@ -917,7 +991,7 @@ let SqlColumnQueryCompiler = class SqlColumnQueryCompiler {
|
|
|
917
991
|
}
|
|
918
992
|
compile() {
|
|
919
993
|
const _stmt = [];
|
|
920
|
-
_stmt.push(
|
|
994
|
+
_stmt.push(escapeIdentifier(this.builder.Name));
|
|
921
995
|
_stmt.push(this._statementsMappings[this.builder.Type](this.builder));
|
|
922
996
|
if (this.builder.Unsigned) {
|
|
923
997
|
_stmt.push(this._statementsMappings.unsigned());
|
|
@@ -954,7 +1028,7 @@ let SqlColumnQueryCompiler = class SqlColumnQueryCompiler {
|
|
|
954
1028
|
return _stmt;
|
|
955
1029
|
}
|
|
956
1030
|
if (lodash_1.default.isString(this.builder.Default.Value)) {
|
|
957
|
-
_stmt = `DEFAULT '${this.builder.Default.Value.trim()}'`;
|
|
1031
|
+
_stmt = `DEFAULT '${escapeStringLiteral(this.builder.Default.Value.trim())}'`;
|
|
958
1032
|
}
|
|
959
1033
|
else if (lodash_1.default.isNumber(this.builder.Default.Value)) {
|
|
960
1034
|
_stmt = `DEFAULT ${this.builder.Default.Value}`;
|
|
@@ -970,39 +1044,85 @@ exports.SqlColumnQueryCompiler = SqlColumnQueryCompiler = __decorate([
|
|
|
970
1044
|
(0, di_1.NewInstance)(),
|
|
971
1045
|
__metadata("design:paramtypes", [orm_1.ColumnQueryBuilder])
|
|
972
1046
|
], SqlColumnQueryCompiler);
|
|
973
|
-
let SqlAlterColumnQueryCompiler = class SqlAlterColumnQueryCompiler extends
|
|
974
|
-
constructor(builder) {
|
|
975
|
-
super(
|
|
1047
|
+
let SqlAlterColumnQueryCompiler = class SqlAlterColumnQueryCompiler extends orm_1.AlterColumnQueryCompiler {
|
|
1048
|
+
constructor(container, builder) {
|
|
1049
|
+
super();
|
|
1050
|
+
this.container = container;
|
|
1051
|
+
this.builder = builder;
|
|
1052
|
+
if (!builder) {
|
|
1053
|
+
throw new exceptions_1.InvalidArgument('builder cannot be null or undefined');
|
|
1054
|
+
}
|
|
1055
|
+
}
|
|
1056
|
+
/**
|
|
1057
|
+
* Renders the column body using the DRIVER's own column compiler, resolved
|
|
1058
|
+
* from the container (late binding) - exactly like the CREATE TABLE path does.
|
|
1059
|
+
* Previously this was `super.compile()`, which statically bound every driver
|
|
1060
|
+
* to orm-sql's MySQL dialect.
|
|
1061
|
+
*/
|
|
1062
|
+
_columnDefinition() {
|
|
1063
|
+
return this.container.resolve(orm_1.ColumnQueryCompiler, [this.builder]).compile();
|
|
1064
|
+
}
|
|
1065
|
+
/**
|
|
1066
|
+
* Whether the expression produced by `compile()` is already a complete, standalone
|
|
1067
|
+
* statement. When true, SqlAlterTableQueryCompiler emits it verbatim instead of
|
|
1068
|
+
* prefixing it with `ALTER TABLE <table> `.
|
|
1069
|
+
*
|
|
1070
|
+
* Needed by dialects whose alteration is not expressible as a suffix of ALTER TABLE,
|
|
1071
|
+
* eg. MSSQL's `EXEC sp_rename '[t].[old]', 'new', 'COLUMN'`.
|
|
1072
|
+
*
|
|
1073
|
+
* It is read AFTER `compile()`, so a subclass may decide per `builder.AlterType`.
|
|
1074
|
+
* Defaults to false - MySQL (this class) always emits a suffix.
|
|
1075
|
+
*/
|
|
1076
|
+
get IsStandaloneStatement() {
|
|
1077
|
+
return false;
|
|
1078
|
+
}
|
|
1079
|
+
/**
|
|
1080
|
+
* Dialect hooks. Returning `null` means "emit no statement at all" - the
|
|
1081
|
+
* parent AlterTableQueryCompiler filters such columns out.
|
|
1082
|
+
*/
|
|
1083
|
+
_add(definition) {
|
|
1084
|
+
// escapeIdentifier, not raw backticks: an identifier containing a backtick would
|
|
1085
|
+
// otherwise terminate the quote and splice arbitrary SQL into the DDL ( A3 ).
|
|
1086
|
+
return `ADD ${definition} ${this.builder.AfterColumn ? `AFTER ${escapeIdentifier(this.builder.AfterColumn)}` : ''}`;
|
|
1087
|
+
}
|
|
1088
|
+
_modify(definition) {
|
|
1089
|
+
return `MODIFY ${definition}`;
|
|
1090
|
+
}
|
|
1091
|
+
_rename() {
|
|
1092
|
+
return `RENAME COLUMN ${escapeIdentifier(this.builder.OldName)} TO ${escapeIdentifier(this.builder.Name)}`;
|
|
976
1093
|
}
|
|
977
1094
|
compile() {
|
|
978
|
-
|
|
979
|
-
if (builder.AlterType === orm_1.ColumnAlterationType.Rename) {
|
|
980
|
-
const bld = this.builder;
|
|
1095
|
+
// rename never renders a column body, so it must not resolve one
|
|
1096
|
+
if (this.builder.AlterType === orm_1.ColumnAlterationType.Rename) {
|
|
981
1097
|
return {
|
|
982
1098
|
bindings: [],
|
|
983
|
-
expression:
|
|
984
|
-
};
|
|
985
|
-
}
|
|
986
|
-
const cDefinition = super.compile();
|
|
987
|
-
if (builder.AlterType === orm_1.ColumnAlterationType.Add) {
|
|
988
|
-
return {
|
|
989
|
-
bindings: cDefinition.bindings,
|
|
990
|
-
expression: `ADD ${cDefinition.expression} ${builder.AfterColumn ? `AFTER \`${builder.AfterColumn}\`` : ''}`,
|
|
1099
|
+
expression: this._rename() ?? '',
|
|
991
1100
|
};
|
|
992
1101
|
}
|
|
993
|
-
|
|
994
|
-
|
|
995
|
-
|
|
996
|
-
|
|
997
|
-
|
|
1102
|
+
const cDefinition = this._columnDefinition();
|
|
1103
|
+
let expression;
|
|
1104
|
+
switch (this.builder.AlterType) {
|
|
1105
|
+
case orm_1.ColumnAlterationType.Add:
|
|
1106
|
+
expression = this._add(cDefinition.expression);
|
|
1107
|
+
break;
|
|
1108
|
+
case orm_1.ColumnAlterationType.Modify:
|
|
1109
|
+
expression = this._modify(cDefinition.expression);
|
|
1110
|
+
break;
|
|
1111
|
+
default:
|
|
1112
|
+
expression = cDefinition.expression;
|
|
1113
|
+
break;
|
|
998
1114
|
}
|
|
999
|
-
return
|
|
1115
|
+
return {
|
|
1116
|
+
bindings: cDefinition.bindings,
|
|
1117
|
+
expression: expression ?? '',
|
|
1118
|
+
};
|
|
1000
1119
|
}
|
|
1001
1120
|
};
|
|
1002
1121
|
exports.SqlAlterColumnQueryCompiler = SqlAlterColumnQueryCompiler;
|
|
1003
1122
|
exports.SqlAlterColumnQueryCompiler = SqlAlterColumnQueryCompiler = __decorate([
|
|
1004
1123
|
(0, di_1.NewInstance)(),
|
|
1005
|
-
|
|
1124
|
+
(0, di_1.Inject)(di_1.Container),
|
|
1125
|
+
__metadata("design:paramtypes", [di_1.Container, orm_1.AlterColumnQueryBuilder])
|
|
1006
1126
|
], SqlAlterColumnQueryCompiler);
|
|
1007
1127
|
let SqlEventQueryCompiler = class SqlEventQueryCompiler extends SqlQueryCompiler {
|
|
1008
1128
|
constructor(container, builder) {
|