knex 2.4.2 → 2.5.0

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 (190) hide show
  1. package/CHANGELOG.md +54 -18
  2. package/CONTRIBUTING.md +194 -194
  3. package/LICENSE +22 -22
  4. package/README.md +147 -148
  5. package/UPGRADING.md +233 -233
  6. package/bin/cli.js +473 -473
  7. package/bin/utils/cli-config-utils.js +210 -210
  8. package/bin/utils/constants.js +7 -7
  9. package/bin/utils/migrationsLister.js +37 -37
  10. package/knex.js +23 -23
  11. package/knex.mjs +11 -0
  12. package/lib/builder-interface-augmenter.js +120 -120
  13. package/lib/client.js +495 -475
  14. package/lib/constants.js +61 -61
  15. package/lib/dialects/better-sqlite3/index.js +77 -72
  16. package/lib/dialects/cockroachdb/crdb-columncompiler.js +14 -14
  17. package/lib/dialects/cockroachdb/crdb-querybuilder.js +11 -11
  18. package/lib/dialects/cockroachdb/crdb-querycompiler.js +122 -122
  19. package/lib/dialects/cockroachdb/crdb-tablecompiler.js +37 -37
  20. package/lib/dialects/cockroachdb/crdb-viewcompiler.js +15 -15
  21. package/lib/dialects/cockroachdb/index.js +86 -86
  22. package/lib/dialects/index.js +33 -33
  23. package/lib/dialects/mssql/index.js +500 -495
  24. package/lib/dialects/mssql/mssql-formatter.js +34 -34
  25. package/lib/dialects/mssql/query/mssql-querycompiler.js +601 -600
  26. package/lib/dialects/mssql/schema/mssql-columncompiler.js +185 -185
  27. package/lib/dialects/mssql/schema/mssql-compiler.js +91 -91
  28. package/lib/dialects/mssql/schema/mssql-tablecompiler.js +378 -378
  29. package/lib/dialects/mssql/schema/mssql-viewcompiler.js +55 -55
  30. package/lib/dialects/mssql/transaction.js +176 -176
  31. package/lib/dialects/mysql/index.js +201 -201
  32. package/lib/dialects/mysql/query/mysql-querycompiler.js +274 -274
  33. package/lib/dialects/mysql/schema/mysql-columncompiler.js +193 -193
  34. package/lib/dialects/mysql/schema/mysql-compiler.js +60 -60
  35. package/lib/dialects/mysql/schema/mysql-tablecompiler.js +381 -381
  36. package/lib/dialects/mysql/schema/mysql-viewbuilder.js +21 -21
  37. package/lib/dialects/mysql/schema/mysql-viewcompiler.js +15 -15
  38. package/lib/dialects/mysql/transaction.js +46 -46
  39. package/lib/dialects/mysql2/index.js +53 -33
  40. package/lib/dialects/mysql2/transaction.js +44 -44
  41. package/lib/dialects/oracle/DEAD_CODE.md +5 -5
  42. package/lib/dialects/oracle/index.js +92 -92
  43. package/lib/dialects/oracle/query/oracle-querycompiler.js +343 -342
  44. package/lib/dialects/oracle/schema/internal/incrementUtils.js +20 -20
  45. package/lib/dialects/oracle/schema/internal/trigger.js +135 -135
  46. package/lib/dialects/oracle/schema/oracle-columnbuilder.js +17 -17
  47. package/lib/dialects/oracle/schema/oracle-columncompiler.js +126 -126
  48. package/lib/dialects/oracle/schema/oracle-compiler.js +122 -122
  49. package/lib/dialects/oracle/schema/oracle-tablecompiler.js +190 -190
  50. package/lib/dialects/oracle/utils.js +87 -87
  51. package/lib/dialects/oracledb/index.js +327 -327
  52. package/lib/dialects/oracledb/query/oracledb-querycompiler.js +481 -481
  53. package/lib/dialects/oracledb/schema/oracledb-columncompiler.js +61 -55
  54. package/lib/dialects/oracledb/schema/oracledb-tablecompiler.js +19 -19
  55. package/lib/dialects/oracledb/schema/oracledb-viewbuilder.js +13 -13
  56. package/lib/dialects/oracledb/schema/oracledb-viewcompiler.js +19 -19
  57. package/lib/dialects/oracledb/transaction.js +98 -98
  58. package/lib/dialects/oracledb/utils.js +208 -208
  59. package/lib/dialects/pgnative/index.js +60 -60
  60. package/lib/dialects/postgres/execution/pg-transaction.js +19 -12
  61. package/lib/dialects/postgres/index.js +358 -358
  62. package/lib/dialects/postgres/query/pg-querybuilder.js +43 -38
  63. package/lib/dialects/postgres/query/pg-querycompiler.js +400 -395
  64. package/lib/dialects/postgres/schema/pg-columncompiler.js +156 -156
  65. package/lib/dialects/postgres/schema/pg-compiler.js +138 -138
  66. package/lib/dialects/postgres/schema/pg-tablecompiler.js +304 -299
  67. package/lib/dialects/postgres/schema/pg-viewbuilder.js +21 -21
  68. package/lib/dialects/postgres/schema/pg-viewcompiler.js +35 -35
  69. package/lib/dialects/redshift/index.js +86 -86
  70. package/lib/dialects/redshift/query/redshift-querycompiler.js +163 -163
  71. package/lib/dialects/redshift/schema/redshift-columnbuilder.js +22 -22
  72. package/lib/dialects/redshift/schema/redshift-columncompiler.js +67 -67
  73. package/lib/dialects/redshift/schema/redshift-compiler.js +14 -14
  74. package/lib/dialects/redshift/schema/redshift-tablecompiler.js +122 -122
  75. package/lib/dialects/redshift/schema/redshift-viewcompiler.js +11 -11
  76. package/lib/dialects/redshift/transaction.js +32 -25
  77. package/lib/dialects/sqlite3/execution/sqlite-transaction.js +25 -18
  78. package/lib/dialects/sqlite3/index.js +250 -250
  79. package/lib/dialects/sqlite3/query/sqlite-querybuilder.js +33 -33
  80. package/lib/dialects/sqlite3/query/sqlite-querycompiler.js +334 -334
  81. package/lib/dialects/sqlite3/schema/ddl.js +400 -400
  82. package/lib/dialects/sqlite3/schema/internal/compiler.js +327 -327
  83. package/lib/dialects/sqlite3/schema/internal/parser-combinator.js +161 -161
  84. package/lib/dialects/sqlite3/schema/internal/parser.js +638 -638
  85. package/lib/dialects/sqlite3/schema/internal/sqlite-ddl-operations.js +41 -41
  86. package/lib/dialects/sqlite3/schema/internal/tokenizer.js +38 -38
  87. package/lib/dialects/sqlite3/schema/internal/utils.js +12 -12
  88. package/lib/dialects/sqlite3/schema/sqlite-columncompiler.js +50 -50
  89. package/lib/dialects/sqlite3/schema/sqlite-compiler.js +80 -80
  90. package/lib/dialects/sqlite3/schema/sqlite-tablecompiler.js +347 -347
  91. package/lib/dialects/sqlite3/schema/sqlite-viewcompiler.js +40 -40
  92. package/lib/execution/batch-insert.js +51 -51
  93. package/lib/execution/internal/delay.js +6 -6
  94. package/lib/execution/internal/ensure-connection-callback.js +41 -41
  95. package/lib/execution/internal/query-executioner.js +62 -62
  96. package/lib/execution/runner.js +325 -307
  97. package/lib/execution/transaction.js +409 -401
  98. package/lib/formatter/formatterUtils.js +42 -42
  99. package/lib/formatter/rawFormatter.js +84 -84
  100. package/lib/formatter/wrappingFormatter.js +250 -250
  101. package/lib/formatter.js +25 -25
  102. package/lib/index.js +3 -3
  103. package/lib/knex-builder/FunctionHelper.js +80 -54
  104. package/lib/knex-builder/Knex.js +59 -59
  105. package/lib/knex-builder/internal/config-resolver.js +57 -57
  106. package/lib/knex-builder/internal/parse-connection.js +87 -87
  107. package/lib/knex-builder/make-knex.js +345 -340
  108. package/lib/logger.js +76 -76
  109. package/lib/migrations/common/MigrationsLoader.js +36 -36
  110. package/lib/migrations/migrate/MigrationGenerator.js +84 -84
  111. package/lib/migrations/migrate/Migrator.js +598 -598
  112. package/lib/migrations/migrate/migrate-stub.js +17 -17
  113. package/lib/migrations/migrate/migration-list-resolver.js +33 -33
  114. package/lib/migrations/migrate/migrator-configuration-merger.js +58 -58
  115. package/lib/migrations/migrate/sources/fs-migrations.js +74 -74
  116. package/lib/migrations/migrate/stub/cjs.stub +15 -15
  117. package/lib/migrations/migrate/stub/coffee.stub +13 -13
  118. package/lib/migrations/migrate/stub/eg.stub +14 -14
  119. package/lib/migrations/migrate/stub/js-schema.stub +22 -22
  120. package/lib/migrations/migrate/stub/js.stub +22 -22
  121. package/lib/migrations/migrate/stub/knexfile-coffee.stub +34 -34
  122. package/lib/migrations/migrate/stub/knexfile-eg.stub +43 -43
  123. package/lib/migrations/migrate/stub/knexfile-js.stub +47 -47
  124. package/lib/migrations/migrate/stub/knexfile-ls.stub +35 -35
  125. package/lib/migrations/migrate/stub/knexfile-ts.stub +47 -47
  126. package/lib/migrations/migrate/stub/ls.stub +14 -14
  127. package/lib/migrations/migrate/stub/mjs.stub +23 -23
  128. package/lib/migrations/migrate/stub/ts-schema.stub +21 -21
  129. package/lib/migrations/migrate/stub/ts.stub +21 -21
  130. package/lib/migrations/migrate/table-creator.js +77 -77
  131. package/lib/migrations/migrate/table-resolver.js +27 -27
  132. package/lib/migrations/seed/Seeder.js +137 -137
  133. package/lib/migrations/seed/seed-stub.js +13 -13
  134. package/lib/migrations/seed/seeder-configuration-merger.js +60 -60
  135. package/lib/migrations/seed/sources/fs-seeds.js +65 -65
  136. package/lib/migrations/seed/stub/coffee.stub +9 -9
  137. package/lib/migrations/seed/stub/eg.stub +11 -11
  138. package/lib/migrations/seed/stub/js.stub +13 -13
  139. package/lib/migrations/seed/stub/ls.stub +11 -11
  140. package/lib/migrations/seed/stub/mjs.stub +12 -12
  141. package/lib/migrations/seed/stub/ts.stub +13 -13
  142. package/lib/migrations/util/fs.js +86 -86
  143. package/lib/migrations/util/import-file.js +12 -12
  144. package/lib/migrations/util/is-module-type.js +9 -9
  145. package/lib/migrations/util/template.js +52 -52
  146. package/lib/migrations/util/timestamp.js +14 -14
  147. package/lib/query/analytic.js +52 -52
  148. package/lib/query/constants.js +15 -15
  149. package/lib/query/joinclause.js +270 -270
  150. package/lib/query/method-constants.js +136 -135
  151. package/lib/query/querybuilder.js +1793 -1794
  152. package/lib/query/querycompiler.js +1591 -1580
  153. package/lib/raw.js +139 -139
  154. package/lib/ref.js +39 -39
  155. package/lib/schema/builder.js +115 -115
  156. package/lib/schema/columnbuilder.js +146 -146
  157. package/lib/schema/columncompiler.js +307 -307
  158. package/lib/schema/compiler.js +187 -187
  159. package/lib/schema/internal/helpers.js +55 -55
  160. package/lib/schema/tablebuilder.js +376 -376
  161. package/lib/schema/tablecompiler.js +433 -433
  162. package/lib/schema/viewbuilder.js +92 -92
  163. package/lib/schema/viewcompiler.js +138 -138
  164. package/lib/util/finally-mixin.js +13 -13
  165. package/lib/util/helpers.js +95 -95
  166. package/lib/util/is.js +32 -32
  167. package/lib/util/nanoid.js +40 -40
  168. package/lib/util/noop.js +1 -1
  169. package/lib/util/save-async-stack.js +14 -14
  170. package/lib/util/security.js +26 -0
  171. package/lib/util/string.js +190 -190
  172. package/lib/util/timeout.js +29 -29
  173. package/package.json +12 -10
  174. package/scripts/build.js +125 -125
  175. package/scripts/clean.js +31 -31
  176. package/scripts/docker-compose.yml +152 -152
  177. package/scripts/next-release-howto.md +24 -24
  178. package/scripts/oracledb-install-driver-libs.sh +82 -82
  179. package/scripts/release.sh +34 -34
  180. package/scripts/runkit-example.js +34 -34
  181. package/scripts/stress-test/README.txt +18 -18
  182. package/scripts/stress-test/docker-compose.yml +57 -57
  183. package/scripts/stress-test/knex-stress-test.js +208 -208
  184. package/scripts/stress-test/mysql2-random-hanging-every-now-and-then.js +145 -145
  185. package/scripts/stress-test/mysql2-sudden-exit-without-error.js +100 -100
  186. package/scripts/stress-test/reconnect-test-mysql-based-drivers.js +184 -184
  187. package/scripts/update_gitignore_for_tsc_output.js +90 -90
  188. package/types/index.d.ts +3273 -3233
  189. package/types/result.d.ts +27 -27
  190. package/types/tables.d.ts +4 -4
@@ -1,347 +1,347 @@
1
- const filter = require('lodash/filter');
2
- const values = require('lodash/values');
3
- const identity = require('lodash/identity');
4
- const { isObject } = require('../../../util/is');
5
-
6
- const TableCompiler = require('../../../schema/tablecompiler');
7
- const { formatDefault } = require('../../../formatter/formatterUtils');
8
-
9
- class TableCompiler_SQLite3 extends TableCompiler {
10
- constructor() {
11
- super(...arguments);
12
- }
13
-
14
- // Create a new table.
15
- createQuery(columns, ifNot, like) {
16
- const createStatement = ifNot
17
- ? 'create table if not exists '
18
- : 'create table ';
19
-
20
- let sql = createStatement + this.tableName();
21
-
22
- if (like && this.tableNameLike()) {
23
- sql += ' as select * from ' + this.tableNameLike() + ' where 0=1';
24
- } else {
25
- // so we will need to check for a primary key commands and add the columns
26
- // to the table's declaration here so they can be created on the tables.
27
- sql += ' (' + columns.sql.join(', ');
28
- sql += this.foreignKeys() || '';
29
- sql += this.primaryKeys() || '';
30
- sql += this._addChecks();
31
- sql += ')';
32
- }
33
- this.pushQuery(sql);
34
-
35
- if (like) {
36
- this.addColumns(columns, this.addColumnsPrefix);
37
- }
38
- }
39
-
40
- addColumns(columns, prefix, colCompilers) {
41
- if (prefix === this.alterColumnsPrefix) {
42
- const compiler = this;
43
-
44
- const columnsInfo = colCompilers.map((col) => {
45
- const name = this.client.customWrapIdentifier(
46
- col.getColumnName(),
47
- identity,
48
- col.columnBuilder.queryContext()
49
- );
50
-
51
- const type = col.getColumnType();
52
-
53
- const defaultTo = col.modified['defaultTo']
54
- ? formatDefault(col.modified['defaultTo'][0], col.type, this.client)
55
- : null;
56
-
57
- const notNull =
58
- col.modified['nullable'] && col.modified['nullable'][0] === false;
59
-
60
- return { name, type, defaultTo, notNull };
61
- });
62
-
63
- this.pushQuery({
64
- sql: `PRAGMA table_info(${this.tableName()})`,
65
- statementsProducer(pragma, connection) {
66
- return compiler.client
67
- .ddl(compiler, pragma, connection)
68
- .alterColumn(columnsInfo);
69
- },
70
- });
71
- } else {
72
- for (let i = 0, l = columns.sql.length; i < l; i++) {
73
- this.pushQuery({
74
- sql: `alter table ${this.tableName()} add column ${columns.sql[i]}`,
75
- bindings: columns.bindings[i],
76
- });
77
- }
78
- }
79
- }
80
-
81
- // Compile a drop unique key command.
82
- dropUnique(columns, indexName) {
83
- indexName = indexName
84
- ? this.formatter.wrap(indexName)
85
- : this._indexCommand('unique', this.tableNameRaw, columns);
86
- this.pushQuery(`drop index ${indexName}`);
87
- }
88
-
89
- // Compile a drop foreign key command.
90
- dropForeign(columns, indexName) {
91
- const compiler = this;
92
-
93
- columns = Array.isArray(columns) ? columns : [columns];
94
- columns = columns.map((column) =>
95
- this.client.customWrapIdentifier(column, identity)
96
- );
97
- indexName = this.client.customWrapIdentifier(indexName, identity);
98
-
99
- this.pushQuery({
100
- sql: `PRAGMA table_info(${this.tableName()})`,
101
- output(pragma) {
102
- return compiler.client
103
- .ddl(compiler, pragma, this.connection)
104
- .dropForeign(columns, indexName);
105
- },
106
- });
107
- }
108
-
109
- // Compile a drop primary key command.
110
- dropPrimary(constraintName) {
111
- const compiler = this;
112
-
113
- constraintName = this.client.customWrapIdentifier(constraintName, identity);
114
-
115
- this.pushQuery({
116
- sql: `PRAGMA table_info(${this.tableName()})`,
117
- output(pragma) {
118
- return compiler.client
119
- .ddl(compiler, pragma, this.connection)
120
- .dropPrimary(constraintName);
121
- },
122
- });
123
- }
124
-
125
- dropIndex(columns, indexName) {
126
- indexName = indexName
127
- ? this.formatter.wrap(indexName)
128
- : this._indexCommand('index', this.tableNameRaw, columns);
129
- this.pushQuery(`drop index ${indexName}`);
130
- }
131
-
132
- // Compile a unique key command.
133
- unique(columns, indexName) {
134
- let deferrable;
135
- let predicate;
136
- if (isObject(indexName)) {
137
- ({ indexName, deferrable, predicate } = indexName);
138
- }
139
- if (deferrable && deferrable !== 'not deferrable') {
140
- this.client.logger.warn(
141
- `sqlite3: unique index \`${indexName}\` will not be deferrable ${deferrable} because sqlite3 does not support deferred constraints.`
142
- );
143
- }
144
- indexName = indexName
145
- ? this.formatter.wrap(indexName)
146
- : this._indexCommand('unique', this.tableNameRaw, columns);
147
- columns = this.formatter.columnize(columns);
148
-
149
- const predicateQuery = predicate
150
- ? ' ' + this.client.queryCompiler(predicate).where()
151
- : '';
152
-
153
- this.pushQuery(
154
- `create unique index ${indexName} on ${this.tableName()} (${columns})${predicateQuery}`
155
- );
156
- }
157
-
158
- // Compile a plain index key command.
159
- index(columns, indexName, options) {
160
- indexName = indexName
161
- ? this.formatter.wrap(indexName)
162
- : this._indexCommand('index', this.tableNameRaw, columns);
163
- columns = this.formatter.columnize(columns);
164
-
165
- let predicate;
166
- if (isObject(options)) {
167
- ({ predicate } = options);
168
- }
169
- const predicateQuery = predicate
170
- ? ' ' + this.client.queryCompiler(predicate).where()
171
- : '';
172
- this.pushQuery(
173
- `create index ${indexName} on ${this.tableName()} (${columns})${predicateQuery}`
174
- );
175
- }
176
-
177
- /**
178
- * Add a primary key to an existing table.
179
- *
180
- * @NOTE The `createQuery` method above handles table creation. Don't do anything regarding table
181
- * creation in this method
182
- *
183
- * @param {string | string[]} columns - Column name(s) to assign as primary keys
184
- * @param {string} [constraintName] - Custom name for the PK constraint
185
- */
186
- primary(columns, constraintName) {
187
- const compiler = this;
188
-
189
- columns = Array.isArray(columns) ? columns : [columns];
190
- columns = columns.map((column) =>
191
- this.client.customWrapIdentifier(column, identity)
192
- );
193
-
194
- let deferrable;
195
- if (isObject(constraintName)) {
196
- ({ constraintName, deferrable } = constraintName);
197
- }
198
- if (deferrable && deferrable !== 'not deferrable') {
199
- this.client.logger.warn(
200
- `sqlite3: primary key constraint \`${constraintName}\` will not be deferrable ${deferrable} because sqlite3 does not support deferred constraints.`
201
- );
202
- }
203
- constraintName = this.client.customWrapIdentifier(constraintName, identity);
204
-
205
- if (this.method !== 'create' && this.method !== 'createIfNot') {
206
- this.pushQuery({
207
- sql: `PRAGMA table_info(${this.tableName()})`,
208
- output(pragma) {
209
- return compiler.client
210
- .ddl(compiler, pragma, this.connection)
211
- .primary(columns, constraintName);
212
- },
213
- });
214
- }
215
- }
216
-
217
- /**
218
- * Add a foreign key constraint to an existing table
219
- *
220
- * @NOTE The `createQuery` method above handles foreign key constraints on table creation. Don't do
221
- * anything regarding table creation in this method
222
- *
223
- * @param {object} foreignInfo - Information about the current column foreign setup
224
- * @param {string | string[]} [foreignInfo.column] - Column in the current constraint
225
- * @param {string | undefined} foreignInfo.keyName - Name of the foreign key constraint
226
- * @param {string | string[]} foreignInfo.references - What column it references in the other table
227
- * @param {string} foreignInfo.inTable - What table is referenced in this constraint
228
- * @param {string} [foreignInfo.onUpdate] - What to do on updates
229
- * @param {string} [foreignInfo.onDelete] - What to do on deletions
230
- */
231
- foreign(foreignInfo) {
232
- const compiler = this;
233
-
234
- if (this.method !== 'create' && this.method !== 'createIfNot') {
235
- foreignInfo.column = Array.isArray(foreignInfo.column)
236
- ? foreignInfo.column
237
- : [foreignInfo.column];
238
- foreignInfo.column = foreignInfo.column.map((column) =>
239
- this.client.customWrapIdentifier(column, identity)
240
- );
241
- foreignInfo.inTable = this.client.customWrapIdentifier(
242
- foreignInfo.inTable,
243
- identity
244
- );
245
- foreignInfo.references = Array.isArray(foreignInfo.references)
246
- ? foreignInfo.references
247
- : [foreignInfo.references];
248
- foreignInfo.references = foreignInfo.references.map((column) =>
249
- this.client.customWrapIdentifier(column, identity)
250
- );
251
-
252
- this.pushQuery({
253
- sql: `PRAGMA table_info(${this.tableName()})`,
254
- statementsProducer(pragma, connection) {
255
- return compiler.client
256
- .ddl(compiler, pragma, connection)
257
- .foreign(foreignInfo);
258
- },
259
- });
260
- }
261
- }
262
-
263
- primaryKeys() {
264
- const pks = filter(this.grouped.alterTable || [], { method: 'primary' });
265
- if (pks.length > 0 && pks[0].args.length > 0) {
266
- const columns = pks[0].args[0];
267
- let constraintName = pks[0].args[1] || '';
268
- if (constraintName) {
269
- constraintName = ' constraint ' + this.formatter.wrap(constraintName);
270
- }
271
- const needUniqueCols =
272
- this.grouped.columns.filter((t) => t.builder._type === 'increments')
273
- .length > 0;
274
- // SQLite dont support autoincrement columns and composite primary keys (autoincrement is always primary key).
275
- // You need to add unique index instead when you have autoincrement columns (https://stackoverflow.com/a/6154876/1535159)
276
- return `,${constraintName} ${
277
- needUniqueCols ? 'unique' : 'primary key'
278
- } (${this.formatter.columnize(columns)})`;
279
- }
280
- }
281
-
282
- foreignKeys() {
283
- let sql = '';
284
- const foreignKeys = filter(this.grouped.alterTable || [], {
285
- method: 'foreign',
286
- });
287
- for (let i = 0, l = foreignKeys.length; i < l; i++) {
288
- const foreign = foreignKeys[i].args[0];
289
- const column = this.formatter.columnize(foreign.column);
290
- const references = this.formatter.columnize(foreign.references);
291
- const foreignTable = this.formatter.wrap(foreign.inTable);
292
- let constraintName = foreign.keyName || '';
293
- if (constraintName) {
294
- constraintName = ' constraint ' + this.formatter.wrap(constraintName);
295
- }
296
- sql += `,${constraintName} foreign key(${column}) references ${foreignTable}(${references})`;
297
- if (foreign.onDelete) sql += ` on delete ${foreign.onDelete}`;
298
- if (foreign.onUpdate) sql += ` on update ${foreign.onUpdate}`;
299
- }
300
- return sql;
301
- }
302
-
303
- createTableBlock() {
304
- return this.getColumns().concat().join(',');
305
- }
306
-
307
- renameColumn(from, to) {
308
- this.pushQuery({
309
- sql: `alter table ${this.tableName()} rename ${this.formatter.wrap(
310
- from
311
- )} to ${this.formatter.wrap(to)}`,
312
- });
313
- }
314
-
315
- _setNullableState(column, isNullable) {
316
- const compiler = this;
317
-
318
- this.pushQuery({
319
- sql: `PRAGMA table_info(${this.tableName()})`,
320
- statementsProducer(pragma, connection) {
321
- return compiler.client
322
- .ddl(compiler, pragma, connection)
323
- .setNullable(column, isNullable);
324
- },
325
- });
326
- }
327
-
328
- dropColumn() {
329
- const compiler = this;
330
- const columns = values(arguments);
331
-
332
- const columnsWrapped = columns.map((column) =>
333
- this.client.customWrapIdentifier(column, identity)
334
- );
335
-
336
- this.pushQuery({
337
- sql: `PRAGMA table_info(${this.tableName()})`,
338
- output(pragma) {
339
- return compiler.client
340
- .ddl(compiler, pragma, this.connection)
341
- .dropColumn(columnsWrapped);
342
- },
343
- });
344
- }
345
- }
346
-
347
- module.exports = TableCompiler_SQLite3;
1
+ const filter = require('lodash/filter');
2
+ const values = require('lodash/values');
3
+ const identity = require('lodash/identity');
4
+ const { isObject } = require('../../../util/is');
5
+
6
+ const TableCompiler = require('../../../schema/tablecompiler');
7
+ const { formatDefault } = require('../../../formatter/formatterUtils');
8
+
9
+ class TableCompiler_SQLite3 extends TableCompiler {
10
+ constructor() {
11
+ super(...arguments);
12
+ }
13
+
14
+ // Create a new table.
15
+ createQuery(columns, ifNot, like) {
16
+ const createStatement = ifNot
17
+ ? 'create table if not exists '
18
+ : 'create table ';
19
+
20
+ let sql = createStatement + this.tableName();
21
+
22
+ if (like && this.tableNameLike()) {
23
+ sql += ' as select * from ' + this.tableNameLike() + ' where 0=1';
24
+ } else {
25
+ // so we will need to check for a primary key commands and add the columns
26
+ // to the table's declaration here so they can be created on the tables.
27
+ sql += ' (' + columns.sql.join(', ');
28
+ sql += this.foreignKeys() || '';
29
+ sql += this.primaryKeys() || '';
30
+ sql += this._addChecks();
31
+ sql += ')';
32
+ }
33
+ this.pushQuery(sql);
34
+
35
+ if (like) {
36
+ this.addColumns(columns, this.addColumnsPrefix);
37
+ }
38
+ }
39
+
40
+ addColumns(columns, prefix, colCompilers) {
41
+ if (prefix === this.alterColumnsPrefix) {
42
+ const compiler = this;
43
+
44
+ const columnsInfo = colCompilers.map((col) => {
45
+ const name = this.client.customWrapIdentifier(
46
+ col.getColumnName(),
47
+ identity,
48
+ col.columnBuilder.queryContext()
49
+ );
50
+
51
+ const type = col.getColumnType();
52
+
53
+ const defaultTo = col.modified['defaultTo']
54
+ ? formatDefault(col.modified['defaultTo'][0], col.type, this.client)
55
+ : null;
56
+
57
+ const notNull =
58
+ col.modified['nullable'] && col.modified['nullable'][0] === false;
59
+
60
+ return { name, type, defaultTo, notNull };
61
+ });
62
+
63
+ this.pushQuery({
64
+ sql: `PRAGMA table_info(${this.tableName()})`,
65
+ statementsProducer(pragma, connection) {
66
+ return compiler.client
67
+ .ddl(compiler, pragma, connection)
68
+ .alterColumn(columnsInfo);
69
+ },
70
+ });
71
+ } else {
72
+ for (let i = 0, l = columns.sql.length; i < l; i++) {
73
+ this.pushQuery({
74
+ sql: `alter table ${this.tableName()} add column ${columns.sql[i]}`,
75
+ bindings: columns.bindings[i],
76
+ });
77
+ }
78
+ }
79
+ }
80
+
81
+ // Compile a drop unique key command.
82
+ dropUnique(columns, indexName) {
83
+ indexName = indexName
84
+ ? this.formatter.wrap(indexName)
85
+ : this._indexCommand('unique', this.tableNameRaw, columns);
86
+ this.pushQuery(`drop index ${indexName}`);
87
+ }
88
+
89
+ // Compile a drop foreign key command.
90
+ dropForeign(columns, indexName) {
91
+ const compiler = this;
92
+
93
+ columns = Array.isArray(columns) ? columns : [columns];
94
+ columns = columns.map((column) =>
95
+ this.client.customWrapIdentifier(column, identity)
96
+ );
97
+ indexName = this.client.customWrapIdentifier(indexName, identity);
98
+
99
+ this.pushQuery({
100
+ sql: `PRAGMA table_info(${this.tableName()})`,
101
+ output(pragma) {
102
+ return compiler.client
103
+ .ddl(compiler, pragma, this.connection)
104
+ .dropForeign(columns, indexName);
105
+ },
106
+ });
107
+ }
108
+
109
+ // Compile a drop primary key command.
110
+ dropPrimary(constraintName) {
111
+ const compiler = this;
112
+
113
+ constraintName = this.client.customWrapIdentifier(constraintName, identity);
114
+
115
+ this.pushQuery({
116
+ sql: `PRAGMA table_info(${this.tableName()})`,
117
+ output(pragma) {
118
+ return compiler.client
119
+ .ddl(compiler, pragma, this.connection)
120
+ .dropPrimary(constraintName);
121
+ },
122
+ });
123
+ }
124
+
125
+ dropIndex(columns, indexName) {
126
+ indexName = indexName
127
+ ? this.formatter.wrap(indexName)
128
+ : this._indexCommand('index', this.tableNameRaw, columns);
129
+ this.pushQuery(`drop index ${indexName}`);
130
+ }
131
+
132
+ // Compile a unique key command.
133
+ unique(columns, indexName) {
134
+ let deferrable;
135
+ let predicate;
136
+ if (isObject(indexName)) {
137
+ ({ indexName, deferrable, predicate } = indexName);
138
+ }
139
+ if (deferrable && deferrable !== 'not deferrable') {
140
+ this.client.logger.warn(
141
+ `sqlite3: unique index \`${indexName}\` will not be deferrable ${deferrable} because sqlite3 does not support deferred constraints.`
142
+ );
143
+ }
144
+ indexName = indexName
145
+ ? this.formatter.wrap(indexName)
146
+ : this._indexCommand('unique', this.tableNameRaw, columns);
147
+ columns = this.formatter.columnize(columns);
148
+
149
+ const predicateQuery = predicate
150
+ ? ' ' + this.client.queryCompiler(predicate).where()
151
+ : '';
152
+
153
+ this.pushQuery(
154
+ `create unique index ${indexName} on ${this.tableName()} (${columns})${predicateQuery}`
155
+ );
156
+ }
157
+
158
+ // Compile a plain index key command.
159
+ index(columns, indexName, options) {
160
+ indexName = indexName
161
+ ? this.formatter.wrap(indexName)
162
+ : this._indexCommand('index', this.tableNameRaw, columns);
163
+ columns = this.formatter.columnize(columns);
164
+
165
+ let predicate;
166
+ if (isObject(options)) {
167
+ ({ predicate } = options);
168
+ }
169
+ const predicateQuery = predicate
170
+ ? ' ' + this.client.queryCompiler(predicate).where()
171
+ : '';
172
+ this.pushQuery(
173
+ `create index ${indexName} on ${this.tableName()} (${columns})${predicateQuery}`
174
+ );
175
+ }
176
+
177
+ /**
178
+ * Add a primary key to an existing table.
179
+ *
180
+ * @NOTE The `createQuery` method above handles table creation. Don't do anything regarding table
181
+ * creation in this method
182
+ *
183
+ * @param {string | string[]} columns - Column name(s) to assign as primary keys
184
+ * @param {string} [constraintName] - Custom name for the PK constraint
185
+ */
186
+ primary(columns, constraintName) {
187
+ const compiler = this;
188
+
189
+ columns = Array.isArray(columns) ? columns : [columns];
190
+ columns = columns.map((column) =>
191
+ this.client.customWrapIdentifier(column, identity)
192
+ );
193
+
194
+ let deferrable;
195
+ if (isObject(constraintName)) {
196
+ ({ constraintName, deferrable } = constraintName);
197
+ }
198
+ if (deferrable && deferrable !== 'not deferrable') {
199
+ this.client.logger.warn(
200
+ `sqlite3: primary key constraint \`${constraintName}\` will not be deferrable ${deferrable} because sqlite3 does not support deferred constraints.`
201
+ );
202
+ }
203
+ constraintName = this.client.customWrapIdentifier(constraintName, identity);
204
+
205
+ if (this.method !== 'create' && this.method !== 'createIfNot') {
206
+ this.pushQuery({
207
+ sql: `PRAGMA table_info(${this.tableName()})`,
208
+ output(pragma) {
209
+ return compiler.client
210
+ .ddl(compiler, pragma, this.connection)
211
+ .primary(columns, constraintName);
212
+ },
213
+ });
214
+ }
215
+ }
216
+
217
+ /**
218
+ * Add a foreign key constraint to an existing table
219
+ *
220
+ * @NOTE The `createQuery` method above handles foreign key constraints on table creation. Don't do
221
+ * anything regarding table creation in this method
222
+ *
223
+ * @param {object} foreignInfo - Information about the current column foreign setup
224
+ * @param {string | string[]} [foreignInfo.column] - Column in the current constraint
225
+ * @param {string | undefined} foreignInfo.keyName - Name of the foreign key constraint
226
+ * @param {string | string[]} foreignInfo.references - What column it references in the other table
227
+ * @param {string} foreignInfo.inTable - What table is referenced in this constraint
228
+ * @param {string} [foreignInfo.onUpdate] - What to do on updates
229
+ * @param {string} [foreignInfo.onDelete] - What to do on deletions
230
+ */
231
+ foreign(foreignInfo) {
232
+ const compiler = this;
233
+
234
+ if (this.method !== 'create' && this.method !== 'createIfNot') {
235
+ foreignInfo.column = Array.isArray(foreignInfo.column)
236
+ ? foreignInfo.column
237
+ : [foreignInfo.column];
238
+ foreignInfo.column = foreignInfo.column.map((column) =>
239
+ this.client.customWrapIdentifier(column, identity)
240
+ );
241
+ foreignInfo.inTable = this.client.customWrapIdentifier(
242
+ foreignInfo.inTable,
243
+ identity
244
+ );
245
+ foreignInfo.references = Array.isArray(foreignInfo.references)
246
+ ? foreignInfo.references
247
+ : [foreignInfo.references];
248
+ foreignInfo.references = foreignInfo.references.map((column) =>
249
+ this.client.customWrapIdentifier(column, identity)
250
+ );
251
+
252
+ this.pushQuery({
253
+ sql: `PRAGMA table_info(${this.tableName()})`,
254
+ statementsProducer(pragma, connection) {
255
+ return compiler.client
256
+ .ddl(compiler, pragma, connection)
257
+ .foreign(foreignInfo);
258
+ },
259
+ });
260
+ }
261
+ }
262
+
263
+ primaryKeys() {
264
+ const pks = filter(this.grouped.alterTable || [], { method: 'primary' });
265
+ if (pks.length > 0 && pks[0].args.length > 0) {
266
+ const columns = pks[0].args[0];
267
+ let constraintName = pks[0].args[1] || '';
268
+ if (constraintName) {
269
+ constraintName = ' constraint ' + this.formatter.wrap(constraintName);
270
+ }
271
+ const needUniqueCols =
272
+ this.grouped.columns.filter((t) => t.builder._type === 'increments')
273
+ .length > 0;
274
+ // SQLite dont support autoincrement columns and composite primary keys (autoincrement is always primary key).
275
+ // You need to add unique index instead when you have autoincrement columns (https://stackoverflow.com/a/6154876/1535159)
276
+ return `,${constraintName} ${
277
+ needUniqueCols ? 'unique' : 'primary key'
278
+ } (${this.formatter.columnize(columns)})`;
279
+ }
280
+ }
281
+
282
+ foreignKeys() {
283
+ let sql = '';
284
+ const foreignKeys = filter(this.grouped.alterTable || [], {
285
+ method: 'foreign',
286
+ });
287
+ for (let i = 0, l = foreignKeys.length; i < l; i++) {
288
+ const foreign = foreignKeys[i].args[0];
289
+ const column = this.formatter.columnize(foreign.column);
290
+ const references = this.formatter.columnize(foreign.references);
291
+ const foreignTable = this.formatter.wrap(foreign.inTable);
292
+ let constraintName = foreign.keyName || '';
293
+ if (constraintName) {
294
+ constraintName = ' constraint ' + this.formatter.wrap(constraintName);
295
+ }
296
+ sql += `,${constraintName} foreign key(${column}) references ${foreignTable}(${references})`;
297
+ if (foreign.onDelete) sql += ` on delete ${foreign.onDelete}`;
298
+ if (foreign.onUpdate) sql += ` on update ${foreign.onUpdate}`;
299
+ }
300
+ return sql;
301
+ }
302
+
303
+ createTableBlock() {
304
+ return this.getColumns().concat().join(',');
305
+ }
306
+
307
+ renameColumn(from, to) {
308
+ this.pushQuery({
309
+ sql: `alter table ${this.tableName()} rename ${this.formatter.wrap(
310
+ from
311
+ )} to ${this.formatter.wrap(to)}`,
312
+ });
313
+ }
314
+
315
+ _setNullableState(column, isNullable) {
316
+ const compiler = this;
317
+
318
+ this.pushQuery({
319
+ sql: `PRAGMA table_info(${this.tableName()})`,
320
+ statementsProducer(pragma, connection) {
321
+ return compiler.client
322
+ .ddl(compiler, pragma, connection)
323
+ .setNullable(column, isNullable);
324
+ },
325
+ });
326
+ }
327
+
328
+ dropColumn() {
329
+ const compiler = this;
330
+ const columns = values(arguments);
331
+
332
+ const columnsWrapped = columns.map((column) =>
333
+ this.client.customWrapIdentifier(column, identity)
334
+ );
335
+
336
+ this.pushQuery({
337
+ sql: `PRAGMA table_info(${this.tableName()})`,
338
+ output(pragma) {
339
+ return compiler.client
340
+ .ddl(compiler, pragma, this.connection)
341
+ .dropColumn(columnsWrapped);
342
+ },
343
+ });
344
+ }
345
+ }
346
+
347
+ module.exports = TableCompiler_SQLite3;