knex 3.2.2 → 3.2.4

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 (199) hide show
  1. package/CHANGELOG.md +2447 -2441
  2. package/CONTRIBUTING.md +190 -190
  3. package/LICENSE +22 -22
  4. package/README.md +156 -156
  5. package/UPGRADING.md +245 -245
  6. package/bin/cli.js +516 -516
  7. package/bin/knexfile-runtime-error.js +27 -27
  8. package/bin/utils/cli-config-utils.js +217 -217
  9. package/bin/utils/constants.js +7 -7
  10. package/bin/utils/migrationsLister.js +37 -37
  11. package/knex.js +23 -23
  12. package/knex.mjs +11 -11
  13. package/lib/builder-interface-augmenter.js +120 -120
  14. package/lib/client.js +585 -585
  15. package/lib/constants.js +61 -61
  16. package/lib/dialects/better-sqlite3/index.js +101 -101
  17. package/lib/dialects/cockroachdb/crdb-columncompiler.js +14 -14
  18. package/lib/dialects/cockroachdb/crdb-querybuilder.js +11 -11
  19. package/lib/dialects/cockroachdb/crdb-querycompiler.js +122 -122
  20. package/lib/dialects/cockroachdb/crdb-tablecompiler.js +46 -46
  21. package/lib/dialects/cockroachdb/crdb-viewcompiler.js +15 -15
  22. package/lib/dialects/cockroachdb/index.js +86 -86
  23. package/lib/dialects/index.js +34 -34
  24. package/lib/dialects/mssql/index.js +498 -498
  25. package/lib/dialects/mssql/mssql-formatter.js +34 -34
  26. package/lib/dialects/mssql/query/mssql-querycompiler.js +601 -601
  27. package/lib/dialects/mssql/schema/mssql-columncompiler.js +185 -185
  28. package/lib/dialects/mssql/schema/mssql-compiler.js +91 -91
  29. package/lib/dialects/mssql/schema/mssql-tablecompiler.js +393 -393
  30. package/lib/dialects/mssql/schema/mssql-viewcompiler.js +55 -55
  31. package/lib/dialects/mssql/transaction.js +176 -176
  32. package/lib/dialects/mysql/index.js +317 -317
  33. package/lib/dialects/mysql/query/mysql-querybuilder.js +14 -14
  34. package/lib/dialects/mysql/query/mysql-querycompiler.js +292 -292
  35. package/lib/dialects/mysql/schema/mysql-columncompiler.js +193 -193
  36. package/lib/dialects/mysql/schema/mysql-compiler.js +60 -60
  37. package/lib/dialects/mysql/schema/mysql-tablecompiler.js +426 -426
  38. package/lib/dialects/mysql/schema/mysql-viewbuilder.js +21 -21
  39. package/lib/dialects/mysql/schema/mysql-viewcompiler.js +15 -15
  40. package/lib/dialects/mysql/transaction.js +46 -46
  41. package/lib/dialects/mysql2/index.js +53 -53
  42. package/lib/dialects/mysql2/transaction.js +44 -44
  43. package/lib/dialects/oracle/DEAD_CODE.md +5 -5
  44. package/lib/dialects/oracle/index.js +92 -92
  45. package/lib/dialects/oracle/query/oracle-querycompiler.js +343 -343
  46. package/lib/dialects/oracle/schema/internal/incrementUtils.js +22 -22
  47. package/lib/dialects/oracle/schema/internal/trigger.js +155 -155
  48. package/lib/dialects/oracle/schema/oracle-columnbuilder.js +17 -17
  49. package/lib/dialects/oracle/schema/oracle-columncompiler.js +126 -126
  50. package/lib/dialects/oracle/schema/oracle-compiler.js +124 -124
  51. package/lib/dialects/oracle/schema/oracle-tablecompiler.js +210 -210
  52. package/lib/dialects/oracle/utils.js +107 -107
  53. package/lib/dialects/oracledb/index.js +381 -381
  54. package/lib/dialects/oracledb/query/oracledb-querycompiler.js +481 -481
  55. package/lib/dialects/oracledb/schema/oracledb-columncompiler.js +61 -61
  56. package/lib/dialects/oracledb/schema/oracledb-tablecompiler.js +19 -19
  57. package/lib/dialects/oracledb/schema/oracledb-viewbuilder.js +13 -13
  58. package/lib/dialects/oracledb/schema/oracledb-viewcompiler.js +19 -19
  59. package/lib/dialects/oracledb/transaction.js +98 -98
  60. package/lib/dialects/oracledb/utils.js +208 -208
  61. package/lib/dialects/pgnative/index.js +60 -60
  62. package/lib/dialects/postgres/execution/pg-transaction.js +19 -19
  63. package/lib/dialects/postgres/index.js +373 -373
  64. package/lib/dialects/postgres/query/pg-querybuilder.js +43 -43
  65. package/lib/dialects/postgres/query/pg-querycompiler.js +400 -400
  66. package/lib/dialects/postgres/schema/pg-columncompiler.js +162 -162
  67. package/lib/dialects/postgres/schema/pg-compiler.js +138 -138
  68. package/lib/dialects/postgres/schema/pg-tablecompiler.js +331 -331
  69. package/lib/dialects/postgres/schema/pg-viewbuilder.js +21 -21
  70. package/lib/dialects/postgres/schema/pg-viewcompiler.js +35 -35
  71. package/lib/dialects/redshift/index.js +86 -86
  72. package/lib/dialects/redshift/query/redshift-querycompiler.js +163 -163
  73. package/lib/dialects/redshift/schema/redshift-columnbuilder.js +22 -22
  74. package/lib/dialects/redshift/schema/redshift-columncompiler.js +67 -67
  75. package/lib/dialects/redshift/schema/redshift-compiler.js +14 -14
  76. package/lib/dialects/redshift/schema/redshift-tablecompiler.js +134 -134
  77. package/lib/dialects/redshift/schema/redshift-viewcompiler.js +11 -11
  78. package/lib/dialects/redshift/transaction.js +32 -32
  79. package/lib/dialects/sqlite3/execution/sqlite-transaction.js +172 -172
  80. package/lib/dialects/sqlite3/index.js +263 -263
  81. package/lib/dialects/sqlite3/query/sqlite-querybuilder.js +33 -33
  82. package/lib/dialects/sqlite3/query/sqlite-querycompiler.js +341 -341
  83. package/lib/dialects/sqlite3/schema/ddl.js +380 -380
  84. package/lib/dialects/sqlite3/schema/internal/compiler.js +327 -327
  85. package/lib/dialects/sqlite3/schema/internal/parser-combinator.js +161 -161
  86. package/lib/dialects/sqlite3/schema/internal/parser.js +638 -638
  87. package/lib/dialects/sqlite3/schema/internal/sqlite-ddl-operations.js +41 -41
  88. package/lib/dialects/sqlite3/schema/internal/tokenizer.js +38 -38
  89. package/lib/dialects/sqlite3/schema/internal/utils.js +12 -12
  90. package/lib/dialects/sqlite3/schema/sqlite-columncompiler.js +50 -50
  91. package/lib/dialects/sqlite3/schema/sqlite-compiler.js +80 -80
  92. package/lib/dialects/sqlite3/schema/sqlite-tablecompiler.js +364 -364
  93. package/lib/dialects/sqlite3/schema/sqlite-viewcompiler.js +40 -40
  94. package/lib/execution/batch-insert.js +51 -51
  95. package/lib/execution/internal/delay.js +6 -6
  96. package/lib/execution/internal/ensure-connection-callback.js +41 -41
  97. package/lib/execution/internal/query-executioner.js +62 -62
  98. package/lib/execution/runner.js +325 -325
  99. package/lib/execution/transaction.js +417 -417
  100. package/lib/formatter/formatterUtils.js +42 -42
  101. package/lib/formatter/rawFormatter.js +84 -84
  102. package/lib/formatter/wrappingFormatter.js +253 -253
  103. package/lib/formatter.js +25 -25
  104. package/lib/index.js +3 -3
  105. package/lib/knex-builder/FunctionHelper.js +80 -80
  106. package/lib/knex-builder/Knex.js +59 -59
  107. package/lib/knex-builder/internal/config-resolver.js +57 -57
  108. package/lib/knex-builder/internal/parse-connection.js +87 -87
  109. package/lib/knex-builder/make-knex.js +345 -345
  110. package/lib/logger.js +76 -76
  111. package/lib/migrations/common/MigrationsLoader.js +36 -36
  112. package/lib/migrations/migrate/MigrationGenerator.js +84 -84
  113. package/lib/migrations/migrate/Migrator.js +632 -632
  114. package/lib/migrations/migrate/migrate-stub.js +17 -17
  115. package/lib/migrations/migrate/migration-list-resolver.js +33 -33
  116. package/lib/migrations/migrate/migrator-configuration-merger.js +58 -58
  117. package/lib/migrations/migrate/sources/fs-migrations.js +74 -74
  118. package/lib/migrations/migrate/stub/cjs.stub +15 -15
  119. package/lib/migrations/migrate/stub/coffee.stub +13 -13
  120. package/lib/migrations/migrate/stub/eg.stub +14 -14
  121. package/lib/migrations/migrate/stub/js-schema.stub +22 -22
  122. package/lib/migrations/migrate/stub/js.stub +22 -22
  123. package/lib/migrations/migrate/stub/knexfile-coffee.stub +34 -34
  124. package/lib/migrations/migrate/stub/knexfile-eg.stub +43 -43
  125. package/lib/migrations/migrate/stub/knexfile-js.stub +47 -47
  126. package/lib/migrations/migrate/stub/knexfile-ls.stub +35 -35
  127. package/lib/migrations/migrate/stub/knexfile-ts.stub +47 -47
  128. package/lib/migrations/migrate/stub/ls.stub +14 -14
  129. package/lib/migrations/migrate/stub/mjs.stub +23 -23
  130. package/lib/migrations/migrate/stub/ts-schema.stub +21 -21
  131. package/lib/migrations/migrate/stub/ts.stub +21 -21
  132. package/lib/migrations/migrate/table-creator.js +77 -77
  133. package/lib/migrations/migrate/table-resolver.js +27 -27
  134. package/lib/migrations/seed/Seeder.js +137 -137
  135. package/lib/migrations/seed/seed-stub.js +13 -13
  136. package/lib/migrations/seed/seeder-configuration-merger.js +60 -60
  137. package/lib/migrations/seed/sources/fs-seeds.js +65 -65
  138. package/lib/migrations/seed/stub/coffee.stub +9 -9
  139. package/lib/migrations/seed/stub/eg.stub +11 -11
  140. package/lib/migrations/seed/stub/js.stub +13 -13
  141. package/lib/migrations/seed/stub/ls.stub +11 -11
  142. package/lib/migrations/seed/stub/mjs.stub +12 -12
  143. package/lib/migrations/seed/stub/ts.stub +13 -13
  144. package/lib/migrations/util/fs.js +86 -86
  145. package/lib/migrations/util/import-file.js +12 -12
  146. package/lib/migrations/util/is-module-type.js +9 -9
  147. package/lib/migrations/util/template.js +52 -52
  148. package/lib/migrations/util/timestamp.js +14 -14
  149. package/lib/query/analytic.js +52 -52
  150. package/lib/query/constants.js +15 -15
  151. package/lib/query/joinclause.js +270 -270
  152. package/lib/query/method-constants.js +136 -136
  153. package/lib/query/querybuilder.js +1793 -1793
  154. package/lib/query/querycompiler.js +1634 -1634
  155. package/lib/raw.js +139 -139
  156. package/lib/ref.js +39 -39
  157. package/lib/schema/builder.js +115 -115
  158. package/lib/schema/columnbuilder.js +146 -146
  159. package/lib/schema/columncompiler.js +307 -307
  160. package/lib/schema/compiler.js +187 -187
  161. package/lib/schema/internal/helpers.js +55 -55
  162. package/lib/schema/tablebuilder.js +379 -379
  163. package/lib/schema/tablecompiler.js +450 -450
  164. package/lib/schema/viewbuilder.js +92 -92
  165. package/lib/schema/viewcompiler.js +138 -138
  166. package/lib/util/finally-mixin.js +13 -13
  167. package/lib/util/helpers.js +95 -95
  168. package/lib/util/is.js +32 -32
  169. package/lib/util/nanoid.js +40 -40
  170. package/lib/util/noop.js +1 -1
  171. package/lib/util/save-async-stack.js +14 -14
  172. package/lib/util/security.js +32 -32
  173. package/lib/util/string.js +190 -190
  174. package/lib/util/timeout.js +29 -29
  175. package/package.json +294 -296
  176. package/scripts/act-testing/act.sh +19 -19
  177. package/scripts/act-testing/merged-no-label.json +11 -11
  178. package/scripts/act-testing/merged-patch-labeled.json +12 -12
  179. package/scripts/act-testing/merged-skip-labeled.json +12 -12
  180. package/scripts/act-testing/not-merged-patch-labeled.json +12 -12
  181. package/scripts/build-for-release.sh +121 -121
  182. package/scripts/build.js +125 -125
  183. package/scripts/clean.js +31 -31
  184. package/scripts/docker-compose.yml +150 -150
  185. package/scripts/format-changelog.js +55 -55
  186. package/scripts/next-release-howto.md +24 -24
  187. package/scripts/oracledb-install-driver-libs.sh +82 -82
  188. package/scripts/release.sh +36 -36
  189. package/scripts/runkit-example.js +35 -35
  190. package/scripts/stress-test/README.txt +18 -18
  191. package/scripts/stress-test/docker-compose.yml +55 -55
  192. package/scripts/stress-test/knex-stress-test.js +212 -212
  193. package/scripts/stress-test/mysql2-random-hanging-every-now-and-then.js +149 -149
  194. package/scripts/stress-test/mysql2-sudden-exit-without-error.js +101 -101
  195. package/scripts/stress-test/reconnect-test-mysql-based-drivers.js +188 -188
  196. package/types/index.d.mts +11 -0
  197. package/types/index.d.ts +3321 -3321
  198. package/types/result.d.ts +27 -27
  199. package/types/tables.d.ts +4 -4
@@ -1,172 +1,172 @@
1
- const Transaction = require('../../../execution/transaction');
2
-
3
- const {
4
- isForeignCheckEnabled,
5
- setForeignCheck,
6
- executeForeignCheck,
7
- } = require('../schema/internal/sqlite-ddl-operations');
8
-
9
- class Transaction_Sqlite extends Transaction {
10
- // Change the `foreign_keys` pragma if it doesn't match what we want it to be.
11
- // Return what it should be set to (if anything) when the transaction completes.
12
- async _setForeignCheck(conn, enforce) {
13
- // do nothing if we're not explicitly opted in
14
- if (enforce == null) return null;
15
-
16
- // see what the current pragma is
17
- const result = await this.client
18
- .raw(isForeignCheckEnabled())
19
- .connection(conn);
20
- const isEnabled = result[0].foreign_keys === 1;
21
-
22
- // do nothing if it's already what we require it to be
23
- if (enforce === isEnabled) return null;
24
-
25
- // make the change and return what it used to be so we can set it back
26
- await this.client.raw(setForeignCheck(enforce)).connection(conn);
27
- return isEnabled;
28
- }
29
-
30
- // When a boolean is supplied, unconditionally set the `foreign_keys` pragma to
31
- // the given value. Otherwise do nothing.
32
- async _restoreForeignCheck(conn, enable) {
33
- if (typeof enable !== 'boolean') return;
34
- await this.client.raw(setForeignCheck(enable)).connection(conn);
35
- }
36
-
37
- // Override Transaction's behavior. Sqlite3 will not error on a `pragma foreign_keys = <value>` statement
38
- // inside of a transaction; it will just silently not take effect: https://sqlite.org/pragma.html#pragma_foreign_keys
39
- // To deal with this, we introduce a config option "enforceForeignCheck". When set to a value, Transaction_Sqlite
40
- // ensures that the transaction received by the caller has this pragma enabled or disabled, and puts it back
41
- // when the transaction is done.
42
- async _evaluateContainer(config, container) {
43
- // this is the same condition used in Transaction._onAcquire() to decide whether to use "BEGIN" or "SAVEPOINT"
44
- const hasOuterTransaction = this.client.transacting;
45
-
46
- // this is true when our client was created by Client_SQLite3._strict()
47
- const strictForeignKeyPragma = this.client.strictForeignKeyPragma;
48
-
49
- // this comes from the options bag passed to client.transaction()
50
- // undefined = wasn't set by caller
51
- // true = ensure foreign_keys pragma is enabled within the transaction
52
- // false = ensure foreign_keys pragma is disabled within the transaction
53
- // null = leave it however it already is
54
- const enforceForeignCheck = config.enforceForeignCheck;
55
-
56
- // if we're in strict mode, require the caller to be explicit about foreign key
57
- // constraint requirements
58
- if (strictForeignKeyPragma === true && enforceForeignCheck === undefined) {
59
- throw new Error(
60
- 'Refusing to create an unsafe transaction: client.strictForeignKeyPragma is true, but check.enforceForeignCheck is unspecified'
61
- );
62
- }
63
-
64
- // call the base class's acquireConnection logic to get ahold of a connection before the transaction is created
65
- return this.acquireConnection(config, async (conn) => {
66
- let restoreForeignCheck = undefined;
67
- try {
68
- // change the `foreign_keys` pragma if we need to, and decide what we should set it back to, if anything
69
- restoreForeignCheck = await this._setForeignCheck(
70
- conn,
71
- enforceForeignCheck
72
- );
73
- } catch (e) {
74
- // We don't need to dispose the connection here, because none of the things that can throw an error
75
- // can leave the connection in an unexpected state. Just reject the begin transaction.
76
- const error = new Error(
77
- `Refusing to create transaction: failed to set \`foreign_keys\` pragma to the required value of ${enforceForeignCheck}`
78
- );
79
- error.cause = e;
80
- throw error;
81
- }
82
-
83
- // if:
84
- // - we're in a nested transaction
85
- // - _and_ we're in strict mode
86
- // - _and_ we are required to change the pragma
87
- // then: we cannot continue, it's out of our hands
88
- if (
89
- strictForeignKeyPragma &&
90
- hasOuterTransaction &&
91
- restoreForeignCheck !== undefined
92
- ) {
93
- throw new Error(
94
- `Refusing to create transaction: unable to change \`foreign_keys\` pragma inside a nested transaction`
95
- );
96
- }
97
-
98
- let maybeWrappedContainer = container;
99
- if (restoreForeignCheck === true) {
100
- // in the case where we are turning foreign key checks off for the duration of a transaction,
101
- // we need to assert that there are no violations once the work of the transaction has been
102
- // completed. this relies on the fact that Transaction._onAcquire runs the "container" promise
103
- // to completion before executing "COMMIT"
104
- maybeWrappedContainer = async (trx) => {
105
- const res = await container(trx);
106
-
107
- const foreignViolations = await this.client
108
- .raw(executeForeignCheck())
109
- .connection(conn);
110
-
111
- if (foreignViolations.length > 0) {
112
- throw new Error(
113
- `Transaction concluded with ${foreignViolations.length} foreign key violations`
114
- );
115
- }
116
- return res;
117
- };
118
- }
119
-
120
- try {
121
- // call out to the base class to actually do the work as it normally would
122
- // note: the await is required here! we need to resolve the promise, not
123
- // return it
124
- return await this._onAcquire(maybeWrappedContainer, conn);
125
- } finally {
126
- // set the foreign_keys pragma back to what it was before we performed the transaction
127
- this._restoreForeignCheck(conn, restoreForeignCheck).catch((e) => {
128
- // we were unable to put it back like we found it. dispose the connection and
129
- // allow any further queries to re-acquire a new, clean connection
130
- this._logAndDispose(
131
- conn,
132
- 'Failed to restore foreign check to expected state',
133
- e
134
- );
135
- });
136
- }
137
- });
138
- }
139
-
140
- _logAndDispose(conn, message, cause) {
141
- const error = new Error(message);
142
- error.cause = cause;
143
- conn.__knex__disposed = error;
144
- this.client.logger.warn(
145
- `Transaction_Sqlite: ${message}:\n${
146
- cause instanceof Error ? cause.message : String(cause)
147
- }`
148
- );
149
- }
150
-
151
- begin(conn) {
152
- // SQLite doesn't really support isolation levels, it is serializable by
153
- // default and so we override it to ignore isolation level.
154
- // There is a `PRAGMA read_uncommitted = true;`, but that's probably not
155
- // what the user wants
156
- if (this.isolationLevel) {
157
- this.client.logger.warn(
158
- 'sqlite3 only supports serializable transactions, ignoring the isolation level param'
159
- );
160
- }
161
- // SQLite infers read vs write transactions from the statement operation
162
- // https://www.sqlite.org/lang_transaction.html#read_transactions_versus_write_transactions
163
- if (this.readOnly) {
164
- this.client.logger.warn(
165
- 'sqlite3 implicitly handles read vs write transactions'
166
- );
167
- }
168
- return this.query(conn, 'BEGIN;');
169
- }
170
- }
171
-
172
- module.exports = Transaction_Sqlite;
1
+ const Transaction = require('../../../execution/transaction');
2
+
3
+ const {
4
+ isForeignCheckEnabled,
5
+ setForeignCheck,
6
+ executeForeignCheck,
7
+ } = require('../schema/internal/sqlite-ddl-operations');
8
+
9
+ class Transaction_Sqlite extends Transaction {
10
+ // Change the `foreign_keys` pragma if it doesn't match what we want it to be.
11
+ // Return what it should be set to (if anything) when the transaction completes.
12
+ async _setForeignCheck(conn, enforce) {
13
+ // do nothing if we're not explicitly opted in
14
+ if (enforce == null) return null;
15
+
16
+ // see what the current pragma is
17
+ const result = await this.client
18
+ .raw(isForeignCheckEnabled())
19
+ .connection(conn);
20
+ const isEnabled = result[0].foreign_keys === 1;
21
+
22
+ // do nothing if it's already what we require it to be
23
+ if (enforce === isEnabled) return null;
24
+
25
+ // make the change and return what it used to be so we can set it back
26
+ await this.client.raw(setForeignCheck(enforce)).connection(conn);
27
+ return isEnabled;
28
+ }
29
+
30
+ // When a boolean is supplied, unconditionally set the `foreign_keys` pragma to
31
+ // the given value. Otherwise do nothing.
32
+ async _restoreForeignCheck(conn, enable) {
33
+ if (typeof enable !== 'boolean') return;
34
+ await this.client.raw(setForeignCheck(enable)).connection(conn);
35
+ }
36
+
37
+ // Override Transaction's behavior. Sqlite3 will not error on a `pragma foreign_keys = <value>` statement
38
+ // inside of a transaction; it will just silently not take effect: https://sqlite.org/pragma.html#pragma_foreign_keys
39
+ // To deal with this, we introduce a config option "enforceForeignCheck". When set to a value, Transaction_Sqlite
40
+ // ensures that the transaction received by the caller has this pragma enabled or disabled, and puts it back
41
+ // when the transaction is done.
42
+ async _evaluateContainer(config, container) {
43
+ // this is the same condition used in Transaction._onAcquire() to decide whether to use "BEGIN" or "SAVEPOINT"
44
+ const hasOuterTransaction = this.client.transacting;
45
+
46
+ // this is true when our client was created by Client_SQLite3._strict()
47
+ const strictForeignKeyPragma = this.client.strictForeignKeyPragma;
48
+
49
+ // this comes from the options bag passed to client.transaction()
50
+ // undefined = wasn't set by caller
51
+ // true = ensure foreign_keys pragma is enabled within the transaction
52
+ // false = ensure foreign_keys pragma is disabled within the transaction
53
+ // null = leave it however it already is
54
+ const enforceForeignCheck = config.enforceForeignCheck;
55
+
56
+ // if we're in strict mode, require the caller to be explicit about foreign key
57
+ // constraint requirements
58
+ if (strictForeignKeyPragma === true && enforceForeignCheck === undefined) {
59
+ throw new Error(
60
+ 'Refusing to create an unsafe transaction: client.strictForeignKeyPragma is true, but check.enforceForeignCheck is unspecified'
61
+ );
62
+ }
63
+
64
+ // call the base class's acquireConnection logic to get ahold of a connection before the transaction is created
65
+ return this.acquireConnection(config, async (conn) => {
66
+ let restoreForeignCheck = undefined;
67
+ try {
68
+ // change the `foreign_keys` pragma if we need to, and decide what we should set it back to, if anything
69
+ restoreForeignCheck = await this._setForeignCheck(
70
+ conn,
71
+ enforceForeignCheck
72
+ );
73
+ } catch (e) {
74
+ // We don't need to dispose the connection here, because none of the things that can throw an error
75
+ // can leave the connection in an unexpected state. Just reject the begin transaction.
76
+ const error = new Error(
77
+ `Refusing to create transaction: failed to set \`foreign_keys\` pragma to the required value of ${enforceForeignCheck}`
78
+ );
79
+ error.cause = e;
80
+ throw error;
81
+ }
82
+
83
+ // if:
84
+ // - we're in a nested transaction
85
+ // - _and_ we're in strict mode
86
+ // - _and_ we are required to change the pragma
87
+ // then: we cannot continue, it's out of our hands
88
+ if (
89
+ strictForeignKeyPragma &&
90
+ hasOuterTransaction &&
91
+ restoreForeignCheck !== undefined
92
+ ) {
93
+ throw new Error(
94
+ `Refusing to create transaction: unable to change \`foreign_keys\` pragma inside a nested transaction`
95
+ );
96
+ }
97
+
98
+ let maybeWrappedContainer = container;
99
+ if (restoreForeignCheck === true) {
100
+ // in the case where we are turning foreign key checks off for the duration of a transaction,
101
+ // we need to assert that there are no violations once the work of the transaction has been
102
+ // completed. this relies on the fact that Transaction._onAcquire runs the "container" promise
103
+ // to completion before executing "COMMIT"
104
+ maybeWrappedContainer = async (trx) => {
105
+ const res = await container(trx);
106
+
107
+ const foreignViolations = await this.client
108
+ .raw(executeForeignCheck())
109
+ .connection(conn);
110
+
111
+ if (foreignViolations.length > 0) {
112
+ throw new Error(
113
+ `Transaction concluded with ${foreignViolations.length} foreign key violations`
114
+ );
115
+ }
116
+ return res;
117
+ };
118
+ }
119
+
120
+ try {
121
+ // call out to the base class to actually do the work as it normally would
122
+ // note: the await is required here! we need to resolve the promise, not
123
+ // return it
124
+ return await this._onAcquire(maybeWrappedContainer, conn);
125
+ } finally {
126
+ // set the foreign_keys pragma back to what it was before we performed the transaction
127
+ this._restoreForeignCheck(conn, restoreForeignCheck).catch((e) => {
128
+ // we were unable to put it back like we found it. dispose the connection and
129
+ // allow any further queries to re-acquire a new, clean connection
130
+ this._logAndDispose(
131
+ conn,
132
+ 'Failed to restore foreign check to expected state',
133
+ e
134
+ );
135
+ });
136
+ }
137
+ });
138
+ }
139
+
140
+ _logAndDispose(conn, message, cause) {
141
+ const error = new Error(message);
142
+ error.cause = cause;
143
+ conn.__knex__disposed = error;
144
+ this.client.logger.warn(
145
+ `Transaction_Sqlite: ${message}:\n${
146
+ cause instanceof Error ? cause.message : String(cause)
147
+ }`
148
+ );
149
+ }
150
+
151
+ begin(conn) {
152
+ // SQLite doesn't really support isolation levels, it is serializable by
153
+ // default and so we override it to ignore isolation level.
154
+ // There is a `PRAGMA read_uncommitted = true;`, but that's probably not
155
+ // what the user wants
156
+ if (this.isolationLevel) {
157
+ this.client.logger.warn(
158
+ 'sqlite3 only supports serializable transactions, ignoring the isolation level param'
159
+ );
160
+ }
161
+ // SQLite infers read vs write transactions from the statement operation
162
+ // https://www.sqlite.org/lang_transaction.html#read_transactions_versus_write_transactions
163
+ if (this.readOnly) {
164
+ this.client.logger.warn(
165
+ 'sqlite3 implicitly handles read vs write transactions'
166
+ );
167
+ }
168
+ return this.query(conn, 'BEGIN;');
169
+ }
170
+ }
171
+
172
+ module.exports = Transaction_Sqlite;