knex 0.21.15 → 0.21.19

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 CHANGED
@@ -1,5 +1,29 @@
1
1
  # Master (Unreleased)
2
2
 
3
+ # 0.21.19 - 02 March, 2021
4
+
5
+ - SQLite: Made the constraint detection case-insensitive #4332
6
+
7
+ # 0.21.18 - 22 February, 2021
8
+
9
+ - CLI: Fix an issue with npm@7 and ESM when type was set to 'module' in package.json #4295
10
+
11
+ # 0.21.17 - 30 January, 2021
12
+
13
+ ### Bug fixes:
14
+
15
+ - SQLite: Fix SQLite foreign on delete when altering a table #4261
16
+
17
+ ### New features:
18
+
19
+ - Add support for optimizer hints (see https://github.com/knex/documentation/pull/306 for documentation) #4243
20
+
21
+ # 0.21.16 - 17 January, 2021
22
+
23
+ ### Bug fixes:
24
+
25
+ - MSSQL: Avoid passing unsupported pool param. Fixes node-mssql 7+ support #4236
26
+
3
27
  # 0.21.15 - 26 December, 2020
4
28
 
5
29
  ### New features:
package/bin/cli.js CHANGED
File without changes
@@ -31,7 +31,6 @@ function Client_MSSQL(config = {}) {
31
31
  min: 1,
32
32
  max: 1,
33
33
  idleTimeoutMillis: Number.MAX_SAFE_INTEGER,
34
- evictionRunIntervalMillis: 0,
35
34
  };
36
35
 
37
36
  Client.call(this, config);
@@ -262,6 +262,7 @@ class QueryCompiler_MSSQL extends QueryCompiler {
262
262
  let distinctClause = '';
263
263
  if (this.onlyUnions()) return '';
264
264
  const top = this.top();
265
+ const hints = this._hintComments()
265
266
  const columns = this.grouped.columns || [];
266
267
  let i = -1,
267
268
  sql = [];
@@ -285,7 +286,7 @@ class QueryCompiler_MSSQL extends QueryCompiler {
285
286
  if (sql.length === 0) sql = ['*'];
286
287
 
287
288
  return (
288
- `select ${distinctClause}` +
289
+ `select ${hints}${distinctClause}` +
289
290
  (top ? top + ' ' : '') +
290
291
  sql.join(', ') +
291
292
  (this.tableName ? ` from ${this.tableName}` : '')
@@ -333,8 +333,8 @@ assign(SQLite3_DDL.prototype, {
333
333
  .map((line) => line.trim())
334
334
  .filter((defLine) => {
335
335
  if (
336
- defLine.startsWith('constraint') === false &&
337
- defLine.includes('foreign key') === false
336
+ defLine.toLowerCase().startsWith('constraint') === false &&
337
+ defLine.toLowerCase().includes('foreign key') === false
338
338
  )
339
339
  return true;
340
340
 
@@ -486,7 +486,7 @@ assign(SQLite3_DDL.prototype, {
486
486
  }
487
487
 
488
488
  if (foreignInfo.onDelete) {
489
- newForeignSQL += ` ON DELETE ${foreignInfo.onUpdate}`;
489
+ newForeignSQL += ` ON DELETE ${foreignInfo.onDelete}`;
490
490
  }
491
491
 
492
492
  newColumnDefinitions.push(newForeignSQL);
@@ -80,12 +80,16 @@ class Migrator {
80
80
 
81
81
  const transactionForAll =
82
82
  !this.config.disableTransactions &&
83
- !migrations.some((migration) => {
84
- const migrationContents = this.config.migrationSource.getMigration(
85
- migration
86
- );
87
- return !this._useTransaction(migrationContents);
88
- });
83
+ !(
84
+ await Promise.all(
85
+ migrations.map(async (migration) => {
86
+ const migrationContents = await this.config.migrationSource.getMigration(
87
+ migration
88
+ );
89
+ return !this._useTransaction(migrationContents);
90
+ })
91
+ )
92
+ ).some((isTransactionUsed) => isTransactionUsed);
89
93
 
90
94
  if (transactionForAll) {
91
95
  return this.knex.transaction((trx) => {
@@ -133,6 +137,16 @@ class Migrator {
133
137
  migrationToRun = newMigrations[0];
134
138
  }
135
139
 
140
+ return {
141
+ migrationToRun,
142
+ useTransaction:
143
+ !migrationToRun ||
144
+ this._useTransaction(
145
+ this.config.migrationSource.getMigration(migrationToRun)
146
+ ),
147
+ };
148
+ })
149
+ .then(({ migrationToRun, useTransaction }) => {
136
150
  const migrationsToRun = [];
137
151
  if (migrationToRun) {
138
152
  migrationsToRun.push(migrationToRun);
@@ -140,10 +154,7 @@ class Migrator {
140
154
 
141
155
  const transactionForAll =
142
156
  !this.config.disableTransactions &&
143
- (!migrationToRun ||
144
- this._useTransaction(
145
- this.config.migrationSource.getMigration(migrationToRun)
146
- ));
157
+ (!migrationToRun || useTransaction);
147
158
 
148
159
  if (transactionForAll) {
149
160
  return this.knex.transaction((trx) => {
@@ -185,6 +185,25 @@ assign(Builder.prototype, {
185
185
  return this;
186
186
  },
187
187
 
188
+ // Adds a single hint or an array of hits to the list of "hintComments" on the query.
189
+ hintComment(hints) {
190
+ hints = Array.isArray(hints) ? hints : [hints]
191
+ if (hints.some((hint) => !isString(hint))) {
192
+ throw new Error('Hint comment must be a string');
193
+ }
194
+ if (hints.some((hint) => hint.includes('/*') || hint.includes('*/'))) {
195
+ throw new Error('Hint comment cannot include "/*" or "*/"');
196
+ }
197
+ if (hints.some((hint) => hint.includes('?'))) {
198
+ throw new Error('Hint comment cannot include "?"');
199
+ }
200
+ this._statements.push({
201
+ grouping: 'hintComments',
202
+ value: hints,
203
+ })
204
+ return this;
205
+ },
206
+
188
207
  // Prepends the `schemaName` on `tableName` defined by `.table` and `.join`.
189
208
  withSchema(schemaName) {
190
209
  this._single.schema = schemaName;
@@ -1064,7 +1083,7 @@ assign(Builder.prototype, {
1064
1083
 
1065
1084
  // Remove everything from statement clause
1066
1085
  clear(statement) {
1067
- if (!['with', 'select', 'columns', 'where', 'union', 'join', 'group', 'order', 'having', 'limit', 'offset', 'counter', 'counters'].includes(statement))
1086
+ if (!['with', 'select', 'columns', 'hintComments', 'where', 'union', 'join', 'group', 'order', 'having', 'limit', 'offset', 'counter', 'counters'].includes(statement))
1068
1087
  throw new Error(`Knex Error: unknown statement '${statement}'`);
1069
1088
  if (statement.startsWith('counter')) return this.clearCounters();
1070
1089
  if (statement === 'select') { statement = 'columns'; }
@@ -182,10 +182,18 @@ class QueryCompiler {
182
182
  );
183
183
  }
184
184
 
185
+ _hintComments() {
186
+ let hints = this.grouped.hintComments || [];
187
+ hints = hints.map((hint) => compact(hint.value).join(' '));
188
+ hints = compact(hints).join(' ');
189
+ return hints ? `/*+ ${hints} */ ` : ''
190
+ }
191
+
185
192
  // Compiles the columns in the query, specifying if an item was distinct.
186
193
  columns() {
187
194
  let distinctClause = '';
188
195
  if (this.onlyUnions()) return '';
196
+ const hints = this._hintComments()
189
197
  const columns = this.grouped.columns || [];
190
198
  let i = -1,
191
199
  sql = [];
@@ -208,7 +216,7 @@ class QueryCompiler {
208
216
  }
209
217
  if (sql.length === 0) sql = ['*'];
210
218
  return (
211
- `select ${distinctClause}` +
219
+ `select ${hints}${distinctClause}` +
212
220
  sql.join(', ') +
213
221
  (this.tableName
214
222
  ? ` from ${this.single.only ? 'only ' : ''}${this.tableName}`
@@ -1,5 +1,4 @@
1
- // When run via npm, we can leverage the injected environment variables to infer the import type
2
- const isTypeModule = process.env.npm_package_type === 'module'
1
+ const isModuleType = require('./is-module-type');
3
2
 
4
3
  /**
5
4
  * imports 'mjs', else requires.
@@ -7,8 +6,8 @@ const isTypeModule = process.env.npm_package_type === 'module'
7
6
  * @param {string} filepath
8
7
  * @todo WARN on version 10 and '--experimental-modules' and '--esm'
9
8
  */
10
- module.exports = function importFile(filepath) {
11
- return isTypeModule || filepath.endsWith('.mjs')
9
+ module.exports = async function importFile(filepath) {
10
+ return (await isModuleType(filepath))
12
11
  ? import(require('url').pathToFileURL(filepath))
13
12
  : require(filepath);
14
13
  };
@@ -0,0 +1,14 @@
1
+ const { readFile } = require('./fs');
2
+
3
+ module.exports = async function isModuleType(filepath) {
4
+ if (process.env.npm_package_json) {
5
+ // npm >= 7.0.0
6
+ const packageJson = JSON.parse(
7
+ await readFile(process.env.npm_package_json, 'utf-8')
8
+ );
9
+ if (packageJson.type === 'module') {
10
+ return true;
11
+ }
12
+ }
13
+ return process.env.npm_package_type === 'module' || filepath.endsWith('.mjs');
14
+ };
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "knex",
3
- "version": "0.21.15",
3
+ "version": "0.21.19",
4
4
  "description": "A batteries-included SQL query & schema builder for Postgres, MySQL and SQLite3 and the Browser",
5
5
  "main": "knex.js",
6
6
  "types": "types/index.d.ts",
package/types/index.d.ts CHANGED
@@ -460,13 +460,14 @@ declare namespace Knex {
460
460
  //
461
461
  // QueryInterface
462
462
  //
463
- type ClearStatements = "with" | "select" | "columns" | "where" | "union" | "join" | "group" | "order" | "having" | "limit" | "offset" | "counter" | "counters";
463
+ type ClearStatements = "with" | "select" | "columns" | "hintComments" | "where" | "union" | "join" | "group" | "order" | "having" | "limit" | "offset" | "counter" | "counters";
464
464
 
465
465
  interface QueryInterface<TRecord extends {} = any, TResult = any> {
466
466
  select: Select<TRecord, TResult>;
467
467
  as: As<TRecord, TResult>;
468
468
  columns: Select<TRecord, TResult>;
469
469
  column: Select<TRecord, TResult>;
470
+ hintComment: HintComment<TRecord, TResult>;
470
471
  from: Table<TRecord, TResult>;
471
472
  into: Table<TRecord, TResult>;
472
473
  table: Table<TRecord, TResult>;
@@ -978,6 +979,11 @@ declare namespace Knex {
978
979
  ): QueryBuilder<TRecord, TResult2>;
979
980
  }
980
981
 
982
+ interface HintComment<TRecord extends {} = any, TResult extends {} = any> {
983
+ (hint: string): QueryBuilder<TRecord, TResult>;
984
+ (hints: readonly string[]): QueryBuilder<TRecord, TResult>;
985
+ }
986
+
981
987
  interface Table<TRecord extends {} = any, TResult extends {} = any> {
982
988
  <
983
989
  TTable extends TableNames,