knex 0.95.13 → 1.0.1
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/CHANGELOG.md +74 -3
- package/README.md +1 -1
- package/UPGRADING.md +7 -0
- package/lib/client.js +14 -1
- package/lib/constants.js +2 -0
- package/lib/dialects/better-sqlite3/index.js +72 -0
- package/lib/dialects/cockroachdb/crdb-querycompiler.js +87 -33
- package/lib/dialects/cockroachdb/crdb-tablecompiler.js +19 -0
- package/lib/dialects/cockroachdb/index.js +13 -0
- package/lib/dialects/mssql/index.js +0 -11
- package/lib/dialects/mssql/query/mssql-querycompiler.js +122 -64
- package/lib/dialects/mssql/schema/mssql-columncompiler.js +41 -6
- package/lib/dialects/mssql/schema/mssql-tablecompiler.js +24 -9
- package/lib/dialects/mssql/schema/mssql-viewcompiler.js +15 -1
- package/lib/dialects/mysql/index.js +3 -7
- package/lib/dialects/mysql/query/mysql-querycompiler.js +91 -5
- package/lib/dialects/mysql/schema/mysql-columncompiler.js +32 -5
- package/lib/dialects/mysql/schema/mysql-tablecompiler.js +28 -4
- package/lib/dialects/mysql2/index.js +7 -4
- package/lib/dialects/oracle/query/oracle-querycompiler.js +7 -6
- package/lib/dialects/oracle/schema/internal/trigger.js +1 -1
- package/lib/dialects/oracle/schema/oracle-columncompiler.js +10 -4
- package/lib/dialects/oracle/schema/oracle-tablecompiler.js +17 -6
- package/lib/dialects/oracledb/index.js +0 -4
- package/lib/dialects/oracledb/query/oracledb-querycompiler.js +104 -0
- package/lib/dialects/oracledb/schema/oracledb-columncompiler.js +23 -0
- package/lib/dialects/postgres/index.js +21 -6
- package/lib/dialects/postgres/query/pg-querybuilder.js +8 -0
- package/lib/dialects/postgres/query/pg-querycompiler.js +166 -5
- package/lib/dialects/postgres/schema/pg-columncompiler.js +24 -4
- package/lib/dialects/postgres/schema/pg-tablecompiler.js +55 -47
- package/lib/dialects/redshift/index.js +12 -0
- package/lib/dialects/redshift/query/redshift-querycompiler.js +62 -26
- package/lib/dialects/redshift/schema/redshift-columncompiler.js +2 -1
- package/lib/dialects/redshift/schema/redshift-tablecompiler.js +4 -1
- package/lib/dialects/sqlite3/index.js +18 -4
- package/lib/dialects/sqlite3/query/sqlite-querycompiler.js +85 -18
- package/lib/dialects/sqlite3/schema/ddl.js +274 -282
- package/lib/dialects/sqlite3/schema/internal/sqlite-ddl-operations.js +18 -8
- package/lib/dialects/sqlite3/schema/sqlite-columncompiler.js +20 -0
- package/lib/dialects/sqlite3/schema/sqlite-compiler.js +16 -12
- package/lib/dialects/sqlite3/schema/sqlite-tablecompiler.js +15 -5
- package/lib/dialects/sqlite3/schema/sqlite-viewcompiler.js +31 -2
- package/lib/execution/runner.js +37 -2
- package/lib/knex-builder/FunctionHelper.js +21 -0
- package/lib/migrations/common/MigrationsLoader.js +36 -0
- package/lib/migrations/migrate/MigrationGenerator.js +1 -1
- package/lib/migrations/migrate/Migrator.js +20 -23
- package/lib/migrations/migrate/migration-list-resolver.js +2 -5
- package/lib/migrations/migrate/{configuration-merger.js → migrator-configuration-merger.js} +2 -4
- package/lib/migrations/migrate/sources/fs-migrations.js +4 -29
- package/lib/migrations/migrate/stub/js.stub +8 -1
- package/lib/migrations/migrate/stub/knexfile-js.stub +3 -0
- package/lib/migrations/migrate/stub/knexfile-ts.stub +5 -2
- package/lib/migrations/migrate/table-creator.js +6 -5
- package/lib/migrations/seed/Seeder.js +25 -92
- package/lib/migrations/seed/seeder-configuration-merger.js +60 -0
- package/lib/migrations/seed/sources/fs-seeds.js +65 -0
- package/lib/migrations/seed/stub/js.stub +4 -1
- package/lib/migrations/util/import-file.js +0 -1
- package/lib/query/joinclause.js +24 -5
- package/lib/query/method-constants.js +37 -0
- package/lib/query/querybuilder.js +230 -5
- package/lib/query/querycompiler.js +269 -84
- package/lib/schema/columnbuilder.js +8 -0
- package/lib/schema/columncompiler.js +132 -5
- package/lib/schema/compiler.js +1 -0
- package/lib/schema/tablebuilder.js +41 -8
- package/lib/schema/tablecompiler.js +57 -0
- package/lib/schema/viewcompiler.js +13 -10
- package/package.json +35 -22
- package/scripts/docker-compose.yml +7 -7
- package/scripts/oracledb-install-driver-libs.sh +82 -0
- package/scripts/runkit-example.js +1 -1
- package/scripts/stress-test/docker-compose.yml +3 -3
- package/scripts/stress-test/knex-stress-test.js +1 -1
- package/scripts/stress-test/reconnect-test-mysql-based-drivers.js +1 -1
- package/types/index.d.ts +124 -20
|
@@ -6,6 +6,9 @@ const compact = require('lodash/compact');
|
|
|
6
6
|
const identity = require('lodash/identity');
|
|
7
7
|
const isEmpty = require('lodash/isEmpty');
|
|
8
8
|
const Raw = require('../../../raw.js');
|
|
9
|
+
const {
|
|
10
|
+
columnize: columnize_,
|
|
11
|
+
} = require('../../../formatter/wrappingFormatter');
|
|
9
12
|
|
|
10
13
|
const components = [
|
|
11
14
|
'columns',
|
|
@@ -100,40 +103,37 @@ class QueryCompiler_MSSQL extends QueryCompiler {
|
|
|
100
103
|
returning,
|
|
101
104
|
};
|
|
102
105
|
}
|
|
106
|
+
sql += this._buildInsertData(insertValues, returningSql);
|
|
103
107
|
|
|
108
|
+
if (returning) {
|
|
109
|
+
sql += this._buildReturningSelect(returning);
|
|
110
|
+
}
|
|
111
|
+
|
|
112
|
+
return {
|
|
113
|
+
sql,
|
|
114
|
+
returning,
|
|
115
|
+
};
|
|
116
|
+
}
|
|
117
|
+
|
|
118
|
+
_buildInsertData(insertValues, returningSql) {
|
|
119
|
+
let sql = '';
|
|
104
120
|
const insertData = this._prepInsert(insertValues);
|
|
105
121
|
if (typeof insertData === 'string') {
|
|
106
122
|
sql += insertData;
|
|
107
123
|
} else {
|
|
108
124
|
if (insertData.columns.length) {
|
|
109
125
|
sql += `(${this.formatter.columnize(insertData.columns)}`;
|
|
110
|
-
sql +=
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
sql += this.client.parameterize(
|
|
115
|
-
insertData.values[i],
|
|
116
|
-
this.client.valueForUndefined,
|
|
117
|
-
this.builder,
|
|
118
|
-
this.bindingsHolder
|
|
119
|
-
);
|
|
120
|
-
}
|
|
121
|
-
sql += ')';
|
|
126
|
+
sql +=
|
|
127
|
+
`) ${returningSql}values (` +
|
|
128
|
+
this._buildInsertValues(insertData) +
|
|
129
|
+
')';
|
|
122
130
|
} else if (insertValues.length === 1 && insertValues[0]) {
|
|
123
131
|
sql += returningSql + this._emptyInsertValue;
|
|
124
132
|
} else {
|
|
125
|
-
|
|
133
|
+
return '';
|
|
126
134
|
}
|
|
127
135
|
}
|
|
128
|
-
|
|
129
|
-
if (returning) {
|
|
130
|
-
sql += this._buildReturningSelect(returning);
|
|
131
|
-
}
|
|
132
|
-
|
|
133
|
-
return {
|
|
134
|
-
sql,
|
|
135
|
-
returning,
|
|
136
|
-
};
|
|
136
|
+
return sql;
|
|
137
137
|
}
|
|
138
138
|
|
|
139
139
|
standardInsert() {
|
|
@@ -155,30 +155,7 @@ class QueryCompiler_MSSQL extends QueryCompiler {
|
|
|
155
155
|
};
|
|
156
156
|
}
|
|
157
157
|
|
|
158
|
-
|
|
159
|
-
if (typeof insertData === 'string') {
|
|
160
|
-
sql += insertData;
|
|
161
|
-
} else {
|
|
162
|
-
if (insertData.columns.length) {
|
|
163
|
-
sql += `(${this.formatter.columnize(insertData.columns)}`;
|
|
164
|
-
sql += `) ${returningSql}values (`;
|
|
165
|
-
let i = -1;
|
|
166
|
-
while (++i < insertData.values.length) {
|
|
167
|
-
if (i !== 0) sql += '), (';
|
|
168
|
-
sql += this.client.parameterize(
|
|
169
|
-
insertData.values[i],
|
|
170
|
-
this.client.valueForUndefined,
|
|
171
|
-
this.builder,
|
|
172
|
-
this.bindingsHolder
|
|
173
|
-
);
|
|
174
|
-
}
|
|
175
|
-
sql += ')';
|
|
176
|
-
} else if (insertValues.length === 1 && insertValues[0]) {
|
|
177
|
-
sql += returningSql + this._emptyInsertValue;
|
|
178
|
-
} else {
|
|
179
|
-
sql = '';
|
|
180
|
-
}
|
|
181
|
-
}
|
|
158
|
+
sql += this._buildInsertData(insertValues, returningSql);
|
|
182
159
|
|
|
183
160
|
return {
|
|
184
161
|
sql,
|
|
@@ -354,15 +331,17 @@ class QueryCompiler_MSSQL extends QueryCompiler {
|
|
|
354
331
|
sql.push(this.aggregateRaw(stmt));
|
|
355
332
|
} else if (stmt.type === 'analytic') {
|
|
356
333
|
sql.push(this.analytic(stmt));
|
|
334
|
+
} else if (stmt.type === 'json') {
|
|
335
|
+
sql.push(this.json(stmt));
|
|
357
336
|
} else if (stmt.value && stmt.value.length > 0) {
|
|
358
337
|
sql.push(this.formatter.columnize(stmt.value));
|
|
359
338
|
}
|
|
360
339
|
}
|
|
361
340
|
}
|
|
362
341
|
if (sql.length === 0) sql = ['*'];
|
|
363
|
-
|
|
342
|
+
const select = this.onlyJson() ? '' : 'select ';
|
|
364
343
|
return (
|
|
365
|
-
|
|
344
|
+
`${select}${hints}${distinctClause}` +
|
|
366
345
|
(top ? top + ' ' : '') +
|
|
367
346
|
sql.join(', ') +
|
|
368
347
|
(this.tableName ? ` from ${this.tableName}` : '')
|
|
@@ -502,11 +481,7 @@ class QueryCompiler_MSSQL extends QueryCompiler {
|
|
|
502
481
|
const noLimit = !this.single.limit && this.single.limit !== 0;
|
|
503
482
|
const noOffset = !this.single.offset;
|
|
504
483
|
if (noLimit || !noOffset) return '';
|
|
505
|
-
return `top (${this.
|
|
506
|
-
this.single.limit,
|
|
507
|
-
this.builder,
|
|
508
|
-
this.bindingsHolder
|
|
509
|
-
)})`;
|
|
484
|
+
return `top (${this._getValueOrParameterFromAttribute('limit')})`;
|
|
510
485
|
}
|
|
511
486
|
|
|
512
487
|
limit() {
|
|
@@ -518,23 +493,106 @@ class QueryCompiler_MSSQL extends QueryCompiler {
|
|
|
518
493
|
const noOffset = !this.single.offset;
|
|
519
494
|
if (noOffset) return '';
|
|
520
495
|
let offset = `offset ${
|
|
521
|
-
noOffset
|
|
522
|
-
? '0'
|
|
523
|
-
: this.client.parameter(
|
|
524
|
-
this.single.offset,
|
|
525
|
-
this.builder,
|
|
526
|
-
this.bindingsHolder
|
|
527
|
-
)
|
|
496
|
+
noOffset ? '0' : this._getValueOrParameterFromAttribute('offset')
|
|
528
497
|
} rows`;
|
|
529
498
|
if (!noLimit) {
|
|
530
|
-
offset += ` fetch next ${this.
|
|
531
|
-
|
|
532
|
-
this.builder,
|
|
533
|
-
this.bindingsHolder
|
|
499
|
+
offset += ` fetch next ${this._getValueOrParameterFromAttribute(
|
|
500
|
+
'limit'
|
|
534
501
|
)} rows only`;
|
|
535
502
|
}
|
|
536
503
|
return offset;
|
|
537
504
|
}
|
|
505
|
+
|
|
506
|
+
whereLike(statement) {
|
|
507
|
+
return `${this._columnClause(
|
|
508
|
+
statement
|
|
509
|
+
)} collate SQL_Latin1_General_CP1_CS_AS ${this._not(
|
|
510
|
+
statement,
|
|
511
|
+
'like '
|
|
512
|
+
)}${this._valueClause(statement)}`;
|
|
513
|
+
}
|
|
514
|
+
|
|
515
|
+
whereILike(statement) {
|
|
516
|
+
return `${this._columnClause(
|
|
517
|
+
statement
|
|
518
|
+
)} collate SQL_Latin1_General_CP1_CI_AS ${this._not(
|
|
519
|
+
statement,
|
|
520
|
+
'like '
|
|
521
|
+
)}${this._valueClause(statement)}`;
|
|
522
|
+
}
|
|
523
|
+
|
|
524
|
+
jsonExtract(params) {
|
|
525
|
+
// JSON_VALUE return NULL if we query object or array
|
|
526
|
+
// JSON_QUERY return NULL if we query literal/single value
|
|
527
|
+
return this._jsonExtract(
|
|
528
|
+
params.singleValue ? 'JSON_VALUE' : 'JSON_QUERY',
|
|
529
|
+
params
|
|
530
|
+
);
|
|
531
|
+
}
|
|
532
|
+
|
|
533
|
+
jsonSet(params) {
|
|
534
|
+
return this._jsonSet('JSON_MODIFY', params);
|
|
535
|
+
}
|
|
536
|
+
|
|
537
|
+
jsonInsert(params) {
|
|
538
|
+
return this._jsonSet('JSON_MODIFY', params);
|
|
539
|
+
}
|
|
540
|
+
|
|
541
|
+
jsonRemove(params) {
|
|
542
|
+
const jsonCol = `JSON_MODIFY(${columnize_(
|
|
543
|
+
params.column,
|
|
544
|
+
this.builder,
|
|
545
|
+
this.client,
|
|
546
|
+
this.bindingsHolder
|
|
547
|
+
)},${this.client.parameter(
|
|
548
|
+
params.path,
|
|
549
|
+
this.builder,
|
|
550
|
+
this.bindingsHolder
|
|
551
|
+
)}, NULL)`;
|
|
552
|
+
return params.alias
|
|
553
|
+
? this.client.alias(jsonCol, this.formatter.wrap(params.alias))
|
|
554
|
+
: jsonCol;
|
|
555
|
+
}
|
|
556
|
+
|
|
557
|
+
whereJsonPath(statement) {
|
|
558
|
+
return this._whereJsonPath('JSON_VALUE', statement);
|
|
559
|
+
}
|
|
560
|
+
|
|
561
|
+
whereJsonSupersetOf(statement) {
|
|
562
|
+
throw new Error(
|
|
563
|
+
'Json superset where clause not actually supported by MSSQL'
|
|
564
|
+
);
|
|
565
|
+
}
|
|
566
|
+
|
|
567
|
+
whereJsonSubsetOf(statement) {
|
|
568
|
+
throw new Error('Json subset where clause not actually supported by MSSQL');
|
|
569
|
+
}
|
|
570
|
+
|
|
571
|
+
_getExtracts(statement, operator) {
|
|
572
|
+
const column = columnize_(
|
|
573
|
+
statement.column,
|
|
574
|
+
this.builder,
|
|
575
|
+
this.client,
|
|
576
|
+
this.bindingsHolder
|
|
577
|
+
);
|
|
578
|
+
return (
|
|
579
|
+
Array.isArray(statement.values) ? statement.values : [statement.values]
|
|
580
|
+
)
|
|
581
|
+
.map(function (value) {
|
|
582
|
+
return (
|
|
583
|
+
'JSON_VALUE(' +
|
|
584
|
+
column +
|
|
585
|
+
',' +
|
|
586
|
+
this.client.parameter(value, this.builder, this.bindingsHolder) +
|
|
587
|
+
')'
|
|
588
|
+
);
|
|
589
|
+
}, this)
|
|
590
|
+
.join(operator);
|
|
591
|
+
}
|
|
592
|
+
|
|
593
|
+
onJsonPathEquals(clause) {
|
|
594
|
+
return this._onJsonPathEquals('JSON_VALUE', clause);
|
|
595
|
+
}
|
|
538
596
|
}
|
|
539
597
|
|
|
540
598
|
// Set the QueryBuilder & QueryCompiler on the client object,
|
|
@@ -3,11 +3,13 @@
|
|
|
3
3
|
const ColumnCompiler = require('../../../schema/columncompiler');
|
|
4
4
|
const { toNumber } = require('../../../util/helpers');
|
|
5
5
|
const { formatDefault } = require('../../../formatter/formatterUtils');
|
|
6
|
+
const { operator: operator_ } = require('../../../formatter/wrappingFormatter');
|
|
6
7
|
|
|
7
8
|
class ColumnCompiler_MSSQL extends ColumnCompiler {
|
|
8
9
|
constructor(client, tableCompiler, columnBuilder) {
|
|
9
10
|
super(client, tableCompiler, columnBuilder);
|
|
10
11
|
this.modifiers = ['nullable', 'defaultTo', 'first', 'after', 'comment'];
|
|
12
|
+
this._addCheckModifiers();
|
|
11
13
|
}
|
|
12
14
|
|
|
13
15
|
// Types
|
|
@@ -126,24 +128,57 @@ class ColumnCompiler_MSSQL extends ColumnCompiler {
|
|
|
126
128
|
});
|
|
127
129
|
return '';
|
|
128
130
|
}
|
|
131
|
+
|
|
132
|
+
checkLength(operator, length, constraintName) {
|
|
133
|
+
return this._check(
|
|
134
|
+
`LEN(${this.formatter.wrap(this.getColumnName())}) ${operator_(
|
|
135
|
+
operator,
|
|
136
|
+
this.columnBuilder,
|
|
137
|
+
this.bindingsHolder
|
|
138
|
+
)} ${toNumber(length)}`,
|
|
139
|
+
constraintName
|
|
140
|
+
);
|
|
141
|
+
}
|
|
142
|
+
|
|
143
|
+
checkRegex(regex, constraintName) {
|
|
144
|
+
return this._check(
|
|
145
|
+
`${this.formatter.wrap(
|
|
146
|
+
this.getColumnName()
|
|
147
|
+
)} LIKE ${this.client._escapeBinding('%' + regex + '%')}`,
|
|
148
|
+
constraintName
|
|
149
|
+
);
|
|
150
|
+
}
|
|
151
|
+
|
|
152
|
+
increments(options = { primaryKey: true }) {
|
|
153
|
+
return (
|
|
154
|
+
'int identity(1,1) not null' +
|
|
155
|
+
(this.tableCompiler._canBeAddPrimaryKey(options) ? ' primary key' : '')
|
|
156
|
+
);
|
|
157
|
+
}
|
|
158
|
+
|
|
159
|
+
bigincrements(options = { primaryKey: true }) {
|
|
160
|
+
return (
|
|
161
|
+
'bigint identity(1,1) not null' +
|
|
162
|
+
(this.tableCompiler._canBeAddPrimaryKey(options) ? ' primary key' : '')
|
|
163
|
+
);
|
|
164
|
+
}
|
|
129
165
|
}
|
|
130
166
|
|
|
131
|
-
ColumnCompiler_MSSQL.prototype.increments = ({ primaryKey = true } = {}) =>
|
|
132
|
-
'int identity(1,1) not null' + (primaryKey ? ' primary key' : '');
|
|
133
|
-
ColumnCompiler_MSSQL.prototype.bigincrements = ({ primaryKey = true } = {}) =>
|
|
134
|
-
'bigint identity(1,1) not null' + (primaryKey ? ' primary key' : '');
|
|
135
167
|
ColumnCompiler_MSSQL.prototype.bigint = 'bigint';
|
|
136
168
|
ColumnCompiler_MSSQL.prototype.mediumint = 'int';
|
|
137
169
|
ColumnCompiler_MSSQL.prototype.smallint = 'smallint';
|
|
138
170
|
ColumnCompiler_MSSQL.prototype.text = 'nvarchar(max)';
|
|
139
171
|
ColumnCompiler_MSSQL.prototype.mediumtext = 'nvarchar(max)';
|
|
140
172
|
ColumnCompiler_MSSQL.prototype.longtext = 'nvarchar(max)';
|
|
141
|
-
ColumnCompiler_MSSQL.prototype.json =
|
|
173
|
+
ColumnCompiler_MSSQL.prototype.json = ColumnCompiler_MSSQL.prototype.jsonb =
|
|
174
|
+
'nvarchar(max)';
|
|
142
175
|
|
|
143
176
|
// TODO: mssql supports check constraints as of SQL Server 2008
|
|
144
177
|
// so make enu here more like postgres
|
|
145
178
|
ColumnCompiler_MSSQL.prototype.enu = 'nvarchar(100)';
|
|
146
|
-
ColumnCompiler_MSSQL.prototype.uuid =
|
|
179
|
+
ColumnCompiler_MSSQL.prototype.uuid = ({ useBinaryUuid = false } = {}) =>
|
|
180
|
+
useBinaryUuid ? 'binary(16)' : 'uniqueidentifier';
|
|
181
|
+
|
|
147
182
|
ColumnCompiler_MSSQL.prototype.datetime = 'datetime2';
|
|
148
183
|
ColumnCompiler_MSSQL.prototype.bool = 'bit';
|
|
149
184
|
|
|
@@ -28,6 +28,7 @@ class TableCompiler_MSSQL extends TableCompiler {
|
|
|
28
28
|
this.tableName() +
|
|
29
29
|
(this._formatting ? ' (\n ' : ' (') +
|
|
30
30
|
columns.sql.join(this._formatting ? ',\n ' : ', ') +
|
|
31
|
+
this._addChecks() +
|
|
31
32
|
')';
|
|
32
33
|
}
|
|
33
34
|
|
|
@@ -36,6 +37,9 @@ class TableCompiler_MSSQL extends TableCompiler {
|
|
|
36
37
|
if (this.single.comment) {
|
|
37
38
|
this.comment(this.single.comment);
|
|
38
39
|
}
|
|
40
|
+
if (like) {
|
|
41
|
+
this.addColumns(columns, this.addColumnsPrefix);
|
|
42
|
+
}
|
|
39
43
|
}
|
|
40
44
|
|
|
41
45
|
comment(/** @type {string} */ comment) {
|
|
@@ -276,13 +280,14 @@ class TableCompiler_MSSQL extends TableCompiler {
|
|
|
276
280
|
* Create a unique index.
|
|
277
281
|
*
|
|
278
282
|
* @param {string | string[]} columns
|
|
279
|
-
* @param {string | {indexName: undefined | string, deferrable?: 'not deferrable'|'deferred'|'immediate' }} indexName
|
|
283
|
+
* @param {string | {indexName: undefined | string, deferrable?: 'not deferrable'|'deferred'|'immediate', useConstraint?: true|false }} indexName
|
|
280
284
|
*/
|
|
281
285
|
unique(columns, indexName) {
|
|
282
286
|
/** @type {string | undefined} */
|
|
283
287
|
let deferrable;
|
|
288
|
+
let useConstraint = false;
|
|
284
289
|
if (isObject(indexName)) {
|
|
285
|
-
({ indexName, deferrable } = indexName);
|
|
290
|
+
({ indexName, deferrable, useConstraint } = indexName);
|
|
286
291
|
}
|
|
287
292
|
if (deferrable && deferrable !== 'not deferrable') {
|
|
288
293
|
this.client.logger.warn(
|
|
@@ -301,13 +306,23 @@ class TableCompiler_MSSQL extends TableCompiler {
|
|
|
301
306
|
.map((column) => this.formatter.columnize(column) + ' IS NOT NULL')
|
|
302
307
|
.join(' AND ');
|
|
303
308
|
|
|
304
|
-
|
|
305
|
-
|
|
306
|
-
|
|
307
|
-
|
|
308
|
-
|
|
309
|
-
|
|
310
|
-
|
|
309
|
+
if (useConstraint) {
|
|
310
|
+
// mssql supports unique indexes and unique constraints.
|
|
311
|
+
// unique indexes cannot be used with foreign key relationships hence unique constraints are used instead.
|
|
312
|
+
this.pushQuery(
|
|
313
|
+
`ALTER TABLE ${this.tableName()} ADD CONSTRAINT ${indexName} UNIQUE (${this.formatter.columnize(
|
|
314
|
+
columns
|
|
315
|
+
)})`
|
|
316
|
+
);
|
|
317
|
+
} else {
|
|
318
|
+
// make unique constraint that allows null https://stackoverflow.com/a/767702/360060
|
|
319
|
+
// to be more or less compatible with other DBs (if any of the columns is NULL then "duplicates" are allowed)
|
|
320
|
+
this.pushQuery(
|
|
321
|
+
`CREATE UNIQUE INDEX ${indexName} ON ${this.tableName()} (${this.formatter.columnize(
|
|
322
|
+
columns
|
|
323
|
+
)}) WHERE ${whereAllTheColumnsAreNotNull}`
|
|
324
|
+
);
|
|
325
|
+
}
|
|
311
326
|
}
|
|
312
327
|
|
|
313
328
|
// Compile a drop index command.
|
|
@@ -1,6 +1,9 @@
|
|
|
1
1
|
/* eslint max-len: 0 */
|
|
2
2
|
|
|
3
3
|
const ViewCompiler = require('../../../schema/viewcompiler.js');
|
|
4
|
+
const {
|
|
5
|
+
columnize: columnize_,
|
|
6
|
+
} = require('../../../formatter/wrappingFormatter');
|
|
4
7
|
|
|
5
8
|
class ViewCompiler_MSSQL extends ViewCompiler {
|
|
6
9
|
constructor(client, viewCompiler) {
|
|
@@ -11,7 +14,18 @@ class ViewCompiler_MSSQL extends ViewCompiler {
|
|
|
11
14
|
const createStatement = 'CREATE ' + (replace ? 'OR ALTER ' : '') + 'VIEW ';
|
|
12
15
|
let sql = createStatement + this.viewName();
|
|
13
16
|
|
|
14
|
-
|
|
17
|
+
const columnList = columns
|
|
18
|
+
? ' (' +
|
|
19
|
+
columnize_(
|
|
20
|
+
columns,
|
|
21
|
+
this.viewBuilder,
|
|
22
|
+
this.client,
|
|
23
|
+
this.bindingsHolder
|
|
24
|
+
) +
|
|
25
|
+
')'
|
|
26
|
+
: '';
|
|
27
|
+
|
|
28
|
+
sql += columnList;
|
|
15
29
|
sql += ' AS ';
|
|
16
30
|
sql += selectQuery.toString();
|
|
17
31
|
this.pushQuery({
|
|
@@ -89,13 +89,9 @@ class Client_MySQL extends Client {
|
|
|
89
89
|
}
|
|
90
90
|
|
|
91
91
|
validateConnection(connection) {
|
|
92
|
-
|
|
93
|
-
connection.state === 'connected' ||
|
|
94
|
-
|
|
95
|
-
) {
|
|
96
|
-
return true;
|
|
97
|
-
}
|
|
98
|
-
return false;
|
|
92
|
+
return (
|
|
93
|
+
connection.state === 'connected' || connection.state === 'authenticated'
|
|
94
|
+
);
|
|
99
95
|
}
|
|
100
96
|
|
|
101
97
|
// Grab a connection, run the query via the MySQL streaming interface,
|
|
@@ -3,6 +3,10 @@
|
|
|
3
3
|
const identity = require('lodash/identity');
|
|
4
4
|
const QueryCompiler = require('../../../query/querycompiler');
|
|
5
5
|
const { wrapAsIdentifier } = require('../../../formatter/formatterUtils');
|
|
6
|
+
const {
|
|
7
|
+
columnize: columnize_,
|
|
8
|
+
wrap: wrap_,
|
|
9
|
+
} = require('../../../formatter/wrappingFormatter');
|
|
6
10
|
|
|
7
11
|
class QueryCompiler_MySQL extends QueryCompiler {
|
|
8
12
|
constructor(client, builder, formatter) {
|
|
@@ -146,13 +150,95 @@ class QueryCompiler_MySQL extends QueryCompiler {
|
|
|
146
150
|
const limit =
|
|
147
151
|
this.single.offset && noLimit
|
|
148
152
|
? '18446744073709551615'
|
|
149
|
-
: this.
|
|
150
|
-
this.single.limit,
|
|
151
|
-
this.builder,
|
|
152
|
-
this.bindingsHolder
|
|
153
|
-
);
|
|
153
|
+
: this._getValueOrParameterFromAttribute('limit');
|
|
154
154
|
return `limit ${limit}`;
|
|
155
155
|
}
|
|
156
|
+
|
|
157
|
+
whereLike(statement) {
|
|
158
|
+
return `${this._columnClause(statement)} ${this._not(
|
|
159
|
+
statement,
|
|
160
|
+
'like '
|
|
161
|
+
)}${this._valueClause(statement)} COLLATE utf8_bin`;
|
|
162
|
+
}
|
|
163
|
+
|
|
164
|
+
whereILike(statement) {
|
|
165
|
+
return `${this._columnClause(statement)} ${this._not(
|
|
166
|
+
statement,
|
|
167
|
+
'like '
|
|
168
|
+
)}${this._valueClause(statement)}`;
|
|
169
|
+
}
|
|
170
|
+
|
|
171
|
+
// Json functions
|
|
172
|
+
jsonExtract(params) {
|
|
173
|
+
return this._jsonExtract(['json_extract', 'json_unquote'], params);
|
|
174
|
+
}
|
|
175
|
+
|
|
176
|
+
jsonSet(params) {
|
|
177
|
+
return this._jsonSet('json_set', params);
|
|
178
|
+
}
|
|
179
|
+
|
|
180
|
+
jsonInsert(params) {
|
|
181
|
+
return this._jsonSet('json_insert', params);
|
|
182
|
+
}
|
|
183
|
+
|
|
184
|
+
jsonRemove(params) {
|
|
185
|
+
const jsonCol = `json_remove(${columnize_(
|
|
186
|
+
params.column,
|
|
187
|
+
this.builder,
|
|
188
|
+
this.client,
|
|
189
|
+
this.bindingsHolder
|
|
190
|
+
)},${this.client.parameter(
|
|
191
|
+
params.path,
|
|
192
|
+
this.builder,
|
|
193
|
+
this.bindingsHolder
|
|
194
|
+
)})`;
|
|
195
|
+
return params.alias
|
|
196
|
+
? this.client.alias(jsonCol, this.formatter.wrap(params.alias))
|
|
197
|
+
: jsonCol;
|
|
198
|
+
}
|
|
199
|
+
|
|
200
|
+
whereJsonObject(statement) {
|
|
201
|
+
return this._not(
|
|
202
|
+
statement,
|
|
203
|
+
`json_contains(${this._columnClause(statement)}, ${this._jsonValueClause(
|
|
204
|
+
statement
|
|
205
|
+
)})`
|
|
206
|
+
);
|
|
207
|
+
}
|
|
208
|
+
|
|
209
|
+
whereJsonPath(statement) {
|
|
210
|
+
return this._whereJsonPath('json_extract', statement);
|
|
211
|
+
}
|
|
212
|
+
|
|
213
|
+
whereJsonSupersetOf(statement) {
|
|
214
|
+
return this._not(
|
|
215
|
+
statement,
|
|
216
|
+
`json_contains(${wrap_(
|
|
217
|
+
statement.column,
|
|
218
|
+
undefined,
|
|
219
|
+
this.builder,
|
|
220
|
+
this.client,
|
|
221
|
+
this.bindingsHolder
|
|
222
|
+
)},${this._jsonValueClause(statement)})`
|
|
223
|
+
);
|
|
224
|
+
}
|
|
225
|
+
|
|
226
|
+
whereJsonSubsetOf(statement) {
|
|
227
|
+
return this._not(
|
|
228
|
+
statement,
|
|
229
|
+
`json_contains(${this._jsonValueClause(statement)},${wrap_(
|
|
230
|
+
statement.column,
|
|
231
|
+
undefined,
|
|
232
|
+
this.builder,
|
|
233
|
+
this.client,
|
|
234
|
+
this.bindingsHolder
|
|
235
|
+
)})`
|
|
236
|
+
);
|
|
237
|
+
}
|
|
238
|
+
|
|
239
|
+
onJsonPathEquals(clause) {
|
|
240
|
+
return this._onJsonPathEquals('json_extract', clause);
|
|
241
|
+
}
|
|
156
242
|
}
|
|
157
243
|
|
|
158
244
|
// Set the QueryBuilder & QueryCompiler on the client object,
|
|
@@ -18,6 +18,7 @@ class ColumnCompiler_MySQL extends ColumnCompiler {
|
|
|
18
18
|
'first',
|
|
19
19
|
'after',
|
|
20
20
|
];
|
|
21
|
+
this._addCheckModifiers();
|
|
21
22
|
}
|
|
22
23
|
|
|
23
24
|
// Types
|
|
@@ -152,13 +153,39 @@ class ColumnCompiler_MySQL extends ColumnCompiler {
|
|
|
152
153
|
collate(collation) {
|
|
153
154
|
return collation && `collate '${collation}'`;
|
|
154
155
|
}
|
|
156
|
+
|
|
157
|
+
checkRegex(regex, constraintName) {
|
|
158
|
+
return this._check(
|
|
159
|
+
`${this.formatter.wrap(
|
|
160
|
+
this.getColumnName()
|
|
161
|
+
)} REGEXP ${this.client._escapeBinding(regex)}`,
|
|
162
|
+
constraintName
|
|
163
|
+
);
|
|
164
|
+
}
|
|
165
|
+
|
|
166
|
+
increments(options = { primaryKey: true }) {
|
|
167
|
+
return (
|
|
168
|
+
'int unsigned not null' +
|
|
169
|
+
// In MySQL autoincrement are always a primary key. If you already have a primary key, we
|
|
170
|
+
// initialize this column as classic int column then modify it later in table compiler
|
|
171
|
+
(this.tableCompiler._canBeAddPrimaryKey(options)
|
|
172
|
+
? ' auto_increment primary key'
|
|
173
|
+
: '')
|
|
174
|
+
);
|
|
175
|
+
}
|
|
176
|
+
|
|
177
|
+
bigincrements(options = { primaryKey: true }) {
|
|
178
|
+
return (
|
|
179
|
+
'bigint unsigned not null' +
|
|
180
|
+
// In MySQL autoincrement are always a primary key. If you already have a primary key, we
|
|
181
|
+
// initialize this column as classic int column then modify it later in table compiler
|
|
182
|
+
(this.tableCompiler._canBeAddPrimaryKey(options)
|
|
183
|
+
? ' auto_increment primary key'
|
|
184
|
+
: '')
|
|
185
|
+
);
|
|
186
|
+
}
|
|
155
187
|
}
|
|
156
188
|
|
|
157
|
-
ColumnCompiler_MySQL.prototype.increments = ({ primaryKey = true } = {}) =>
|
|
158
|
-
'int unsigned not null auto_increment' + (primaryKey ? ' primary key' : '');
|
|
159
|
-
ColumnCompiler_MySQL.prototype.bigincrements = ({ primaryKey = true } = {}) =>
|
|
160
|
-
'bigint unsigned not null auto_increment' +
|
|
161
|
-
(primaryKey ? ' primary key' : '');
|
|
162
189
|
ColumnCompiler_MySQL.prototype.bigint = 'bigint';
|
|
163
190
|
ColumnCompiler_MySQL.prototype.mediumint = 'mediumint';
|
|
164
191
|
ColumnCompiler_MySQL.prototype.smallint = 'smallint';
|
|
@@ -19,7 +19,7 @@ class TableCompiler_MySQL extends TableCompiler {
|
|
|
19
19
|
: 'create table ';
|
|
20
20
|
const { client } = this;
|
|
21
21
|
let conn = {};
|
|
22
|
-
const columnsSql = ' (' + columns.sql.join(', ') + ')';
|
|
22
|
+
const columnsSql = ' (' + columns.sql.join(', ') + this._addChecks() + ')';
|
|
23
23
|
let sql =
|
|
24
24
|
createStatement +
|
|
25
25
|
this.tableName() +
|
|
@@ -42,14 +42,18 @@ class TableCompiler_MySQL extends TableCompiler {
|
|
|
42
42
|
|
|
43
43
|
if (this.single.comment) {
|
|
44
44
|
const comment = this.single.comment || '';
|
|
45
|
-
|
|
45
|
+
const MAX_COMMENT_LENGTH = 1024;
|
|
46
|
+
if (comment.length > MAX_COMMENT_LENGTH)
|
|
46
47
|
this.client.logger.warn(
|
|
47
|
-
|
|
48
|
+
`The max length for a table comment is ${MAX_COMMENT_LENGTH} characters`
|
|
48
49
|
);
|
|
49
50
|
sql += ` comment = '${comment}'`;
|
|
50
51
|
}
|
|
51
52
|
|
|
52
53
|
this.pushQuery(sql);
|
|
54
|
+
if (like) {
|
|
55
|
+
this.addColumns(columns, this.addColumnsPrefix);
|
|
56
|
+
}
|
|
53
57
|
}
|
|
54
58
|
|
|
55
59
|
// Compiles the comment on the table.
|
|
@@ -249,11 +253,31 @@ class TableCompiler_MySQL extends TableCompiler {
|
|
|
249
253
|
constraintName = constraintName
|
|
250
254
|
? this.formatter.wrap(constraintName)
|
|
251
255
|
: this.formatter.wrap(`${this.tableNameRaw}_pkey`);
|
|
256
|
+
|
|
257
|
+
const primaryCols = columns;
|
|
258
|
+
let incrementsCols = [];
|
|
259
|
+
if (this.grouped.columns) {
|
|
260
|
+
incrementsCols = this._getIncrementsColumnNames();
|
|
261
|
+
if (incrementsCols) {
|
|
262
|
+
incrementsCols.forEach((c) => {
|
|
263
|
+
if (!primaryCols.includes(c)) {
|
|
264
|
+
primaryCols.unshift(c);
|
|
265
|
+
}
|
|
266
|
+
});
|
|
267
|
+
}
|
|
268
|
+
}
|
|
252
269
|
this.pushQuery(
|
|
253
270
|
`alter table ${this.tableName()} add primary key ${constraintName}(${this.formatter.columnize(
|
|
254
|
-
|
|
271
|
+
primaryCols
|
|
255
272
|
)})`
|
|
256
273
|
);
|
|
274
|
+
if (incrementsCols.length) {
|
|
275
|
+
this.pushQuery(
|
|
276
|
+
`alter table ${this.tableName()} modify column ${this.formatter.columnize(
|
|
277
|
+
incrementsCols
|
|
278
|
+
)} int unsigned not null auto_increment`
|
|
279
|
+
);
|
|
280
|
+
}
|
|
257
281
|
}
|
|
258
282
|
|
|
259
283
|
unique(columns, indexName) {
|
|
@@ -15,10 +15,13 @@ class Client_MySQL2 extends Client_MySQL {
|
|
|
15
15
|
return require('mysql2');
|
|
16
16
|
}
|
|
17
17
|
validateConnection(connection) {
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
18
|
+
return (
|
|
19
|
+
connection &&
|
|
20
|
+
!connection._fatalError &&
|
|
21
|
+
!connection._protocolError &&
|
|
22
|
+
!connection._closing &&
|
|
23
|
+
!connection.stream.destroyed
|
|
24
|
+
);
|
|
22
25
|
}
|
|
23
26
|
}
|
|
24
27
|
|