knex 0.95.15 → 1.0.3

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 (77) hide show
  1. package/CHANGELOG.md +107 -1
  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 +92 -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-compiler.js +3 -4
  14. package/lib/dialects/mssql/schema/mssql-tablecompiler.js +24 -9
  15. package/lib/dialects/mssql/schema/mssql-viewcompiler.js +15 -1
  16. package/lib/dialects/mysql/query/mysql-querycompiler.js +93 -5
  17. package/lib/dialects/mysql/schema/mysql-columncompiler.js +32 -5
  18. package/lib/dialects/mysql/schema/mysql-tablecompiler.js +72 -10
  19. package/lib/dialects/oracle/query/oracle-querycompiler.js +7 -6
  20. package/lib/dialects/oracle/schema/internal/trigger.js +1 -1
  21. package/lib/dialects/oracle/schema/oracle-columncompiler.js +10 -4
  22. package/lib/dialects/oracle/schema/oracle-tablecompiler.js +17 -6
  23. package/lib/dialects/oracledb/index.js +0 -4
  24. package/lib/dialects/oracledb/query/oracledb-querycompiler.js +89 -0
  25. package/lib/dialects/oracledb/schema/oracledb-columncompiler.js +23 -0
  26. package/lib/dialects/postgres/index.js +21 -6
  27. package/lib/dialects/postgres/query/pg-querybuilder.js +38 -0
  28. package/lib/dialects/postgres/query/pg-querycompiler.js +172 -9
  29. package/lib/dialects/postgres/schema/pg-columncompiler.js +24 -4
  30. package/lib/dialects/postgres/schema/pg-tablecompiler.js +63 -46
  31. package/lib/dialects/redshift/index.js +12 -0
  32. package/lib/dialects/redshift/query/redshift-querycompiler.js +62 -26
  33. package/lib/dialects/redshift/schema/redshift-columncompiler.js +2 -1
  34. package/lib/dialects/redshift/schema/redshift-tablecompiler.js +4 -1
  35. package/lib/dialects/sqlite3/index.js +23 -4
  36. package/lib/dialects/sqlite3/query/sqlite-querybuilder.js +33 -0
  37. package/lib/dialects/sqlite3/query/sqlite-querycompiler.js +87 -22
  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 +36 -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 +21 -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/seed/Seeder.js +25 -92
  56. package/lib/migrations/seed/seeder-configuration-merger.js +60 -0
  57. package/lib/migrations/seed/sources/fs-seeds.js +65 -0
  58. package/lib/migrations/seed/stub/js.stub +11 -11
  59. package/lib/migrations/util/import-file.js +0 -1
  60. package/lib/query/joinclause.js +24 -5
  61. package/lib/query/method-constants.js +39 -0
  62. package/lib/query/querybuilder.js +292 -53
  63. package/lib/query/querycompiler.js +309 -85
  64. package/lib/schema/columnbuilder.js +14 -1
  65. package/lib/schema/columncompiler.js +132 -5
  66. package/lib/schema/compiler.js +1 -0
  67. package/lib/schema/tablebuilder.js +41 -8
  68. package/lib/schema/tablecompiler.js +61 -4
  69. package/lib/schema/viewcompiler.js +13 -10
  70. package/package.json +37 -27
  71. package/scripts/docker-compose.yml +7 -7
  72. package/scripts/oracledb-install-driver-libs.sh +82 -0
  73. package/scripts/runkit-example.js +1 -1
  74. package/scripts/stress-test/docker-compose.yml +3 -3
  75. package/scripts/stress-test/knex-stress-test.js +1 -1
  76. package/scripts/stress-test/reconnect-test-mysql-based-drivers.js +1 -1
  77. package/types/index.d.ts +134 -22
package/CHANGELOG.md CHANGED
@@ -1,5 +1,111 @@
1
1
  # Master (Unreleased)
2
2
 
3
+ # 1.0.3 - 11 February, 2022
4
+
5
+ ### Bug fixes:
6
+
7
+ - Fix error message for missing migration files #4937
8
+ - Add withMaterialized and withNotMaterialized to method-constants #5009
9
+ - PostgreSQL: Fix whereJsonPath queries #5011
10
+ - PostgreSQL: Fix delete joins #5016
11
+ - CockroachDB: Fix whereJsonPath queries #5011
12
+ - MySQL: Create primary keys in same statement #5017
13
+
14
+ ### Typings:
15
+
16
+ - Fix type definition for getMigration in MigrationSource #4998
17
+ - Fix argument type of alter method #4996
18
+
19
+ ### Improvements:
20
+
21
+ - Use async / await syntax in seeds as default #5005
22
+
23
+ ### Documentation:
24
+
25
+ - Add Firebird dialect to ECOSYSTEM.md #5003
26
+
27
+ # 1.0.2 - 02 February, 2022
28
+
29
+ ### New features:
30
+
31
+ - Support of MATERIALIZED and NOT MATERIALIZED with WITH/CTE #4940
32
+ - Add raw support in onConflict clause #4960
33
+ - Alter nullable constraint when alterNullable is set to true #4730
34
+ - Add alterType parameter for alter function #4967
35
+ - Support string json in json values #4988
36
+ - MySQL: add with clause #4508
37
+
38
+ ### Bug fixes:
39
+
40
+ - Fix error message for missing migration files #4937
41
+ - Move deferrable to after on update/on delete #4976
42
+ - Do not use sys.tables to find if a table exists #2328
43
+ - PostgreSQL: Fix Order nulls #4989
44
+ - MySQL: Fix collation when renaming column #2666
45
+ - SQLite: Same boolean handling in better-sqlite3 as in sqlite3 #4982
46
+
47
+ ### Typings:
48
+
49
+ - WhereILike - fix typo #4941
50
+
51
+ # 1.0.1 - 16 January, 2022
52
+
53
+ ### Bug fixes:
54
+
55
+ - Fix package.json metadata
56
+
57
+ # 1.0.0 - 16 January, 2022
58
+
59
+ ### Breaking changes
60
+
61
+ - Dropped support for Node 10;
62
+ - Replaced unsupported `sqlite3` driver with `@vscode/sqlite3`;
63
+ - Changed data structure from `RETURNING` operation to be consistent with `SELECT`;
64
+ - Changed Migrator to return list of migrations as objects consistently.
65
+
66
+ ### New features:
67
+
68
+ - Support fromRaw #4781
69
+ - Support zero precision in timestamp/datetime #4784
70
+ - Support whereLike and whereILike #4779
71
+ - Add JSDoc (TS flavor) to stub files #4809
72
+ - Allow skip binding in limit and offset #4811
73
+ - Support creating a new table in the database based on another table #4821
74
+ - Accept Raw on onIn joins #4830
75
+ - Implement support for custom seed sources #4842
76
+ - Add binary uuid option #4836
77
+ - ForUpdate array parameter #4882
78
+ - Add camel case to timestamps method #4803
79
+ - Advanced JSON support #4859
80
+ - Add type to TypeScript knexfile #4909
81
+ - Checks Constraints Support #4874
82
+ - Support creating multiple PKs with increments #4903
83
+ - Enable wrapIdentifier for SQLite .hasTable #4915
84
+ - MSSQL: Add support for unique constraint #4887
85
+ - SQLite: New dialect, using better-sqlite3 driver #4871
86
+ - SQLite: Switch to @vscode/sqlite3 #4866
87
+ - SQLite: Support createViewOrReplace #4856
88
+ - SQLite: Support RETURNING statements for better-sqlite3 driver #4934
89
+ - PostgreSQL: Support JOIN and USING syntax for Delete Statement #4800
90
+
91
+ ### Bug fixes:
92
+
93
+ - Fix overzealous warning on use of whereNot with "in" or "between" #4780
94
+ - Fix Union all + first syntax error #4799
95
+ - Make view columns optional in create view like #4829
96
+ - Insert lock row fix during migration #4865
97
+ - Fix for createViewOrReplace #4856
98
+ - SQLite: Fix foreign key constraints when altering a table #4189
99
+ - MySQL: Validate connection fix #4794
100
+ - MySQL: Set comment size warning limit to 1024 #4867
101
+
102
+ ### Typings:
103
+
104
+ - Allow string indexType in index creation #4791
105
+ - Add missing ints typings #4832
106
+ - Returning method types #4881
107
+ - Improve columnInfo type #4868
108
+
3
109
  # 0.95.15 - 22 December, 2021
4
110
 
5
111
  ### Bug fixes:
@@ -18,7 +124,7 @@
18
124
  ### Bug fixes:
19
125
 
20
126
  - PostgreSQL: Support zero precision in timestamp/datetime #4784
21
-
127
+
22
128
  ### Typings:
23
129
 
24
130
  - Allow string indexType in index creation #4791
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 dependency, please replace it with `@vscode/sqlite3` in your `package.json`;
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 Number(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,99 @@ 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
+ _groupOrder(item, type) {
32
+ // CockroachDB don't support PostgreSQL order nulls first/last syntax, we take the generic one.
33
+ return this._basicGroupOrder(item, type);
34
+ }
35
+
36
+ whereJsonPath(statement) {
37
+ let castValue = '';
38
+ if (!isNaN(statement.value) && parseInt(statement.value)) {
39
+ castValue = '::int';
40
+ } else if (!isNaN(statement.value) && parseFloat(statement.value)) {
41
+ castValue = '::float';
42
+ } else {
43
+ castValue = " #>> '{}'";
28
44
  }
45
+ return `json_extract_path(${this._columnClause(
46
+ statement
47
+ )}, ${this.client.toArrayPathFromJsonPath(
48
+ statement.jsonPath,
49
+ this.builder,
50
+ this.bindingsHolder
51
+ )})${castValue} ${operator_(
52
+ statement.operator,
53
+ this.builder,
54
+ this.client,
55
+ this.bindingsHolder
56
+ )} ${this._jsonValueClause(statement)}`;
57
+ }
29
58
 
30
- const upsertData = this._prepInsert(upsertValues);
31
- if (typeof upsertData === 'string') {
32
- sql += upsertData;
59
+ // Json common functions
60
+ _jsonExtract(nameFunction, params) {
61
+ let extractions;
62
+ if (Array.isArray(params.column)) {
63
+ extractions = params.column;
33
64
  } else {
34
- if (upsertData.columns.length) {
35
- sql += `(${columnize_(
36
- upsertData.columns,
65
+ extractions = [params];
66
+ }
67
+ return extractions
68
+ .map((extraction) => {
69
+ const jsonCol = `json_extract_path(${columnize_(
70
+ extraction.column || extraction[0],
37
71
  this.builder,
38
72
  this.client,
39
73
  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;
74
+ )}, ${this.client.toArrayPathFromJsonPath(
75
+ extraction.path || extraction[1],
76
+ this.builder,
77
+ this.bindingsHolder
78
+ )})`;
79
+ const alias = extraction.alias || extraction[2];
80
+ return alias
81
+ ? this.client.alias(jsonCol, this.formatter.wrap(alias))
82
+ : jsonCol;
83
+ })
84
+ .join(', ');
85
+ }
86
+
87
+ _onJsonPathEquals(nameJoinFunction, clause) {
88
+ return (
89
+ 'json_extract_path(' +
90
+ wrap_(
91
+ clause.columnFirst,
92
+ undefined,
93
+ this.builder,
94
+ this.client,
95
+ this.bindingsHolder
96
+ ) +
97
+ ', ' +
98
+ this.client.toArrayPathFromJsonPath(
99
+ clause.jsonPathFirst,
100
+ this.builder,
101
+ this.bindingsHolder
102
+ ) +
103
+ ') = json_extract_path(' +
104
+ wrap_(
105
+ clause.columnSecond,
106
+ undefined,
107
+ this.builder,
108
+ this.client,
109
+ this.bindingsHolder
110
+ ) +
111
+ ', ' +
112
+ this.client.toArrayPathFromJsonPath(
113
+ clause.jsonPathSecond,
114
+ this.builder,
115
+ this.bindingsHolder
116
+ ) +
117
+ ')'
118
+ );
60
119
  }
61
120
  }
62
121
 
@@ -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: