knex 3.1.0 → 3.2.1

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 +2441 -2380
  2. package/CONTRIBUTING.md +190 -194
  3. package/LICENSE +22 -22
  4. package/README.md +156 -149
  5. package/UPGRADING.md +245 -245
  6. package/bin/cli.js +516 -475
  7. package/bin/knexfile-runtime-error.js +27 -0
  8. package/bin/utils/cli-config-utils.js +217 -212
  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 -495
  15. package/lib/constants.js +61 -61
  16. package/lib/dialects/better-sqlite3/index.js +101 -77
  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 -37
  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 -500
  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 -378
  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 -206
  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 -405
  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 -197
  52. package/lib/dialects/oracle/utils.js +107 -106
  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 -361
  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 -156
  67. package/lib/dialects/postgres/schema/pg-compiler.js +138 -138
  68. package/lib/dialects/postgres/schema/pg-tablecompiler.js +331 -304
  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 -122
  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 -25
  80. package/lib/dialects/sqlite3/index.js +263 -250
  81. package/lib/dialects/sqlite3/query/sqlite-querybuilder.js +33 -33
  82. package/lib/dialects/sqlite3/query/sqlite-querycompiler.js +341 -334
  83. package/lib/dialects/sqlite3/schema/ddl.js +380 -400
  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 -347
  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 -413
  100. package/lib/formatter/formatterUtils.js +42 -42
  101. package/lib/formatter/rawFormatter.js +84 -84
  102. package/lib/formatter/wrappingFormatter.js +253 -250
  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 -599
  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 -1591
  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 -376
  163. package/lib/schema/tablecompiler.js +450 -439
  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 -26
  173. package/lib/util/string.js +190 -190
  174. package/lib/util/timeout.js +29 -29
  175. package/package.json +291 -267
  176. package/scripts/act-testing/act.sh +19 -0
  177. package/scripts/act-testing/merged-no-label.json +11 -0
  178. package/scripts/act-testing/merged-patch-labeled.json +12 -0
  179. package/scripts/act-testing/merged-skip-labeled.json +12 -0
  180. package/scripts/act-testing/not-merged-patch-labeled.json +12 -0
  181. package/scripts/build-for-release.sh +122 -0
  182. package/scripts/build.js +125 -125
  183. package/scripts/clean.js +31 -31
  184. package/scripts/docker-compose.yml +150 -152
  185. package/scripts/format-changelog.js +55 -0
  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 -57
  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.ts +3321 -3275
  197. package/types/result.d.ts +27 -27
  198. package/types/tables.d.ts +4 -4
  199. package/scripts/update_gitignore_for_tsc_output.js +0 -90
@@ -1,378 +1,393 @@
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
+ dropForeignIfExists() {
353
+ throw new Error('.dropForeignIfExists is not supported for mssql.');
354
+ }
355
+
356
+ // Compile a drop primary key command.
357
+ dropPrimary(constraintName) {
358
+ constraintName = constraintName
359
+ ? this.formatter.wrap(constraintName)
360
+ : this.formatter.wrap(`${this.tableNameRaw}_pkey`);
361
+ this.pushQuery(
362
+ `ALTER TABLE ${this.tableName()} DROP CONSTRAINT ${constraintName}`
363
+ );
364
+ }
365
+
366
+ dropPrimaryIfExists() {
367
+ throw new Error('.dropPrimaryIfExists is not supported for mssql.');
368
+ }
369
+
370
+ // Compile a drop unique key command.
371
+ dropUnique(column, indexName) {
372
+ indexName = indexName
373
+ ? this.formatter.wrap(indexName)
374
+ : this._indexCommand('unique', this.tableNameRaw, column);
375
+ this.pushQuery(`DROP INDEX ${indexName} ON ${this.tableName()}`);
376
+ }
377
+
378
+ dropUniqueIfExists(column, indexName) {
379
+ indexName = indexName
380
+ ? this.formatter.wrap(indexName)
381
+ : this._indexCommand('unique', this.tableNameRaw, column);
382
+ this.pushQuery(`DROP INDEX IF EXISTS ${indexName} ON ${this.tableName()}`);
383
+ }
384
+ }
385
+
386
+ TableCompiler_MSSQL.prototype.createAlterTableMethods = ['foreign', 'primary'];
387
+ TableCompiler_MSSQL.prototype.lowerCase = false;
388
+
389
+ TableCompiler_MSSQL.prototype.addColumnsPrefix = 'ADD ';
390
+ TableCompiler_MSSQL.prototype.dropColumnPrefix = 'DROP COLUMN ';
391
+ TableCompiler_MSSQL.prototype.alterColumnPrefix = 'ALTER COLUMN ';
392
+
393
+ module.exports = TableCompiler_MSSQL;