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
package/CHANGELOG.md CHANGED
@@ -1,14 +1,85 @@
1
1
  # Master (Unreleased)
2
2
 
3
+ # 1.0.1 - 16 January, 2022
4
+
5
+ ### Bug fixes:
6
+
7
+ - Fix package.json metadata
8
+
9
+ # 1.0.0 - 16 January, 2022
10
+
11
+ ### Breaking changes
12
+
13
+ - Dropped support for Node 10;
14
+ - Replaced unsupported `sqlite3` driver with `@vscode/sqlite3`;
15
+ - Changed data structure from `RETURNING` operation to be consistent with `SELECT`;
16
+ - Changed Migrator to return list of migrations as objects consistently.
17
+
18
+ ### New features:
19
+
20
+ - Support fromRaw #4781
21
+ - Support zero precision in timestamp/datetime #4784
22
+ - Support whereLike and whereILike #4779
23
+ - Add JSDoc (TS flavor) to stub files #4809
24
+ - Allow skip binding in limit and offset #4811
25
+ - Support creating a new table in the database based on another table #4821
26
+ - Accept Raw on onIn joins #4830
27
+ - Implement support for custom seed sources #4842
28
+ - Add binary uuid option #4836
29
+ - ForUpdate array parameter #4882
30
+ - Add camel case to timestamps method #4803
31
+ - Advanced JSON support #4859
32
+ - Add type to TypeScript knexfile #4909
33
+ - Checks Constraints Support #4874
34
+ - Support creating multiple PKs with increments #4903
35
+ - Enable wrapIdentifier for SQLite .hasTable #4915
36
+ - MSSQL: Add support for unique constraint #4887
37
+ - SQLite: New dialect, using better-sqlite3 driver #4871
38
+ - SQLite: Switch to @vscode/sqlite3 #4866
39
+ - SQLite: Support createViewOrReplace #4856
40
+ - SQLite: Support RETURNING statements for better-sqlite3 driver #4934
41
+ - PostgreSQL: Support JOIN and USING syntax for Delete Statement #4800
42
+
43
+ ### Bug fixes:
44
+
45
+ - Fix overzealous warning on use of whereNot with "in" or "between" #4780
46
+ - Fix Union all + first syntax error #4799
47
+ - Make view columns optional in create view like #4829
48
+ - Insert lock row fix during migration #4865
49
+ - Fix for createViewOrReplace #4856
50
+ - SQLite: Fix foreign key constraints when altering a table #4189
51
+ - MySQL: Validate connection fix #4794
52
+ - MySQL: Set comment size warning limit to 1024 #4867
53
+
54
+ ### Typings:
55
+
56
+ - Allow string indexType in index creation #4791
57
+ - Add missing ints typings #4832
58
+ - Returning method types #4881
59
+ - Improve columnInfo type #4868
60
+
61
+ # 0.95.15 - 22 December, 2021
62
+
63
+ ### Bug fixes:
64
+
65
+ - Oracle:
66
+ - MariaDB: lock row fix during migration in MariaDB and Oracle #4865
67
+
68
+ # 0.95.14 - 09 November, 2021
69
+
70
+ ### Bug fixes:
71
+
72
+ - MySQL: mysql2 dialect validate connection fix #4794
73
+
3
74
  # 0.95.13 - 02 November, 2021
4
75
 
5
76
  ### Bug fixes:
6
77
 
7
- - PostgreSQL: Support zero precision in timestamp/datetime #4784
8
-
78
+ - PostgreSQL: Support zero precision in timestamp/datetime #4784
79
+
9
80
  ### Typings:
10
81
 
11
- - Allow string indexType in index creation #4791
82
+ - Allow string indexType in index creation #4791
12
83
 
13
84
  # 0.95.12 - 28 October, 2021
14
85
 
package/README.md CHANGED
@@ -19,7 +19,7 @@ Node.js, featuring:
19
19
  - both a [promise](https://knexjs.org/#Interfaces-Promises) and [callback](https://knexjs.org/#Interfaces-Callbacks) API
20
20
  - a [thorough test suite](https://github.com/knex/knex/actions)
21
21
 
22
- Node.js versions 10+ are supported.
22
+ Node.js versions 12+ are supported.
23
23
 
24
24
  * Take a look at the [full documentation](https://knexjs.org) to get started!
25
25
  * Browse the [list of plugins and tools](https://github.com/knex/knex/blob/master/ECOSYSTEM.md) built for knex
package/UPGRADING.md CHANGED
@@ -1,5 +1,12 @@
1
1
  ## Upgrading to new knex.js versions
2
2
 
3
+ ### Upgrading to version 1.0.0+
4
+
5
+ * Node.js older than 12 is no longer supported, make sure to update your environment;
6
+ * If you are using `sqlite3` driver, please replace it with `@vscode/sqlite3`;
7
+ * `RETURNING` operations now always return an object with column names;
8
+ * Migrator now returns list of migrations as objects.
9
+
3
10
  ### Upgrading to version 0.95.0+
4
11
 
5
12
  * TypeScript type exports changed significantly. While `import Knex from 'knex';` used to import the knex instantiation function, the namespace and the interface for the knex instantiation function/object, there is now a clear distinction between them:
package/lib/client.js CHANGED
@@ -30,6 +30,7 @@ const Logger = require('./logger');
30
30
  const { POOL_CONFIG_OPTIONS } = require('./constants');
31
31
  const ViewBuilder = require('./schema/viewbuilder.js');
32
32
  const ViewCompiler = require('./schema/viewcompiler.js');
33
+ const isPlainObject = require('lodash/isPlainObject');
33
34
 
34
35
  const debug = require('debug')('knex:client');
35
36
 
@@ -51,6 +52,7 @@ class Client extends EventEmitter {
51
52
  `Using 'this.dialect' to identify the client is deprecated and support for it will be removed in the future. Please use configuration option 'client' instead.`
52
53
  );
53
54
  }
55
+
54
56
  const dbClient = this.config.client || this.dialect;
55
57
  if (!dbClient) {
56
58
  throw new Error(
@@ -392,8 +394,13 @@ class Client extends EventEmitter {
392
394
  i = -1;
393
395
  while (++i < values.length) {
394
396
  if (i > 0) str += ', ';
397
+ let value = values[i];
398
+ // json columns can have object in values.
399
+ if (isPlainObject(value)) {
400
+ value = JSON.stringify(value);
401
+ }
395
402
  str += this.parameter(
396
- values[i] === undefined ? notSetValue : values[i],
403
+ value === undefined ? notSetValue : value,
397
404
  builder,
398
405
  bindingsHolder
399
406
  );
@@ -442,6 +449,12 @@ class Client extends EventEmitter {
442
449
  processPassedConnection(connection) {
443
450
  // Default implementation is noop
444
451
  }
452
+
453
+ toPathForJson(jsonPath) {
454
+ // By default, we want a json path, so if this function is not overriden,
455
+ // we return the path.
456
+ return jsonPath;
457
+ }
445
458
  }
446
459
 
447
460
  Object.assign(Client.prototype, {
package/lib/constants.js CHANGED
@@ -16,6 +16,7 @@ const SUPPORTED_CLIENTS = Object.freeze(
16
16
  'redshift',
17
17
  'sqlite3',
18
18
  'cockroachdb',
19
+ 'better-sqlite3',
19
20
  ].concat(Object.keys(CLIENT_ALIASES))
20
21
  );
21
22
 
@@ -29,6 +30,7 @@ const DRIVER_NAMES = Object.freeze({
29
30
  Redshift: 'pg-redshift',
30
31
  SQLite: 'sqlite3',
31
32
  CockroachDB: 'cockroachdb',
33
+ BetterSQLite3: 'better-sqlite3',
32
34
  });
33
35
 
34
36
  const POOL_CONFIG_OPTIONS = Object.freeze([
@@ -0,0 +1,72 @@
1
+ // better-sqlite3 Client
2
+ // -------
3
+ const Client_SQLite3 = require('../sqlite3');
4
+
5
+ class Client_BetterSQLite3 extends Client_SQLite3 {
6
+ _driver() {
7
+ return require('better-sqlite3');
8
+ }
9
+
10
+ // Get a raw connection from the database, returning a promise with the connection object.
11
+ async acquireRawConnection() {
12
+ return new this.driver(this.connectionSettings.filename);
13
+ }
14
+
15
+ // Used to explicitly close a connection, called internally by the pool when
16
+ // a connection times out or the pool is shutdown.
17
+ async destroyRawConnection(connection) {
18
+ return connection.close();
19
+ }
20
+
21
+ // Runs the query on the specified connection, providing the bindings and any
22
+ // other necessary prep work.
23
+ async _query(connection, obj) {
24
+ if (!obj.sql) throw new Error('The query is empty');
25
+
26
+ if (!connection) {
27
+ throw new Error('No connection provided');
28
+ }
29
+
30
+ const statement = connection.prepare(obj.sql);
31
+ const bindings = this._formatBindings(obj.bindings);
32
+
33
+ if (statement.reader) {
34
+ const response = await statement.all(bindings);
35
+ obj.response = response;
36
+ return obj;
37
+ }
38
+
39
+ const response = await statement.run(bindings);
40
+ obj.response = response;
41
+ obj.context = {
42
+ lastID: response.lastInsertRowid,
43
+ changes: response.changes,
44
+ };
45
+
46
+ return obj;
47
+ }
48
+
49
+ _formatBindings(bindings) {
50
+ if (!bindings) {
51
+ return [];
52
+ }
53
+ return bindings.map((binding) => {
54
+ if (binding instanceof Date) {
55
+ return binding.valueOf();
56
+ }
57
+
58
+ if (typeof binding === 'boolean') {
59
+ return String(binding);
60
+ }
61
+
62
+ return binding;
63
+ });
64
+ }
65
+ }
66
+
67
+ Object.assign(Client_BetterSQLite3.prototype, {
68
+ // The "dialect", for reference .
69
+ driverName: 'better-sqlite3',
70
+ });
71
+
72
+ module.exports = Client_BetterSQLite3;
@@ -1,6 +1,9 @@
1
1
  const QueryCompiler_PG = require('../postgres/query/pg-querycompiler');
2
- const isEmpty = require('lodash/isEmpty');
3
- const { columnize: columnize_ } = require('../../formatter/wrappingFormatter');
2
+ const {
3
+ columnize: columnize_,
4
+ wrap: wrap_,
5
+ operator: operator_,
6
+ } = require('../../formatter/wrappingFormatter');
4
7
 
5
8
  class QueryCompiler_CRDB extends QueryCompiler_PG {
6
9
  truncate() {
@@ -20,43 +23,94 @@ class QueryCompiler_CRDB extends QueryCompiler_PG {
20
23
 
21
24
  _upsert() {
22
25
  const upsertValues = this.single.upsert || [];
23
- let sql = this.with() + `upsert into ${this.tableName} `;
24
- if (Array.isArray(upsertValues)) {
25
- if (upsertValues.length === 0) return '';
26
- } else if (typeof upsertValues === 'object' && isEmpty(upsertValues)) {
27
- return sql + this._emptyInsertValue;
26
+ const sql = this.with() + `upsert into ${this.tableName} `;
27
+ const body = this._insertBody(upsertValues);
28
+ return body === '' ? '' : sql + body;
29
+ }
30
+
31
+ whereJsonPath(statement) {
32
+ let castValue = '';
33
+ if (parseInt(statement.value)) {
34
+ castValue = '::int';
35
+ } else if (parseFloat(statement.value)) {
36
+ castValue = '::float';
37
+ } else {
38
+ castValue = " #>> '{}'";
28
39
  }
40
+ return `json_extract_path(${this._columnClause(
41
+ statement
42
+ )}, ${this.client.toArrayPathFromJsonPath(
43
+ statement.jsonPath,
44
+ this.builder,
45
+ this.bindingsHolder
46
+ )})${castValue} ${operator_(
47
+ statement.operator,
48
+ this.builder,
49
+ this.client,
50
+ this.bindingsHolder
51
+ )} ${this._jsonValueClause(statement)}`;
52
+ }
29
53
 
30
- const upsertData = this._prepInsert(upsertValues);
31
- if (typeof upsertData === 'string') {
32
- sql += upsertData;
54
+ // Json common functions
55
+ _jsonExtract(nameFunction, params) {
56
+ let extractions;
57
+ if (Array.isArray(params.column)) {
58
+ extractions = params.column;
33
59
  } else {
34
- if (upsertData.columns.length) {
35
- sql += `(${columnize_(
36
- upsertData.columns,
60
+ extractions = [params];
61
+ }
62
+ return extractions
63
+ .map((extraction) => {
64
+ const jsonCol = `json_extract_path(${columnize_(
65
+ extraction.column || extraction[0],
37
66
  this.builder,
38
67
  this.client,
39
68
  this.bindingsHolder
40
- )}`;
41
- sql += ') values (';
42
- let i = -1;
43
- while (++i < upsertData.values.length) {
44
- if (i !== 0) sql += '), (';
45
- sql += this.client.parameterize(
46
- upsertData.values[i],
47
- this.client.valueForUndefined,
48
- this.builder,
49
- this.bindingsHolder
50
- );
51
- }
52
- sql += ')';
53
- } else if (upsertValues.length === 1 && upsertValues[0]) {
54
- sql += this._emptyInsertValue;
55
- } else {
56
- sql = '';
57
- }
58
- }
59
- return sql;
69
+ )}, ${this.client.toArrayPathFromJsonPath(
70
+ extraction.path || extraction[1],
71
+ this.builder,
72
+ this.bindingsHolder
73
+ )})`;
74
+ const alias = extraction.alias || extraction[2];
75
+ return alias
76
+ ? this.client.alias(jsonCol, this.formatter.wrap(alias))
77
+ : jsonCol;
78
+ })
79
+ .join(', ');
80
+ }
81
+
82
+ _onJsonPathEquals(nameJoinFunction, clause) {
83
+ return (
84
+ 'json_extract_path(' +
85
+ wrap_(
86
+ clause.columnFirst,
87
+ undefined,
88
+ this.builder,
89
+ this.client,
90
+ this.bindingsHolder
91
+ ) +
92
+ ', ' +
93
+ this.client.toArrayPathFromJsonPath(
94
+ clause.jsonPathFirst,
95
+ this.builder,
96
+ this.bindingsHolder
97
+ ) +
98
+ ') = json_extract_path(' +
99
+ wrap_(
100
+ clause.columnSecond,
101
+ undefined,
102
+ this.builder,
103
+ this.client,
104
+ this.bindingsHolder
105
+ ) +
106
+ ', ' +
107
+ this.client.toArrayPathFromJsonPath(
108
+ clause.jsonPathSecond,
109
+ this.builder,
110
+ this.bindingsHolder
111
+ ) +
112
+ ')'
113
+ );
60
114
  }
61
115
  }
62
116
 
@@ -7,6 +7,25 @@ class TableCompiler_CRDB extends TableCompiler {
7
7
  super(client, tableBuilder);
8
8
  }
9
9
 
10
+ addColumns(columns, prefix, colCompilers) {
11
+ if (prefix === this.alterColumnsPrefix) {
12
+ // alter columns
13
+ for (const col of colCompilers) {
14
+ this.client.logger.warn(
15
+ 'Experimental alter column in use, see issue: https://github.com/cockroachdb/cockroach/issues/49329'
16
+ );
17
+ this.pushQuery({
18
+ sql: 'SET enable_experimental_alter_column_type_general = true',
19
+ bindings: [],
20
+ });
21
+ super._addColumn(col);
22
+ }
23
+ } else {
24
+ // base class implementation for normal add
25
+ super.addColumns(columns, prefix);
26
+ }
27
+ }
28
+
10
29
  dropUnique(columns, indexName) {
11
30
  indexName = indexName
12
31
  ? this.formatter.wrap(indexName)
@@ -58,6 +58,19 @@ class Client_CockroachDB extends Client_PostgreSQL {
58
58
  connectionToKill.activeQuery
59
59
  );
60
60
  }
61
+
62
+ toArrayPathFromJsonPath(jsonPath, builder, bindingsHolder) {
63
+ return jsonPath
64
+ .replace(/^(\$\.)/, '') // remove the first dollar
65
+ .replace(/\[([0-9]+)]/, '.$1')
66
+ .split('.')
67
+ .map(
68
+ function (v) {
69
+ return this.parameter(v, builder, bindingsHolder);
70
+ }.bind(this)
71
+ )
72
+ .join(', ');
73
+ }
61
74
  }
62
75
 
63
76
  Object.assign(Client_CockroachDB.prototype, {
@@ -1,8 +1,6 @@
1
1
  // MSSQL Client
2
2
  // -------
3
- const flatten = require('lodash/flatten');
4
3
  const map = require('lodash/map');
5
- const values = require('lodash/values');
6
4
  const isNil = require('lodash/isNil');
7
5
 
8
6
  const Client = require('../../client');
@@ -472,15 +470,6 @@ class Client_MSSQL extends Client {
472
470
  if (query.returning === '@@rowcount') {
473
471
  return response[0][''];
474
472
  }
475
-
476
- if (
477
- (Array.isArray(query.returning) && query.returning.length > 1) ||
478
- query.returning[0] === '*'
479
- ) {
480
- return response;
481
- }
482
- // return an array with values if only one returning value was specified
483
- return flatten(map(response, values));
484
473
  }
485
474
  return response;
486
475
  default: