knex 2.5.0 → 3.0.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 +78 -59
  2. package/CONTRIBUTING.md +194 -194
  3. package/LICENSE +22 -22
  4. package/README.md +149 -147
  5. package/UPGRADING.md +245 -233
  6. package/bin/cli.js +475 -473
  7. package/bin/utils/cli-config-utils.js +212 -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 -11
  12. package/lib/builder-interface-augmenter.js +120 -120
  13. package/lib/client.js +495 -495
  14. package/lib/constants.js +61 -61
  15. package/lib/dialects/better-sqlite3/index.js +77 -77
  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/mssql/index.js +500 -500
  23. package/lib/dialects/mssql/mssql-formatter.js +34 -34
  24. package/lib/dialects/mssql/query/mssql-querycompiler.js +601 -601
  25. package/lib/dialects/mssql/schema/mssql-columncompiler.js +185 -185
  26. package/lib/dialects/mssql/schema/mssql-compiler.js +91 -91
  27. package/lib/dialects/mssql/schema/mssql-tablecompiler.js +378 -378
  28. package/lib/dialects/mssql/schema/mssql-viewcompiler.js +55 -55
  29. package/lib/dialects/mssql/transaction.js +176 -176
  30. package/lib/dialects/mysql/index.js +201 -201
  31. package/lib/dialects/mysql/query/mysql-querycompiler.js +274 -274
  32. package/lib/dialects/mysql/schema/mysql-columncompiler.js +193 -193
  33. package/lib/dialects/mysql/schema/mysql-compiler.js +60 -60
  34. package/lib/dialects/mysql/schema/mysql-tablecompiler.js +381 -381
  35. package/lib/dialects/mysql/schema/mysql-viewbuilder.js +21 -21
  36. package/lib/dialects/mysql/schema/mysql-viewcompiler.js +15 -15
  37. package/lib/dialects/mysql/transaction.js +46 -46
  38. package/lib/dialects/mysql2/index.js +53 -53
  39. package/lib/dialects/mysql2/transaction.js +44 -44
  40. package/lib/dialects/oracle/DEAD_CODE.md +5 -5
  41. package/lib/dialects/oracle/index.js +92 -92
  42. package/lib/dialects/oracle/query/oracle-querycompiler.js +343 -343
  43. package/lib/dialects/oracle/schema/internal/incrementUtils.js +20 -20
  44. package/lib/dialects/oracle/schema/internal/trigger.js +135 -135
  45. package/lib/dialects/oracle/schema/oracle-columnbuilder.js +17 -17
  46. package/lib/dialects/oracle/schema/oracle-columncompiler.js +126 -126
  47. package/lib/dialects/oracle/schema/oracle-compiler.js +122 -122
  48. package/lib/dialects/oracle/schema/oracle-tablecompiler.js +190 -190
  49. package/lib/dialects/oracle/utils.js +87 -87
  50. package/lib/dialects/oracledb/index.js +327 -327
  51. package/lib/dialects/oracledb/query/oracledb-querycompiler.js +481 -481
  52. package/lib/dialects/oracledb/schema/oracledb-columncompiler.js +61 -61
  53. package/lib/dialects/oracledb/schema/oracledb-tablecompiler.js +19 -19
  54. package/lib/dialects/oracledb/schema/oracledb-viewbuilder.js +13 -13
  55. package/lib/dialects/oracledb/schema/oracledb-viewcompiler.js +19 -19
  56. package/lib/dialects/oracledb/transaction.js +98 -98
  57. package/lib/dialects/oracledb/utils.js +208 -208
  58. package/lib/dialects/pgnative/index.js +60 -60
  59. package/lib/dialects/postgres/execution/pg-transaction.js +19 -19
  60. package/lib/dialects/postgres/index.js +358 -358
  61. package/lib/dialects/postgres/query/pg-querybuilder.js +43 -43
  62. package/lib/dialects/postgres/query/pg-querycompiler.js +400 -400
  63. package/lib/dialects/postgres/schema/pg-columncompiler.js +156 -156
  64. package/lib/dialects/postgres/schema/pg-compiler.js +138 -138
  65. package/lib/dialects/postgres/schema/pg-tablecompiler.js +304 -304
  66. package/lib/dialects/postgres/schema/pg-viewbuilder.js +21 -21
  67. package/lib/dialects/postgres/schema/pg-viewcompiler.js +35 -35
  68. package/lib/dialects/redshift/index.js +86 -86
  69. package/lib/dialects/redshift/query/redshift-querycompiler.js +163 -163
  70. package/lib/dialects/redshift/schema/redshift-columnbuilder.js +22 -22
  71. package/lib/dialects/redshift/schema/redshift-columncompiler.js +67 -67
  72. package/lib/dialects/redshift/schema/redshift-compiler.js +14 -14
  73. package/lib/dialects/redshift/schema/redshift-tablecompiler.js +122 -122
  74. package/lib/dialects/redshift/schema/redshift-viewcompiler.js +11 -11
  75. package/lib/dialects/redshift/transaction.js +32 -32
  76. package/lib/dialects/sqlite3/execution/sqlite-transaction.js +25 -25
  77. package/lib/dialects/sqlite3/index.js +250 -250
  78. package/lib/dialects/sqlite3/query/sqlite-querybuilder.js +33 -33
  79. package/lib/dialects/sqlite3/query/sqlite-querycompiler.js +334 -334
  80. package/lib/dialects/sqlite3/schema/ddl.js +400 -400
  81. package/lib/dialects/sqlite3/schema/internal/compiler.js +327 -327
  82. package/lib/dialects/sqlite3/schema/internal/parser-combinator.js +161 -161
  83. package/lib/dialects/sqlite3/schema/internal/parser.js +638 -638
  84. package/lib/dialects/sqlite3/schema/internal/sqlite-ddl-operations.js +41 -41
  85. package/lib/dialects/sqlite3/schema/internal/tokenizer.js +38 -38
  86. package/lib/dialects/sqlite3/schema/internal/utils.js +12 -12
  87. package/lib/dialects/sqlite3/schema/sqlite-columncompiler.js +50 -50
  88. package/lib/dialects/sqlite3/schema/sqlite-compiler.js +80 -80
  89. package/lib/dialects/sqlite3/schema/sqlite-tablecompiler.js +347 -347
  90. package/lib/dialects/sqlite3/schema/sqlite-viewcompiler.js +40 -40
  91. package/lib/execution/batch-insert.js +51 -51
  92. package/lib/execution/internal/delay.js +6 -6
  93. package/lib/execution/internal/ensure-connection-callback.js +41 -41
  94. package/lib/execution/internal/query-executioner.js +62 -62
  95. package/lib/execution/runner.js +325 -325
  96. package/lib/execution/transaction.js +409 -409
  97. package/lib/formatter/formatterUtils.js +42 -42
  98. package/lib/formatter/rawFormatter.js +84 -84
  99. package/lib/formatter/wrappingFormatter.js +250 -250
  100. package/lib/formatter.js +25 -25
  101. package/lib/index.js +3 -3
  102. package/lib/knex-builder/FunctionHelper.js +80 -80
  103. package/lib/knex-builder/Knex.js +59 -59
  104. package/lib/knex-builder/internal/config-resolver.js +57 -57
  105. package/lib/knex-builder/internal/parse-connection.js +87 -87
  106. package/lib/knex-builder/make-knex.js +345 -345
  107. package/lib/logger.js +76 -76
  108. package/lib/migrations/common/MigrationsLoader.js +36 -36
  109. package/lib/migrations/migrate/MigrationGenerator.js +84 -84
  110. package/lib/migrations/migrate/Migrator.js +599 -598
  111. package/lib/migrations/migrate/migrate-stub.js +17 -17
  112. package/lib/migrations/migrate/migration-list-resolver.js +33 -33
  113. package/lib/migrations/migrate/migrator-configuration-merger.js +58 -58
  114. package/lib/migrations/migrate/sources/fs-migrations.js +74 -74
  115. package/lib/migrations/migrate/stub/cjs.stub +15 -15
  116. package/lib/migrations/migrate/stub/coffee.stub +13 -13
  117. package/lib/migrations/migrate/stub/eg.stub +14 -14
  118. package/lib/migrations/migrate/stub/js-schema.stub +22 -22
  119. package/lib/migrations/migrate/stub/js.stub +22 -22
  120. package/lib/migrations/migrate/stub/knexfile-coffee.stub +34 -34
  121. package/lib/migrations/migrate/stub/knexfile-eg.stub +43 -43
  122. package/lib/migrations/migrate/stub/knexfile-js.stub +47 -47
  123. package/lib/migrations/migrate/stub/knexfile-ls.stub +35 -35
  124. package/lib/migrations/migrate/stub/knexfile-ts.stub +47 -47
  125. package/lib/migrations/migrate/stub/ls.stub +14 -14
  126. package/lib/migrations/migrate/stub/mjs.stub +23 -23
  127. package/lib/migrations/migrate/stub/ts-schema.stub +21 -21
  128. package/lib/migrations/migrate/stub/ts.stub +21 -21
  129. package/lib/migrations/migrate/table-creator.js +77 -77
  130. package/lib/migrations/migrate/table-resolver.js +27 -27
  131. package/lib/migrations/seed/Seeder.js +137 -137
  132. package/lib/migrations/seed/seed-stub.js +13 -13
  133. package/lib/migrations/seed/seeder-configuration-merger.js +60 -60
  134. package/lib/migrations/seed/sources/fs-seeds.js +65 -65
  135. package/lib/migrations/seed/stub/coffee.stub +9 -9
  136. package/lib/migrations/seed/stub/eg.stub +11 -11
  137. package/lib/migrations/seed/stub/js.stub +13 -13
  138. package/lib/migrations/seed/stub/ls.stub +11 -11
  139. package/lib/migrations/seed/stub/mjs.stub +12 -12
  140. package/lib/migrations/seed/stub/ts.stub +13 -13
  141. package/lib/migrations/util/fs.js +86 -86
  142. package/lib/migrations/util/import-file.js +12 -12
  143. package/lib/migrations/util/is-module-type.js +9 -9
  144. package/lib/migrations/util/template.js +52 -52
  145. package/lib/migrations/util/timestamp.js +14 -14
  146. package/lib/query/analytic.js +52 -52
  147. package/lib/query/constants.js +15 -15
  148. package/lib/query/joinclause.js +270 -270
  149. package/lib/query/method-constants.js +136 -136
  150. package/lib/query/querybuilder.js +1793 -1793
  151. package/lib/query/querycompiler.js +1591 -1591
  152. package/lib/raw.js +139 -139
  153. package/lib/ref.js +39 -39
  154. package/lib/schema/builder.js +115 -115
  155. package/lib/schema/columnbuilder.js +146 -146
  156. package/lib/schema/columncompiler.js +307 -307
  157. package/lib/schema/compiler.js +187 -187
  158. package/lib/schema/internal/helpers.js +55 -55
  159. package/lib/schema/tablebuilder.js +376 -376
  160. package/lib/schema/tablecompiler.js +433 -433
  161. package/lib/schema/viewbuilder.js +92 -92
  162. package/lib/schema/viewcompiler.js +138 -138
  163. package/lib/util/finally-mixin.js +13 -13
  164. package/lib/util/helpers.js +95 -95
  165. package/lib/util/is.js +32 -32
  166. package/lib/util/nanoid.js +40 -40
  167. package/lib/util/noop.js +1 -1
  168. package/lib/util/save-async-stack.js +14 -14
  169. package/lib/util/security.js +26 -26
  170. package/lib/util/string.js +190 -190
  171. package/lib/util/timeout.js +29 -29
  172. package/package.json +13 -12
  173. package/scripts/build.js +125 -125
  174. package/scripts/clean.js +31 -31
  175. package/scripts/docker-compose.yml +152 -152
  176. package/scripts/next-release-howto.md +24 -24
  177. package/scripts/oracledb-install-driver-libs.sh +82 -82
  178. package/scripts/release.sh +36 -34
  179. package/scripts/runkit-example.js +35 -34
  180. package/scripts/stress-test/README.txt +18 -18
  181. package/scripts/stress-test/docker-compose.yml +57 -57
  182. package/scripts/stress-test/knex-stress-test.js +212 -208
  183. package/scripts/stress-test/mysql2-random-hanging-every-now-and-then.js +149 -145
  184. package/scripts/stress-test/mysql2-sudden-exit-without-error.js +101 -100
  185. package/scripts/stress-test/reconnect-test-mysql-based-drivers.js +188 -184
  186. package/scripts/update_gitignore_for_tsc_output.js +90 -90
  187. package/types/index.d.ts +3272 -3273
  188. package/types/result.d.ts +27 -27
  189. package/types/tables.d.ts +4 -4
  190. package/lib/dialects/index.js +0 -34
@@ -1,378 +1,378 @@
1
- /* eslint max-len:0 */
2
-
3
- // MSSQL Table Builder & Compiler
4
- // -------
5
- const TableCompiler = require('../../../schema/tablecompiler');
6
- const helpers = require('../../../util/helpers');
7
- const { isObject } = require('../../../util/is');
8
-
9
- // Table Compiler
10
- // ------
11
-
12
- class TableCompiler_MSSQL extends TableCompiler {
13
- constructor(client, tableBuilder) {
14
- super(client, tableBuilder);
15
- }
16
-
17
- createQuery(columns, ifNot, like) {
18
- let createStatement = ifNot
19
- ? `if object_id('${this.tableName()}', 'U') is null `
20
- : '';
21
-
22
- if (like) {
23
- // This query copy only columns and not all indexes and keys like other databases.
24
- createStatement += `SELECT * INTO ${this.tableName()} FROM ${this.tableNameLike()} WHERE 0=1`;
25
- } else {
26
- createStatement +=
27
- 'CREATE TABLE ' +
28
- this.tableName() +
29
- (this._formatting ? ' (\n ' : ' (') +
30
- columns.sql.join(this._formatting ? ',\n ' : ', ') +
31
- this._addChecks() +
32
- ')';
33
- }
34
-
35
- this.pushQuery(createStatement);
36
-
37
- if (this.single.comment) {
38
- this.comment(this.single.comment);
39
- }
40
- if (like) {
41
- this.addColumns(columns, this.addColumnsPrefix);
42
- }
43
- }
44
-
45
- comment(/** @type {string} */ comment) {
46
- if (!comment) {
47
- return;
48
- }
49
-
50
- // XXX: This is a byte limit, not character, so we cannot definitively say they'll exceed the limit without server collation info.
51
- // When I checked in SQL Server 2019, the ctext column in sys.syscomments is defined as a varbinary(8000), so it doesn't even have its own defined collation.
52
- if (comment.length > 7500 / 2) {
53
- this.client.logger.warn(
54
- 'Your comment might be longer than the max comment length for MSSQL of 7,500 bytes.'
55
- );
56
- }
57
-
58
- // See: https://docs.microsoft.com/en-us/sql/relational-databases/system-stored-procedures/sp-addextendedproperty-transact-sql?view=sql-server-ver15#f-adding-an-extended-property-to-a-table
59
- const value = this.formatter.escapingStringDelimiters(comment);
60
- const level0name = this.formatter.escapingStringDelimiters(
61
- this.schemaNameRaw || 'dbo'
62
- );
63
- const level1name = this.formatter.escapingStringDelimiters(
64
- this.tableNameRaw
65
- );
66
- const args = `N'MS_Description', N'${value}', N'Schema', N'${level0name}', N'Table', N'${level1name}'`;
67
- const isAlreadyDefined = `EXISTS(SELECT * FROM sys.fn_listextendedproperty(N'MS_Description', N'Schema', N'${level0name}', N'Table', N'${level1name}', NULL, NULL))`;
68
- this.pushQuery(
69
- `IF ${isAlreadyDefined}\n EXEC sys.sp_updateextendedproperty ${args}\nELSE\n EXEC sys.sp_addextendedproperty ${args}`
70
- );
71
- }
72
-
73
- // Compiles column add. Multiple columns need only one ADD clause (not one ADD per column) so core addColumns doesn't work. #1348
74
- addColumns(columns, prefix) {
75
- prefix = prefix || this.addColumnsPrefix;
76
-
77
- if (columns.sql.length > 0) {
78
- this.pushQuery({
79
- sql:
80
- (this.lowerCase ? 'alter table ' : 'ALTER TABLE ') +
81
- this.tableName() +
82
- ' ' +
83
- prefix +
84
- columns.sql.join(', '),
85
- bindings: columns.bindings,
86
- });
87
- }
88
- }
89
-
90
- alterColumns(columns, colBuilder) {
91
- for (let i = 0, l = colBuilder.length; i < l; i++) {
92
- const builder = colBuilder[i];
93
- if (builder.modified.defaultTo) {
94
- const schema = this.schemaNameRaw || 'dbo';
95
- const baseQuery = `
96
- DECLARE @constraint varchar(100) = (SELECT default_constraints.name
97
- FROM sys.all_columns
98
- INNER JOIN sys.tables
99
- ON all_columns.object_id = tables.object_id
100
- INNER JOIN sys.schemas
101
- ON tables.schema_id = schemas.schema_id
102
- INNER JOIN sys.default_constraints
103
- ON all_columns.default_object_id = default_constraints.object_id
104
- WHERE schemas.name = '${schema}'
105
- AND tables.name = '${
106
- this.tableNameRaw
107
- }'
108
- AND all_columns.name = '${builder.getColumnName()}')
109
-
110
- IF @constraint IS NOT NULL EXEC('ALTER TABLE ${
111
- this.tableNameRaw
112
- } DROP CONSTRAINT ' + @constraint)`;
113
- this.pushQuery(baseQuery);
114
- }
115
- }
116
- // in SQL server only one column can be altered at a time
117
- columns.sql.forEach((sql) => {
118
- this.pushQuery({
119
- sql:
120
- (this.lowerCase ? 'alter table ' : 'ALTER TABLE ') +
121
- this.tableName() +
122
- ' ' +
123
- (this.lowerCase
124
- ? this.alterColumnPrefix.toLowerCase()
125
- : this.alterColumnPrefix) +
126
- sql,
127
- bindings: columns.bindings,
128
- });
129
- });
130
- }
131
-
132
- // Compiles column drop. Multiple columns need only one DROP clause (not one DROP per column) so core dropColumn doesn't work. #1348
133
- dropColumn() {
134
- const _this2 = this;
135
- const columns = helpers.normalizeArr.apply(null, arguments);
136
- const columnsArray = Array.isArray(columns) ? columns : [columns];
137
- const drops = columnsArray.map((column) => _this2.formatter.wrap(column));
138
- const schema = this.schemaNameRaw || 'dbo';
139
-
140
- for (const column of columns) {
141
- const baseQuery = `
142
- DECLARE @constraint varchar(100) = (SELECT default_constraints.name
143
- FROM sys.all_columns
144
- INNER JOIN sys.tables
145
- ON all_columns.object_id = tables.object_id
146
- INNER JOIN sys.schemas
147
- ON tables.schema_id = schemas.schema_id
148
- INNER JOIN sys.default_constraints
149
- ON all_columns.default_object_id = default_constraints.object_id
150
- WHERE schemas.name = '${schema}'
151
- AND tables.name = '${this.tableNameRaw}'
152
- AND all_columns.name = '${column}')
153
-
154
- IF @constraint IS NOT NULL EXEC('ALTER TABLE ${this.tableNameRaw} DROP CONSTRAINT ' + @constraint)`;
155
- this.pushQuery(baseQuery);
156
- }
157
- this.pushQuery(
158
- (this.lowerCase ? 'alter table ' : 'ALTER TABLE ') +
159
- this.tableName() +
160
- ' ' +
161
- this.dropColumnPrefix +
162
- drops.join(', ')
163
- );
164
- }
165
-
166
- changeType() {}
167
-
168
- // Renames a column on the table.
169
- renameColumn(from, to) {
170
- this.pushQuery(
171
- `exec sp_rename ${this.client.parameter(
172
- this.tableName() + '.' + from,
173
- this.tableBuilder,
174
- this.bindingsHolder
175
- )}, ${this.client.parameter(
176
- to,
177
- this.tableBuilder,
178
- this.bindingsHolder
179
- )}, 'COLUMN'`
180
- );
181
- }
182
-
183
- dropFKRefs(runner, refs) {
184
- const formatter = this.client.formatter(this.tableBuilder);
185
- return Promise.all(
186
- refs.map(function (ref) {
187
- const constraintName = formatter.wrap(ref.CONSTRAINT_NAME);
188
- const tableName = formatter.wrap(ref.TABLE_NAME);
189
- return runner.query({
190
- sql: `ALTER TABLE ${tableName} DROP CONSTRAINT ${constraintName}`,
191
- });
192
- })
193
- );
194
- }
195
-
196
- createFKRefs(runner, refs) {
197
- const formatter = this.client.formatter(this.tableBuilder);
198
-
199
- return Promise.all(
200
- refs.map(function (ref) {
201
- const tableName = formatter.wrap(ref.TABLE_NAME);
202
- const keyName = formatter.wrap(ref.CONSTRAINT_NAME);
203
- const column = formatter.columnize(ref.COLUMN_NAME);
204
- const references = formatter.columnize(ref.REFERENCED_COLUMN_NAME);
205
- const inTable = formatter.wrap(ref.REFERENCED_TABLE_NAME);
206
- const onUpdate = ` ON UPDATE ${ref.UPDATE_RULE}`;
207
- const onDelete = ` ON DELETE ${ref.DELETE_RULE}`;
208
-
209
- return runner.query({
210
- sql:
211
- `ALTER TABLE ${tableName} ADD CONSTRAINT ${keyName}` +
212
- ' FOREIGN KEY (' +
213
- column +
214
- ') REFERENCES ' +
215
- inTable +
216
- ' (' +
217
- references +
218
- ')' +
219
- onUpdate +
220
- onDelete,
221
- });
222
- })
223
- );
224
- }
225
-
226
- index(columns, indexName, options) {
227
- indexName = indexName
228
- ? this.formatter.wrap(indexName)
229
- : this._indexCommand('index', this.tableNameRaw, columns);
230
-
231
- let predicate;
232
- if (isObject(options)) {
233
- ({ predicate } = options);
234
- }
235
- const predicateQuery = predicate
236
- ? ' ' + this.client.queryCompiler(predicate).where()
237
- : '';
238
- this.pushQuery(
239
- `CREATE INDEX ${indexName} ON ${this.tableName()} (${this.formatter.columnize(
240
- columns
241
- )})${predicateQuery}`
242
- );
243
- }
244
-
245
- /**
246
- * Create a primary key.
247
- *
248
- * @param {undefined | string | string[]} columns
249
- * @param {string | {constraintName: string, deferrable?: 'not deferrable'|'deferred'|'immediate' }} constraintName
250
- */
251
- primary(columns, constraintName) {
252
- let deferrable;
253
- if (isObject(constraintName)) {
254
- ({ constraintName, deferrable } = constraintName);
255
- }
256
- if (deferrable && deferrable !== 'not deferrable') {
257
- this.client.logger.warn(
258
- `mssql: primary key constraint [${constraintName}] will not be deferrable ${deferrable} because mssql does not support deferred constraints.`
259
- );
260
- }
261
- constraintName = constraintName
262
- ? this.formatter.wrap(constraintName)
263
- : this.formatter.wrap(`${this.tableNameRaw}_pkey`);
264
- if (!this.forCreate) {
265
- this.pushQuery(
266
- `ALTER TABLE ${this.tableName()} ADD CONSTRAINT ${constraintName} PRIMARY KEY (${this.formatter.columnize(
267
- columns
268
- )})`
269
- );
270
- } else {
271
- this.pushQuery(
272
- `CONSTRAINT ${constraintName} PRIMARY KEY (${this.formatter.columnize(
273
- columns
274
- )})`
275
- );
276
- }
277
- }
278
-
279
- /**
280
- * Create a unique index.
281
- *
282
- * @param {string | string[]} columns
283
- * @param {string | {indexName: undefined | string, deferrable?: 'not deferrable'|'deferred'|'immediate', useConstraint?: true|false, predicate?: QueryBuilder }} indexName
284
- */
285
- unique(columns, indexName) {
286
- /** @type {string | undefined} */
287
- let deferrable;
288
- let useConstraint = false;
289
- let predicate;
290
- if (isObject(indexName)) {
291
- ({ indexName, deferrable, useConstraint, predicate } = indexName);
292
- }
293
- if (deferrable && deferrable !== 'not deferrable') {
294
- this.client.logger.warn(
295
- `mssql: unique index [${indexName}] will not be deferrable ${deferrable} because mssql does not support deferred constraints.`
296
- );
297
- }
298
- if (useConstraint && predicate) {
299
- throw new Error('mssql cannot create constraint with predicate');
300
- }
301
- indexName = indexName
302
- ? this.formatter.wrap(indexName)
303
- : this._indexCommand('unique', this.tableNameRaw, columns);
304
-
305
- if (!Array.isArray(columns)) {
306
- columns = [columns];
307
- }
308
-
309
- if (useConstraint) {
310
- // mssql supports unique indexes and unique constraints.
311
- // unique indexes cannot be used with foreign key relationships hence unique constraints are used instead.
312
- this.pushQuery(
313
- `ALTER TABLE ${this.tableName()} ADD CONSTRAINT ${indexName} UNIQUE (${this.formatter.columnize(
314
- columns
315
- )})`
316
- );
317
- } else {
318
- // default to making unique index that allows null https://stackoverflow.com/a/767702/360060
319
- // to be more or less compatible with other DBs (if any of the columns is NULL then "duplicates" are allowed)
320
- const predicateQuery = predicate
321
- ? ' ' + this.client.queryCompiler(predicate).where()
322
- : ' WHERE ' +
323
- columns
324
- .map((column) => this.formatter.columnize(column) + ' IS NOT NULL')
325
- .join(' AND ');
326
- this.pushQuery(
327
- `CREATE UNIQUE INDEX ${indexName} ON ${this.tableName()} (${this.formatter.columnize(
328
- columns
329
- )})${predicateQuery}`
330
- );
331
- }
332
- }
333
-
334
- // Compile a drop index command.
335
- dropIndex(columns, indexName) {
336
- indexName = indexName
337
- ? this.formatter.wrap(indexName)
338
- : this._indexCommand('index', this.tableNameRaw, columns);
339
- this.pushQuery(`DROP INDEX ${indexName} ON ${this.tableName()}`);
340
- }
341
-
342
- // Compile a drop foreign key command.
343
- dropForeign(columns, indexName) {
344
- indexName = indexName
345
- ? this.formatter.wrap(indexName)
346
- : this._indexCommand('foreign', this.tableNameRaw, columns);
347
- this.pushQuery(
348
- `ALTER TABLE ${this.tableName()} DROP CONSTRAINT ${indexName}`
349
- );
350
- }
351
-
352
- // Compile a drop primary key command.
353
- dropPrimary(constraintName) {
354
- constraintName = constraintName
355
- ? this.formatter.wrap(constraintName)
356
- : this.formatter.wrap(`${this.tableNameRaw}_pkey`);
357
- this.pushQuery(
358
- `ALTER TABLE ${this.tableName()} DROP CONSTRAINT ${constraintName}`
359
- );
360
- }
361
-
362
- // Compile a drop unique key command.
363
- dropUnique(column, indexName) {
364
- indexName = indexName
365
- ? this.formatter.wrap(indexName)
366
- : this._indexCommand('unique', this.tableNameRaw, column);
367
- this.pushQuery(`DROP INDEX ${indexName} ON ${this.tableName()}`);
368
- }
369
- }
370
-
371
- TableCompiler_MSSQL.prototype.createAlterTableMethods = ['foreign', 'primary'];
372
- TableCompiler_MSSQL.prototype.lowerCase = false;
373
-
374
- TableCompiler_MSSQL.prototype.addColumnsPrefix = 'ADD ';
375
- TableCompiler_MSSQL.prototype.dropColumnPrefix = 'DROP COLUMN ';
376
- TableCompiler_MSSQL.prototype.alterColumnPrefix = 'ALTER COLUMN ';
377
-
378
- module.exports = TableCompiler_MSSQL;
1
+ /* eslint max-len:0 */
2
+
3
+ // MSSQL Table Builder & Compiler
4
+ // -------
5
+ const TableCompiler = require('../../../schema/tablecompiler');
6
+ const helpers = require('../../../util/helpers');
7
+ const { isObject } = require('../../../util/is');
8
+
9
+ // Table Compiler
10
+ // ------
11
+
12
+ class TableCompiler_MSSQL extends TableCompiler {
13
+ constructor(client, tableBuilder) {
14
+ super(client, tableBuilder);
15
+ }
16
+
17
+ createQuery(columns, ifNot, like) {
18
+ let createStatement = ifNot
19
+ ? `if object_id('${this.tableName()}', 'U') is null `
20
+ : '';
21
+
22
+ if (like) {
23
+ // This query copy only columns and not all indexes and keys like other databases.
24
+ createStatement += `SELECT * INTO ${this.tableName()} FROM ${this.tableNameLike()} WHERE 0=1`;
25
+ } else {
26
+ createStatement +=
27
+ 'CREATE TABLE ' +
28
+ this.tableName() +
29
+ (this._formatting ? ' (\n ' : ' (') +
30
+ columns.sql.join(this._formatting ? ',\n ' : ', ') +
31
+ this._addChecks() +
32
+ ')';
33
+ }
34
+
35
+ this.pushQuery(createStatement);
36
+
37
+ if (this.single.comment) {
38
+ this.comment(this.single.comment);
39
+ }
40
+ if (like) {
41
+ this.addColumns(columns, this.addColumnsPrefix);
42
+ }
43
+ }
44
+
45
+ comment(/** @type {string} */ comment) {
46
+ if (!comment) {
47
+ return;
48
+ }
49
+
50
+ // XXX: This is a byte limit, not character, so we cannot definitively say they'll exceed the limit without server collation info.
51
+ // When I checked in SQL Server 2019, the ctext column in sys.syscomments is defined as a varbinary(8000), so it doesn't even have its own defined collation.
52
+ if (comment.length > 7500 / 2) {
53
+ this.client.logger.warn(
54
+ 'Your comment might be longer than the max comment length for MSSQL of 7,500 bytes.'
55
+ );
56
+ }
57
+
58
+ // See: https://docs.microsoft.com/en-us/sql/relational-databases/system-stored-procedures/sp-addextendedproperty-transact-sql?view=sql-server-ver15#f-adding-an-extended-property-to-a-table
59
+ const value = this.formatter.escapingStringDelimiters(comment);
60
+ const level0name = this.formatter.escapingStringDelimiters(
61
+ this.schemaNameRaw || 'dbo'
62
+ );
63
+ const level1name = this.formatter.escapingStringDelimiters(
64
+ this.tableNameRaw
65
+ );
66
+ const args = `N'MS_Description', N'${value}', N'Schema', N'${level0name}', N'Table', N'${level1name}'`;
67
+ const isAlreadyDefined = `EXISTS(SELECT * FROM sys.fn_listextendedproperty(N'MS_Description', N'Schema', N'${level0name}', N'Table', N'${level1name}', NULL, NULL))`;
68
+ this.pushQuery(
69
+ `IF ${isAlreadyDefined}\n EXEC sys.sp_updateextendedproperty ${args}\nELSE\n EXEC sys.sp_addextendedproperty ${args}`
70
+ );
71
+ }
72
+
73
+ // Compiles column add. Multiple columns need only one ADD clause (not one ADD per column) so core addColumns doesn't work. #1348
74
+ addColumns(columns, prefix) {
75
+ prefix = prefix || this.addColumnsPrefix;
76
+
77
+ if (columns.sql.length > 0) {
78
+ this.pushQuery({
79
+ sql:
80
+ (this.lowerCase ? 'alter table ' : 'ALTER TABLE ') +
81
+ this.tableName() +
82
+ ' ' +
83
+ prefix +
84
+ columns.sql.join(', '),
85
+ bindings: columns.bindings,
86
+ });
87
+ }
88
+ }
89
+
90
+ alterColumns(columns, colBuilder) {
91
+ for (let i = 0, l = colBuilder.length; i < l; i++) {
92
+ const builder = colBuilder[i];
93
+ if (builder.modified.defaultTo) {
94
+ const schema = this.schemaNameRaw || 'dbo';
95
+ const baseQuery = `
96
+ DECLARE @constraint varchar(100) = (SELECT default_constraints.name
97
+ FROM sys.all_columns
98
+ INNER JOIN sys.tables
99
+ ON all_columns.object_id = tables.object_id
100
+ INNER JOIN sys.schemas
101
+ ON tables.schema_id = schemas.schema_id
102
+ INNER JOIN sys.default_constraints
103
+ ON all_columns.default_object_id = default_constraints.object_id
104
+ WHERE schemas.name = '${schema}'
105
+ AND tables.name = '${
106
+ this.tableNameRaw
107
+ }'
108
+ AND all_columns.name = '${builder.getColumnName()}')
109
+
110
+ IF @constraint IS NOT NULL EXEC('ALTER TABLE ${
111
+ this.tableNameRaw
112
+ } DROP CONSTRAINT ' + @constraint)`;
113
+ this.pushQuery(baseQuery);
114
+ }
115
+ }
116
+ // in SQL server only one column can be altered at a time
117
+ columns.sql.forEach((sql) => {
118
+ this.pushQuery({
119
+ sql:
120
+ (this.lowerCase ? 'alter table ' : 'ALTER TABLE ') +
121
+ this.tableName() +
122
+ ' ' +
123
+ (this.lowerCase
124
+ ? this.alterColumnPrefix.toLowerCase()
125
+ : this.alterColumnPrefix) +
126
+ sql,
127
+ bindings: columns.bindings,
128
+ });
129
+ });
130
+ }
131
+
132
+ // Compiles column drop. Multiple columns need only one DROP clause (not one DROP per column) so core dropColumn doesn't work. #1348
133
+ dropColumn() {
134
+ const _this2 = this;
135
+ const columns = helpers.normalizeArr.apply(null, arguments);
136
+ const columnsArray = Array.isArray(columns) ? columns : [columns];
137
+ const drops = columnsArray.map((column) => _this2.formatter.wrap(column));
138
+ const schema = this.schemaNameRaw || 'dbo';
139
+
140
+ for (const column of columns) {
141
+ const baseQuery = `
142
+ DECLARE @constraint varchar(100) = (SELECT default_constraints.name
143
+ FROM sys.all_columns
144
+ INNER JOIN sys.tables
145
+ ON all_columns.object_id = tables.object_id
146
+ INNER JOIN sys.schemas
147
+ ON tables.schema_id = schemas.schema_id
148
+ INNER JOIN sys.default_constraints
149
+ ON all_columns.default_object_id = default_constraints.object_id
150
+ WHERE schemas.name = '${schema}'
151
+ AND tables.name = '${this.tableNameRaw}'
152
+ AND all_columns.name = '${column}')
153
+
154
+ IF @constraint IS NOT NULL EXEC('ALTER TABLE ${this.tableNameRaw} DROP CONSTRAINT ' + @constraint)`;
155
+ this.pushQuery(baseQuery);
156
+ }
157
+ this.pushQuery(
158
+ (this.lowerCase ? 'alter table ' : 'ALTER TABLE ') +
159
+ this.tableName() +
160
+ ' ' +
161
+ this.dropColumnPrefix +
162
+ drops.join(', ')
163
+ );
164
+ }
165
+
166
+ changeType() {}
167
+
168
+ // Renames a column on the table.
169
+ renameColumn(from, to) {
170
+ this.pushQuery(
171
+ `exec sp_rename ${this.client.parameter(
172
+ this.tableName() + '.' + from,
173
+ this.tableBuilder,
174
+ this.bindingsHolder
175
+ )}, ${this.client.parameter(
176
+ to,
177
+ this.tableBuilder,
178
+ this.bindingsHolder
179
+ )}, 'COLUMN'`
180
+ );
181
+ }
182
+
183
+ dropFKRefs(runner, refs) {
184
+ const formatter = this.client.formatter(this.tableBuilder);
185
+ return Promise.all(
186
+ refs.map(function (ref) {
187
+ const constraintName = formatter.wrap(ref.CONSTRAINT_NAME);
188
+ const tableName = formatter.wrap(ref.TABLE_NAME);
189
+ return runner.query({
190
+ sql: `ALTER TABLE ${tableName} DROP CONSTRAINT ${constraintName}`,
191
+ });
192
+ })
193
+ );
194
+ }
195
+
196
+ createFKRefs(runner, refs) {
197
+ const formatter = this.client.formatter(this.tableBuilder);
198
+
199
+ return Promise.all(
200
+ refs.map(function (ref) {
201
+ const tableName = formatter.wrap(ref.TABLE_NAME);
202
+ const keyName = formatter.wrap(ref.CONSTRAINT_NAME);
203
+ const column = formatter.columnize(ref.COLUMN_NAME);
204
+ const references = formatter.columnize(ref.REFERENCED_COLUMN_NAME);
205
+ const inTable = formatter.wrap(ref.REFERENCED_TABLE_NAME);
206
+ const onUpdate = ` ON UPDATE ${ref.UPDATE_RULE}`;
207
+ const onDelete = ` ON DELETE ${ref.DELETE_RULE}`;
208
+
209
+ return runner.query({
210
+ sql:
211
+ `ALTER TABLE ${tableName} ADD CONSTRAINT ${keyName}` +
212
+ ' FOREIGN KEY (' +
213
+ column +
214
+ ') REFERENCES ' +
215
+ inTable +
216
+ ' (' +
217
+ references +
218
+ ')' +
219
+ onUpdate +
220
+ onDelete,
221
+ });
222
+ })
223
+ );
224
+ }
225
+
226
+ index(columns, indexName, options) {
227
+ indexName = indexName
228
+ ? this.formatter.wrap(indexName)
229
+ : this._indexCommand('index', this.tableNameRaw, columns);
230
+
231
+ let predicate;
232
+ if (isObject(options)) {
233
+ ({ predicate } = options);
234
+ }
235
+ const predicateQuery = predicate
236
+ ? ' ' + this.client.queryCompiler(predicate).where()
237
+ : '';
238
+ this.pushQuery(
239
+ `CREATE INDEX ${indexName} ON ${this.tableName()} (${this.formatter.columnize(
240
+ columns
241
+ )})${predicateQuery}`
242
+ );
243
+ }
244
+
245
+ /**
246
+ * Create a primary key.
247
+ *
248
+ * @param {undefined | string | string[]} columns
249
+ * @param {string | {constraintName: string, deferrable?: 'not deferrable'|'deferred'|'immediate' }} constraintName
250
+ */
251
+ primary(columns, constraintName) {
252
+ let deferrable;
253
+ if (isObject(constraintName)) {
254
+ ({ constraintName, deferrable } = constraintName);
255
+ }
256
+ if (deferrable && deferrable !== 'not deferrable') {
257
+ this.client.logger.warn(
258
+ `mssql: primary key constraint [${constraintName}] will not be deferrable ${deferrable} because mssql does not support deferred constraints.`
259
+ );
260
+ }
261
+ constraintName = constraintName
262
+ ? this.formatter.wrap(constraintName)
263
+ : this.formatter.wrap(`${this.tableNameRaw}_pkey`);
264
+ if (!this.forCreate) {
265
+ this.pushQuery(
266
+ `ALTER TABLE ${this.tableName()} ADD CONSTRAINT ${constraintName} PRIMARY KEY (${this.formatter.columnize(
267
+ columns
268
+ )})`
269
+ );
270
+ } else {
271
+ this.pushQuery(
272
+ `CONSTRAINT ${constraintName} PRIMARY KEY (${this.formatter.columnize(
273
+ columns
274
+ )})`
275
+ );
276
+ }
277
+ }
278
+
279
+ /**
280
+ * Create a unique index.
281
+ *
282
+ * @param {string | string[]} columns
283
+ * @param {string | {indexName: undefined | string, deferrable?: 'not deferrable'|'deferred'|'immediate', useConstraint?: true|false, predicate?: QueryBuilder }} indexName
284
+ */
285
+ unique(columns, indexName) {
286
+ /** @type {string | undefined} */
287
+ let deferrable;
288
+ let useConstraint = false;
289
+ let predicate;
290
+ if (isObject(indexName)) {
291
+ ({ indexName, deferrable, useConstraint, predicate } = indexName);
292
+ }
293
+ if (deferrable && deferrable !== 'not deferrable') {
294
+ this.client.logger.warn(
295
+ `mssql: unique index [${indexName}] will not be deferrable ${deferrable} because mssql does not support deferred constraints.`
296
+ );
297
+ }
298
+ if (useConstraint && predicate) {
299
+ throw new Error('mssql cannot create constraint with predicate');
300
+ }
301
+ indexName = indexName
302
+ ? this.formatter.wrap(indexName)
303
+ : this._indexCommand('unique', this.tableNameRaw, columns);
304
+
305
+ if (!Array.isArray(columns)) {
306
+ columns = [columns];
307
+ }
308
+
309
+ if (useConstraint) {
310
+ // mssql supports unique indexes and unique constraints.
311
+ // unique indexes cannot be used with foreign key relationships hence unique constraints are used instead.
312
+ this.pushQuery(
313
+ `ALTER TABLE ${this.tableName()} ADD CONSTRAINT ${indexName} UNIQUE (${this.formatter.columnize(
314
+ columns
315
+ )})`
316
+ );
317
+ } else {
318
+ // default to making unique index that allows null https://stackoverflow.com/a/767702/360060
319
+ // to be more or less compatible with other DBs (if any of the columns is NULL then "duplicates" are allowed)
320
+ const predicateQuery = predicate
321
+ ? ' ' + this.client.queryCompiler(predicate).where()
322
+ : ' WHERE ' +
323
+ columns
324
+ .map((column) => this.formatter.columnize(column) + ' IS NOT NULL')
325
+ .join(' AND ');
326
+ this.pushQuery(
327
+ `CREATE UNIQUE INDEX ${indexName} ON ${this.tableName()} (${this.formatter.columnize(
328
+ columns
329
+ )})${predicateQuery}`
330
+ );
331
+ }
332
+ }
333
+
334
+ // Compile a drop index command.
335
+ dropIndex(columns, indexName) {
336
+ indexName = indexName
337
+ ? this.formatter.wrap(indexName)
338
+ : this._indexCommand('index', this.tableNameRaw, columns);
339
+ this.pushQuery(`DROP INDEX ${indexName} ON ${this.tableName()}`);
340
+ }
341
+
342
+ // Compile a drop foreign key command.
343
+ dropForeign(columns, indexName) {
344
+ indexName = indexName
345
+ ? this.formatter.wrap(indexName)
346
+ : this._indexCommand('foreign', this.tableNameRaw, columns);
347
+ this.pushQuery(
348
+ `ALTER TABLE ${this.tableName()} DROP CONSTRAINT ${indexName}`
349
+ );
350
+ }
351
+
352
+ // Compile a drop primary key command.
353
+ dropPrimary(constraintName) {
354
+ constraintName = constraintName
355
+ ? this.formatter.wrap(constraintName)
356
+ : this.formatter.wrap(`${this.tableNameRaw}_pkey`);
357
+ this.pushQuery(
358
+ `ALTER TABLE ${this.tableName()} DROP CONSTRAINT ${constraintName}`
359
+ );
360
+ }
361
+
362
+ // Compile a drop unique key command.
363
+ dropUnique(column, indexName) {
364
+ indexName = indexName
365
+ ? this.formatter.wrap(indexName)
366
+ : this._indexCommand('unique', this.tableNameRaw, column);
367
+ this.pushQuery(`DROP INDEX ${indexName} ON ${this.tableName()}`);
368
+ }
369
+ }
370
+
371
+ TableCompiler_MSSQL.prototype.createAlterTableMethods = ['foreign', 'primary'];
372
+ TableCompiler_MSSQL.prototype.lowerCase = false;
373
+
374
+ TableCompiler_MSSQL.prototype.addColumnsPrefix = 'ADD ';
375
+ TableCompiler_MSSQL.prototype.dropColumnPrefix = 'DROP COLUMN ';
376
+ TableCompiler_MSSQL.prototype.alterColumnPrefix = 'ALTER COLUMN ';
377
+
378
+ module.exports = TableCompiler_MSSQL;