n8n-nodes-base 1.114.1 → 1.116.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/credentials/MongoDb.credentials.d.ts.map +1 -1
- package/dist/credentials/MongoDb.credentials.js +3 -0
- package/dist/credentials/MongoDb.credentials.js.map +1 -1
- package/dist/credentials/OracleDBApi.credentials.d.ts +8 -0
- package/dist/credentials/OracleDBApi.credentials.d.ts.map +1 -0
- package/dist/credentials/OracleDBApi.credentials.js +205 -0
- package/dist/credentials/OracleDBApi.credentials.js.map +1 -0
- package/dist/credentials/SentryIoApi.credentials.d.ts +3 -1
- package/dist/credentials/SentryIoApi.credentials.d.ts.map +1 -1
- package/dist/credentials/SentryIoApi.credentials.js +15 -0
- package/dist/credentials/SentryIoApi.credentials.js.map +1 -1
- package/dist/credentials/SentryIoServerApi.credentials.d.ts +3 -1
- package/dist/credentials/SentryIoServerApi.credentials.d.ts.map +1 -1
- package/dist/credentials/SentryIoServerApi.credentials.js +15 -0
- package/dist/credentials/SentryIoServerApi.credentials.js.map +1 -1
- package/dist/known/credentials.json +7 -0
- package/dist/known/nodes.json +4 -0
- package/dist/methods/defined.json +4 -0
- package/dist/methods/referenced.json +4 -0
- package/dist/nodes/Form/Form.node.d.ts.map +1 -1
- package/dist/nodes/Form/Form.node.js +3 -4
- package/dist/nodes/Form/Form.node.js.map +1 -1
- package/dist/nodes/Form/utils/formCompletionUtils.d.ts.map +1 -1
- package/dist/nodes/Form/utils/formCompletionUtils.js +5 -4
- package/dist/nodes/Form/utils/formCompletionUtils.js.map +1 -1
- package/dist/nodes/Form/utils/formNodeUtils.d.ts +11 -0
- package/dist/nodes/Form/utils/formNodeUtils.d.ts.map +1 -1
- package/dist/nodes/Form/utils/formNodeUtils.js +29 -0
- package/dist/nodes/Form/utils/formNodeUtils.js.map +1 -1
- package/dist/nodes/Google/Gmail/GmailTrigger.node.d.ts.map +1 -1
- package/dist/nodes/Google/Gmail/GmailTrigger.node.js +12 -12
- package/dist/nodes/Google/Gmail/GmailTrigger.node.js.map +1 -1
- package/dist/nodes/HttpRequest/GenericFunctions.d.ts +3 -0
- package/dist/nodes/HttpRequest/GenericFunctions.d.ts.map +1 -1
- package/dist/nodes/HttpRequest/GenericFunctions.js +20 -1
- package/dist/nodes/HttpRequest/GenericFunctions.js.map +1 -1
- package/dist/nodes/HttpRequest/HttpRequest.node.d.ts.map +1 -1
- package/dist/nodes/HttpRequest/HttpRequest.node.js +2 -1
- package/dist/nodes/HttpRequest/HttpRequest.node.js.map +1 -1
- package/dist/nodes/HttpRequest/V3/HttpRequestV3.node.d.ts.map +1 -1
- package/dist/nodes/HttpRequest/V3/HttpRequestV3.node.js +7 -2
- package/dist/nodes/HttpRequest/V3/HttpRequestV3.node.js.map +1 -1
- package/dist/nodes/JotForm/JotFormTrigger.node.d.ts.map +1 -1
- package/dist/nodes/JotForm/JotFormTrigger.node.js +4 -5
- package/dist/nodes/JotForm/JotFormTrigger.node.js.map +1 -1
- package/dist/nodes/JotForm/jotform.dark.svg +13 -0
- package/dist/nodes/JotForm/jotform.svg +1 -0
- package/dist/nodes/Merge/v3/actions/mode/combineBySql.d.ts.map +1 -1
- package/dist/nodes/Merge/v3/actions/mode/combineBySql.js +40 -4
- package/dist/nodes/Merge/v3/actions/mode/combineBySql.js.map +1 -1
- package/dist/nodes/MongoDb/GenericFunctions.d.ts +3 -3
- package/dist/nodes/MongoDb/GenericFunctions.d.ts.map +1 -1
- package/dist/nodes/MongoDb/GenericFunctions.js +5 -5
- package/dist/nodes/MongoDb/GenericFunctions.js.map +1 -1
- package/dist/nodes/MongoDb/MongoDb.node.d.ts.map +1 -1
- package/dist/nodes/MongoDb/MongoDb.node.js +3 -2
- package/dist/nodes/MongoDb/MongoDb.node.js.map +1 -1
- package/dist/nodes/Notion/shared/descriptions/DatabasePageDescription.js +1 -1
- package/dist/nodes/Notion/shared/descriptions/DatabasePageDescription.js.map +1 -1
- package/dist/nodes/Oracle/Sql/OracleSql.node.d.ts +14 -0
- package/dist/nodes/Oracle/Sql/OracleSql.node.d.ts.map +1 -0
- package/dist/nodes/Oracle/Sql/OracleSql.node.js +22 -0
- package/dist/nodes/Oracle/Sql/OracleSql.node.js.map +1 -0
- package/dist/nodes/Oracle/Sql/actions/common.descriptions.d.ts +8 -0
- package/dist/nodes/Oracle/Sql/actions/common.descriptions.d.ts.map +1 -0
- package/dist/nodes/Oracle/Sql/actions/common.descriptions.js +531 -0
- package/dist/nodes/Oracle/Sql/actions/common.descriptions.js.map +1 -0
- package/dist/nodes/Oracle/Sql/actions/database/Database.resource.d.ts +10 -0
- package/dist/nodes/Oracle/Sql/actions/database/Database.resource.d.ts.map +1 -0
- package/dist/nodes/Oracle/Sql/actions/database/Database.resource.js +112 -0
- package/dist/nodes/Oracle/Sql/actions/database/Database.resource.js.map +1 -0
- package/dist/nodes/Oracle/Sql/actions/database/deleteTable.operation.d.ts +30 -0
- package/dist/nodes/Oracle/Sql/actions/database/deleteTable.operation.d.ts.map +1 -0
- package/dist/nodes/Oracle/Sql/actions/database/deleteTable.operation.js +138 -0
- package/dist/nodes/Oracle/Sql/actions/database/deleteTable.operation.js.map +1 -0
- package/dist/nodes/Oracle/Sql/actions/database/executeQuery.operation.d.ts +40 -0
- package/dist/nodes/Oracle/Sql/actions/database/executeQuery.operation.d.ts.map +1 -0
- package/dist/nodes/Oracle/Sql/actions/database/executeQuery.operation.js +66 -0
- package/dist/nodes/Oracle/Sql/actions/database/executeQuery.operation.js.map +1 -0
- package/dist/nodes/Oracle/Sql/actions/database/insert.operation.d.ts +30 -0
- package/dist/nodes/Oracle/Sql/actions/database/insert.operation.d.ts.map +1 -0
- package/dist/nodes/Oracle/Sql/actions/database/insert.operation.js +146 -0
- package/dist/nodes/Oracle/Sql/actions/database/insert.operation.js.map +1 -0
- package/dist/nodes/Oracle/Sql/actions/database/select.operation.d.ts +30 -0
- package/dist/nodes/Oracle/Sql/actions/database/select.operation.d.ts.map +1 -0
- package/dist/nodes/Oracle/Sql/actions/database/select.operation.js +90 -0
- package/dist/nodes/Oracle/Sql/actions/database/select.operation.js.map +1 -0
- package/dist/nodes/Oracle/Sql/actions/database/update.operation.d.ts +30 -0
- package/dist/nodes/Oracle/Sql/actions/database/update.operation.d.ts.map +1 -0
- package/dist/nodes/Oracle/Sql/actions/database/update.operation.js +147 -0
- package/dist/nodes/Oracle/Sql/actions/database/update.operation.js.map +1 -0
- package/dist/nodes/Oracle/Sql/actions/database/upsert.operation.d.ts +30 -0
- package/dist/nodes/Oracle/Sql/actions/database/upsert.operation.d.ts.map +1 -0
- package/dist/nodes/Oracle/Sql/actions/database/upsert.operation.js +150 -0
- package/dist/nodes/Oracle/Sql/actions/database/upsert.operation.js.map +1 -0
- package/dist/nodes/Oracle/Sql/actions/node.type.d.ts +9 -0
- package/dist/nodes/Oracle/Sql/actions/node.type.d.ts.map +1 -0
- package/dist/nodes/Oracle/Sql/actions/node.type.js +7 -0
- package/dist/nodes/Oracle/Sql/actions/node.type.js.map +1 -0
- package/dist/nodes/Oracle/Sql/actions/router.d.ts +3 -0
- package/dist/nodes/Oracle/Sql/actions/router.d.ts.map +1 -0
- package/dist/nodes/Oracle/Sql/actions/router.js +77 -0
- package/dist/nodes/Oracle/Sql/actions/router.js.map +1 -0
- package/dist/nodes/Oracle/Sql/actions/versionDescription.d.ts +3 -0
- package/dist/nodes/Oracle/Sql/actions/versionDescription.d.ts.map +1 -0
- package/dist/nodes/Oracle/Sql/actions/versionDescription.js +78 -0
- package/dist/nodes/Oracle/Sql/actions/versionDescription.js.map +1 -0
- package/dist/nodes/Oracle/Sql/helpers/interfaces.d.ts +118 -0
- package/dist/nodes/Oracle/Sql/helpers/interfaces.d.ts.map +1 -0
- package/dist/nodes/Oracle/Sql/helpers/interfaces.js +3 -0
- package/dist/nodes/Oracle/Sql/helpers/interfaces.js.map +1 -0
- package/dist/nodes/Oracle/Sql/helpers/utils.d.ts +38 -0
- package/dist/nodes/Oracle/Sql/helpers/utils.d.ts.map +1 -0
- package/dist/nodes/Oracle/Sql/helpers/utils.js +859 -0
- package/dist/nodes/Oracle/Sql/helpers/utils.js.map +1 -0
- package/dist/nodes/Oracle/Sql/methods/credentialTest.d.ts +3 -0
- package/dist/nodes/Oracle/Sql/methods/credentialTest.d.ts.map +1 -0
- package/dist/nodes/Oracle/Sql/methods/credentialTest.js +25 -0
- package/dist/nodes/Oracle/Sql/methods/credentialTest.js.map +1 -0
- package/dist/nodes/Oracle/Sql/methods/index.d.ts +5 -0
- package/dist/nodes/Oracle/Sql/methods/index.d.ts.map +1 -0
- package/dist/nodes/Oracle/Sql/methods/index.js +41 -0
- package/dist/nodes/Oracle/Sql/methods/index.js.map +1 -0
- package/dist/nodes/Oracle/Sql/methods/listSearch.d.ts +4 -0
- package/dist/nodes/Oracle/Sql/methods/listSearch.d.ts.map +1 -0
- package/dist/nodes/Oracle/Sql/methods/listSearch.js +100 -0
- package/dist/nodes/Oracle/Sql/methods/listSearch.js.map +1 -0
- package/dist/nodes/Oracle/Sql/methods/loadOptions.d.ts +4 -0
- package/dist/nodes/Oracle/Sql/methods/loadOptions.d.ts.map +1 -0
- package/dist/nodes/Oracle/Sql/methods/loadOptions.js +29 -0
- package/dist/nodes/Oracle/Sql/methods/loadOptions.js.map +1 -0
- package/dist/nodes/Oracle/Sql/methods/resourceMapping.d.ts +3 -0
- package/dist/nodes/Oracle/Sql/methods/resourceMapping.d.ts.map +1 -0
- package/dist/nodes/Oracle/Sql/methods/resourceMapping.js +32 -0
- package/dist/nodes/Oracle/Sql/methods/resourceMapping.js.map +1 -0
- package/dist/nodes/Oracle/Sql/oracle.svg +4 -0
- package/dist/nodes/Oracle/Sql/transport/index.d.ts +5 -0
- package/dist/nodes/Oracle/Sql/transport/index.d.ts.map +1 -0
- package/dist/nodes/Oracle/Sql/transport/index.js +53 -0
- package/dist/nodes/Oracle/Sql/transport/index.js.map +1 -0
- package/dist/nodes/SentryIo/GenericFunctions.d.ts.map +1 -1
- package/dist/nodes/SentryIo/GenericFunctions.js +13 -16
- package/dist/nodes/SentryIo/GenericFunctions.js.map +1 -1
- package/dist/nodes/SentryIo/SentryIo.node.d.ts.map +1 -1
- package/dist/nodes/SentryIo/SentryIo.node.js +5 -42
- package/dist/nodes/SentryIo/SentryIo.node.js.map +1 -1
- package/dist/nodes/Slack/V2/SlackV2.node.js +2 -2
- package/dist/nodes/Slack/V2/SlackV2.node.js.map +1 -1
- package/dist/typecheck.tsbuildinfo +1 -1
- package/dist/types/credentials.json +5 -4
- package/dist/types/nodes.json +10 -9
- package/package.json +9 -5
|
@@ -0,0 +1,859 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
3
|
+
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
4
|
+
};
|
|
5
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
6
|
+
exports.configureTableSchemaUpdater = void 0;
|
|
7
|
+
exports.mapDbType = mapDbType;
|
|
8
|
+
exports.getCompatibleValue = getCompatibleValue;
|
|
9
|
+
exports.quoteSqlIdentifier = quoteSqlIdentifier;
|
|
10
|
+
exports.addSortRules = addSortRules;
|
|
11
|
+
exports.getColumnMetaData = getColumnMetaData;
|
|
12
|
+
exports.prepareErrorItem = prepareErrorItem;
|
|
13
|
+
exports.configureQueryRunner = configureQueryRunner;
|
|
14
|
+
exports.getColumnMap = getColumnMap;
|
|
15
|
+
exports.addWhereClauses = addWhereClauses;
|
|
16
|
+
exports.checkItemAgainstSchema = checkItemAgainstSchema;
|
|
17
|
+
exports.getBindParameters = getBindParameters;
|
|
18
|
+
exports.getInBindParametersForSourceSelect = getInBindParametersForSourceSelect;
|
|
19
|
+
exports.getOnClauseFromColumns = getOnClauseFromColumns;
|
|
20
|
+
exports.getUpdateSetClause = getUpdateSetClause;
|
|
21
|
+
exports.getInsertClauseAndBinds = getInsertClauseAndBinds;
|
|
22
|
+
exports.getInBindParametersForExecute = getInBindParametersForExecute;
|
|
23
|
+
exports.getOutBindDefsForExecute = getOutBindDefsForExecute;
|
|
24
|
+
exports.getBindDefsForExecuteMany = getBindDefsForExecuteMany;
|
|
25
|
+
exports.formatItemValues = formatItemValues;
|
|
26
|
+
const crypto_1 = require("crypto");
|
|
27
|
+
const luxon_1 = require("luxon");
|
|
28
|
+
const n8n_workflow_1 = require("n8n-workflow");
|
|
29
|
+
const oracledb_1 = __importDefault(require("oracledb"));
|
|
30
|
+
const utilities_1 = require("../../../../utils/utilities");
|
|
31
|
+
const n8nTypetoDBType = {
|
|
32
|
+
boolean: oracledb_1.default.DB_TYPE_BOOLEAN,
|
|
33
|
+
date: oracledb_1.default.DATE,
|
|
34
|
+
dateTime: oracledb_1.default.DB_TYPE_TIMESTAMP,
|
|
35
|
+
json: oracledb_1.default.DB_TYPE_JSON,
|
|
36
|
+
number: oracledb_1.default.NUMBER,
|
|
37
|
+
sparse: oracledb_1.default.DB_TYPE_VECTOR,
|
|
38
|
+
vector: oracledb_1.default.DB_TYPE_VECTOR,
|
|
39
|
+
string: oracledb_1.default.STRING,
|
|
40
|
+
blob: oracledb_1.default.BLOB,
|
|
41
|
+
};
|
|
42
|
+
function isDateType(type) {
|
|
43
|
+
return /^(timestamp(\(\d+\))?( with(?: local)? time zone)?|date)$/i.test(type);
|
|
44
|
+
}
|
|
45
|
+
function mapDbType(dbType) {
|
|
46
|
+
const type = dbType.toLowerCase().trim();
|
|
47
|
+
switch (true) {
|
|
48
|
+
// Date & Time
|
|
49
|
+
case /^timestamp(\(\d+\))?$/.test(type):
|
|
50
|
+
return { oracledbType: oracledb_1.default.DB_TYPE_TIMESTAMP, n8nType: 'dateTime' };
|
|
51
|
+
case /^timestamp(\(\d+\))? with time zone$/.test(type):
|
|
52
|
+
return { oracledbType: oracledb_1.default.DB_TYPE_TIMESTAMP_TZ, n8nType: 'dateTime' };
|
|
53
|
+
case /^timestamp(\(\d+\))? with local time zone$/.test(type):
|
|
54
|
+
return { oracledbType: oracledb_1.default.DB_TYPE_TIMESTAMP_LTZ, n8nType: 'dateTime' };
|
|
55
|
+
case type === 'date':
|
|
56
|
+
return { oracledbType: oracledb_1.default.DATE, n8nType: 'dateTime' };
|
|
57
|
+
// Numbers
|
|
58
|
+
case type === 'number':
|
|
59
|
+
case /^(binary_double|binary_float|decimal|float|int|integer|smallint)$/.test(type):
|
|
60
|
+
return { oracledbType: oracledb_1.default.DB_TYPE_NUMBER, n8nType: 'number' };
|
|
61
|
+
// Strings
|
|
62
|
+
case /^(char|clob|long|nchar|nclob|nvarchar2|rowid|urowid|varchar|varchar2|xmltype)$/.test(type):
|
|
63
|
+
return { oracledbType: oracledb_1.default.STRING, n8nType: 'string' };
|
|
64
|
+
// Boolean
|
|
65
|
+
case type === 'boolean':
|
|
66
|
+
return { oracledbType: oracledb_1.default.DB_TYPE_BOOLEAN, n8nType: 'boolean' };
|
|
67
|
+
// Binary / LOB
|
|
68
|
+
case /^(raw|long raw)$/.test(type):
|
|
69
|
+
return { oracledbType: oracledb_1.default.BUFFER, n8nType: 'json' };
|
|
70
|
+
case type === 'blob':
|
|
71
|
+
return { oracledbType: oracledb_1.default.BLOB, n8nType: 'json' };
|
|
72
|
+
// JSON
|
|
73
|
+
case type === 'json':
|
|
74
|
+
return { oracledbType: oracledb_1.default.DB_TYPE_JSON, n8nType: 'object' };
|
|
75
|
+
// Vector
|
|
76
|
+
case /^vector(\([^)]*\))?$/.test(type):
|
|
77
|
+
return { oracledbType: oracledb_1.default.DB_TYPE_VECTOR, n8nType: 'array' };
|
|
78
|
+
// Fallback
|
|
79
|
+
default:
|
|
80
|
+
return { oracledbType: oracledb_1.default.STRING, n8nType: 'string' };
|
|
81
|
+
}
|
|
82
|
+
}
|
|
83
|
+
/*
|
|
84
|
+
* It returns the value compatible based on input
|
|
85
|
+
* sql types (VARCHAR2, TIMESTAMP, NUMBER..)
|
|
86
|
+
*/
|
|
87
|
+
function getCompatibleValue(type, value) {
|
|
88
|
+
if (value === null || value === undefined)
|
|
89
|
+
return value;
|
|
90
|
+
if (isDateType(type)) {
|
|
91
|
+
if (value instanceof luxon_1.DateTime) {
|
|
92
|
+
return value.isValid ? value.toJSDate() : null;
|
|
93
|
+
}
|
|
94
|
+
if (value instanceof Date) {
|
|
95
|
+
return isNaN(value.getTime()) ? null : value;
|
|
96
|
+
}
|
|
97
|
+
else if (typeof value === 'string') {
|
|
98
|
+
return new Date(value);
|
|
99
|
+
}
|
|
100
|
+
}
|
|
101
|
+
if (type === 'BOOLEAN') {
|
|
102
|
+
if (typeof value === 'string')
|
|
103
|
+
return value === 'true';
|
|
104
|
+
return Boolean(value);
|
|
105
|
+
}
|
|
106
|
+
if (type === 'NUMBER' && typeof value === 'string') {
|
|
107
|
+
return Number(value);
|
|
108
|
+
}
|
|
109
|
+
if ((type === 'BLOB' || type === 'RAW' || type === 'LONG RAW') && !Buffer.isBuffer(value)) {
|
|
110
|
+
// User enters an array or string(For BLOB) manually, we convert to buffer.
|
|
111
|
+
return Buffer.from(value);
|
|
112
|
+
}
|
|
113
|
+
return value;
|
|
114
|
+
}
|
|
115
|
+
function getExecuteOptions(options = {}) {
|
|
116
|
+
const execOptions = {
|
|
117
|
+
autoCommit: options.autoCommit,
|
|
118
|
+
fetchArraySize: options.fetchArraySize,
|
|
119
|
+
maxRows: options.maxRows,
|
|
120
|
+
prefetchRows: options.prefetchRows,
|
|
121
|
+
stmtCacheSize: options.stmtCacheSize,
|
|
122
|
+
keepInStmtCache: options.keepInStmtCache,
|
|
123
|
+
bindDefs: options.bindDefs,
|
|
124
|
+
};
|
|
125
|
+
return execOptions;
|
|
126
|
+
}
|
|
127
|
+
function getExecuteManyOptions(options = {}) {
|
|
128
|
+
const execOptions = {
|
|
129
|
+
autoCommit: options.autoCommit,
|
|
130
|
+
keepInStmtCache: options.keepInStmtCache,
|
|
131
|
+
stmtCacheSize: options.stmtCacheSize,
|
|
132
|
+
bindDefs: options.bindDefs,
|
|
133
|
+
};
|
|
134
|
+
return execOptions;
|
|
135
|
+
}
|
|
136
|
+
function addBindParam(colInfo, value, bindParameters, bindDefs = null) {
|
|
137
|
+
const obj = {};
|
|
138
|
+
const { type, maxSize } = colInfo;
|
|
139
|
+
obj.type = mapDbType(type).oracledbType;
|
|
140
|
+
if (bindDefs) {
|
|
141
|
+
if (obj.type === oracledb_1.default.STRING) {
|
|
142
|
+
obj.maxSize = maxSize;
|
|
143
|
+
}
|
|
144
|
+
else if (obj.type === oracledb_1.default.DB_TYPE_RAW) {
|
|
145
|
+
obj.maxSize = maxSize;
|
|
146
|
+
}
|
|
147
|
+
bindDefs.push(obj);
|
|
148
|
+
}
|
|
149
|
+
else {
|
|
150
|
+
value = getCompatibleValue(type, value);
|
|
151
|
+
obj.val = value;
|
|
152
|
+
bindParameters.push(obj);
|
|
153
|
+
}
|
|
154
|
+
}
|
|
155
|
+
function quoteSqlIdentifier(name) {
|
|
156
|
+
name = name.trim();
|
|
157
|
+
/*
|
|
158
|
+
* This regex ensures the identifier is valid.
|
|
159
|
+
* It allows:
|
|
160
|
+
* Quoted identifiers: "MyColumn"
|
|
161
|
+
* Unquoted identifiers without . or " inside: my_column
|
|
162
|
+
* Dot-separated identifiers (like schema.table.column), each part following the rules above.
|
|
163
|
+
*
|
|
164
|
+
* Invalid examples:
|
|
165
|
+
* my"column → contains an illegal ".
|
|
166
|
+
* my..column → double dot not allowed.
|
|
167
|
+
*/
|
|
168
|
+
const validateRegex = /^(?:"[^"]+"|[^".]+)(?:\.(?:"[^"]+"|[^".]+))*$/;
|
|
169
|
+
if (!validateRegex.test(name)) {
|
|
170
|
+
throw new Error(`Identifier name ${name} is not valid.`);
|
|
171
|
+
}
|
|
172
|
+
// Extract each part.
|
|
173
|
+
const matchRegex = /"([^"]+)"|([^".]+)/g;
|
|
174
|
+
const groups = [];
|
|
175
|
+
let match;
|
|
176
|
+
while ((match = matchRegex.exec(name)) !== null) {
|
|
177
|
+
groups.push(match[1] || match[2]); // match[1] = quoted, match[2] = unquoted
|
|
178
|
+
}
|
|
179
|
+
// Re-quote each part
|
|
180
|
+
const quotedParts = groups.map((g) => `"${g}"`);
|
|
181
|
+
return quotedParts.join('.');
|
|
182
|
+
}
|
|
183
|
+
function addSortRules(query, rules) {
|
|
184
|
+
if (rules.length === 0)
|
|
185
|
+
return query;
|
|
186
|
+
let orderByQuery = ' ORDER BY';
|
|
187
|
+
rules.forEach((rule, index) => {
|
|
188
|
+
const endWith = index === rules.length - 1 ? '' : ',';
|
|
189
|
+
const sortDirection = rule.direction === 'DESC' ? 'DESC' : 'ASC';
|
|
190
|
+
orderByQuery += ` ${quoteSqlIdentifier(rule.column)} ${sortDirection}${endWith}`;
|
|
191
|
+
});
|
|
192
|
+
return `${query}${orderByQuery}`;
|
|
193
|
+
}
|
|
194
|
+
async function getColumnMetaData(node, pool, schema, table, index = 0) {
|
|
195
|
+
let conn;
|
|
196
|
+
try {
|
|
197
|
+
conn = await pool.getConnection();
|
|
198
|
+
const sql = `WITH constraint_info AS (
|
|
199
|
+
SELECT
|
|
200
|
+
acc.owner,
|
|
201
|
+
acc.table_name,
|
|
202
|
+
acc.column_name,
|
|
203
|
+
LISTAGG(ac.constraint_type, ',')
|
|
204
|
+
WITHIN GROUP (ORDER BY ac.constraint_type) AS constraint_types
|
|
205
|
+
FROM all_cons_columns acc
|
|
206
|
+
JOIN all_constraints ac
|
|
207
|
+
ON acc.constraint_name = ac.constraint_name
|
|
208
|
+
AND acc.owner = ac.owner
|
|
209
|
+
GROUP BY acc.owner, acc.table_name, acc.column_name
|
|
210
|
+
)
|
|
211
|
+
SELECT
|
|
212
|
+
atc.COLUMN_NAME,
|
|
213
|
+
atc.DATA_TYPE,
|
|
214
|
+
atc.DATA_LENGTH,
|
|
215
|
+
atc.CHAR_LENGTH,
|
|
216
|
+
atc.DEFAULT_LENGTH,
|
|
217
|
+
atc.NULLABLE,
|
|
218
|
+
atc.IDENTITY_COLUMN,
|
|
219
|
+
CASE WHEN atc.DATA_DEFAULT IS NOT NULL THEN 'YES' ELSE 'NO' END AS HAS_DEFAULT,
|
|
220
|
+
ci.constraint_types
|
|
221
|
+
FROM all_tab_columns atc
|
|
222
|
+
LEFT JOIN constraint_info ci
|
|
223
|
+
ON atc.owner = ci.owner
|
|
224
|
+
AND atc.table_name = ci.table_name
|
|
225
|
+
AND atc.column_name = ci.column_name
|
|
226
|
+
WHERE atc.owner = :schema_name
|
|
227
|
+
AND atc.table_name = :table_name
|
|
228
|
+
ORDER BY atc.COLUMN_NAME`;
|
|
229
|
+
const result = await conn.execute(sql, { table_name: table, schema_name: schema }, { outFormat: oracledb_1.default.OUT_FORMAT_OBJECT });
|
|
230
|
+
// If schema is not available, throw error.
|
|
231
|
+
if (!result.rows || result.rows.length === 0) {
|
|
232
|
+
throw new n8n_workflow_1.NodeOperationError(node, 'Schema Information does not exist for selected table', {
|
|
233
|
+
itemIndex: index,
|
|
234
|
+
});
|
|
235
|
+
}
|
|
236
|
+
return (result.rows?.map((row) => ({
|
|
237
|
+
columnName: row.COLUMN_NAME,
|
|
238
|
+
isGenerated: row.IDENTITY_COLUMN === 'YES' ? 'ALWAYS' : 'NEVER',
|
|
239
|
+
columnDefault: row.HAS_DEFAULT,
|
|
240
|
+
dataType: row.DATA_TYPE,
|
|
241
|
+
isNullable: row.NULLABLE === 'Y',
|
|
242
|
+
maxSize: row.DATA_LENGTH,
|
|
243
|
+
})) ?? []);
|
|
244
|
+
}
|
|
245
|
+
finally {
|
|
246
|
+
if (conn) {
|
|
247
|
+
await conn.close(); // Ensure connection is closed
|
|
248
|
+
}
|
|
249
|
+
}
|
|
250
|
+
}
|
|
251
|
+
function prepareErrorItem(items, error, index) {
|
|
252
|
+
return {
|
|
253
|
+
json: { message: error.message, item: { ...items[index].json }, error: { ...error } },
|
|
254
|
+
pairedItem: { item: index },
|
|
255
|
+
};
|
|
256
|
+
}
|
|
257
|
+
function parseOracleError(node, error, itemIndex = 0) {
|
|
258
|
+
return new n8n_workflow_1.NodeOperationError(node, error, {
|
|
259
|
+
message: error.message,
|
|
260
|
+
itemIndex,
|
|
261
|
+
});
|
|
262
|
+
}
|
|
263
|
+
/*
|
|
264
|
+
* The outbinds returned in result.outBinds will be returned as batch of rows in case
|
|
265
|
+
* of executeMany and a single row for execute.
|
|
266
|
+
* This function would return the rows of output columns in an array for both cases.
|
|
267
|
+
*/
|
|
268
|
+
function normalizeOutBinds(outBinds, stmtBatching, outputColumns) {
|
|
269
|
+
if (!Array.isArray(outBinds))
|
|
270
|
+
return [];
|
|
271
|
+
const rows = [];
|
|
272
|
+
// executeMany case outBinds-> [ [[col1Row1Val], [col2Row1Val]], [[col1Row2Val], [col2Row2Val]], ...]
|
|
273
|
+
if (stmtBatching === 'single') {
|
|
274
|
+
for (const batch of outBinds) {
|
|
275
|
+
rows.push(Object.fromEntries(outputColumns.map((col, i) => [col, batch[i][0]])));
|
|
276
|
+
}
|
|
277
|
+
return rows;
|
|
278
|
+
}
|
|
279
|
+
// execute case outBinds-> [[col1Row1Val], [col2Row1Val]]
|
|
280
|
+
const row = {};
|
|
281
|
+
for (let i = 0; i < outBinds.length; i++) {
|
|
282
|
+
row[`${outputColumns[i]}`] = outBinds[i][0];
|
|
283
|
+
}
|
|
284
|
+
rows.push(row);
|
|
285
|
+
return rows;
|
|
286
|
+
}
|
|
287
|
+
function _getResponseForOutbinds(results, stmtBatching, outputColumns = [], returnData = []) {
|
|
288
|
+
if (results.outBinds) {
|
|
289
|
+
const normalizedRows = normalizeOutBinds(results.outBinds, stmtBatching, outputColumns);
|
|
290
|
+
for (let j = 0; j < normalizedRows.length; j++) {
|
|
291
|
+
const executionData = this.helpers.constructExecutionMetaData((0, utilities_1.wrapData)(normalizedRows[j]), {
|
|
292
|
+
itemData: { item: j },
|
|
293
|
+
});
|
|
294
|
+
if (executionData) {
|
|
295
|
+
returnData.push(...executionData);
|
|
296
|
+
}
|
|
297
|
+
}
|
|
298
|
+
}
|
|
299
|
+
}
|
|
300
|
+
/*
|
|
301
|
+
* Returns true, if update sql is tried and either row does not
|
|
302
|
+
* exist or could not find row with matching values.
|
|
303
|
+
*/
|
|
304
|
+
function doesRowExist(query, results) {
|
|
305
|
+
if (/^\s*UPDATE\b/i.test(query) && results.rowsAffected === 0) {
|
|
306
|
+
throw new Error("The row you are trying to update doesn't exist");
|
|
307
|
+
}
|
|
308
|
+
}
|
|
309
|
+
function configureQueryRunner(node, continueOnFail, pool) {
|
|
310
|
+
return async (queries, items, options) => {
|
|
311
|
+
let returnData = [];
|
|
312
|
+
const emptyRowData = { success: true };
|
|
313
|
+
let execOptions = {};
|
|
314
|
+
const defaultBatching = options.operation === 'insert' ||
|
|
315
|
+
options.operation === 'update' ||
|
|
316
|
+
options.operation === 'upsert'
|
|
317
|
+
? 'single'
|
|
318
|
+
: 'independently';
|
|
319
|
+
const stmtBatching = options.stmtBatching || defaultBatching;
|
|
320
|
+
if (stmtBatching === 'transaction' || stmtBatching === 'independently') {
|
|
321
|
+
// setup fetch Handler for specific types.
|
|
322
|
+
const executeFetchHandler = function (metaData) {
|
|
323
|
+
if (metaData.dbType &&
|
|
324
|
+
[
|
|
325
|
+
oracledb_1.default.DB_TYPE_DATE,
|
|
326
|
+
oracledb_1.default.DB_TYPE_TIMESTAMP_TZ,
|
|
327
|
+
oracledb_1.default.DB_TYPE_TIMESTAMP_LTZ,
|
|
328
|
+
].includes(metaData.dbType)) {
|
|
329
|
+
return {
|
|
330
|
+
converter: (val) => {
|
|
331
|
+
if (!(val instanceof Date))
|
|
332
|
+
return val;
|
|
333
|
+
return val.toISOString();
|
|
334
|
+
},
|
|
335
|
+
};
|
|
336
|
+
}
|
|
337
|
+
if (metaData.dbType === oracledb_1.default.CLOB) {
|
|
338
|
+
return { type: oracledb_1.default.STRING };
|
|
339
|
+
}
|
|
340
|
+
if (metaData.dbType === oracledb_1.default.DB_TYPE_BLOB) {
|
|
341
|
+
return { type: oracledb_1.default.BUFFER };
|
|
342
|
+
}
|
|
343
|
+
if (options.largeNumbersOutputAsString) {
|
|
344
|
+
if (metaData.dbType === oracledb_1.default.NUMBER) {
|
|
345
|
+
return { type: oracledb_1.default.STRING };
|
|
346
|
+
}
|
|
347
|
+
}
|
|
348
|
+
if (metaData.dbType === oracledb_1.default.DB_TYPE_VECTOR) {
|
|
349
|
+
const myConverter = (v) => {
|
|
350
|
+
if (v !== null) {
|
|
351
|
+
return Array.from(v);
|
|
352
|
+
}
|
|
353
|
+
return v;
|
|
354
|
+
};
|
|
355
|
+
return { converter: myConverter };
|
|
356
|
+
}
|
|
357
|
+
return undefined;
|
|
358
|
+
};
|
|
359
|
+
execOptions = getExecuteOptions(options);
|
|
360
|
+
execOptions.outFormat = oracledb_1.default.OUT_FORMAT_OBJECT; // used for execute operation.
|
|
361
|
+
execOptions.fetchTypeHandler = executeFetchHandler;
|
|
362
|
+
}
|
|
363
|
+
if (stmtBatching === 'single' && queries[0].executeManyValues) {
|
|
364
|
+
const connection = await pool.getConnection();
|
|
365
|
+
try {
|
|
366
|
+
execOptions = getExecuteManyOptions(options);
|
|
367
|
+
if (continueOnFail) {
|
|
368
|
+
execOptions.batchErrors = true;
|
|
369
|
+
}
|
|
370
|
+
const results = await connection.executeMany(queries[0].query, queries[0].executeManyValues, execOptions);
|
|
371
|
+
doesRowExist(queries[0].query, results);
|
|
372
|
+
if (results.batchErrors) {
|
|
373
|
+
// If there are batch errors, we just show them but not the
|
|
374
|
+
// partial outbinds.
|
|
375
|
+
const batchErrors = results.batchErrors;
|
|
376
|
+
for (let i = 0; i < batchErrors.length; i++) {
|
|
377
|
+
const failedIndex = batchErrors[i].offset;
|
|
378
|
+
const error = parseOracleError(node, batchErrors[i], failedIndex);
|
|
379
|
+
const pairedItem = { item: failedIndex };
|
|
380
|
+
returnData.push({ json: { message: error.message }, pairedItem });
|
|
381
|
+
}
|
|
382
|
+
}
|
|
383
|
+
else {
|
|
384
|
+
_getResponseForOutbinds.call(this, results, stmtBatching, queries[0].outputColumns, returnData);
|
|
385
|
+
}
|
|
386
|
+
if (!returnData.length) {
|
|
387
|
+
// returning Clause is not given.
|
|
388
|
+
const pairedItem = (0, utilities_1.generatePairedItemData)(queries.length);
|
|
389
|
+
returnData = [{ json: emptyRowData, pairedItem }];
|
|
390
|
+
}
|
|
391
|
+
}
|
|
392
|
+
catch (caughtError) {
|
|
393
|
+
const error = parseOracleError(node, caughtError);
|
|
394
|
+
if (!continueOnFail)
|
|
395
|
+
throw error;
|
|
396
|
+
return [{ json: { message: error.message, error } }];
|
|
397
|
+
}
|
|
398
|
+
finally {
|
|
399
|
+
if (connection) {
|
|
400
|
+
await connection.close();
|
|
401
|
+
}
|
|
402
|
+
}
|
|
403
|
+
}
|
|
404
|
+
else if (stmtBatching === 'transaction') {
|
|
405
|
+
execOptions.autoCommit = false; // for transaction mode forcefully overwrite it.
|
|
406
|
+
const connection = await pool.getConnection();
|
|
407
|
+
try {
|
|
408
|
+
for (let i = 0; i < queries.length; i++) {
|
|
409
|
+
try {
|
|
410
|
+
const { query, values, outputColumns } = queries[i];
|
|
411
|
+
let transactionResults;
|
|
412
|
+
if (values) {
|
|
413
|
+
transactionResults = await connection.execute(query, values, execOptions);
|
|
414
|
+
}
|
|
415
|
+
else {
|
|
416
|
+
transactionResults = await connection.execute(query, [], execOptions);
|
|
417
|
+
}
|
|
418
|
+
doesRowExist(query, transactionResults);
|
|
419
|
+
const resultOutBinds = [];
|
|
420
|
+
_getResponseForOutbinds.call(this, transactionResults, stmtBatching, outputColumns, resultOutBinds);
|
|
421
|
+
if (!resultOutBinds.length) {
|
|
422
|
+
let rowData = transactionResults.rows ?? [];
|
|
423
|
+
if (!rowData.length) {
|
|
424
|
+
rowData = [emptyRowData];
|
|
425
|
+
}
|
|
426
|
+
const executionData = this.helpers.constructExecutionMetaData((0, utilities_1.wrapData)(rowData), { itemData: { item: i } });
|
|
427
|
+
returnData.push.apply(returnData, executionData);
|
|
428
|
+
}
|
|
429
|
+
else {
|
|
430
|
+
returnData.push.apply(returnData, resultOutBinds);
|
|
431
|
+
}
|
|
432
|
+
}
|
|
433
|
+
catch (caughtError) {
|
|
434
|
+
const error = parseOracleError(node, caughtError, i);
|
|
435
|
+
if (!continueOnFail)
|
|
436
|
+
throw error;
|
|
437
|
+
returnData.push(prepareErrorItem(items, error, i));
|
|
438
|
+
// The rollback happens automatically, so just return.
|
|
439
|
+
return returnData;
|
|
440
|
+
}
|
|
441
|
+
}
|
|
442
|
+
// All succeeded, commit
|
|
443
|
+
await connection.commit();
|
|
444
|
+
}
|
|
445
|
+
finally {
|
|
446
|
+
await connection.close();
|
|
447
|
+
}
|
|
448
|
+
}
|
|
449
|
+
else if (stmtBatching === 'independently') {
|
|
450
|
+
const connection = await pool.getConnection();
|
|
451
|
+
try {
|
|
452
|
+
for (let i = 0; i < queries.length; i++) {
|
|
453
|
+
try {
|
|
454
|
+
const { query, values, outputColumns } = queries[i];
|
|
455
|
+
let taskResults;
|
|
456
|
+
if (values) {
|
|
457
|
+
taskResults = await connection.execute(query, values, execOptions);
|
|
458
|
+
}
|
|
459
|
+
else {
|
|
460
|
+
taskResults = await connection.execute(query, [], execOptions);
|
|
461
|
+
}
|
|
462
|
+
doesRowExist(query, taskResults);
|
|
463
|
+
const resultOutBinds = [];
|
|
464
|
+
_getResponseForOutbinds.call(this, taskResults, stmtBatching, outputColumns, resultOutBinds);
|
|
465
|
+
if (!resultOutBinds.length) {
|
|
466
|
+
// select query or no returning clause in DML
|
|
467
|
+
let rowData = taskResults.rows ?? [];
|
|
468
|
+
if (!rowData.length) {
|
|
469
|
+
rowData = [emptyRowData];
|
|
470
|
+
}
|
|
471
|
+
const executionData = this.helpers.constructExecutionMetaData((0, utilities_1.wrapData)(rowData), { itemData: { item: i } });
|
|
472
|
+
returnData.push.apply(returnData, executionData);
|
|
473
|
+
}
|
|
474
|
+
else {
|
|
475
|
+
returnData.push.apply(returnData, resultOutBinds);
|
|
476
|
+
}
|
|
477
|
+
}
|
|
478
|
+
catch (caughtError) {
|
|
479
|
+
const error = parseOracleError(node, caughtError, i);
|
|
480
|
+
if (!continueOnFail)
|
|
481
|
+
throw error;
|
|
482
|
+
returnData.push(prepareErrorItem(items, error, i));
|
|
483
|
+
}
|
|
484
|
+
}
|
|
485
|
+
}
|
|
486
|
+
finally {
|
|
487
|
+
await connection.close();
|
|
488
|
+
}
|
|
489
|
+
}
|
|
490
|
+
return returnData;
|
|
491
|
+
};
|
|
492
|
+
}
|
|
493
|
+
// Returns a function which returns updated table schema, if the schema
|
|
494
|
+
// or table name has changed.
|
|
495
|
+
const configureTableSchemaUpdater = (node, initialSchema, initialTable) => {
|
|
496
|
+
let currentSchema = initialSchema;
|
|
497
|
+
let currentTable = initialTable;
|
|
498
|
+
return async (pool, tableSchema, schema, table, index = 0) => {
|
|
499
|
+
if (currentSchema !== schema || currentTable !== table) {
|
|
500
|
+
currentSchema = schema;
|
|
501
|
+
currentTable = table;
|
|
502
|
+
tableSchema = await getColumnMetaData(node, pool, schema, table, index);
|
|
503
|
+
}
|
|
504
|
+
return tableSchema;
|
|
505
|
+
};
|
|
506
|
+
};
|
|
507
|
+
exports.configureTableSchemaUpdater = configureTableSchemaUpdater;
|
|
508
|
+
function getColumnMap(tableSchema) {
|
|
509
|
+
const columnMetaDataObject = tableSchema.reduce((acc, { columnName, dataType, isNullable, maxSize }) => {
|
|
510
|
+
acc[columnName] = {
|
|
511
|
+
type: dataType.toUpperCase(),
|
|
512
|
+
nullable: isNullable,
|
|
513
|
+
maxSize,
|
|
514
|
+
};
|
|
515
|
+
return acc;
|
|
516
|
+
}, {});
|
|
517
|
+
return columnMetaDataObject;
|
|
518
|
+
}
|
|
519
|
+
function addWhereClauses(query, clauses, combineConditions, schema, isExecuteMany = false) {
|
|
520
|
+
if (clauses.length === 0)
|
|
521
|
+
return [query, []];
|
|
522
|
+
const combineWith = combineConditions === 'OR' ? 'OR' : 'AND';
|
|
523
|
+
let whereQuery = ' WHERE';
|
|
524
|
+
const bindParameters = [];
|
|
525
|
+
const bindDefs = isExecuteMany ? [] : null;
|
|
526
|
+
let posIndex = 0;
|
|
527
|
+
clauses.forEach((clause, index) => {
|
|
528
|
+
if (clause.condition === 'equal') {
|
|
529
|
+
clause.condition = '=';
|
|
530
|
+
}
|
|
531
|
+
// The condition value is json type, so convert to required type only
|
|
532
|
+
// if fixed expression is used instead of n8n expressions.
|
|
533
|
+
if (typeof clause.value === 'string') {
|
|
534
|
+
try {
|
|
535
|
+
clause.value = JSON.parse(clause.value); // "2" → 2 (number)
|
|
536
|
+
}
|
|
537
|
+
catch {
|
|
538
|
+
// if it wasn't valid JSON, keep original string
|
|
539
|
+
}
|
|
540
|
+
}
|
|
541
|
+
const quotedColumnName = quoteSqlIdentifier(clause.column); // escape column name
|
|
542
|
+
let conditionExpr;
|
|
543
|
+
if (clause.condition === 'IS NULL' || clause.condition === 'IS NOT NULL') {
|
|
544
|
+
conditionExpr = `${quotedColumnName} ${clause.condition}`;
|
|
545
|
+
}
|
|
546
|
+
else {
|
|
547
|
+
conditionExpr = `${quotedColumnName} ${clause.condition} :${posIndex++}`;
|
|
548
|
+
addBindParam(schema[clause.column], clause.value, bindParameters, bindDefs);
|
|
549
|
+
}
|
|
550
|
+
whereQuery += (index > 0 ? ` ${combineWith}` : '') + ` ${conditionExpr}`;
|
|
551
|
+
});
|
|
552
|
+
return [`${query}${whereQuery}`, bindDefs ?? bindParameters];
|
|
553
|
+
}
|
|
554
|
+
/*
|
|
555
|
+
Verifies all provided keys (item fields) exist in the table schema.
|
|
556
|
+
Ensures that non-nullable columns aren't being given null values.
|
|
557
|
+
*/
|
|
558
|
+
function checkItemAgainstSchema(node, columns, schema, item, index = 0) {
|
|
559
|
+
for (const key of columns) {
|
|
560
|
+
const columnDef = schema[key];
|
|
561
|
+
if (!columnDef) {
|
|
562
|
+
throw new n8n_workflow_1.NodeOperationError(node, `Column '${key}' does not exist in selected table`, {
|
|
563
|
+
itemIndex: index,
|
|
564
|
+
});
|
|
565
|
+
}
|
|
566
|
+
if (item[key] === null && !columnDef.nullable) {
|
|
567
|
+
throw new n8n_workflow_1.NodeOperationError(node, `Column '${key}' is not nullable`, {
|
|
568
|
+
itemIndex: index,
|
|
569
|
+
});
|
|
570
|
+
}
|
|
571
|
+
}
|
|
572
|
+
}
|
|
573
|
+
/*
|
|
574
|
+
* Given a query with bindname which accepts string(comma separated values) for IN clause, It
|
|
575
|
+
* generates multiple unique bindnames separated by comma. This bindname should be only used in IN clause.
|
|
576
|
+
*
|
|
577
|
+
* Ex: For input: SELECT * from dual where DUMMY in :param1
|
|
578
|
+
* It generates
|
|
579
|
+
* "SELECT * from dual where DUMMY in (:param1f8b29e29_edef_454a_b003_18fa1debff55,:param1bc8a5a46_5bfd_4ddb_851e_2ac4c243a26b)"
|
|
580
|
+
*
|
|
581
|
+
* The logic is taken from here
|
|
582
|
+
* https://github.com/jgriffin1/n8n-nodes-oracle-database-parameterization
|
|
583
|
+
*
|
|
584
|
+
*/
|
|
585
|
+
function generateBindVariablesList(item, bindParameters, query) {
|
|
586
|
+
if (item.datatype !== 'string') {
|
|
587
|
+
throw new n8n_workflow_1.UserError(`Unsupported datatype '${item.datatype}' for IN clause expansion. Only 'string' of comma-separated values is allowed. `);
|
|
588
|
+
}
|
|
589
|
+
const valList = item.valueString.split(',');
|
|
590
|
+
// Escape bind name for regex safely
|
|
591
|
+
const escapedName = item.name.replace(/[-/\\^$*+?.()|[\]{}]/g, '\\$&');
|
|
592
|
+
let generatedSqlString = '(';
|
|
593
|
+
for (let i = 0; i < valList.length; i++) {
|
|
594
|
+
// replace parameters with Dashes to underscore
|
|
595
|
+
const uniqueId = (0, crypto_1.randomUUID)().replace(/-/g, '_');
|
|
596
|
+
const newParamName = `${item.name}${uniqueId}`;
|
|
597
|
+
bindParameters[newParamName] = {
|
|
598
|
+
type: mapDbType(item.datatype).oracledbType,
|
|
599
|
+
val: getCompatibleValue(item.datatype, valList[i]),
|
|
600
|
+
};
|
|
601
|
+
generatedSqlString += `:${newParamName},`;
|
|
602
|
+
}
|
|
603
|
+
// replace :bindname
|
|
604
|
+
const regex = new RegExp(`:${escapedName}(?![A-Za-z0-9_$#])`, 'g');
|
|
605
|
+
generatedSqlString = generatedSqlString.slice(0, -1) + ')'; //replace trailing comma with closing parenthesis.
|
|
606
|
+
return query.replace(regex, generatedSqlString);
|
|
607
|
+
}
|
|
608
|
+
function getBindParameters(query, parameterList) {
|
|
609
|
+
const bindParameters = {};
|
|
610
|
+
for (const item of parameterList) {
|
|
611
|
+
if (!item.parseInStatement) {
|
|
612
|
+
let bindVal = null;
|
|
613
|
+
const type = item.datatype;
|
|
614
|
+
switch (type) {
|
|
615
|
+
case 'number':
|
|
616
|
+
bindVal = item.valueNumber;
|
|
617
|
+
break;
|
|
618
|
+
case 'string':
|
|
619
|
+
bindVal = item.valueString;
|
|
620
|
+
break;
|
|
621
|
+
case 'boolean':
|
|
622
|
+
bindVal = item.valueBoolean;
|
|
623
|
+
break;
|
|
624
|
+
case 'blob':
|
|
625
|
+
bindVal = item.valueBlob;
|
|
626
|
+
break;
|
|
627
|
+
case 'date': {
|
|
628
|
+
const val = item.valueDate;
|
|
629
|
+
if (typeof val === 'string') {
|
|
630
|
+
bindVal = new Date(val); // string → Date
|
|
631
|
+
}
|
|
632
|
+
else if (val instanceof Date) {
|
|
633
|
+
bindVal = val; // already a Date
|
|
634
|
+
}
|
|
635
|
+
else {
|
|
636
|
+
// Luxon DateTime
|
|
637
|
+
if (val instanceof luxon_1.DateTime) {
|
|
638
|
+
bindVal = val.isValid ? val.toJSDate() : null;
|
|
639
|
+
}
|
|
640
|
+
}
|
|
641
|
+
break;
|
|
642
|
+
}
|
|
643
|
+
case 'sparse': {
|
|
644
|
+
const val = item.valueSparse;
|
|
645
|
+
let indices = val.indices;
|
|
646
|
+
let values = val.values;
|
|
647
|
+
const dims = val.dimensions;
|
|
648
|
+
if (typeof indices === 'string') {
|
|
649
|
+
try {
|
|
650
|
+
indices = JSON.parse(indices);
|
|
651
|
+
}
|
|
652
|
+
catch (caughtError) {
|
|
653
|
+
throw new n8n_workflow_1.UserError(`Indices field must be a valid JSON array or use an expression like {{ [1, 2, 3] }}, Err:${caughtError}`);
|
|
654
|
+
}
|
|
655
|
+
}
|
|
656
|
+
if (typeof values === 'string') {
|
|
657
|
+
try {
|
|
658
|
+
values = JSON.parse(values);
|
|
659
|
+
}
|
|
660
|
+
catch (caughtError) {
|
|
661
|
+
throw new n8n_workflow_1.UserError(`Values field must be a valid JSON array or use an expression like {{ [1, 2, 3] }}, Err:${caughtError} `);
|
|
662
|
+
}
|
|
663
|
+
}
|
|
664
|
+
bindVal = new oracledb_1.default.SparseVector({
|
|
665
|
+
indices,
|
|
666
|
+
values,
|
|
667
|
+
numDimensions: dims,
|
|
668
|
+
});
|
|
669
|
+
break;
|
|
670
|
+
}
|
|
671
|
+
case 'vector':
|
|
672
|
+
{
|
|
673
|
+
const val = item.valueVector;
|
|
674
|
+
bindVal = val;
|
|
675
|
+
if (typeof val === 'string') {
|
|
676
|
+
try {
|
|
677
|
+
bindVal = JSON.parse(val);
|
|
678
|
+
}
|
|
679
|
+
catch (caughtError) {
|
|
680
|
+
throw new n8n_workflow_1.UserError(`Value field must be a valid JSON array or use an expression like {{ [1, 2, 3] }}, Err: ${caughtError}`);
|
|
681
|
+
}
|
|
682
|
+
}
|
|
683
|
+
}
|
|
684
|
+
break;
|
|
685
|
+
case 'json':
|
|
686
|
+
{
|
|
687
|
+
const val = item.valueJson;
|
|
688
|
+
bindVal = val;
|
|
689
|
+
if (typeof val === 'string') {
|
|
690
|
+
try {
|
|
691
|
+
bindVal = JSON.parse(val);
|
|
692
|
+
}
|
|
693
|
+
catch {
|
|
694
|
+
throw new n8n_workflow_1.UserError('Value must be a valid JSON ');
|
|
695
|
+
}
|
|
696
|
+
}
|
|
697
|
+
}
|
|
698
|
+
break;
|
|
699
|
+
default:
|
|
700
|
+
throw new n8n_workflow_1.UserError(`Unsupported Bind type: ${type}`);
|
|
701
|
+
}
|
|
702
|
+
const dir = item.bindDirection === 'in'
|
|
703
|
+
? oracledb_1.default.BIND_IN
|
|
704
|
+
: item.bindDirection === 'out'
|
|
705
|
+
? oracledb_1.default.BIND_OUT
|
|
706
|
+
: oracledb_1.default.BIND_INOUT;
|
|
707
|
+
bindParameters[item.name] = {
|
|
708
|
+
type: n8nTypetoDBType[item.datatype],
|
|
709
|
+
val: bindVal,
|
|
710
|
+
dir,
|
|
711
|
+
};
|
|
712
|
+
}
|
|
713
|
+
else {
|
|
714
|
+
query = generateBindVariablesList(item, bindParameters, query);
|
|
715
|
+
}
|
|
716
|
+
}
|
|
717
|
+
return { updatedQuery: query, bindParameters };
|
|
718
|
+
}
|
|
719
|
+
function getInBindParametersForSourceSelect(inputColumns, schema, valData, bindParameters, bindDefs, posIndex = 0) {
|
|
720
|
+
const quotedColsArray = [];
|
|
721
|
+
let index = posIndex;
|
|
722
|
+
for (const col of inputColumns) {
|
|
723
|
+
const quotedCol = quoteSqlIdentifier(col);
|
|
724
|
+
quotedColsArray.push(`:${index++} as ${quotedCol}`);
|
|
725
|
+
addBindParam(schema[col], valData[col], bindParameters, bindDefs);
|
|
726
|
+
}
|
|
727
|
+
return [quotedColsArray.join(','), index];
|
|
728
|
+
}
|
|
729
|
+
function getOnClauseFromColumns(columns) {
|
|
730
|
+
return columns
|
|
731
|
+
.map((col) => {
|
|
732
|
+
const quoted = quoteSqlIdentifier(col);
|
|
733
|
+
return `t.${quoted} = s.${quoted}`;
|
|
734
|
+
})
|
|
735
|
+
.join(' AND ');
|
|
736
|
+
}
|
|
737
|
+
function getUpdateSetClause(updateCols, schema, valData, bindParameters, bindDefs, posIndex) {
|
|
738
|
+
const setClauses = [];
|
|
739
|
+
let index = posIndex;
|
|
740
|
+
for (const col of updateCols) {
|
|
741
|
+
const quoted = quoteSqlIdentifier(col);
|
|
742
|
+
setClauses.push(`t.${quoted} = :${index}`);
|
|
743
|
+
addBindParam(schema[col], valData[col], bindParameters, bindDefs);
|
|
744
|
+
index++;
|
|
745
|
+
}
|
|
746
|
+
return [setClauses.join(', '), index];
|
|
747
|
+
}
|
|
748
|
+
function getInsertClauseAndBinds(insertCols, schema, valData, bindParameters, bindDefs, posIndex) {
|
|
749
|
+
const quotedCols = [];
|
|
750
|
+
const placeholders = [];
|
|
751
|
+
let index = posIndex;
|
|
752
|
+
for (const col of insertCols) {
|
|
753
|
+
const quoted = quoteSqlIdentifier(col);
|
|
754
|
+
quotedCols.push(quoted);
|
|
755
|
+
placeholders.push(`:${index}`);
|
|
756
|
+
addBindParam(schema[col], valData[col], bindParameters, bindDefs);
|
|
757
|
+
index++;
|
|
758
|
+
}
|
|
759
|
+
return [quotedCols.join(', '), placeholders.join(', '), index];
|
|
760
|
+
}
|
|
761
|
+
function getInBindParametersForExecute(inputColumns, schema, valData, operation, bindParameters, posIndex = 0) {
|
|
762
|
+
const quotedColsArray = [];
|
|
763
|
+
const replacementsArray = [];
|
|
764
|
+
let index = posIndex;
|
|
765
|
+
for (const col of inputColumns) {
|
|
766
|
+
const quotedCol = quoteSqlIdentifier(col);
|
|
767
|
+
if (operation === 'insert') {
|
|
768
|
+
quotedColsArray.push(quotedCol);
|
|
769
|
+
replacementsArray.push(`:${index++}`);
|
|
770
|
+
}
|
|
771
|
+
else if (operation === 'update') {
|
|
772
|
+
quotedColsArray.push(`${quotedCol}=:${index++}`);
|
|
773
|
+
}
|
|
774
|
+
addBindParam(schema[col], valData[col], bindParameters);
|
|
775
|
+
}
|
|
776
|
+
const replacements = replacementsArray.join(',');
|
|
777
|
+
return [quotedColsArray, replacements, index];
|
|
778
|
+
}
|
|
779
|
+
function getInBindDefsForExecuteMany(query, columnMetaDataObject, columns, bindInfo, posIndex = 0, operation = 'insert') {
|
|
780
|
+
const quotedColsArray = [];
|
|
781
|
+
const replacementsArray = [];
|
|
782
|
+
let resultIndex = posIndex;
|
|
783
|
+
for (const col of columns) {
|
|
784
|
+
const quotedCol = quoteSqlIdentifier(col);
|
|
785
|
+
if (operation === 'update' || operation === 'updatewhere') {
|
|
786
|
+
quotedColsArray.push(`${quotedCol}=:${resultIndex++}`);
|
|
787
|
+
}
|
|
788
|
+
else {
|
|
789
|
+
// insert case.
|
|
790
|
+
quotedColsArray.push(quotedCol);
|
|
791
|
+
replacementsArray.push(`:${resultIndex++}`);
|
|
792
|
+
}
|
|
793
|
+
addBindParam(columnMetaDataObject[col], null, [], bindInfo);
|
|
794
|
+
}
|
|
795
|
+
const quotedCols = quotedColsArray.join(operation === 'updatewhere' ? ' AND ' : ',');
|
|
796
|
+
switch (operation) {
|
|
797
|
+
case 'insert':
|
|
798
|
+
query += ` (${quotedCols}) VALUES (${replacementsArray.join(',')})`;
|
|
799
|
+
break;
|
|
800
|
+
case 'update':
|
|
801
|
+
query += ` SET ${quotedCols}`;
|
|
802
|
+
break;
|
|
803
|
+
case 'updatewhere':
|
|
804
|
+
query += ` WHERE ${quotedCols}`;
|
|
805
|
+
break;
|
|
806
|
+
}
|
|
807
|
+
return [query, resultIndex];
|
|
808
|
+
}
|
|
809
|
+
function getOutBindDefsForExecute(query, columnMetaDataObject, outputColumns, bindInfo, bindIndex = 0) {
|
|
810
|
+
let returningClause = 'RETURNING ';
|
|
811
|
+
let intoClause = 'INTO ';
|
|
812
|
+
let posIndex = bindIndex;
|
|
813
|
+
for (const [i, col] of outputColumns.entries()) {
|
|
814
|
+
if (i > 0) {
|
|
815
|
+
returningClause += ', ';
|
|
816
|
+
intoClause += ', ';
|
|
817
|
+
}
|
|
818
|
+
const obj = {};
|
|
819
|
+
obj.type = mapDbType(columnMetaDataObject[col].type).oracledbType;
|
|
820
|
+
obj.dir = oracledb_1.default.BIND_OUT;
|
|
821
|
+
if (obj.type === oracledb_1.default.STRING) {
|
|
822
|
+
obj.maxSize = columnMetaDataObject[col].maxSize;
|
|
823
|
+
}
|
|
824
|
+
else if (obj.type === oracledb_1.default.DB_TYPE_RAW) {
|
|
825
|
+
obj.maxSize = columnMetaDataObject[col].maxSize;
|
|
826
|
+
}
|
|
827
|
+
bindInfo.push(obj);
|
|
828
|
+
returningClause += `${quoteSqlIdentifier(col)}`;
|
|
829
|
+
intoClause += `:${posIndex++}`;
|
|
830
|
+
}
|
|
831
|
+
query = `${query} ${returningClause} ${intoClause}`;
|
|
832
|
+
return query;
|
|
833
|
+
}
|
|
834
|
+
function getBindDefsForExecuteMany(node, query, columnMetaDataObject, inputColumns, outputColumns, item, options, operation = 'insert', columnsToMatchOn = []) {
|
|
835
|
+
checkItemAgainstSchema(node, inputColumns, columnMetaDataObject, item);
|
|
836
|
+
let posIndex = 0;
|
|
837
|
+
const bindDefs = [];
|
|
838
|
+
[query, posIndex] = getInBindDefsForExecuteMany(query, columnMetaDataObject, inputColumns, bindDefs, posIndex, operation);
|
|
839
|
+
if (columnsToMatchOn.length) {
|
|
840
|
+
[query, posIndex] = getInBindDefsForExecuteMany(query, columnMetaDataObject, columnsToMatchOn, bindDefs, posIndex, 'updatewhere');
|
|
841
|
+
}
|
|
842
|
+
if (outputColumns.length > 0) {
|
|
843
|
+
const updatedQuery = getOutBindDefsForExecute(query, columnMetaDataObject, outputColumns, bindDefs, posIndex);
|
|
844
|
+
query = updatedQuery;
|
|
845
|
+
}
|
|
846
|
+
options.bindDefs = bindDefs;
|
|
847
|
+
return query;
|
|
848
|
+
}
|
|
849
|
+
// It will convert the n8n values to compatible bind values.
|
|
850
|
+
function formatItemValues(item, col) {
|
|
851
|
+
const result = [];
|
|
852
|
+
for (const key of Object.keys(item)) {
|
|
853
|
+
const type = col[key].type;
|
|
854
|
+
const value = getCompatibleValue(type, item[key]);
|
|
855
|
+
result.push(value);
|
|
856
|
+
}
|
|
857
|
+
return result;
|
|
858
|
+
}
|
|
859
|
+
//# sourceMappingURL=utils.js.map
|