knex 0.21.20 → 0.21.21

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 (141) hide show
  1. package/CHANGELOG.md +6 -0
  2. package/CONTRIBUTING.md +184 -184
  3. package/LICENSE +22 -22
  4. package/README.md +95 -95
  5. package/bin/cli.js +414 -414
  6. package/bin/utils/cli-config-utils.js +151 -151
  7. package/bin/utils/constants.js +7 -7
  8. package/bin/utils/migrationsLister.js +37 -37
  9. package/knex.js +8 -8
  10. package/lib/client.js +413 -413
  11. package/lib/config-resolver.js +61 -61
  12. package/lib/constants.js +44 -44
  13. package/lib/dialects/mssql/index.js +390 -390
  14. package/lib/dialects/mssql/query/compiler.js +444 -444
  15. package/lib/dialects/mssql/schema/columncompiler.js +103 -103
  16. package/lib/dialects/mssql/schema/compiler.js +59 -59
  17. package/lib/dialects/mssql/schema/tablecompiler.js +245 -245
  18. package/lib/dialects/mssql/transaction.js +97 -97
  19. package/lib/dialects/mysql/index.js +191 -191
  20. package/lib/dialects/mysql/query/compiler.js +142 -142
  21. package/lib/dialects/mysql/schema/columncompiler.js +171 -171
  22. package/lib/dialects/mysql/schema/compiler.js +60 -60
  23. package/lib/dialects/mysql/schema/tablecompiler.js +262 -262
  24. package/lib/dialects/mysql/transaction.js +48 -48
  25. package/lib/dialects/mysql2/index.js +35 -35
  26. package/lib/dialects/mysql2/transaction.js +46 -46
  27. package/lib/dialects/oracle/DEAD_CODE.md +5 -5
  28. package/lib/dialects/oracle/formatter.js +20 -20
  29. package/lib/dialects/oracle/index.js +79 -79
  30. package/lib/dialects/oracle/query/compiler.js +327 -327
  31. package/lib/dialects/oracle/schema/columnbuilder.js +18 -18
  32. package/lib/dialects/oracle/schema/columncompiler.js +139 -139
  33. package/lib/dialects/oracle/schema/compiler.js +81 -81
  34. package/lib/dialects/oracle/schema/tablecompiler.js +165 -165
  35. package/lib/dialects/oracle/schema/trigger.js +126 -126
  36. package/lib/dialects/oracle/utils.js +86 -86
  37. package/lib/dialects/oracledb/index.js +489 -489
  38. package/lib/dialects/oracledb/query/compiler.js +363 -363
  39. package/lib/dialects/oracledb/schema/columncompiler.js +35 -35
  40. package/lib/dialects/oracledb/transaction.js +76 -76
  41. package/lib/dialects/oracledb/utils.js +14 -14
  42. package/lib/dialects/postgres/index.js +319 -319
  43. package/lib/dialects/postgres/query/compiler.js +206 -206
  44. package/lib/dialects/postgres/schema/columncompiler.js +125 -125
  45. package/lib/dialects/postgres/schema/compiler.js +109 -109
  46. package/lib/dialects/postgres/schema/tablecompiler.js +183 -183
  47. package/lib/dialects/redshift/index.js +73 -73
  48. package/lib/dialects/redshift/query/compiler.js +119 -119
  49. package/lib/dialects/redshift/schema/columnbuilder.js +20 -20
  50. package/lib/dialects/redshift/schema/columncompiler.js +60 -60
  51. package/lib/dialects/redshift/schema/compiler.js +14 -14
  52. package/lib/dialects/redshift/schema/tablecompiler.js +123 -123
  53. package/lib/dialects/redshift/transaction.js +18 -18
  54. package/lib/dialects/sqlite3/formatter.js +21 -21
  55. package/lib/dialects/sqlite3/index.js +169 -169
  56. package/lib/dialects/sqlite3/query/compiler.js +222 -222
  57. package/lib/dialects/sqlite3/schema/columncompiler.js +27 -27
  58. package/lib/dialects/sqlite3/schema/compiler.js +49 -49
  59. package/lib/dialects/sqlite3/schema/ddl.js +525 -525
  60. package/lib/dialects/sqlite3/schema/tablecompiler.js +238 -238
  61. package/lib/formatter.js +295 -295
  62. package/lib/functionhelper.js +14 -14
  63. package/lib/helpers.js +92 -92
  64. package/lib/index.js +3 -3
  65. package/lib/interface.js +115 -115
  66. package/lib/knex.js +42 -42
  67. package/lib/logger.js +76 -76
  68. package/lib/migrate/MigrationGenerator.js +82 -82
  69. package/lib/migrate/Migrator.js +611 -611
  70. package/lib/migrate/configuration-merger.js +60 -60
  71. package/lib/migrate/migrate-stub.js +17 -17
  72. package/lib/migrate/migration-list-resolver.js +36 -36
  73. package/lib/migrate/sources/fs-migrations.js +99 -99
  74. package/lib/migrate/stub/cjs.stub +15 -15
  75. package/lib/migrate/stub/coffee.stub +13 -13
  76. package/lib/migrate/stub/eg.stub +14 -14
  77. package/lib/migrate/stub/js.stub +15 -15
  78. package/lib/migrate/stub/knexfile-coffee.stub +34 -34
  79. package/lib/migrate/stub/knexfile-eg.stub +43 -43
  80. package/lib/migrate/stub/knexfile-js.stub +44 -44
  81. package/lib/migrate/stub/knexfile-ls.stub +35 -35
  82. package/lib/migrate/stub/knexfile-ts.stub +44 -44
  83. package/lib/migrate/stub/ls.stub +14 -14
  84. package/lib/migrate/stub/ts.stub +21 -21
  85. package/lib/migrate/table-creator.js +67 -67
  86. package/lib/migrate/table-resolver.js +27 -27
  87. package/lib/query/builder.js +1372 -1372
  88. package/lib/query/compiler.js +889 -889
  89. package/lib/query/constants.js +13 -13
  90. package/lib/query/joinclause.js +263 -263
  91. package/lib/query/methods.js +92 -92
  92. package/lib/query/string.js +190 -190
  93. package/lib/raw.js +188 -188
  94. package/lib/ref.js +39 -39
  95. package/lib/runner.js +285 -285
  96. package/lib/schema/builder.js +82 -82
  97. package/lib/schema/columnbuilder.js +117 -117
  98. package/lib/schema/columncompiler.js +177 -177
  99. package/lib/schema/compiler.js +101 -101
  100. package/lib/schema/helpers.js +51 -51
  101. package/lib/schema/tablebuilder.js +288 -288
  102. package/lib/schema/tablecompiler.js +296 -296
  103. package/lib/seed/Seeder.js +203 -203
  104. package/lib/seed/seed-stub.js +13 -13
  105. package/lib/seed/stub/coffee.stub +9 -9
  106. package/lib/seed/stub/eg.stub +11 -11
  107. package/lib/seed/stub/js.stub +13 -13
  108. package/lib/seed/stub/ls.stub +11 -11
  109. package/lib/seed/stub/ts.stub +13 -13
  110. package/lib/transaction.js +363 -363
  111. package/lib/util/batchInsert.js +59 -59
  112. package/lib/util/delay.js +6 -6
  113. package/lib/util/fake-client.js +9 -9
  114. package/lib/util/finally-mixin.js +13 -13
  115. package/lib/util/fs.js +76 -76
  116. package/lib/util/import-file.js +13 -13
  117. package/lib/util/is-module-type.js +14 -14
  118. package/lib/util/is.js +32 -32
  119. package/lib/util/make-knex.js +338 -338
  120. package/lib/util/nanoid.js +29 -29
  121. package/lib/util/noop.js +1 -1
  122. package/lib/util/parse-connection.js +66 -66
  123. package/lib/util/save-async-stack.js +14 -14
  124. package/lib/util/template.js +52 -52
  125. package/lib/util/timeout.js +29 -29
  126. package/lib/util/timestamp.js +16 -16
  127. package/package.json +1 -1
  128. package/scripts/build.js +125 -125
  129. package/scripts/docker-compose.yml +111 -111
  130. package/scripts/next-release-howto.md +24 -24
  131. package/scripts/release.sh +34 -34
  132. package/scripts/runkit-example.js +34 -34
  133. package/scripts/stress-test/README.txt +18 -18
  134. package/scripts/stress-test/docker-compose.yml +47 -47
  135. package/scripts/stress-test/knex-stress-test.js +196 -196
  136. package/scripts/stress-test/mysql2-random-hanging-every-now-and-then.js +145 -145
  137. package/scripts/stress-test/mysql2-sudden-exit-without-error.js +100 -100
  138. package/scripts/stress-test/reconnect-test-mysql-based-drivers.js +184 -184
  139. package/types/index.d.ts +2249 -2249
  140. package/types/result.d.ts +27 -27
  141. package/types/tables.d.ts +4 -4
@@ -1,327 +1,327 @@
1
- /* eslint max-len:0 */
2
-
3
- // Oracle Query Builder & Compiler
4
- // ------
5
- const compact = require('lodash/compact');
6
- const identity = require('lodash/identity');
7
- const isEmpty = require('lodash/isEmpty');
8
- const isPlainObject = require('lodash/isPlainObject');
9
- const reduce = require('lodash/reduce');
10
- const QueryCompiler = require('../../../query/compiler');
11
- const { ReturningHelper } = require('../utils');
12
- const { isString } = require('../../../util/is');
13
-
14
- const components = [
15
- 'columns',
16
- 'join',
17
- 'where',
18
- 'union',
19
- 'group',
20
- 'having',
21
- 'order',
22
- 'lock',
23
- ];
24
-
25
- // Query Compiler
26
- // -------
27
-
28
- // Set the "Formatter" to use for the queries,
29
- // ensuring that all parameterized values (even across sub-queries)
30
- // are properly built into the same query.
31
- class QueryCompiler_Oracle extends QueryCompiler {
32
- constructor(client, builder) {
33
- super(client, builder);
34
-
35
- const { onConflict } = this.single;
36
- if (onConflict) {
37
- throw new Error('.onConflict() is not supported for oracledb.');
38
- }
39
-
40
- // Compiles the `select` statement, or nested sub-selects
41
- // by calling each of the component compilers, trimming out
42
- // the empties, and returning a generated query string.
43
- this.first = this.select;
44
- }
45
-
46
- // Compiles an "insert" query, allowing for multiple
47
- // inserts using a single query statement.
48
- insert() {
49
- let insertValues = this.single.insert || [];
50
- let { returning } = this.single;
51
-
52
- if (!Array.isArray(insertValues) && isPlainObject(this.single.insert)) {
53
- insertValues = [this.single.insert];
54
- }
55
-
56
- // always wrap returning argument in array
57
- if (returning && !Array.isArray(returning)) {
58
- returning = [returning];
59
- }
60
-
61
- if (
62
- Array.isArray(insertValues) &&
63
- insertValues.length === 1 &&
64
- isEmpty(insertValues[0])
65
- ) {
66
- return this._addReturningToSqlAndConvert(
67
- `insert into ${this.tableName} (${this.formatter.wrap(
68
- this.single.returning
69
- )}) values (default)`,
70
- returning,
71
- this.tableName
72
- );
73
- }
74
-
75
- if (
76
- isEmpty(this.single.insert) &&
77
- typeof this.single.insert !== 'function'
78
- ) {
79
- return '';
80
- }
81
-
82
- const insertData = this._prepInsert(insertValues);
83
-
84
- const sql = {};
85
-
86
- if (isString(insertData)) {
87
- return this._addReturningToSqlAndConvert(
88
- `insert into ${this.tableName} ${insertData}`,
89
- returning
90
- );
91
- }
92
-
93
- if (insertData.values.length === 1) {
94
- return this._addReturningToSqlAndConvert(
95
- `insert into ${this.tableName} (${this.formatter.columnize(
96
- insertData.columns
97
- )}) values (${this.formatter.parameterize(insertData.values[0])})`,
98
- returning,
99
- this.tableName
100
- );
101
- }
102
-
103
- const insertDefaultsOnly = insertData.columns.length === 0;
104
-
105
- sql.sql =
106
- 'begin ' +
107
- insertData.values
108
- .map((value) => {
109
- let returningHelper;
110
- const parameterizedValues = !insertDefaultsOnly
111
- ? this.formatter.parameterize(value, this.client.valueForUndefined)
112
- : '';
113
- const returningValues = Array.isArray(returning)
114
- ? returning
115
- : [returning];
116
- let subSql = `insert into ${this.tableName} `;
117
-
118
- if (returning) {
119
- returningHelper = new ReturningHelper(returningValues.join(':'));
120
- sql.outParams = (sql.outParams || []).concat(returningHelper);
121
- }
122
-
123
- if (insertDefaultsOnly) {
124
- // no columns given so only the default value
125
- subSql += `(${this.formatter.wrap(
126
- this.single.returning
127
- )}) values (default)`;
128
- } else {
129
- subSql += `(${this.formatter.columnize(
130
- insertData.columns
131
- )}) values (${parameterizedValues})`;
132
- }
133
- subSql += returning
134
- ? ` returning ROWID into ${this.formatter.parameter(
135
- returningHelper
136
- )}`
137
- : '';
138
-
139
- // pre bind position because subSql is an execute immediate parameter
140
- // later position binding will only convert the ? params
141
-
142
- subSql = this.formatter.client.positionBindings(subSql);
143
-
144
- const parameterizedValuesWithoutDefault = parameterizedValues
145
- .replace('DEFAULT, ', '')
146
- .replace(', DEFAULT', '');
147
- return (
148
- `execute immediate '${subSql.replace(/'/g, "''")}` +
149
- (parameterizedValuesWithoutDefault || returning ? "' using " : '') +
150
- parameterizedValuesWithoutDefault +
151
- (parameterizedValuesWithoutDefault && returning ? ', ' : '') +
152
- (returning ? 'out ?' : '') +
153
- ';'
154
- );
155
- })
156
- .join(' ') +
157
- 'end;';
158
-
159
- if (returning) {
160
- sql.returning = returning;
161
- // generate select statement with special order by to keep the order because 'in (..)' may change the order
162
- sql.returningSql =
163
- `select ${this.formatter.columnize(returning)}` +
164
- ' from ' +
165
- this.tableName +
166
- ' where ROWID in (' +
167
- sql.outParams.map((v, i) => `:${i + 1}`).join(', ') +
168
- ')' +
169
- ' order by case ROWID ' +
170
- sql.outParams
171
- .map((v, i) => `when CHARTOROWID(:${i + 1}) then ${i}`)
172
- .join(' ') +
173
- ' end';
174
- }
175
-
176
- return sql;
177
- }
178
-
179
- // Update method, including joins, wheres, order & limits.
180
- update() {
181
- const updates = this._prepUpdate(this.single.update);
182
- const where = this.where();
183
- let { returning } = this.single;
184
- const sql =
185
- `update ${this.tableName}` +
186
- ' set ' +
187
- updates.join(', ') +
188
- (where ? ` ${where}` : '');
189
-
190
- if (!returning) {
191
- return sql;
192
- }
193
-
194
- // always wrap returning argument in array
195
- if (!Array.isArray(returning)) {
196
- returning = [returning];
197
- }
198
-
199
- return this._addReturningToSqlAndConvert(sql, returning, this.tableName);
200
- }
201
-
202
- // Compiles a `truncate` query.
203
- truncate() {
204
- return `truncate table ${this.tableName}`;
205
- }
206
-
207
- forUpdate() {
208
- return 'for update';
209
- }
210
-
211
- forShare() {
212
- // lock for share is not directly supported by oracle
213
- // use LOCK TABLE .. IN SHARE MODE; instead
214
- this.client.logger.warn(
215
- 'lock for share is not supported by oracle dialect'
216
- );
217
- return '';
218
- }
219
-
220
- // Compiles a `columnInfo` query.
221
- columnInfo() {
222
- const column = this.single.columnInfo;
223
-
224
- // The user may have specified a custom wrapIdentifier function in the config. We
225
- // need to run the identifiers through that function, but not format them as
226
- // identifiers otherwise.
227
- const table = this.client.customWrapIdentifier(this.single.table, identity);
228
-
229
- // Node oracle drivers doesn't support LONG type (which is data_default type)
230
- const sql = `select * from xmltable( '/ROWSET/ROW'
231
- passing dbms_xmlgen.getXMLType('
232
- select char_col_decl_length, column_name, data_type, data_default, nullable
233
- from all_tab_columns where table_name = ''${table}'' ')
234
- columns
235
- CHAR_COL_DECL_LENGTH number, COLUMN_NAME varchar2(200), DATA_TYPE varchar2(106),
236
- DATA_DEFAULT clob, NULLABLE varchar2(1))`;
237
-
238
- return {
239
- sql: sql,
240
- output(resp) {
241
- const out = reduce(
242
- resp,
243
- function (columns, val) {
244
- columns[val.COLUMN_NAME] = {
245
- type: val.DATA_TYPE,
246
- defaultValue: val.DATA_DEFAULT,
247
- maxLength: val.CHAR_COL_DECL_LENGTH,
248
- nullable: val.NULLABLE === 'Y',
249
- };
250
- return columns;
251
- },
252
- {}
253
- );
254
- return (column && out[column]) || out;
255
- },
256
- };
257
- }
258
-
259
- select() {
260
- let query = this.with();
261
- const statements = components.map((component) => {
262
- return this[component]();
263
- });
264
- query += compact(statements).join(' ');
265
- return this._surroundQueryWithLimitAndOffset(query);
266
- }
267
-
268
- aggregate(stmt) {
269
- return this._aggregate(stmt, { aliasSeparator: ' ' });
270
- }
271
-
272
- // for single commands only
273
- _addReturningToSqlAndConvert(sql, returning, tableName) {
274
- const res = {
275
- sql,
276
- };
277
-
278
- if (!returning) {
279
- return res;
280
- }
281
-
282
- const returningValues = Array.isArray(returning) ? returning : [returning];
283
- const returningHelper = new ReturningHelper(returningValues.join(':'));
284
- res.sql =
285
- sql +
286
- ' returning ROWID into ' +
287
- this.formatter.parameter(returningHelper);
288
- res.returningSql = `select ${this.formatter.columnize(
289
- returning
290
- )} from ${tableName} where ROWID = :1`;
291
- res.outParams = [returningHelper];
292
- res.returning = returning;
293
- return res;
294
- }
295
-
296
- _surroundQueryWithLimitAndOffset(query) {
297
- let { limit } = this.single;
298
- const { offset } = this.single;
299
- const hasLimit = limit || limit === 0 || limit === '0';
300
- limit = +limit;
301
-
302
- if (!hasLimit && !offset) return query;
303
- query = query || '';
304
-
305
- if (hasLimit && !offset) {
306
- return `select * from (${query}) where rownum <= ${this.formatter.parameter(
307
- limit
308
- )}`;
309
- }
310
-
311
- const endRow = +offset + (hasLimit ? limit : 10000000000000);
312
-
313
- return (
314
- 'select * from ' +
315
- '(select row_.*, ROWNUM rownum_ from (' +
316
- query +
317
- ') row_ ' +
318
- 'where rownum <= ' +
319
- this.formatter.parameter(endRow) +
320
- ') ' +
321
- 'where rownum_ > ' +
322
- this.formatter.parameter(offset)
323
- );
324
- }
325
- }
326
-
327
- module.exports = QueryCompiler_Oracle;
1
+ /* eslint max-len:0 */
2
+
3
+ // Oracle Query Builder & Compiler
4
+ // ------
5
+ const compact = require('lodash/compact');
6
+ const identity = require('lodash/identity');
7
+ const isEmpty = require('lodash/isEmpty');
8
+ const isPlainObject = require('lodash/isPlainObject');
9
+ const reduce = require('lodash/reduce');
10
+ const QueryCompiler = require('../../../query/compiler');
11
+ const { ReturningHelper } = require('../utils');
12
+ const { isString } = require('../../../util/is');
13
+
14
+ const components = [
15
+ 'columns',
16
+ 'join',
17
+ 'where',
18
+ 'union',
19
+ 'group',
20
+ 'having',
21
+ 'order',
22
+ 'lock',
23
+ ];
24
+
25
+ // Query Compiler
26
+ // -------
27
+
28
+ // Set the "Formatter" to use for the queries,
29
+ // ensuring that all parameterized values (even across sub-queries)
30
+ // are properly built into the same query.
31
+ class QueryCompiler_Oracle extends QueryCompiler {
32
+ constructor(client, builder) {
33
+ super(client, builder);
34
+
35
+ const { onConflict } = this.single;
36
+ if (onConflict) {
37
+ throw new Error('.onConflict() is not supported for oracledb.');
38
+ }
39
+
40
+ // Compiles the `select` statement, or nested sub-selects
41
+ // by calling each of the component compilers, trimming out
42
+ // the empties, and returning a generated query string.
43
+ this.first = this.select;
44
+ }
45
+
46
+ // Compiles an "insert" query, allowing for multiple
47
+ // inserts using a single query statement.
48
+ insert() {
49
+ let insertValues = this.single.insert || [];
50
+ let { returning } = this.single;
51
+
52
+ if (!Array.isArray(insertValues) && isPlainObject(this.single.insert)) {
53
+ insertValues = [this.single.insert];
54
+ }
55
+
56
+ // always wrap returning argument in array
57
+ if (returning && !Array.isArray(returning)) {
58
+ returning = [returning];
59
+ }
60
+
61
+ if (
62
+ Array.isArray(insertValues) &&
63
+ insertValues.length === 1 &&
64
+ isEmpty(insertValues[0])
65
+ ) {
66
+ return this._addReturningToSqlAndConvert(
67
+ `insert into ${this.tableName} (${this.formatter.wrap(
68
+ this.single.returning
69
+ )}) values (default)`,
70
+ returning,
71
+ this.tableName
72
+ );
73
+ }
74
+
75
+ if (
76
+ isEmpty(this.single.insert) &&
77
+ typeof this.single.insert !== 'function'
78
+ ) {
79
+ return '';
80
+ }
81
+
82
+ const insertData = this._prepInsert(insertValues);
83
+
84
+ const sql = {};
85
+
86
+ if (isString(insertData)) {
87
+ return this._addReturningToSqlAndConvert(
88
+ `insert into ${this.tableName} ${insertData}`,
89
+ returning
90
+ );
91
+ }
92
+
93
+ if (insertData.values.length === 1) {
94
+ return this._addReturningToSqlAndConvert(
95
+ `insert into ${this.tableName} (${this.formatter.columnize(
96
+ insertData.columns
97
+ )}) values (${this.formatter.parameterize(insertData.values[0])})`,
98
+ returning,
99
+ this.tableName
100
+ );
101
+ }
102
+
103
+ const insertDefaultsOnly = insertData.columns.length === 0;
104
+
105
+ sql.sql =
106
+ 'begin ' +
107
+ insertData.values
108
+ .map((value) => {
109
+ let returningHelper;
110
+ const parameterizedValues = !insertDefaultsOnly
111
+ ? this.formatter.parameterize(value, this.client.valueForUndefined)
112
+ : '';
113
+ const returningValues = Array.isArray(returning)
114
+ ? returning
115
+ : [returning];
116
+ let subSql = `insert into ${this.tableName} `;
117
+
118
+ if (returning) {
119
+ returningHelper = new ReturningHelper(returningValues.join(':'));
120
+ sql.outParams = (sql.outParams || []).concat(returningHelper);
121
+ }
122
+
123
+ if (insertDefaultsOnly) {
124
+ // no columns given so only the default value
125
+ subSql += `(${this.formatter.wrap(
126
+ this.single.returning
127
+ )}) values (default)`;
128
+ } else {
129
+ subSql += `(${this.formatter.columnize(
130
+ insertData.columns
131
+ )}) values (${parameterizedValues})`;
132
+ }
133
+ subSql += returning
134
+ ? ` returning ROWID into ${this.formatter.parameter(
135
+ returningHelper
136
+ )}`
137
+ : '';
138
+
139
+ // pre bind position because subSql is an execute immediate parameter
140
+ // later position binding will only convert the ? params
141
+
142
+ subSql = this.formatter.client.positionBindings(subSql);
143
+
144
+ const parameterizedValuesWithoutDefault = parameterizedValues
145
+ .replace('DEFAULT, ', '')
146
+ .replace(', DEFAULT', '');
147
+ return (
148
+ `execute immediate '${subSql.replace(/'/g, "''")}` +
149
+ (parameterizedValuesWithoutDefault || returning ? "' using " : '') +
150
+ parameterizedValuesWithoutDefault +
151
+ (parameterizedValuesWithoutDefault && returning ? ', ' : '') +
152
+ (returning ? 'out ?' : '') +
153
+ ';'
154
+ );
155
+ })
156
+ .join(' ') +
157
+ 'end;';
158
+
159
+ if (returning) {
160
+ sql.returning = returning;
161
+ // generate select statement with special order by to keep the order because 'in (..)' may change the order
162
+ sql.returningSql =
163
+ `select ${this.formatter.columnize(returning)}` +
164
+ ' from ' +
165
+ this.tableName +
166
+ ' where ROWID in (' +
167
+ sql.outParams.map((v, i) => `:${i + 1}`).join(', ') +
168
+ ')' +
169
+ ' order by case ROWID ' +
170
+ sql.outParams
171
+ .map((v, i) => `when CHARTOROWID(:${i + 1}) then ${i}`)
172
+ .join(' ') +
173
+ ' end';
174
+ }
175
+
176
+ return sql;
177
+ }
178
+
179
+ // Update method, including joins, wheres, order & limits.
180
+ update() {
181
+ const updates = this._prepUpdate(this.single.update);
182
+ const where = this.where();
183
+ let { returning } = this.single;
184
+ const sql =
185
+ `update ${this.tableName}` +
186
+ ' set ' +
187
+ updates.join(', ') +
188
+ (where ? ` ${where}` : '');
189
+
190
+ if (!returning) {
191
+ return sql;
192
+ }
193
+
194
+ // always wrap returning argument in array
195
+ if (!Array.isArray(returning)) {
196
+ returning = [returning];
197
+ }
198
+
199
+ return this._addReturningToSqlAndConvert(sql, returning, this.tableName);
200
+ }
201
+
202
+ // Compiles a `truncate` query.
203
+ truncate() {
204
+ return `truncate table ${this.tableName}`;
205
+ }
206
+
207
+ forUpdate() {
208
+ return 'for update';
209
+ }
210
+
211
+ forShare() {
212
+ // lock for share is not directly supported by oracle
213
+ // use LOCK TABLE .. IN SHARE MODE; instead
214
+ this.client.logger.warn(
215
+ 'lock for share is not supported by oracle dialect'
216
+ );
217
+ return '';
218
+ }
219
+
220
+ // Compiles a `columnInfo` query.
221
+ columnInfo() {
222
+ const column = this.single.columnInfo;
223
+
224
+ // The user may have specified a custom wrapIdentifier function in the config. We
225
+ // need to run the identifiers through that function, but not format them as
226
+ // identifiers otherwise.
227
+ const table = this.client.customWrapIdentifier(this.single.table, identity);
228
+
229
+ // Node oracle drivers doesn't support LONG type (which is data_default type)
230
+ const sql = `select * from xmltable( '/ROWSET/ROW'
231
+ passing dbms_xmlgen.getXMLType('
232
+ select char_col_decl_length, column_name, data_type, data_default, nullable
233
+ from all_tab_columns where table_name = ''${table}'' ')
234
+ columns
235
+ CHAR_COL_DECL_LENGTH number, COLUMN_NAME varchar2(200), DATA_TYPE varchar2(106),
236
+ DATA_DEFAULT clob, NULLABLE varchar2(1))`;
237
+
238
+ return {
239
+ sql: sql,
240
+ output(resp) {
241
+ const out = reduce(
242
+ resp,
243
+ function (columns, val) {
244
+ columns[val.COLUMN_NAME] = {
245
+ type: val.DATA_TYPE,
246
+ defaultValue: val.DATA_DEFAULT,
247
+ maxLength: val.CHAR_COL_DECL_LENGTH,
248
+ nullable: val.NULLABLE === 'Y',
249
+ };
250
+ return columns;
251
+ },
252
+ {}
253
+ );
254
+ return (column && out[column]) || out;
255
+ },
256
+ };
257
+ }
258
+
259
+ select() {
260
+ let query = this.with();
261
+ const statements = components.map((component) => {
262
+ return this[component]();
263
+ });
264
+ query += compact(statements).join(' ');
265
+ return this._surroundQueryWithLimitAndOffset(query);
266
+ }
267
+
268
+ aggregate(stmt) {
269
+ return this._aggregate(stmt, { aliasSeparator: ' ' });
270
+ }
271
+
272
+ // for single commands only
273
+ _addReturningToSqlAndConvert(sql, returning, tableName) {
274
+ const res = {
275
+ sql,
276
+ };
277
+
278
+ if (!returning) {
279
+ return res;
280
+ }
281
+
282
+ const returningValues = Array.isArray(returning) ? returning : [returning];
283
+ const returningHelper = new ReturningHelper(returningValues.join(':'));
284
+ res.sql =
285
+ sql +
286
+ ' returning ROWID into ' +
287
+ this.formatter.parameter(returningHelper);
288
+ res.returningSql = `select ${this.formatter.columnize(
289
+ returning
290
+ )} from ${tableName} where ROWID = :1`;
291
+ res.outParams = [returningHelper];
292
+ res.returning = returning;
293
+ return res;
294
+ }
295
+
296
+ _surroundQueryWithLimitAndOffset(query) {
297
+ let { limit } = this.single;
298
+ const { offset } = this.single;
299
+ const hasLimit = limit || limit === 0 || limit === '0';
300
+ limit = +limit;
301
+
302
+ if (!hasLimit && !offset) return query;
303
+ query = query || '';
304
+
305
+ if (hasLimit && !offset) {
306
+ return `select * from (${query}) where rownum <= ${this.formatter.parameter(
307
+ limit
308
+ )}`;
309
+ }
310
+
311
+ const endRow = +offset + (hasLimit ? limit : 10000000000000);
312
+
313
+ return (
314
+ 'select * from ' +
315
+ '(select row_.*, ROWNUM rownum_ from (' +
316
+ query +
317
+ ') row_ ' +
318
+ 'where rownum <= ' +
319
+ this.formatter.parameter(endRow) +
320
+ ') ' +
321
+ 'where rownum_ > ' +
322
+ this.formatter.parameter(offset)
323
+ );
324
+ }
325
+ }
326
+
327
+ module.exports = QueryCompiler_Oracle;