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.
Files changed (78) hide show
  1. package/CHANGELOG.md +74 -3
  2. package/README.md +1 -1
  3. package/UPGRADING.md +7 -0
  4. package/lib/client.js +14 -1
  5. package/lib/constants.js +2 -0
  6. package/lib/dialects/better-sqlite3/index.js +72 -0
  7. package/lib/dialects/cockroachdb/crdb-querycompiler.js +87 -33
  8. package/lib/dialects/cockroachdb/crdb-tablecompiler.js +19 -0
  9. package/lib/dialects/cockroachdb/index.js +13 -0
  10. package/lib/dialects/mssql/index.js +0 -11
  11. package/lib/dialects/mssql/query/mssql-querycompiler.js +122 -64
  12. package/lib/dialects/mssql/schema/mssql-columncompiler.js +41 -6
  13. package/lib/dialects/mssql/schema/mssql-tablecompiler.js +24 -9
  14. package/lib/dialects/mssql/schema/mssql-viewcompiler.js +15 -1
  15. package/lib/dialects/mysql/index.js +3 -7
  16. package/lib/dialects/mysql/query/mysql-querycompiler.js +91 -5
  17. package/lib/dialects/mysql/schema/mysql-columncompiler.js +32 -5
  18. package/lib/dialects/mysql/schema/mysql-tablecompiler.js +28 -4
  19. package/lib/dialects/mysql2/index.js +7 -4
  20. package/lib/dialects/oracle/query/oracle-querycompiler.js +7 -6
  21. package/lib/dialects/oracle/schema/internal/trigger.js +1 -1
  22. package/lib/dialects/oracle/schema/oracle-columncompiler.js +10 -4
  23. package/lib/dialects/oracle/schema/oracle-tablecompiler.js +17 -6
  24. package/lib/dialects/oracledb/index.js +0 -4
  25. package/lib/dialects/oracledb/query/oracledb-querycompiler.js +104 -0
  26. package/lib/dialects/oracledb/schema/oracledb-columncompiler.js +23 -0
  27. package/lib/dialects/postgres/index.js +21 -6
  28. package/lib/dialects/postgres/query/pg-querybuilder.js +8 -0
  29. package/lib/dialects/postgres/query/pg-querycompiler.js +166 -5
  30. package/lib/dialects/postgres/schema/pg-columncompiler.js +24 -4
  31. package/lib/dialects/postgres/schema/pg-tablecompiler.js +55 -47
  32. package/lib/dialects/redshift/index.js +12 -0
  33. package/lib/dialects/redshift/query/redshift-querycompiler.js +62 -26
  34. package/lib/dialects/redshift/schema/redshift-columncompiler.js +2 -1
  35. package/lib/dialects/redshift/schema/redshift-tablecompiler.js +4 -1
  36. package/lib/dialects/sqlite3/index.js +18 -4
  37. package/lib/dialects/sqlite3/query/sqlite-querycompiler.js +85 -18
  38. package/lib/dialects/sqlite3/schema/ddl.js +274 -282
  39. package/lib/dialects/sqlite3/schema/internal/sqlite-ddl-operations.js +18 -8
  40. package/lib/dialects/sqlite3/schema/sqlite-columncompiler.js +20 -0
  41. package/lib/dialects/sqlite3/schema/sqlite-compiler.js +16 -12
  42. package/lib/dialects/sqlite3/schema/sqlite-tablecompiler.js +15 -5
  43. package/lib/dialects/sqlite3/schema/sqlite-viewcompiler.js +31 -2
  44. package/lib/execution/runner.js +37 -2
  45. package/lib/knex-builder/FunctionHelper.js +21 -0
  46. package/lib/migrations/common/MigrationsLoader.js +36 -0
  47. package/lib/migrations/migrate/MigrationGenerator.js +1 -1
  48. package/lib/migrations/migrate/Migrator.js +20 -23
  49. package/lib/migrations/migrate/migration-list-resolver.js +2 -5
  50. package/lib/migrations/migrate/{configuration-merger.js → migrator-configuration-merger.js} +2 -4
  51. package/lib/migrations/migrate/sources/fs-migrations.js +4 -29
  52. package/lib/migrations/migrate/stub/js.stub +8 -1
  53. package/lib/migrations/migrate/stub/knexfile-js.stub +3 -0
  54. package/lib/migrations/migrate/stub/knexfile-ts.stub +5 -2
  55. package/lib/migrations/migrate/table-creator.js +6 -5
  56. package/lib/migrations/seed/Seeder.js +25 -92
  57. package/lib/migrations/seed/seeder-configuration-merger.js +60 -0
  58. package/lib/migrations/seed/sources/fs-seeds.js +65 -0
  59. package/lib/migrations/seed/stub/js.stub +4 -1
  60. package/lib/migrations/util/import-file.js +0 -1
  61. package/lib/query/joinclause.js +24 -5
  62. package/lib/query/method-constants.js +37 -0
  63. package/lib/query/querybuilder.js +230 -5
  64. package/lib/query/querycompiler.js +269 -84
  65. package/lib/schema/columnbuilder.js +8 -0
  66. package/lib/schema/columncompiler.js +132 -5
  67. package/lib/schema/compiler.js +1 -0
  68. package/lib/schema/tablebuilder.js +41 -8
  69. package/lib/schema/tablecompiler.js +57 -0
  70. package/lib/schema/viewcompiler.js +13 -10
  71. package/package.json +35 -22
  72. package/scripts/docker-compose.yml +7 -7
  73. package/scripts/oracledb-install-driver-libs.sh +82 -0
  74. package/scripts/runkit-example.js +1 -1
  75. package/scripts/stress-test/docker-compose.yml +3 -3
  76. package/scripts/stress-test/knex-stress-test.js +1 -1
  77. package/scripts/stress-test/reconnect-test-mysql-based-drivers.js +1 -1
  78. 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 += `) ${returningSql}values (`;
111
- let i = -1;
112
- while (++i < insertData.values.length) {
113
- if (i !== 0) sql += '), (';
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
- sql = '';
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
- const insertData = this._prepInsert(insertValues);
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
- `select ${hints}${distinctClause}` +
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.client.parameter(
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.client.parameter(
531
- this.single.limit,
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 = 'nvarchar(max)';
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 = 'uniqueidentifier';
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
- // make unique constraint that allows null https://stackoverflow.com/a/767702/360060
305
- // to be more or less compatible with other DBs (if any of the columns is NULL then "duplicates" are allowed)
306
- this.pushQuery(
307
- `CREATE UNIQUE INDEX ${indexName} ON ${this.tableName()} (${this.formatter.columnize(
308
- columns
309
- )}) WHERE ${whereAllTheColumnsAreNotNull}`
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
- sql += ' (' + columns.join(', ') + ')';
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
- if (
93
- connection.state === 'connected' ||
94
- connection.state === 'authenticated'
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.client.parameter(
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
- if (comment.length > 60)
45
+ const MAX_COMMENT_LENGTH = 1024;
46
+ if (comment.length > MAX_COMMENT_LENGTH)
46
47
  this.client.logger.warn(
47
- 'The max length for a table comment is 60 characters'
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
- columns
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
- if (connection._fatalError) {
19
- return false;
20
- }
21
- return true;
18
+ return (
19
+ connection &&
20
+ !connection._fatalError &&
21
+ !connection._protocolError &&
22
+ !connection._closing &&
23
+ !connection.stream.destroyed
24
+ );
22
25
  }
23
26
  }
24
27