knex 3.2.2 → 3.2.4
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +2447 -2441
- package/CONTRIBUTING.md +190 -190
- package/LICENSE +22 -22
- package/README.md +156 -156
- package/UPGRADING.md +245 -245
- package/bin/cli.js +516 -516
- package/bin/knexfile-runtime-error.js +27 -27
- package/bin/utils/cli-config-utils.js +217 -217
- package/bin/utils/constants.js +7 -7
- package/bin/utils/migrationsLister.js +37 -37
- package/knex.js +23 -23
- package/knex.mjs +11 -11
- package/lib/builder-interface-augmenter.js +120 -120
- package/lib/client.js +585 -585
- package/lib/constants.js +61 -61
- package/lib/dialects/better-sqlite3/index.js +101 -101
- package/lib/dialects/cockroachdb/crdb-columncompiler.js +14 -14
- package/lib/dialects/cockroachdb/crdb-querybuilder.js +11 -11
- package/lib/dialects/cockroachdb/crdb-querycompiler.js +122 -122
- package/lib/dialects/cockroachdb/crdb-tablecompiler.js +46 -46
- package/lib/dialects/cockroachdb/crdb-viewcompiler.js +15 -15
- package/lib/dialects/cockroachdb/index.js +86 -86
- package/lib/dialects/index.js +34 -34
- package/lib/dialects/mssql/index.js +498 -498
- package/lib/dialects/mssql/mssql-formatter.js +34 -34
- package/lib/dialects/mssql/query/mssql-querycompiler.js +601 -601
- package/lib/dialects/mssql/schema/mssql-columncompiler.js +185 -185
- package/lib/dialects/mssql/schema/mssql-compiler.js +91 -91
- package/lib/dialects/mssql/schema/mssql-tablecompiler.js +393 -393
- package/lib/dialects/mssql/schema/mssql-viewcompiler.js +55 -55
- package/lib/dialects/mssql/transaction.js +176 -176
- package/lib/dialects/mysql/index.js +317 -317
- package/lib/dialects/mysql/query/mysql-querybuilder.js +14 -14
- package/lib/dialects/mysql/query/mysql-querycompiler.js +292 -292
- package/lib/dialects/mysql/schema/mysql-columncompiler.js +193 -193
- package/lib/dialects/mysql/schema/mysql-compiler.js +60 -60
- package/lib/dialects/mysql/schema/mysql-tablecompiler.js +426 -426
- package/lib/dialects/mysql/schema/mysql-viewbuilder.js +21 -21
- package/lib/dialects/mysql/schema/mysql-viewcompiler.js +15 -15
- package/lib/dialects/mysql/transaction.js +46 -46
- package/lib/dialects/mysql2/index.js +53 -53
- package/lib/dialects/mysql2/transaction.js +44 -44
- package/lib/dialects/oracle/DEAD_CODE.md +5 -5
- package/lib/dialects/oracle/index.js +92 -92
- package/lib/dialects/oracle/query/oracle-querycompiler.js +343 -343
- package/lib/dialects/oracle/schema/internal/incrementUtils.js +22 -22
- package/lib/dialects/oracle/schema/internal/trigger.js +155 -155
- package/lib/dialects/oracle/schema/oracle-columnbuilder.js +17 -17
- package/lib/dialects/oracle/schema/oracle-columncompiler.js +126 -126
- package/lib/dialects/oracle/schema/oracle-compiler.js +124 -124
- package/lib/dialects/oracle/schema/oracle-tablecompiler.js +210 -210
- package/lib/dialects/oracle/utils.js +107 -107
- package/lib/dialects/oracledb/index.js +381 -381
- package/lib/dialects/oracledb/query/oracledb-querycompiler.js +481 -481
- package/lib/dialects/oracledb/schema/oracledb-columncompiler.js +61 -61
- package/lib/dialects/oracledb/schema/oracledb-tablecompiler.js +19 -19
- package/lib/dialects/oracledb/schema/oracledb-viewbuilder.js +13 -13
- package/lib/dialects/oracledb/schema/oracledb-viewcompiler.js +19 -19
- package/lib/dialects/oracledb/transaction.js +98 -98
- package/lib/dialects/oracledb/utils.js +208 -208
- package/lib/dialects/pgnative/index.js +60 -60
- package/lib/dialects/postgres/execution/pg-transaction.js +19 -19
- package/lib/dialects/postgres/index.js +373 -373
- package/lib/dialects/postgres/query/pg-querybuilder.js +43 -43
- package/lib/dialects/postgres/query/pg-querycompiler.js +400 -400
- package/lib/dialects/postgres/schema/pg-columncompiler.js +162 -162
- package/lib/dialects/postgres/schema/pg-compiler.js +138 -138
- package/lib/dialects/postgres/schema/pg-tablecompiler.js +331 -331
- package/lib/dialects/postgres/schema/pg-viewbuilder.js +21 -21
- package/lib/dialects/postgres/schema/pg-viewcompiler.js +35 -35
- package/lib/dialects/redshift/index.js +86 -86
- package/lib/dialects/redshift/query/redshift-querycompiler.js +163 -163
- package/lib/dialects/redshift/schema/redshift-columnbuilder.js +22 -22
- package/lib/dialects/redshift/schema/redshift-columncompiler.js +67 -67
- package/lib/dialects/redshift/schema/redshift-compiler.js +14 -14
- package/lib/dialects/redshift/schema/redshift-tablecompiler.js +134 -134
- package/lib/dialects/redshift/schema/redshift-viewcompiler.js +11 -11
- package/lib/dialects/redshift/transaction.js +32 -32
- package/lib/dialects/sqlite3/execution/sqlite-transaction.js +172 -172
- package/lib/dialects/sqlite3/index.js +263 -263
- package/lib/dialects/sqlite3/query/sqlite-querybuilder.js +33 -33
- package/lib/dialects/sqlite3/query/sqlite-querycompiler.js +341 -341
- package/lib/dialects/sqlite3/schema/ddl.js +380 -380
- package/lib/dialects/sqlite3/schema/internal/compiler.js +327 -327
- package/lib/dialects/sqlite3/schema/internal/parser-combinator.js +161 -161
- package/lib/dialects/sqlite3/schema/internal/parser.js +638 -638
- package/lib/dialects/sqlite3/schema/internal/sqlite-ddl-operations.js +41 -41
- package/lib/dialects/sqlite3/schema/internal/tokenizer.js +38 -38
- package/lib/dialects/sqlite3/schema/internal/utils.js +12 -12
- package/lib/dialects/sqlite3/schema/sqlite-columncompiler.js +50 -50
- package/lib/dialects/sqlite3/schema/sqlite-compiler.js +80 -80
- package/lib/dialects/sqlite3/schema/sqlite-tablecompiler.js +364 -364
- package/lib/dialects/sqlite3/schema/sqlite-viewcompiler.js +40 -40
- package/lib/execution/batch-insert.js +51 -51
- package/lib/execution/internal/delay.js +6 -6
- package/lib/execution/internal/ensure-connection-callback.js +41 -41
- package/lib/execution/internal/query-executioner.js +62 -62
- package/lib/execution/runner.js +325 -325
- package/lib/execution/transaction.js +417 -417
- package/lib/formatter/formatterUtils.js +42 -42
- package/lib/formatter/rawFormatter.js +84 -84
- package/lib/formatter/wrappingFormatter.js +253 -253
- package/lib/formatter.js +25 -25
- package/lib/index.js +3 -3
- package/lib/knex-builder/FunctionHelper.js +80 -80
- package/lib/knex-builder/Knex.js +59 -59
- package/lib/knex-builder/internal/config-resolver.js +57 -57
- package/lib/knex-builder/internal/parse-connection.js +87 -87
- package/lib/knex-builder/make-knex.js +345 -345
- package/lib/logger.js +76 -76
- package/lib/migrations/common/MigrationsLoader.js +36 -36
- package/lib/migrations/migrate/MigrationGenerator.js +84 -84
- package/lib/migrations/migrate/Migrator.js +632 -632
- package/lib/migrations/migrate/migrate-stub.js +17 -17
- package/lib/migrations/migrate/migration-list-resolver.js +33 -33
- package/lib/migrations/migrate/migrator-configuration-merger.js +58 -58
- package/lib/migrations/migrate/sources/fs-migrations.js +74 -74
- package/lib/migrations/migrate/stub/cjs.stub +15 -15
- package/lib/migrations/migrate/stub/coffee.stub +13 -13
- package/lib/migrations/migrate/stub/eg.stub +14 -14
- package/lib/migrations/migrate/stub/js-schema.stub +22 -22
- package/lib/migrations/migrate/stub/js.stub +22 -22
- package/lib/migrations/migrate/stub/knexfile-coffee.stub +34 -34
- package/lib/migrations/migrate/stub/knexfile-eg.stub +43 -43
- package/lib/migrations/migrate/stub/knexfile-js.stub +47 -47
- package/lib/migrations/migrate/stub/knexfile-ls.stub +35 -35
- package/lib/migrations/migrate/stub/knexfile-ts.stub +47 -47
- package/lib/migrations/migrate/stub/ls.stub +14 -14
- package/lib/migrations/migrate/stub/mjs.stub +23 -23
- package/lib/migrations/migrate/stub/ts-schema.stub +21 -21
- package/lib/migrations/migrate/stub/ts.stub +21 -21
- package/lib/migrations/migrate/table-creator.js +77 -77
- package/lib/migrations/migrate/table-resolver.js +27 -27
- package/lib/migrations/seed/Seeder.js +137 -137
- package/lib/migrations/seed/seed-stub.js +13 -13
- package/lib/migrations/seed/seeder-configuration-merger.js +60 -60
- package/lib/migrations/seed/sources/fs-seeds.js +65 -65
- package/lib/migrations/seed/stub/coffee.stub +9 -9
- package/lib/migrations/seed/stub/eg.stub +11 -11
- package/lib/migrations/seed/stub/js.stub +13 -13
- package/lib/migrations/seed/stub/ls.stub +11 -11
- package/lib/migrations/seed/stub/mjs.stub +12 -12
- package/lib/migrations/seed/stub/ts.stub +13 -13
- package/lib/migrations/util/fs.js +86 -86
- package/lib/migrations/util/import-file.js +12 -12
- package/lib/migrations/util/is-module-type.js +9 -9
- package/lib/migrations/util/template.js +52 -52
- package/lib/migrations/util/timestamp.js +14 -14
- package/lib/query/analytic.js +52 -52
- package/lib/query/constants.js +15 -15
- package/lib/query/joinclause.js +270 -270
- package/lib/query/method-constants.js +136 -136
- package/lib/query/querybuilder.js +1793 -1793
- package/lib/query/querycompiler.js +1634 -1634
- package/lib/raw.js +139 -139
- package/lib/ref.js +39 -39
- package/lib/schema/builder.js +115 -115
- package/lib/schema/columnbuilder.js +146 -146
- package/lib/schema/columncompiler.js +307 -307
- package/lib/schema/compiler.js +187 -187
- package/lib/schema/internal/helpers.js +55 -55
- package/lib/schema/tablebuilder.js +379 -379
- package/lib/schema/tablecompiler.js +450 -450
- package/lib/schema/viewbuilder.js +92 -92
- package/lib/schema/viewcompiler.js +138 -138
- package/lib/util/finally-mixin.js +13 -13
- package/lib/util/helpers.js +95 -95
- package/lib/util/is.js +32 -32
- package/lib/util/nanoid.js +40 -40
- package/lib/util/noop.js +1 -1
- package/lib/util/save-async-stack.js +14 -14
- package/lib/util/security.js +32 -32
- package/lib/util/string.js +190 -190
- package/lib/util/timeout.js +29 -29
- package/package.json +294 -296
- package/scripts/act-testing/act.sh +19 -19
- package/scripts/act-testing/merged-no-label.json +11 -11
- package/scripts/act-testing/merged-patch-labeled.json +12 -12
- package/scripts/act-testing/merged-skip-labeled.json +12 -12
- package/scripts/act-testing/not-merged-patch-labeled.json +12 -12
- package/scripts/build-for-release.sh +121 -121
- package/scripts/build.js +125 -125
- package/scripts/clean.js +31 -31
- package/scripts/docker-compose.yml +150 -150
- package/scripts/format-changelog.js +55 -55
- package/scripts/next-release-howto.md +24 -24
- package/scripts/oracledb-install-driver-libs.sh +82 -82
- package/scripts/release.sh +36 -36
- package/scripts/runkit-example.js +35 -35
- package/scripts/stress-test/README.txt +18 -18
- package/scripts/stress-test/docker-compose.yml +55 -55
- package/scripts/stress-test/knex-stress-test.js +212 -212
- package/scripts/stress-test/mysql2-random-hanging-every-now-and-then.js +149 -149
- package/scripts/stress-test/mysql2-sudden-exit-without-error.js +101 -101
- package/scripts/stress-test/reconnect-test-mysql-based-drivers.js +188 -188
- package/types/index.d.mts +11 -0
- package/types/index.d.ts +3321 -3321
- package/types/result.d.ts +27 -27
- package/types/tables.d.ts +4 -4
|
@@ -1,481 +1,481 @@
|
|
|
1
|
-
const clone = require('lodash/clone');
|
|
2
|
-
const each = require('lodash/each');
|
|
3
|
-
const isEmpty = require('lodash/isEmpty');
|
|
4
|
-
const isPlainObject = require('lodash/isPlainObject');
|
|
5
|
-
const Oracle_Compiler = require('../../oracle/query/oracle-querycompiler');
|
|
6
|
-
const ReturningHelper = require('../utils').ReturningHelper;
|
|
7
|
-
const BlobHelper = require('../utils').BlobHelper;
|
|
8
|
-
const { isString } = require('../../../util/is');
|
|
9
|
-
const {
|
|
10
|
-
columnize: columnize_,
|
|
11
|
-
} = require('../../../formatter/wrappingFormatter');
|
|
12
|
-
|
|
13
|
-
class Oracledb_Compiler extends Oracle_Compiler {
|
|
14
|
-
// Compiles an "insert" query, allowing for multiple
|
|
15
|
-
// inserts using a single query statement.
|
|
16
|
-
insert() {
|
|
17
|
-
const self = this;
|
|
18
|
-
const outBindPrep = this._prepOutbindings(
|
|
19
|
-
this.single.insert,
|
|
20
|
-
this.single.returning
|
|
21
|
-
);
|
|
22
|
-
const outBinding = outBindPrep.outBinding;
|
|
23
|
-
const returning = outBindPrep.returning;
|
|
24
|
-
const insertValues = outBindPrep.values;
|
|
25
|
-
|
|
26
|
-
if (
|
|
27
|
-
Array.isArray(insertValues) &&
|
|
28
|
-
insertValues.length === 1 &&
|
|
29
|
-
isEmpty(insertValues[0])
|
|
30
|
-
) {
|
|
31
|
-
const returningFragment = this.single.returning
|
|
32
|
-
? ' (' + this.formatter.wrap(this.single.returning) + ')'
|
|
33
|
-
: '';
|
|
34
|
-
|
|
35
|
-
return this._addReturningToSqlAndConvert(
|
|
36
|
-
'insert into ' +
|
|
37
|
-
this.tableName +
|
|
38
|
-
returningFragment +
|
|
39
|
-
' values (default)',
|
|
40
|
-
outBinding[0],
|
|
41
|
-
this.tableName,
|
|
42
|
-
returning
|
|
43
|
-
);
|
|
44
|
-
}
|
|
45
|
-
|
|
46
|
-
if (
|
|
47
|
-
isEmpty(this.single.insert) &&
|
|
48
|
-
typeof this.single.insert !== 'function'
|
|
49
|
-
) {
|
|
50
|
-
return '';
|
|
51
|
-
}
|
|
52
|
-
|
|
53
|
-
const insertData = this._prepInsert(insertValues);
|
|
54
|
-
|
|
55
|
-
const sql = {};
|
|
56
|
-
|
|
57
|
-
if (isString(insertData)) {
|
|
58
|
-
return this._addReturningToSqlAndConvert(
|
|
59
|
-
'insert into ' + this.tableName + ' ' + insertData,
|
|
60
|
-
outBinding[0],
|
|
61
|
-
this.tableName,
|
|
62
|
-
returning
|
|
63
|
-
);
|
|
64
|
-
}
|
|
65
|
-
|
|
66
|
-
if (insertData.values.length === 1) {
|
|
67
|
-
return this._addReturningToSqlAndConvert(
|
|
68
|
-
'insert into ' +
|
|
69
|
-
this.tableName +
|
|
70
|
-
' (' +
|
|
71
|
-
this.formatter.columnize(insertData.columns) +
|
|
72
|
-
') values (' +
|
|
73
|
-
this.client.parameterize(
|
|
74
|
-
insertData.values[0],
|
|
75
|
-
undefined,
|
|
76
|
-
this.builder,
|
|
77
|
-
this.bindingsHolder
|
|
78
|
-
) +
|
|
79
|
-
')',
|
|
80
|
-
outBinding[0],
|
|
81
|
-
this.tableName,
|
|
82
|
-
returning
|
|
83
|
-
);
|
|
84
|
-
}
|
|
85
|
-
|
|
86
|
-
const insertDefaultsOnly = insertData.columns.length === 0;
|
|
87
|
-
sql.returning = returning;
|
|
88
|
-
sql.sql =
|
|
89
|
-
'begin ' +
|
|
90
|
-
insertData.values
|
|
91
|
-
.map(function (value, index) {
|
|
92
|
-
const parameterizedValues = !insertDefaultsOnly
|
|
93
|
-
? self.client.parameterize(
|
|
94
|
-
value,
|
|
95
|
-
self.client.valueForUndefined,
|
|
96
|
-
self.builder,
|
|
97
|
-
self.bindingsHolder
|
|
98
|
-
)
|
|
99
|
-
: '';
|
|
100
|
-
let subSql = 'insert into ' + self.tableName;
|
|
101
|
-
|
|
102
|
-
if (insertDefaultsOnly) {
|
|
103
|
-
// No columns given so only the default value
|
|
104
|
-
subSql +=
|
|
105
|
-
' (' +
|
|
106
|
-
self.formatter.wrap(self.single.returning) +
|
|
107
|
-
') values (default)';
|
|
108
|
-
} else {
|
|
109
|
-
subSql +=
|
|
110
|
-
' (' +
|
|
111
|
-
self.formatter.columnize(insertData.columns) +
|
|
112
|
-
') values (' +
|
|
113
|
-
parameterizedValues +
|
|
114
|
-
')';
|
|
115
|
-
}
|
|
116
|
-
|
|
117
|
-
let returningClause = '';
|
|
118
|
-
let intoClause = '';
|
|
119
|
-
// ToDo review if this code is still needed or could be dropped
|
|
120
|
-
// eslint-disable-next-line no-unused-vars
|
|
121
|
-
let usingClause = '';
|
|
122
|
-
let outClause = '';
|
|
123
|
-
|
|
124
|
-
each(value, function (val) {
|
|
125
|
-
if (!(val instanceof BlobHelper)) {
|
|
126
|
-
usingClause += ' ?,';
|
|
127
|
-
}
|
|
128
|
-
});
|
|
129
|
-
// eslint-disable-next-line no-unused-vars
|
|
130
|
-
usingClause = usingClause.slice(0, -1);
|
|
131
|
-
|
|
132
|
-
// Build returning and into clauses
|
|
133
|
-
outBinding[index].forEach(function (ret) {
|
|
134
|
-
const columnName = ret.columnName || ret;
|
|
135
|
-
returningClause += self.formatter.wrap(columnName) + ',';
|
|
136
|
-
intoClause += ' ?,';
|
|
137
|
-
outClause += ' out ?,';
|
|
138
|
-
|
|
139
|
-
// Add Helpers to bindings
|
|
140
|
-
if (ret instanceof BlobHelper) {
|
|
141
|
-
return self.formatter.bindings.push(ret);
|
|
142
|
-
}
|
|
143
|
-
self.formatter.bindings.push(new ReturningHelper(columnName));
|
|
144
|
-
});
|
|
145
|
-
|
|
146
|
-
// Strip last comma
|
|
147
|
-
returningClause = returningClause.slice(0, -1);
|
|
148
|
-
intoClause = intoClause.slice(0, -1);
|
|
149
|
-
outClause = outClause.slice(0, -1);
|
|
150
|
-
|
|
151
|
-
if (returningClause && intoClause) {
|
|
152
|
-
subSql += ' returning ' + returningClause + ' into' + intoClause;
|
|
153
|
-
}
|
|
154
|
-
|
|
155
|
-
// Pre bind position because subSql is an execute immediate parameter
|
|
156
|
-
// later position binding will only convert the ? params
|
|
157
|
-
subSql = self.formatter.client.positionBindings(subSql);
|
|
158
|
-
const parameterizedValuesWithoutDefaultAndBlob = parameterizedValues
|
|
159
|
-
.replace(/DEFAULT, /g, '')
|
|
160
|
-
.replace(/, DEFAULT/g, '')
|
|
161
|
-
.replace('EMPTY_BLOB(), ', '')
|
|
162
|
-
.replace(', EMPTY_BLOB()', '');
|
|
163
|
-
return (
|
|
164
|
-
"execute immediate '" +
|
|
165
|
-
subSql.replace(/'/g, "''") +
|
|
166
|
-
(parameterizedValuesWithoutDefaultAndBlob || value
|
|
167
|
-
? "' using "
|
|
168
|
-
: '') +
|
|
169
|
-
parameterizedValuesWithoutDefaultAndBlob +
|
|
170
|
-
(parameterizedValuesWithoutDefaultAndBlob && outClause ? ',' : '') +
|
|
171
|
-
outClause +
|
|
172
|
-
';'
|
|
173
|
-
);
|
|
174
|
-
})
|
|
175
|
-
.join(' ') +
|
|
176
|
-
'end;';
|
|
177
|
-
|
|
178
|
-
sql.outBinding = outBinding;
|
|
179
|
-
if (returning[0] === '*') {
|
|
180
|
-
// Generate select statement with special order by
|
|
181
|
-
// to keep the order because 'in (..)' may change the order
|
|
182
|
-
sql.returningSql = function () {
|
|
183
|
-
return (
|
|
184
|
-
'select * from ' +
|
|
185
|
-
self.tableName +
|
|
186
|
-
' where ROWID in (' +
|
|
187
|
-
this.outBinding
|
|
188
|
-
.map(function (v, i) {
|
|
189
|
-
return ':' + (i + 1);
|
|
190
|
-
})
|
|
191
|
-
.join(', ') +
|
|
192
|
-
')' +
|
|
193
|
-
' order by case ROWID ' +
|
|
194
|
-
this.outBinding
|
|
195
|
-
.map(function (v, i) {
|
|
196
|
-
return 'when CHARTOROWID(:' + (i + 1) + ') then ' + i;
|
|
197
|
-
})
|
|
198
|
-
.join(' ') +
|
|
199
|
-
' end'
|
|
200
|
-
);
|
|
201
|
-
};
|
|
202
|
-
}
|
|
203
|
-
|
|
204
|
-
return sql;
|
|
205
|
-
}
|
|
206
|
-
|
|
207
|
-
with() {
|
|
208
|
-
// WITH RECURSIVE is a syntax error in Oracle SQL.
|
|
209
|
-
// So mark all statements as non-recursive, generate the SQL, then restore.
|
|
210
|
-
// This approach ensures any changes in base class with() get propagated here.
|
|
211
|
-
const undoList = [];
|
|
212
|
-
if (this.grouped.with) {
|
|
213
|
-
for (const stmt of this.grouped.with) {
|
|
214
|
-
if (stmt.recursive) {
|
|
215
|
-
undoList.push(stmt);
|
|
216
|
-
stmt.recursive = false;
|
|
217
|
-
}
|
|
218
|
-
}
|
|
219
|
-
}
|
|
220
|
-
|
|
221
|
-
const result = super.with();
|
|
222
|
-
|
|
223
|
-
// Restore the recursive markings, in case this same query gets cloned and passed to other drivers.
|
|
224
|
-
for (const stmt of undoList) {
|
|
225
|
-
stmt.recursive = true;
|
|
226
|
-
}
|
|
227
|
-
return result;
|
|
228
|
-
}
|
|
229
|
-
|
|
230
|
-
_addReturningToSqlAndConvert(sql, outBinding, tableName, returning) {
|
|
231
|
-
const self = this;
|
|
232
|
-
const res = {
|
|
233
|
-
sql: sql,
|
|
234
|
-
};
|
|
235
|
-
|
|
236
|
-
if (!outBinding) {
|
|
237
|
-
return res;
|
|
238
|
-
}
|
|
239
|
-
const returningValues = Array.isArray(outBinding)
|
|
240
|
-
? outBinding
|
|
241
|
-
: [outBinding];
|
|
242
|
-
let returningClause = '';
|
|
243
|
-
let intoClause = '';
|
|
244
|
-
// Build returning and into clauses
|
|
245
|
-
returningValues.forEach(function (ret) {
|
|
246
|
-
const columnName = ret.columnName || ret;
|
|
247
|
-
returningClause += self.formatter.wrap(columnName) + ',';
|
|
248
|
-
intoClause += '?,';
|
|
249
|
-
|
|
250
|
-
// Add Helpers to bindings
|
|
251
|
-
if (ret instanceof BlobHelper) {
|
|
252
|
-
return self.formatter.bindings.push(ret);
|
|
253
|
-
}
|
|
254
|
-
self.formatter.bindings.push(new ReturningHelper(columnName));
|
|
255
|
-
});
|
|
256
|
-
res.sql = sql;
|
|
257
|
-
|
|
258
|
-
// Strip last comma
|
|
259
|
-
returningClause = returningClause.slice(0, -1);
|
|
260
|
-
intoClause = intoClause.slice(0, -1);
|
|
261
|
-
if (returningClause && intoClause) {
|
|
262
|
-
res.sql += ' returning ' + returningClause + ' into ' + intoClause;
|
|
263
|
-
}
|
|
264
|
-
res.outBinding = [outBinding];
|
|
265
|
-
if (returning[0] === '*') {
|
|
266
|
-
res.returningSql = function () {
|
|
267
|
-
return 'select * from ' + self.tableName + ' where ROWID = :1';
|
|
268
|
-
};
|
|
269
|
-
}
|
|
270
|
-
res.returning = returning;
|
|
271
|
-
|
|
272
|
-
return res;
|
|
273
|
-
}
|
|
274
|
-
|
|
275
|
-
_prepOutbindings(paramValues, paramReturning) {
|
|
276
|
-
const result = {};
|
|
277
|
-
let params = paramValues || [];
|
|
278
|
-
let returning = paramReturning || [];
|
|
279
|
-
if (!Array.isArray(params) && isPlainObject(paramValues)) {
|
|
280
|
-
params = [params];
|
|
281
|
-
}
|
|
282
|
-
// Always wrap returning argument in array
|
|
283
|
-
if (returning && !Array.isArray(returning)) {
|
|
284
|
-
returning = [returning];
|
|
285
|
-
}
|
|
286
|
-
|
|
287
|
-
const outBinding = [];
|
|
288
|
-
// Handle Buffer value as Blob
|
|
289
|
-
each(params, function (values, index) {
|
|
290
|
-
if (returning[0] === '*') {
|
|
291
|
-
outBinding[index] = ['ROWID'];
|
|
292
|
-
} else {
|
|
293
|
-
outBinding[index] = clone(returning);
|
|
294
|
-
}
|
|
295
|
-
each(values, function (value, key) {
|
|
296
|
-
if (value instanceof Buffer) {
|
|
297
|
-
values[key] = new BlobHelper(key, value);
|
|
298
|
-
|
|
299
|
-
// Delete blob duplicate in returning
|
|
300
|
-
const blobIndex = outBinding[index].indexOf(key);
|
|
301
|
-
if (blobIndex >= 0) {
|
|
302
|
-
outBinding[index].splice(blobIndex, 1);
|
|
303
|
-
values[key].returning = true;
|
|
304
|
-
}
|
|
305
|
-
outBinding[index].push(values[key]);
|
|
306
|
-
}
|
|
307
|
-
if (value === undefined) {
|
|
308
|
-
delete params[index][key];
|
|
309
|
-
}
|
|
310
|
-
});
|
|
311
|
-
});
|
|
312
|
-
result.returning = returning;
|
|
313
|
-
result.outBinding = outBinding;
|
|
314
|
-
result.values = params;
|
|
315
|
-
return result;
|
|
316
|
-
}
|
|
317
|
-
|
|
318
|
-
_groupOrder(item, type) {
|
|
319
|
-
return super._groupOrderNulls(item, type);
|
|
320
|
-
}
|
|
321
|
-
|
|
322
|
-
update() {
|
|
323
|
-
const self = this;
|
|
324
|
-
const sql = {};
|
|
325
|
-
const outBindPrep = this._prepOutbindings(
|
|
326
|
-
this.single.update || this.single.counter,
|
|
327
|
-
this.single.returning
|
|
328
|
-
);
|
|
329
|
-
const outBinding = outBindPrep.outBinding;
|
|
330
|
-
const returning = outBindPrep.returning;
|
|
331
|
-
|
|
332
|
-
const updates = this._prepUpdate(this.single.update);
|
|
333
|
-
const where = this.where();
|
|
334
|
-
|
|
335
|
-
let returningClause = '';
|
|
336
|
-
let intoClause = '';
|
|
337
|
-
|
|
338
|
-
if (isEmpty(updates) && typeof this.single.update !== 'function') {
|
|
339
|
-
return '';
|
|
340
|
-
}
|
|
341
|
-
|
|
342
|
-
// Build returning and into clauses
|
|
343
|
-
outBinding.forEach(function (out) {
|
|
344
|
-
out.forEach(function (ret) {
|
|
345
|
-
const columnName = ret.columnName || ret;
|
|
346
|
-
returningClause += self.formatter.wrap(columnName) + ',';
|
|
347
|
-
intoClause += ' ?,';
|
|
348
|
-
|
|
349
|
-
// Add Helpers to bindings
|
|
350
|
-
if (ret instanceof BlobHelper) {
|
|
351
|
-
return self.formatter.bindings.push(ret);
|
|
352
|
-
}
|
|
353
|
-
self.formatter.bindings.push(new ReturningHelper(columnName));
|
|
354
|
-
});
|
|
355
|
-
});
|
|
356
|
-
// Strip last comma
|
|
357
|
-
returningClause = returningClause.slice(0, -1);
|
|
358
|
-
intoClause = intoClause.slice(0, -1);
|
|
359
|
-
|
|
360
|
-
sql.outBinding = outBinding;
|
|
361
|
-
sql.returning = returning;
|
|
362
|
-
sql.sql =
|
|
363
|
-
'update ' +
|
|
364
|
-
this.tableName +
|
|
365
|
-
' set ' +
|
|
366
|
-
updates.join(', ') +
|
|
367
|
-
(where ? ' ' + where : '');
|
|
368
|
-
if (outBinding.length && !isEmpty(outBinding[0])) {
|
|
369
|
-
sql.sql += ' returning ' + returningClause + ' into' + intoClause;
|
|
370
|
-
}
|
|
371
|
-
if (returning[0] === '*') {
|
|
372
|
-
sql.returningSql = function () {
|
|
373
|
-
let sql = 'select * from ' + self.tableName;
|
|
374
|
-
const modifiedRowsCount = this.rowsAffected.length || this.rowsAffected;
|
|
375
|
-
let returningSqlIn = ' where ROWID in (';
|
|
376
|
-
let returningSqlOrderBy = ') order by case ROWID ';
|
|
377
|
-
|
|
378
|
-
// Needs special order by because in(...) change result order
|
|
379
|
-
for (let i = 0; i < modifiedRowsCount; i++) {
|
|
380
|
-
if (this.returning[0] === '*') {
|
|
381
|
-
returningSqlIn += ':' + (i + 1) + ', ';
|
|
382
|
-
returningSqlOrderBy +=
|
|
383
|
-
'when CHARTOROWID(:' + (i + 1) + ') then ' + i + ' ';
|
|
384
|
-
}
|
|
385
|
-
}
|
|
386
|
-
if (this.returning[0] === '*') {
|
|
387
|
-
this.returning = this.returning.slice(0, -1);
|
|
388
|
-
returningSqlIn = returningSqlIn.slice(0, -2);
|
|
389
|
-
returningSqlOrderBy = returningSqlOrderBy.slice(0, -1);
|
|
390
|
-
}
|
|
391
|
-
return (sql += returningSqlIn + returningSqlOrderBy + ' end');
|
|
392
|
-
};
|
|
393
|
-
}
|
|
394
|
-
|
|
395
|
-
return sql;
|
|
396
|
-
}
|
|
397
|
-
|
|
398
|
-
_jsonPathWrap(extraction) {
|
|
399
|
-
return `'${extraction.path || extraction[1]}'`;
|
|
400
|
-
}
|
|
401
|
-
|
|
402
|
-
// Json functions
|
|
403
|
-
jsonExtract(params) {
|
|
404
|
-
return this._jsonExtract(
|
|
405
|
-
params.singleValue ? 'json_value' : 'json_query',
|
|
406
|
-
params
|
|
407
|
-
);
|
|
408
|
-
}
|
|
409
|
-
|
|
410
|
-
jsonSet(params) {
|
|
411
|
-
return `json_transform(${columnize_(
|
|
412
|
-
params.column,
|
|
413
|
-
this.builder,
|
|
414
|
-
this.client,
|
|
415
|
-
this.bindingsHolder
|
|
416
|
-
)}, set ${this.client.parameter(
|
|
417
|
-
params.path,
|
|
418
|
-
this.builder,
|
|
419
|
-
this.bindingsHolder
|
|
420
|
-
)} = ${this.client.parameter(
|
|
421
|
-
params.value,
|
|
422
|
-
this.builder,
|
|
423
|
-
this.bindingsHolder
|
|
424
|
-
)})`;
|
|
425
|
-
}
|
|
426
|
-
|
|
427
|
-
jsonInsert(params) {
|
|
428
|
-
return `json_transform(${columnize_(
|
|
429
|
-
params.column,
|
|
430
|
-
this.builder,
|
|
431
|
-
this.client,
|
|
432
|
-
this.bindingsHolder
|
|
433
|
-
)}, insert ${this.client.parameter(
|
|
434
|
-
params.path,
|
|
435
|
-
this.builder,
|
|
436
|
-
this.bindingsHolder
|
|
437
|
-
)} = ${this.client.parameter(
|
|
438
|
-
params.value,
|
|
439
|
-
this.builder,
|
|
440
|
-
this.bindingsHolder
|
|
441
|
-
)})`;
|
|
442
|
-
}
|
|
443
|
-
|
|
444
|
-
jsonRemove(params) {
|
|
445
|
-
const jsonCol = `json_transform(${columnize_(
|
|
446
|
-
params.column,
|
|
447
|
-
this.builder,
|
|
448
|
-
this.client,
|
|
449
|
-
this.bindingsHolder
|
|
450
|
-
)}, remove ${this.client.parameter(
|
|
451
|
-
params.path,
|
|
452
|
-
this.builder,
|
|
453
|
-
this.bindingsHolder
|
|
454
|
-
)})`;
|
|
455
|
-
return params.alias
|
|
456
|
-
? this.client.alias(jsonCol, this.formatter.wrap(params.alias))
|
|
457
|
-
: jsonCol;
|
|
458
|
-
}
|
|
459
|
-
|
|
460
|
-
whereJsonPath(statement) {
|
|
461
|
-
return this._whereJsonPath('json_value', statement);
|
|
462
|
-
}
|
|
463
|
-
|
|
464
|
-
whereJsonSupersetOf(statement) {
|
|
465
|
-
throw new Error(
|
|
466
|
-
'Json superset where clause not actually supported by Oracle'
|
|
467
|
-
);
|
|
468
|
-
}
|
|
469
|
-
|
|
470
|
-
whereJsonSubsetOf(statement) {
|
|
471
|
-
throw new Error(
|
|
472
|
-
'Json subset where clause not actually supported by Oracle'
|
|
473
|
-
);
|
|
474
|
-
}
|
|
475
|
-
|
|
476
|
-
onJsonPathEquals(clause) {
|
|
477
|
-
return this._onJsonPathEquals('json_value', clause);
|
|
478
|
-
}
|
|
479
|
-
}
|
|
480
|
-
|
|
481
|
-
module.exports = Oracledb_Compiler;
|
|
1
|
+
const clone = require('lodash/clone');
|
|
2
|
+
const each = require('lodash/each');
|
|
3
|
+
const isEmpty = require('lodash/isEmpty');
|
|
4
|
+
const isPlainObject = require('lodash/isPlainObject');
|
|
5
|
+
const Oracle_Compiler = require('../../oracle/query/oracle-querycompiler');
|
|
6
|
+
const ReturningHelper = require('../utils').ReturningHelper;
|
|
7
|
+
const BlobHelper = require('../utils').BlobHelper;
|
|
8
|
+
const { isString } = require('../../../util/is');
|
|
9
|
+
const {
|
|
10
|
+
columnize: columnize_,
|
|
11
|
+
} = require('../../../formatter/wrappingFormatter');
|
|
12
|
+
|
|
13
|
+
class Oracledb_Compiler extends Oracle_Compiler {
|
|
14
|
+
// Compiles an "insert" query, allowing for multiple
|
|
15
|
+
// inserts using a single query statement.
|
|
16
|
+
insert() {
|
|
17
|
+
const self = this;
|
|
18
|
+
const outBindPrep = this._prepOutbindings(
|
|
19
|
+
this.single.insert,
|
|
20
|
+
this.single.returning
|
|
21
|
+
);
|
|
22
|
+
const outBinding = outBindPrep.outBinding;
|
|
23
|
+
const returning = outBindPrep.returning;
|
|
24
|
+
const insertValues = outBindPrep.values;
|
|
25
|
+
|
|
26
|
+
if (
|
|
27
|
+
Array.isArray(insertValues) &&
|
|
28
|
+
insertValues.length === 1 &&
|
|
29
|
+
isEmpty(insertValues[0])
|
|
30
|
+
) {
|
|
31
|
+
const returningFragment = this.single.returning
|
|
32
|
+
? ' (' + this.formatter.wrap(this.single.returning) + ')'
|
|
33
|
+
: '';
|
|
34
|
+
|
|
35
|
+
return this._addReturningToSqlAndConvert(
|
|
36
|
+
'insert into ' +
|
|
37
|
+
this.tableName +
|
|
38
|
+
returningFragment +
|
|
39
|
+
' values (default)',
|
|
40
|
+
outBinding[0],
|
|
41
|
+
this.tableName,
|
|
42
|
+
returning
|
|
43
|
+
);
|
|
44
|
+
}
|
|
45
|
+
|
|
46
|
+
if (
|
|
47
|
+
isEmpty(this.single.insert) &&
|
|
48
|
+
typeof this.single.insert !== 'function'
|
|
49
|
+
) {
|
|
50
|
+
return '';
|
|
51
|
+
}
|
|
52
|
+
|
|
53
|
+
const insertData = this._prepInsert(insertValues);
|
|
54
|
+
|
|
55
|
+
const sql = {};
|
|
56
|
+
|
|
57
|
+
if (isString(insertData)) {
|
|
58
|
+
return this._addReturningToSqlAndConvert(
|
|
59
|
+
'insert into ' + this.tableName + ' ' + insertData,
|
|
60
|
+
outBinding[0],
|
|
61
|
+
this.tableName,
|
|
62
|
+
returning
|
|
63
|
+
);
|
|
64
|
+
}
|
|
65
|
+
|
|
66
|
+
if (insertData.values.length === 1) {
|
|
67
|
+
return this._addReturningToSqlAndConvert(
|
|
68
|
+
'insert into ' +
|
|
69
|
+
this.tableName +
|
|
70
|
+
' (' +
|
|
71
|
+
this.formatter.columnize(insertData.columns) +
|
|
72
|
+
') values (' +
|
|
73
|
+
this.client.parameterize(
|
|
74
|
+
insertData.values[0],
|
|
75
|
+
undefined,
|
|
76
|
+
this.builder,
|
|
77
|
+
this.bindingsHolder
|
|
78
|
+
) +
|
|
79
|
+
')',
|
|
80
|
+
outBinding[0],
|
|
81
|
+
this.tableName,
|
|
82
|
+
returning
|
|
83
|
+
);
|
|
84
|
+
}
|
|
85
|
+
|
|
86
|
+
const insertDefaultsOnly = insertData.columns.length === 0;
|
|
87
|
+
sql.returning = returning;
|
|
88
|
+
sql.sql =
|
|
89
|
+
'begin ' +
|
|
90
|
+
insertData.values
|
|
91
|
+
.map(function (value, index) {
|
|
92
|
+
const parameterizedValues = !insertDefaultsOnly
|
|
93
|
+
? self.client.parameterize(
|
|
94
|
+
value,
|
|
95
|
+
self.client.valueForUndefined,
|
|
96
|
+
self.builder,
|
|
97
|
+
self.bindingsHolder
|
|
98
|
+
)
|
|
99
|
+
: '';
|
|
100
|
+
let subSql = 'insert into ' + self.tableName;
|
|
101
|
+
|
|
102
|
+
if (insertDefaultsOnly) {
|
|
103
|
+
// No columns given so only the default value
|
|
104
|
+
subSql +=
|
|
105
|
+
' (' +
|
|
106
|
+
self.formatter.wrap(self.single.returning) +
|
|
107
|
+
') values (default)';
|
|
108
|
+
} else {
|
|
109
|
+
subSql +=
|
|
110
|
+
' (' +
|
|
111
|
+
self.formatter.columnize(insertData.columns) +
|
|
112
|
+
') values (' +
|
|
113
|
+
parameterizedValues +
|
|
114
|
+
')';
|
|
115
|
+
}
|
|
116
|
+
|
|
117
|
+
let returningClause = '';
|
|
118
|
+
let intoClause = '';
|
|
119
|
+
// ToDo review if this code is still needed or could be dropped
|
|
120
|
+
// eslint-disable-next-line no-unused-vars
|
|
121
|
+
let usingClause = '';
|
|
122
|
+
let outClause = '';
|
|
123
|
+
|
|
124
|
+
each(value, function (val) {
|
|
125
|
+
if (!(val instanceof BlobHelper)) {
|
|
126
|
+
usingClause += ' ?,';
|
|
127
|
+
}
|
|
128
|
+
});
|
|
129
|
+
// eslint-disable-next-line no-unused-vars
|
|
130
|
+
usingClause = usingClause.slice(0, -1);
|
|
131
|
+
|
|
132
|
+
// Build returning and into clauses
|
|
133
|
+
outBinding[index].forEach(function (ret) {
|
|
134
|
+
const columnName = ret.columnName || ret;
|
|
135
|
+
returningClause += self.formatter.wrap(columnName) + ',';
|
|
136
|
+
intoClause += ' ?,';
|
|
137
|
+
outClause += ' out ?,';
|
|
138
|
+
|
|
139
|
+
// Add Helpers to bindings
|
|
140
|
+
if (ret instanceof BlobHelper) {
|
|
141
|
+
return self.formatter.bindings.push(ret);
|
|
142
|
+
}
|
|
143
|
+
self.formatter.bindings.push(new ReturningHelper(columnName));
|
|
144
|
+
});
|
|
145
|
+
|
|
146
|
+
// Strip last comma
|
|
147
|
+
returningClause = returningClause.slice(0, -1);
|
|
148
|
+
intoClause = intoClause.slice(0, -1);
|
|
149
|
+
outClause = outClause.slice(0, -1);
|
|
150
|
+
|
|
151
|
+
if (returningClause && intoClause) {
|
|
152
|
+
subSql += ' returning ' + returningClause + ' into' + intoClause;
|
|
153
|
+
}
|
|
154
|
+
|
|
155
|
+
// Pre bind position because subSql is an execute immediate parameter
|
|
156
|
+
// later position binding will only convert the ? params
|
|
157
|
+
subSql = self.formatter.client.positionBindings(subSql);
|
|
158
|
+
const parameterizedValuesWithoutDefaultAndBlob = parameterizedValues
|
|
159
|
+
.replace(/DEFAULT, /g, '')
|
|
160
|
+
.replace(/, DEFAULT/g, '')
|
|
161
|
+
.replace('EMPTY_BLOB(), ', '')
|
|
162
|
+
.replace(', EMPTY_BLOB()', '');
|
|
163
|
+
return (
|
|
164
|
+
"execute immediate '" +
|
|
165
|
+
subSql.replace(/'/g, "''") +
|
|
166
|
+
(parameterizedValuesWithoutDefaultAndBlob || value
|
|
167
|
+
? "' using "
|
|
168
|
+
: '') +
|
|
169
|
+
parameterizedValuesWithoutDefaultAndBlob +
|
|
170
|
+
(parameterizedValuesWithoutDefaultAndBlob && outClause ? ',' : '') +
|
|
171
|
+
outClause +
|
|
172
|
+
';'
|
|
173
|
+
);
|
|
174
|
+
})
|
|
175
|
+
.join(' ') +
|
|
176
|
+
'end;';
|
|
177
|
+
|
|
178
|
+
sql.outBinding = outBinding;
|
|
179
|
+
if (returning[0] === '*') {
|
|
180
|
+
// Generate select statement with special order by
|
|
181
|
+
// to keep the order because 'in (..)' may change the order
|
|
182
|
+
sql.returningSql = function () {
|
|
183
|
+
return (
|
|
184
|
+
'select * from ' +
|
|
185
|
+
self.tableName +
|
|
186
|
+
' where ROWID in (' +
|
|
187
|
+
this.outBinding
|
|
188
|
+
.map(function (v, i) {
|
|
189
|
+
return ':' + (i + 1);
|
|
190
|
+
})
|
|
191
|
+
.join(', ') +
|
|
192
|
+
')' +
|
|
193
|
+
' order by case ROWID ' +
|
|
194
|
+
this.outBinding
|
|
195
|
+
.map(function (v, i) {
|
|
196
|
+
return 'when CHARTOROWID(:' + (i + 1) + ') then ' + i;
|
|
197
|
+
})
|
|
198
|
+
.join(' ') +
|
|
199
|
+
' end'
|
|
200
|
+
);
|
|
201
|
+
};
|
|
202
|
+
}
|
|
203
|
+
|
|
204
|
+
return sql;
|
|
205
|
+
}
|
|
206
|
+
|
|
207
|
+
with() {
|
|
208
|
+
// WITH RECURSIVE is a syntax error in Oracle SQL.
|
|
209
|
+
// So mark all statements as non-recursive, generate the SQL, then restore.
|
|
210
|
+
// This approach ensures any changes in base class with() get propagated here.
|
|
211
|
+
const undoList = [];
|
|
212
|
+
if (this.grouped.with) {
|
|
213
|
+
for (const stmt of this.grouped.with) {
|
|
214
|
+
if (stmt.recursive) {
|
|
215
|
+
undoList.push(stmt);
|
|
216
|
+
stmt.recursive = false;
|
|
217
|
+
}
|
|
218
|
+
}
|
|
219
|
+
}
|
|
220
|
+
|
|
221
|
+
const result = super.with();
|
|
222
|
+
|
|
223
|
+
// Restore the recursive markings, in case this same query gets cloned and passed to other drivers.
|
|
224
|
+
for (const stmt of undoList) {
|
|
225
|
+
stmt.recursive = true;
|
|
226
|
+
}
|
|
227
|
+
return result;
|
|
228
|
+
}
|
|
229
|
+
|
|
230
|
+
_addReturningToSqlAndConvert(sql, outBinding, tableName, returning) {
|
|
231
|
+
const self = this;
|
|
232
|
+
const res = {
|
|
233
|
+
sql: sql,
|
|
234
|
+
};
|
|
235
|
+
|
|
236
|
+
if (!outBinding) {
|
|
237
|
+
return res;
|
|
238
|
+
}
|
|
239
|
+
const returningValues = Array.isArray(outBinding)
|
|
240
|
+
? outBinding
|
|
241
|
+
: [outBinding];
|
|
242
|
+
let returningClause = '';
|
|
243
|
+
let intoClause = '';
|
|
244
|
+
// Build returning and into clauses
|
|
245
|
+
returningValues.forEach(function (ret) {
|
|
246
|
+
const columnName = ret.columnName || ret;
|
|
247
|
+
returningClause += self.formatter.wrap(columnName) + ',';
|
|
248
|
+
intoClause += '?,';
|
|
249
|
+
|
|
250
|
+
// Add Helpers to bindings
|
|
251
|
+
if (ret instanceof BlobHelper) {
|
|
252
|
+
return self.formatter.bindings.push(ret);
|
|
253
|
+
}
|
|
254
|
+
self.formatter.bindings.push(new ReturningHelper(columnName));
|
|
255
|
+
});
|
|
256
|
+
res.sql = sql;
|
|
257
|
+
|
|
258
|
+
// Strip last comma
|
|
259
|
+
returningClause = returningClause.slice(0, -1);
|
|
260
|
+
intoClause = intoClause.slice(0, -1);
|
|
261
|
+
if (returningClause && intoClause) {
|
|
262
|
+
res.sql += ' returning ' + returningClause + ' into ' + intoClause;
|
|
263
|
+
}
|
|
264
|
+
res.outBinding = [outBinding];
|
|
265
|
+
if (returning[0] === '*') {
|
|
266
|
+
res.returningSql = function () {
|
|
267
|
+
return 'select * from ' + self.tableName + ' where ROWID = :1';
|
|
268
|
+
};
|
|
269
|
+
}
|
|
270
|
+
res.returning = returning;
|
|
271
|
+
|
|
272
|
+
return res;
|
|
273
|
+
}
|
|
274
|
+
|
|
275
|
+
_prepOutbindings(paramValues, paramReturning) {
|
|
276
|
+
const result = {};
|
|
277
|
+
let params = paramValues || [];
|
|
278
|
+
let returning = paramReturning || [];
|
|
279
|
+
if (!Array.isArray(params) && isPlainObject(paramValues)) {
|
|
280
|
+
params = [params];
|
|
281
|
+
}
|
|
282
|
+
// Always wrap returning argument in array
|
|
283
|
+
if (returning && !Array.isArray(returning)) {
|
|
284
|
+
returning = [returning];
|
|
285
|
+
}
|
|
286
|
+
|
|
287
|
+
const outBinding = [];
|
|
288
|
+
// Handle Buffer value as Blob
|
|
289
|
+
each(params, function (values, index) {
|
|
290
|
+
if (returning[0] === '*') {
|
|
291
|
+
outBinding[index] = ['ROWID'];
|
|
292
|
+
} else {
|
|
293
|
+
outBinding[index] = clone(returning);
|
|
294
|
+
}
|
|
295
|
+
each(values, function (value, key) {
|
|
296
|
+
if (value instanceof Buffer) {
|
|
297
|
+
values[key] = new BlobHelper(key, value);
|
|
298
|
+
|
|
299
|
+
// Delete blob duplicate in returning
|
|
300
|
+
const blobIndex = outBinding[index].indexOf(key);
|
|
301
|
+
if (blobIndex >= 0) {
|
|
302
|
+
outBinding[index].splice(blobIndex, 1);
|
|
303
|
+
values[key].returning = true;
|
|
304
|
+
}
|
|
305
|
+
outBinding[index].push(values[key]);
|
|
306
|
+
}
|
|
307
|
+
if (value === undefined) {
|
|
308
|
+
delete params[index][key];
|
|
309
|
+
}
|
|
310
|
+
});
|
|
311
|
+
});
|
|
312
|
+
result.returning = returning;
|
|
313
|
+
result.outBinding = outBinding;
|
|
314
|
+
result.values = params;
|
|
315
|
+
return result;
|
|
316
|
+
}
|
|
317
|
+
|
|
318
|
+
_groupOrder(item, type) {
|
|
319
|
+
return super._groupOrderNulls(item, type);
|
|
320
|
+
}
|
|
321
|
+
|
|
322
|
+
update() {
|
|
323
|
+
const self = this;
|
|
324
|
+
const sql = {};
|
|
325
|
+
const outBindPrep = this._prepOutbindings(
|
|
326
|
+
this.single.update || this.single.counter,
|
|
327
|
+
this.single.returning
|
|
328
|
+
);
|
|
329
|
+
const outBinding = outBindPrep.outBinding;
|
|
330
|
+
const returning = outBindPrep.returning;
|
|
331
|
+
|
|
332
|
+
const updates = this._prepUpdate(this.single.update);
|
|
333
|
+
const where = this.where();
|
|
334
|
+
|
|
335
|
+
let returningClause = '';
|
|
336
|
+
let intoClause = '';
|
|
337
|
+
|
|
338
|
+
if (isEmpty(updates) && typeof this.single.update !== 'function') {
|
|
339
|
+
return '';
|
|
340
|
+
}
|
|
341
|
+
|
|
342
|
+
// Build returning and into clauses
|
|
343
|
+
outBinding.forEach(function (out) {
|
|
344
|
+
out.forEach(function (ret) {
|
|
345
|
+
const columnName = ret.columnName || ret;
|
|
346
|
+
returningClause += self.formatter.wrap(columnName) + ',';
|
|
347
|
+
intoClause += ' ?,';
|
|
348
|
+
|
|
349
|
+
// Add Helpers to bindings
|
|
350
|
+
if (ret instanceof BlobHelper) {
|
|
351
|
+
return self.formatter.bindings.push(ret);
|
|
352
|
+
}
|
|
353
|
+
self.formatter.bindings.push(new ReturningHelper(columnName));
|
|
354
|
+
});
|
|
355
|
+
});
|
|
356
|
+
// Strip last comma
|
|
357
|
+
returningClause = returningClause.slice(0, -1);
|
|
358
|
+
intoClause = intoClause.slice(0, -1);
|
|
359
|
+
|
|
360
|
+
sql.outBinding = outBinding;
|
|
361
|
+
sql.returning = returning;
|
|
362
|
+
sql.sql =
|
|
363
|
+
'update ' +
|
|
364
|
+
this.tableName +
|
|
365
|
+
' set ' +
|
|
366
|
+
updates.join(', ') +
|
|
367
|
+
(where ? ' ' + where : '');
|
|
368
|
+
if (outBinding.length && !isEmpty(outBinding[0])) {
|
|
369
|
+
sql.sql += ' returning ' + returningClause + ' into' + intoClause;
|
|
370
|
+
}
|
|
371
|
+
if (returning[0] === '*') {
|
|
372
|
+
sql.returningSql = function () {
|
|
373
|
+
let sql = 'select * from ' + self.tableName;
|
|
374
|
+
const modifiedRowsCount = this.rowsAffected.length || this.rowsAffected;
|
|
375
|
+
let returningSqlIn = ' where ROWID in (';
|
|
376
|
+
let returningSqlOrderBy = ') order by case ROWID ';
|
|
377
|
+
|
|
378
|
+
// Needs special order by because in(...) change result order
|
|
379
|
+
for (let i = 0; i < modifiedRowsCount; i++) {
|
|
380
|
+
if (this.returning[0] === '*') {
|
|
381
|
+
returningSqlIn += ':' + (i + 1) + ', ';
|
|
382
|
+
returningSqlOrderBy +=
|
|
383
|
+
'when CHARTOROWID(:' + (i + 1) + ') then ' + i + ' ';
|
|
384
|
+
}
|
|
385
|
+
}
|
|
386
|
+
if (this.returning[0] === '*') {
|
|
387
|
+
this.returning = this.returning.slice(0, -1);
|
|
388
|
+
returningSqlIn = returningSqlIn.slice(0, -2);
|
|
389
|
+
returningSqlOrderBy = returningSqlOrderBy.slice(0, -1);
|
|
390
|
+
}
|
|
391
|
+
return (sql += returningSqlIn + returningSqlOrderBy + ' end');
|
|
392
|
+
};
|
|
393
|
+
}
|
|
394
|
+
|
|
395
|
+
return sql;
|
|
396
|
+
}
|
|
397
|
+
|
|
398
|
+
_jsonPathWrap(extraction) {
|
|
399
|
+
return `'${extraction.path || extraction[1]}'`;
|
|
400
|
+
}
|
|
401
|
+
|
|
402
|
+
// Json functions
|
|
403
|
+
jsonExtract(params) {
|
|
404
|
+
return this._jsonExtract(
|
|
405
|
+
params.singleValue ? 'json_value' : 'json_query',
|
|
406
|
+
params
|
|
407
|
+
);
|
|
408
|
+
}
|
|
409
|
+
|
|
410
|
+
jsonSet(params) {
|
|
411
|
+
return `json_transform(${columnize_(
|
|
412
|
+
params.column,
|
|
413
|
+
this.builder,
|
|
414
|
+
this.client,
|
|
415
|
+
this.bindingsHolder
|
|
416
|
+
)}, set ${this.client.parameter(
|
|
417
|
+
params.path,
|
|
418
|
+
this.builder,
|
|
419
|
+
this.bindingsHolder
|
|
420
|
+
)} = ${this.client.parameter(
|
|
421
|
+
params.value,
|
|
422
|
+
this.builder,
|
|
423
|
+
this.bindingsHolder
|
|
424
|
+
)})`;
|
|
425
|
+
}
|
|
426
|
+
|
|
427
|
+
jsonInsert(params) {
|
|
428
|
+
return `json_transform(${columnize_(
|
|
429
|
+
params.column,
|
|
430
|
+
this.builder,
|
|
431
|
+
this.client,
|
|
432
|
+
this.bindingsHolder
|
|
433
|
+
)}, insert ${this.client.parameter(
|
|
434
|
+
params.path,
|
|
435
|
+
this.builder,
|
|
436
|
+
this.bindingsHolder
|
|
437
|
+
)} = ${this.client.parameter(
|
|
438
|
+
params.value,
|
|
439
|
+
this.builder,
|
|
440
|
+
this.bindingsHolder
|
|
441
|
+
)})`;
|
|
442
|
+
}
|
|
443
|
+
|
|
444
|
+
jsonRemove(params) {
|
|
445
|
+
const jsonCol = `json_transform(${columnize_(
|
|
446
|
+
params.column,
|
|
447
|
+
this.builder,
|
|
448
|
+
this.client,
|
|
449
|
+
this.bindingsHolder
|
|
450
|
+
)}, remove ${this.client.parameter(
|
|
451
|
+
params.path,
|
|
452
|
+
this.builder,
|
|
453
|
+
this.bindingsHolder
|
|
454
|
+
)})`;
|
|
455
|
+
return params.alias
|
|
456
|
+
? this.client.alias(jsonCol, this.formatter.wrap(params.alias))
|
|
457
|
+
: jsonCol;
|
|
458
|
+
}
|
|
459
|
+
|
|
460
|
+
whereJsonPath(statement) {
|
|
461
|
+
return this._whereJsonPath('json_value', statement);
|
|
462
|
+
}
|
|
463
|
+
|
|
464
|
+
whereJsonSupersetOf(statement) {
|
|
465
|
+
throw new Error(
|
|
466
|
+
'Json superset where clause not actually supported by Oracle'
|
|
467
|
+
);
|
|
468
|
+
}
|
|
469
|
+
|
|
470
|
+
whereJsonSubsetOf(statement) {
|
|
471
|
+
throw new Error(
|
|
472
|
+
'Json subset where clause not actually supported by Oracle'
|
|
473
|
+
);
|
|
474
|
+
}
|
|
475
|
+
|
|
476
|
+
onJsonPathEquals(clause) {
|
|
477
|
+
return this._onJsonPathEquals('json_value', clause);
|
|
478
|
+
}
|
|
479
|
+
}
|
|
480
|
+
|
|
481
|
+
module.exports = Oracledb_Compiler;
|