-
Notifications
You must be signed in to change notification settings - Fork 3
/
OracleRequest.js
110 lines (104 loc) · 3.79 KB
/
OracleRequest.js
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
module.exports = class OracleRequest {
/**
* @param {Promise<import('oracledb').Pool>} pool
*/
constructor(pool) {
this.pool = pool;
const oracle = this.oracle = require('oracledb');
this.directions = {
in: oracle.BIND_IN,
out: oracle.BIND_OUT,
inout: oracle.BIND_INOUT
};
this.type = {
varchar2: oracle.DB_TYPE_VARCHAR,
char: oracle.DB_TYPE_CHAR,
nvarchar: oracle.DB_TYPE_NVARCHAR,
nchar: oracle.DB_TYPE_NCHAR,
number: oracle.DB_TYPE_NUMBER,
binary_double: oracle.DB_TYPE_BINARY_DOUBLE,
binary_float: oracle.DB_TYPE_BINARY_FLOAT,
binary_integer: oracle.DB_TYPE_BINARY_INTEGER,
date: oracle.DB_TYPE_DATE,
timestamp: oracle.DB_TYPE_TIMESTAMP,
raw: oracle.DB_TYPE_RAW,
clob: oracle.DB_TYPE_CLOB,
blob: oracle.DB_TYPE_BLOB,
nclob: oracle.DB_TYPE_NCLOB,
rowid: oracle.DB_TYPE_VARCHAR,
urowid: oracle.DB_TYPE_VARCHAR,
json: oracle.DB_TYPE_JSON,
xmltype: oracle.DB_TYPE_VARCHAR,
cursor: oracle.DB_TYPE_CURSOR
};
this.parameters = [];
}
input(name, type, value) {
this.parameters.push([name, value, type, 'input']);
}
output(name, type, value) {
this.parameters.push([name, value, type, 'output']);
}
/**
* @param {import('oracledb').ResultSet<{}>[]} resultSets
*/
async results(resultSets = [], outBinds, outNames) {
const results = [];
for (const resultSet of resultSets) {
results.push(await resultSet.getRows());
};
for (const index in outNames) {
results.push([{resultSetName: outNames[index]}]);
const value = outBinds[index];
results.push(typeof value.getRows === 'function' ? await outBinds[index].getRows() : value);
};
return results;
}
async query(query, options) {
const connection = await this.pool.getConnection();
try {
const params = this.parameters.map(([, val, type]) => {
const dir = this.directions[type?.dir || 'in'];
switch (type?.type) {
case 'nested': return {
type: `"${type.typeName.replace('.', '"."')}"`,
val,
dir
};
case 'sys_refcursor': return {
type: this.oracle.CURSOR,
dir
};
default: return {
type: this.type[type.type] || this.oracle.DB_TYPE_VARCHAR,
val,
dir
};
}
});
const outNames = params.map((param, index) => [this.oracle.BIND_INOUT, this.oracle.BIND_OUT].includes(param?.dir) && this.parameters[index][0]).filter(Boolean);
const result = await connection.execute(
query,
params,
options || {}
);
const recordsets = (result.implicitResults || outNames.length)
? await this.results(result.implicitResults, result.outBinds, outNames)
: result.rows
? [result.rows]
: [];
return {
recordsets,
recordset: recordsets?.[0]
};
} finally {
connection.close();
}
}
execute(procedure) {
return this.query(`BEGIN "${procedure}"(${this.parameters.map(([name]) => ':' + name).join(', ')}); COMMIT; END;`, {resultSet: true});
}
batch(query) {
return this.query(query);
}
};