web_plsql 0.16.1 → 0.17.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/package.json +13 -15
- package/src/handler/plsql/cgi.js +1 -1
- package/src/handler/plsql/procedure.js +185 -140
- package/src/handler/plsql/procedureNamed.js +1 -1
- package/src/handler/plsql/procedureVariable.js +1 -1
- package/src/handler/plsql/request.js +6 -1
- package/src/index.js +5 -1
- package/src/server/config.js +1 -1
- package/src/{server/version.js → version.js} +1 -1
- package/types/index.d.ts +3 -1
- /package/types/{server/version.d.ts → version.d.ts} +0 -0
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "web_plsql",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.17.1",
|
|
4
4
|
"author": "Dieter Oberkofler <dieter.oberkofler@gmail.com>",
|
|
5
5
|
"license": "MIT",
|
|
6
6
|
"description": "The Express Middleware for Oracle PL/SQL",
|
|
@@ -47,7 +47,8 @@
|
|
|
47
47
|
"test": "node --test --test-concurrency=1 \"./tests/**/*.test.js\"",
|
|
48
48
|
"types": "rm -rf types && tsc --noEmit false --declaration true --declarationDir types --emitDeclarationOnly true --allowJs true --target es2020 --module es2020 --moduleResolution node --allowSyntheticDefaultImports true src/*.js",
|
|
49
49
|
"clean": "shx rm -f *.tgz && shx rm -f *.log",
|
|
50
|
-
"ci": "npm run clean && npm run lint && npm run test && npm run types",
|
|
50
|
+
"ci": "npm run clean && npm run version && npm run lint && npm run test && npm run types",
|
|
51
|
+
"version": "node update-version.js",
|
|
51
52
|
"create-package": "shx rm -f *.tgz && npm pack",
|
|
52
53
|
"image-build": "docker build --no-cache --progress=plain --tag=web_plsql .",
|
|
53
54
|
"image-save": "docker save web_plsql | gzip > web_plsql.tar.gz"
|
|
@@ -56,35 +57,32 @@
|
|
|
56
57
|
"oracledb": "6.10.0"
|
|
57
58
|
},
|
|
58
59
|
"dependencies": {
|
|
59
|
-
"basic-auth": "2.0.1",
|
|
60
60
|
"compression": "1.8.1",
|
|
61
61
|
"cookie-parser": "1.4.7",
|
|
62
62
|
"debug": "4.4.3",
|
|
63
63
|
"express": "5.2.1",
|
|
64
|
-
"fs-extra": "11.3.2",
|
|
65
64
|
"http-parser-js": "0.5.10",
|
|
66
65
|
"morgan": "1.10.1",
|
|
67
66
|
"multer": "2.0.2",
|
|
68
|
-
"rotating-file-stream": "3.2.
|
|
69
|
-
"zod": "4.
|
|
67
|
+
"rotating-file-stream": "3.2.8",
|
|
68
|
+
"zod": "4.3.6"
|
|
70
69
|
},
|
|
71
70
|
"devDependencies": {
|
|
72
|
-
"@types/basic-auth": "1.1.8",
|
|
73
71
|
"@types/compression": "1.8.1",
|
|
74
72
|
"@types/cookie-parser": "1.4.10",
|
|
75
73
|
"@types/debug": "4.1.12",
|
|
76
|
-
"@types/fs-extra": "11.0.4",
|
|
77
74
|
"@types/morgan": "1.9.10",
|
|
78
75
|
"@types/multer": "2.0.0",
|
|
79
|
-
"@types/node": "
|
|
80
|
-
"@types/oracledb": "6.10.
|
|
76
|
+
"@types/node": "25.2.0",
|
|
77
|
+
"@types/oracledb": "6.10.1",
|
|
81
78
|
"@types/supertest": "6.0.3",
|
|
82
|
-
"eslint": "9.39.
|
|
83
|
-
"eslint-plugin-jsdoc": "
|
|
84
|
-
"
|
|
79
|
+
"eslint": "9.39.2",
|
|
80
|
+
"eslint-plugin-jsdoc": "62.5.1",
|
|
81
|
+
"oracledb": "6.10.0",
|
|
82
|
+
"prettier": "3.8.1",
|
|
85
83
|
"shx": "0.4.0",
|
|
86
|
-
"supertest": "7.
|
|
84
|
+
"supertest": "7.2.2",
|
|
87
85
|
"typescript": "5.9.3",
|
|
88
|
-
"typescript-eslint": "8.
|
|
86
|
+
"typescript-eslint": "8.54.0"
|
|
89
87
|
}
|
|
90
88
|
}
|
package/src/handler/plsql/cgi.js
CHANGED
|
@@ -109,7 +109,7 @@ export const getCGI = (req, doctable, cgi) => {
|
|
|
109
109
|
const CGI = {
|
|
110
110
|
SERVER_PORT: typeof req.socket.localPort === 'number' ? req.socket.localPort.toString() : '',
|
|
111
111
|
REQUEST_METHOD: req.method,
|
|
112
|
-
PATH_INFO: req.params.name,
|
|
112
|
+
PATH_INFO: Array.isArray(req.params.name) ? req.params.name[0] : req.params.name,
|
|
113
113
|
SCRIPT_NAME: PATH.script,
|
|
114
114
|
REMOTE_ADDR: (req.ip ?? '').replace('::ffff:', ''),
|
|
115
115
|
SERVER_PROTOCOL: `${PROTOCOL}/${req.httpVersion}`,
|
|
@@ -32,48 +32,6 @@ import {sanitizeProcName} from './procedureSanitize.js';
|
|
|
32
32
|
* @typedef {import('../../types.js').BindParameterConfig} BindParameterConfig
|
|
33
33
|
*/
|
|
34
34
|
|
|
35
|
-
/**
|
|
36
|
-
* Get the SQL statement to execute when a new procedure is invoked
|
|
37
|
-
*
|
|
38
|
-
* NOTE:
|
|
39
|
-
* 1) dbms_session.modify_package_state(dbms_session.reinitialize) is used to ensure a stateless environment by resetting package state (dbms_session.reset_package)
|
|
40
|
-
*
|
|
41
|
-
* @param {string} procedure - The procedure
|
|
42
|
-
* @returns {string} - The SQL statement to execute
|
|
43
|
-
*/
|
|
44
|
-
const getProcedureSQL = (procedure) => `
|
|
45
|
-
DECLARE
|
|
46
|
-
l_file_type VARCHAR2(32767);
|
|
47
|
-
l_file_size INTEGER;
|
|
48
|
-
l_file_exists INTEGER := 0;
|
|
49
|
-
BEGIN
|
|
50
|
-
dbms_session.modify_package_state(dbms_session.reinitialize);
|
|
51
|
-
owa.init_cgi_env(:cgicount, :cginames, :cgivalues);
|
|
52
|
-
htp.init;
|
|
53
|
-
htp.HTBUF_LEN := :htbuflen;
|
|
54
|
-
|
|
55
|
-
BEGIN
|
|
56
|
-
${procedure}
|
|
57
|
-
EXCEPTION WHEN OTHERS THEN
|
|
58
|
-
raise_application_error(-20000, 'Error executing "${procedure}"', TRUE);
|
|
59
|
-
END;
|
|
60
|
-
|
|
61
|
-
IF (wpg_docload.is_file_download()) THEN
|
|
62
|
-
wpg_docload.get_download_file(l_file_type);
|
|
63
|
-
IF (l_file_type = 'B') THEN
|
|
64
|
-
l_file_exists := 1;
|
|
65
|
-
wpg_docload.get_download_blob(:fileBlob);
|
|
66
|
-
l_file_size := dbms_lob.getlength(:fileBlob);
|
|
67
|
-
END IF;
|
|
68
|
-
END IF;
|
|
69
|
-
:fileExist := l_file_exists;
|
|
70
|
-
:fileType := l_file_type;
|
|
71
|
-
:fileSize := l_file_size;
|
|
72
|
-
|
|
73
|
-
owa.get_page(thepage=>:lines, irows=>:irows);
|
|
74
|
-
END;
|
|
75
|
-
`;
|
|
76
|
-
|
|
77
35
|
/**
|
|
78
36
|
* Get the procedure and arguments to execute
|
|
79
37
|
* @param {Request} req - The req object represents the HTTP request. (only used for debugging)
|
|
@@ -85,10 +43,10 @@ END;
|
|
|
85
43
|
*/
|
|
86
44
|
const getProcedure = async (req, procName, argObj, options, databaseConnection) => {
|
|
87
45
|
// path alias
|
|
88
|
-
if (options.pathAlias
|
|
46
|
+
if (options.pathAlias?.toLowerCase() === procName.toLowerCase()) {
|
|
89
47
|
debug(`getProcedure: path alias "${options.pathAlias}" redirects to "${options.pathAliasProcedure}"`);
|
|
90
48
|
return {
|
|
91
|
-
sql: `${options.pathAliasProcedure}(p_path=>:p_path)
|
|
49
|
+
sql: `${options.pathAliasProcedure}(p_path=>:p_path)`,
|
|
92
50
|
bind: {
|
|
93
51
|
p_path: {dir: oracledb.BIND_IN, type: oracledb.STRING, val: procName},
|
|
94
52
|
},
|
|
@@ -110,154 +68,241 @@ const getProcedure = async (req, procName, argObj, options, databaseConnection)
|
|
|
110
68
|
};
|
|
111
69
|
|
|
112
70
|
/**
|
|
113
|
-
*
|
|
71
|
+
* Prepare procedure
|
|
72
|
+
*
|
|
73
|
+
* NOTE:
|
|
74
|
+
* 1) dbms_session.modify_package_state(dbms_session.reinitialize) is used to ensure a stateless environment by resetting package state (dbms_session.reset_package)
|
|
114
75
|
*
|
|
115
|
-
* @param {Request} req - The req object represents the HTTP request.
|
|
116
|
-
* @param {Response} res - The res object represents the HTTP response that an Express app sends when it gets an HTTP request.
|
|
117
|
-
* @param {argObjType} argObj - - The arguments of the procedure to invoke.
|
|
118
76
|
* @param {environmentType} cgiObj - The cgi of the procedure to invoke.
|
|
119
|
-
* @param {fileUploadType[]} filesToUpload - Array of files to be uploaded
|
|
120
|
-
* @param {configPlSqlHandlerType} options - the options for the middleware.
|
|
121
77
|
* @param {Connection} databaseConnection - Database connection.
|
|
122
|
-
* @returns {Promise<void>} Promise resolving to
|
|
78
|
+
* @returns {Promise<void>} Promise resolving to void.
|
|
123
79
|
*/
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
80
|
+
const procedurePrepare = async (cgiObj, databaseConnection) => {
|
|
81
|
+
let sqlStatement = 'BEGIN dbms_session.modify_package_state(dbms_session.reinitialize); END;';
|
|
82
|
+
try {
|
|
83
|
+
await databaseConnection.execute(sqlStatement);
|
|
84
|
+
} catch (err) {
|
|
85
|
+
throw new ProcedureError(`procedurePrepare: error when preparing procedure\n${errorToString(err)}`, cgiObj, sqlStatement, {});
|
|
86
|
+
}
|
|
128
87
|
|
|
129
|
-
//
|
|
130
|
-
//
|
|
131
|
-
//
|
|
88
|
+
// htbuf_len: reduce this limit based on your worst-case character size.
|
|
89
|
+
// For most character sets, this will be 2 bytes per character, so the limit would be 127.
|
|
90
|
+
// For UTF8 Unicode, it's 3 bytes per character, meaning the limit should be 85.
|
|
91
|
+
// For the newer AL32UTF8 Unicode, it's 4 bytes per character, and the limit should be 63.
|
|
92
|
+
sqlStatement = 'BEGIN owa.init_cgi_env(:cgicount, :cginames, :cgivalues); htp.init; htp.htbuf_len := 63; END;';
|
|
93
|
+
/** @type {BindParameterConfig} */
|
|
94
|
+
const bindParameter = {
|
|
95
|
+
cgicount: {dir: oracledb.BIND_IN, type: oracledb.NUMBER, val: Object.keys(cgiObj).length},
|
|
96
|
+
cginames: {dir: oracledb.BIND_IN, type: oracledb.STRING, val: Object.keys(cgiObj)},
|
|
97
|
+
cgivalues: {dir: oracledb.BIND_IN, type: oracledb.STRING, val: Object.values(cgiObj)},
|
|
98
|
+
};
|
|
99
|
+
try {
|
|
100
|
+
await databaseConnection.execute(sqlStatement, bindParameter);
|
|
101
|
+
} catch (err) {
|
|
102
|
+
throw new ProcedureError(`procedurePrepare: error when preparing procedure\n${errorToString(err)}`, cgiObj, sqlStatement, bindParameter);
|
|
103
|
+
}
|
|
104
|
+
};
|
|
132
105
|
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
106
|
+
/**
|
|
107
|
+
* Execute procedure
|
|
108
|
+
*
|
|
109
|
+
* @param {{sql: string; bind: BindParameterConfig}} para - The statement and binding to use when executing the procedure.
|
|
110
|
+
* @param {Connection} databaseConnection - Database connection.
|
|
111
|
+
* @returns {Promise<void>} Promise resolving to void.
|
|
112
|
+
*/
|
|
113
|
+
const procedureExecute = async (para, databaseConnection) => {
|
|
114
|
+
const sqlStatement = `BEGIN ${para.sql}; END;`;
|
|
137
115
|
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
}
|
|
116
|
+
try {
|
|
117
|
+
await databaseConnection.execute(sqlStatement, para.bind);
|
|
118
|
+
} catch (err) {
|
|
119
|
+
throw new ProcedureError(`procedureExecute: error when executing procedure:\n${sqlStatement}\n${errorToString(err)}`, {}, para.sql, para.bind);
|
|
142
120
|
}
|
|
121
|
+
};
|
|
143
122
|
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
|
|
123
|
+
/**
|
|
124
|
+
* Get page from procedure
|
|
125
|
+
*
|
|
126
|
+
* @param {boolean} test - Test.
|
|
127
|
+
* @param {Connection} databaseConnection - Database connection.
|
|
128
|
+
* @returns {Promise<string>} Promise resolving to the returned page content.
|
|
129
|
+
*/
|
|
130
|
+
const procedureGetPage = async (test, databaseConnection) => {
|
|
131
|
+
const MAX_IROWS = 100000;
|
|
147
132
|
|
|
148
|
-
|
|
133
|
+
/** @type {BindParameterConfig} */
|
|
134
|
+
const bindParameter = {
|
|
135
|
+
lines: {dir: oracledb.BIND_OUT, type: oracledb.STRING, maxArraySize: MAX_IROWS},
|
|
136
|
+
irows: {dir: oracledb.BIND_INOUT, type: oracledb.NUMBER, val: MAX_IROWS},
|
|
137
|
+
};
|
|
149
138
|
|
|
150
|
-
|
|
151
|
-
// 3) EXECUTE PROCEDURE
|
|
152
|
-
//
|
|
139
|
+
const sqlStatement = 'BEGIN owa.get_page(thepage=>:lines, irows=>:irows); END;';
|
|
153
140
|
|
|
154
|
-
|
|
155
|
-
|
|
141
|
+
/** @type {Result} */
|
|
142
|
+
let result = {};
|
|
143
|
+
try {
|
|
144
|
+
result = await databaseConnection.execute(sqlStatement, bindParameter);
|
|
145
|
+
} catch (err) {
|
|
146
|
+
if (debug.enabled) {
|
|
147
|
+
debug(getBlock('procedureGetPage: results', inspect(result)));
|
|
148
|
+
}
|
|
156
149
|
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
values: Object.values(cgiObj),
|
|
160
|
-
};
|
|
150
|
+
throw new ProcedureError(`procedureGetPage: error when getting page returned by procedure\n${errorToString(err)}`, {}, sqlStatement, bindParameter);
|
|
151
|
+
}
|
|
161
152
|
|
|
162
|
-
const
|
|
153
|
+
const {lines, irows} = z.object({irows: z.number(), lines: z.array(z.string())}).parse(result.outBinds);
|
|
154
|
+
|
|
155
|
+
// Make sure that we have retrieved all the rows
|
|
156
|
+
if (irows > MAX_IROWS) {
|
|
157
|
+
/* istanbul ignore next */
|
|
158
|
+
throw new ProcedureError(`procedureGetPage: error when retrieving rows. irows="${irows}"`, {}, sqlStatement, bindParameter);
|
|
159
|
+
}
|
|
160
|
+
|
|
161
|
+
return lines.join('');
|
|
162
|
+
};
|
|
163
163
|
|
|
164
|
+
/**
|
|
165
|
+
* Download files from procedure
|
|
166
|
+
*
|
|
167
|
+
* @param {oracledb.Lob} fileBlob - The blob eventually containing the file.
|
|
168
|
+
* @param {Connection} databaseConnection - Database connection.
|
|
169
|
+
* @returns {Promise<{fileType: string, fileSize: number, fileBlob: stream.Readable | null}>} Promise resolving to the result.
|
|
170
|
+
*/
|
|
171
|
+
const procedureDownloadFiles = async (fileBlob, databaseConnection) => {
|
|
164
172
|
/** @type {BindParameterConfig} */
|
|
165
|
-
const
|
|
166
|
-
cgicount: {dir: oracledb.BIND_IN, type: oracledb.NUMBER, val: cgi.keys.length},
|
|
167
|
-
cginames: {dir: oracledb.BIND_IN, type: oracledb.STRING, val: cgi.keys},
|
|
168
|
-
cgivalues: {dir: oracledb.BIND_IN, type: oracledb.STRING, val: cgi.values},
|
|
169
|
-
htbuflen: {dir: oracledb.BIND_IN, type: oracledb.NUMBER, val: HTBUF_LEN},
|
|
170
|
-
fileExist: {dir: oracledb.BIND_OUT, type: oracledb.NUMBER},
|
|
173
|
+
const bindParameter = {
|
|
171
174
|
fileType: {dir: oracledb.BIND_OUT, type: oracledb.STRING},
|
|
172
175
|
fileSize: {dir: oracledb.BIND_OUT, type: oracledb.NUMBER},
|
|
173
176
|
fileBlob: {dir: oracledb.BIND_INOUT, type: oracledb.BLOB, val: fileBlob},
|
|
174
|
-
lines: {dir: oracledb.BIND_OUT, type: oracledb.STRING, maxSize: HTBUF_LEN * 2, maxArraySize: MAX_IROWS},
|
|
175
|
-
irows: {dir: oracledb.BIND_INOUT, type: oracledb.NUMBER, val: MAX_IROWS},
|
|
176
177
|
};
|
|
177
178
|
|
|
178
|
-
|
|
179
|
-
|
|
179
|
+
const sqlStatement = `
|
|
180
|
+
DECLARE
|
|
181
|
+
l_file_type VARCHAR2(32767) := '';
|
|
182
|
+
l_file_size INTEGER := 0;
|
|
183
|
+
BEGIN
|
|
184
|
+
IF (wpg_docload.is_file_download()) THEN
|
|
185
|
+
wpg_docload.get_download_file(l_file_type);
|
|
186
|
+
IF (l_file_type = 'B') THEN
|
|
187
|
+
wpg_docload.get_download_blob(:fileBlob);
|
|
188
|
+
l_file_size := dbms_lob.getlength(:fileBlob);
|
|
189
|
+
END IF;
|
|
190
|
+
END IF;
|
|
191
|
+
:fileType := l_file_type;
|
|
192
|
+
:fileSize := l_file_size;
|
|
193
|
+
END;
|
|
194
|
+
`;
|
|
195
|
+
|
|
180
196
|
/** @type {Result | null} */
|
|
181
197
|
let result = null;
|
|
182
|
-
const bindParams = Object.assign({}, bind, para.bind);
|
|
183
198
|
try {
|
|
184
|
-
|
|
185
|
-
if (debug.enabled) {
|
|
186
|
-
debug(getBlock('execute', sqlStatement));
|
|
187
|
-
// NOTE: Because inspecting a BLOB value generates a craxy amount of text, we somply remove it.
|
|
188
|
-
const temp = Object.assign({}, bindParams);
|
|
189
|
-
delete temp.fileBlob.val;
|
|
190
|
-
debug(getBlock('bindParams', inspect(temp)));
|
|
191
|
-
}
|
|
192
|
-
}
|
|
193
|
-
result = await databaseConnection.execute(sqlStatement, bindParams);
|
|
199
|
+
result = await databaseConnection.execute(sqlStatement, bindParameter);
|
|
194
200
|
} catch (err) {
|
|
195
201
|
if (debug.enabled) {
|
|
196
|
-
debug(getBlock('results', inspect(result)));
|
|
202
|
+
debug(getBlock('procedureDownloadFiles: results', inspect(result)));
|
|
197
203
|
}
|
|
198
204
|
|
|
199
|
-
throw new ProcedureError(`
|
|
205
|
+
throw new ProcedureError(`procedureDownloadFiles: error when downloading files\n${errorToString(err)}`, {}, sqlStatement, bindParameter);
|
|
200
206
|
}
|
|
201
207
|
|
|
202
|
-
|
|
203
|
-
// 4) PROCESS RESULTS
|
|
204
|
-
//
|
|
205
|
-
|
|
206
|
-
// validate results
|
|
207
|
-
const data = z
|
|
208
|
+
return z
|
|
208
209
|
.object({
|
|
209
|
-
|
|
210
|
-
|
|
211
|
-
|
|
212
|
-
|
|
213
|
-
fileSize: z
|
|
210
|
+
fileType: z
|
|
211
|
+
.string()
|
|
212
|
+
.nullable()
|
|
213
|
+
.transform((val) => val ?? ''),
|
|
214
|
+
fileSize: z
|
|
215
|
+
.number()
|
|
216
|
+
.nullable()
|
|
217
|
+
.transform((val) => val ?? 0),
|
|
214
218
|
fileBlob: z.instanceof(stream.Readable).nullable(),
|
|
215
219
|
})
|
|
216
220
|
.parse(result.outBinds);
|
|
221
|
+
};
|
|
217
222
|
|
|
218
|
-
|
|
219
|
-
|
|
223
|
+
/**
|
|
224
|
+
* Invoke the Oracle procedure and return the page content
|
|
225
|
+
*
|
|
226
|
+
* @param {Request} req - The req object represents the HTTP request.
|
|
227
|
+
* @param {Response} res - The res object represents the HTTP response that an Express app sends when it gets an HTTP request.
|
|
228
|
+
* @param {argObjType} argObj - - The arguments of the procedure to invoke.
|
|
229
|
+
* @param {environmentType} cgiObj - The cgi of the procedure to invoke.
|
|
230
|
+
* @param {fileUploadType[]} filesToUpload - Array of files to be uploaded
|
|
231
|
+
* @param {configPlSqlHandlerType} options - the options for the middleware.
|
|
232
|
+
* @param {Connection} databaseConnection - Database connection.
|
|
233
|
+
* @returns {Promise<void>} Promise resolving to the page content generated by the executed procedure
|
|
234
|
+
*/
|
|
235
|
+
export const invokeProcedure = async (req, res, argObj, cgiObj, filesToUpload, options, databaseConnection) => {
|
|
236
|
+
debug('invokeProcedure: begin');
|
|
237
|
+
|
|
238
|
+
// 1) upload files
|
|
239
|
+
debug(`invokeProcedure: upload "${filesToUpload.length}" files`);
|
|
240
|
+
if (filesToUpload.length > 0) {
|
|
241
|
+
if (typeof options.documentTable === 'string' && options.documentTable.length > 0) {
|
|
242
|
+
const {documentTable} = options;
|
|
243
|
+
|
|
244
|
+
await Promise.all(filesToUpload.map((file) => uploadFile(file, documentTable, databaseConnection)));
|
|
245
|
+
} else {
|
|
246
|
+
console.warn(`Unable to upload "${filesToUpload.length}" files because the option ""doctable" has not been defined`);
|
|
247
|
+
}
|
|
220
248
|
}
|
|
221
249
|
|
|
222
|
-
//
|
|
223
|
-
|
|
224
|
-
|
|
225
|
-
|
|
250
|
+
// 2) get procedure to execute and the arguments
|
|
251
|
+
|
|
252
|
+
debug('invokeProcedure: get procedure to execute and the arguments');
|
|
253
|
+
const para = await getProcedure(req, Array.isArray(req.params.name) ? req.params.name[0] : req.params.name, argObj, options, databaseConnection);
|
|
254
|
+
|
|
255
|
+
// 3) prepare the session
|
|
256
|
+
|
|
257
|
+
debug('invokeProcedure: prepare the session');
|
|
258
|
+
await procedurePrepare(cgiObj, databaseConnection);
|
|
259
|
+
|
|
260
|
+
// 4) execute the procedure
|
|
261
|
+
|
|
262
|
+
debug('invokeProcedure: execute the session');
|
|
263
|
+
await procedureExecute(para, databaseConnection);
|
|
264
|
+
|
|
265
|
+
// 5) get the page returned from the procedure
|
|
266
|
+
|
|
267
|
+
debug('invokeProcedure: get the page returned from the procedure');
|
|
268
|
+
const lines = await procedureGetPage(true, databaseConnection);
|
|
269
|
+
if (debug.enabled) {
|
|
270
|
+
debug(getBlock('data', lines));
|
|
226
271
|
}
|
|
227
272
|
|
|
228
|
-
//
|
|
229
|
-
|
|
273
|
+
// 6) download files
|
|
274
|
+
|
|
275
|
+
debug('invokeProcedure: download files');
|
|
276
|
+
const fileBlob = await databaseConnection.createLob(oracledb.BLOB);
|
|
277
|
+
const fileDownload = await procedureDownloadFiles(fileBlob, databaseConnection);
|
|
278
|
+
if (debug.enabled) {
|
|
279
|
+
debug(getBlock('fileDownload', inspect({fileType: fileDownload.fileType, fileSize: fileDownload.fileSize})));
|
|
280
|
+
}
|
|
230
281
|
|
|
231
|
-
//
|
|
232
|
-
// 6) PARSE PAGE
|
|
233
|
-
//
|
|
282
|
+
// 7) parse the page
|
|
234
283
|
|
|
235
|
-
|
|
236
|
-
const pageComponents = parsePage(
|
|
284
|
+
debug('invokeProcedure: parse the page');
|
|
285
|
+
const pageComponents = parsePage(lines);
|
|
237
286
|
|
|
238
287
|
// add "Server" header
|
|
239
288
|
pageComponents.head.server = cgiObj.SERVER_SOFTWARE;
|
|
240
289
|
|
|
241
290
|
// add file download information
|
|
242
|
-
if (
|
|
243
|
-
pageComponents.file.fileType =
|
|
244
|
-
pageComponents.file.fileSize =
|
|
245
|
-
|
|
246
|
-
pageComponents.file.fileBlob = await streamToBuffer(data.fileBlob);
|
|
247
|
-
}
|
|
291
|
+
if (fileDownload.fileType !== '' && fileDownload.fileSize > 0 && fileDownload.fileBlob !== null) {
|
|
292
|
+
pageComponents.file.fileType = fileDownload.fileType;
|
|
293
|
+
pageComponents.file.fileSize = fileDownload.fileSize;
|
|
294
|
+
pageComponents.file.fileBlob = await streamToBuffer(fileDownload.fileBlob);
|
|
248
295
|
}
|
|
249
296
|
|
|
250
|
-
//
|
|
251
|
-
// 5) SEND THE RESPONSE
|
|
252
|
-
//
|
|
297
|
+
// 8) send the page to browser
|
|
253
298
|
|
|
299
|
+
debug('invokeProcedure: send the page to browser');
|
|
254
300
|
sendResponse(req, res, pageComponents);
|
|
255
301
|
|
|
256
|
-
//
|
|
257
|
-
// 6) CLEANUP
|
|
258
|
-
//
|
|
302
|
+
// 9) cleanup
|
|
259
303
|
|
|
304
|
+
debug('invokeProcedure: cleanup');
|
|
260
305
|
fileBlob.destroy();
|
|
261
306
|
|
|
262
|
-
debug('invokeProcedure:
|
|
307
|
+
debug('invokeProcedure: end');
|
|
263
308
|
};
|
|
@@ -291,7 +291,7 @@ export const getProcedureNamed = async (req, procName, argObj, databaseConnectio
|
|
|
291
291
|
}
|
|
292
292
|
|
|
293
293
|
// select statement
|
|
294
|
-
const sql = `${procName}(${sqlParameter.join(', ')})
|
|
294
|
+
const sql = `${procName}(${sqlParameter.join(', ')})`;
|
|
295
295
|
|
|
296
296
|
if (debug.enabled) {
|
|
297
297
|
debug(sql);
|
|
@@ -45,7 +45,7 @@ export const getProcedureVariable = (req, procName, argObj) => {
|
|
|
45
45
|
}
|
|
46
46
|
|
|
47
47
|
return {
|
|
48
|
-
sql: `${procName}(:argnames, :argvalues)
|
|
48
|
+
sql: `${procName}(:argnames, :argvalues)`,
|
|
49
49
|
bind: {
|
|
50
50
|
argnames: {dir: oracledb.BIND_IN, type: oracledb.STRING, val: names},
|
|
51
51
|
argvalues: {dir: oracledb.BIND_IN, type: oracledb.STRING, val: values},
|
|
@@ -33,6 +33,11 @@ import {isStringOrArrayOfString} from '../../util/type.js';
|
|
|
33
33
|
export const processRequest = async (req, res, options, connectionPool) => {
|
|
34
34
|
debug('processRequest: ENTER');
|
|
35
35
|
|
|
36
|
+
//
|
|
37
|
+
if (Array.isArray(req.params.name)) {
|
|
38
|
+
console.warn(`processRequest: WARNING: the req.params.name is not a string but an array of string: ${req.params.name.join(',')}`);
|
|
39
|
+
}
|
|
40
|
+
|
|
36
41
|
// open database connection
|
|
37
42
|
const connection = await connectionPool.getConnection();
|
|
38
43
|
|
|
@@ -68,7 +73,7 @@ export const processRequest = async (req, res, options, connectionPool) => {
|
|
|
68
73
|
await connection.rollback();
|
|
69
74
|
} else if (typeof options.transactionMode === 'function') {
|
|
70
75
|
debug('transactionMode: callback');
|
|
71
|
-
const result = options.transactionMode(connection, req.params.name);
|
|
76
|
+
const result = options.transactionMode(connection, Array.isArray(req.params.name) ? req.params.name[0] : req.params.name);
|
|
72
77
|
debug('transactionMode: callback restult', result);
|
|
73
78
|
if (result && typeof result.then === 'function') {
|
|
74
79
|
await result;
|
package/src/index.js
CHANGED
|
@@ -1,5 +1,9 @@
|
|
|
1
|
+
// libraries
|
|
2
|
+
import oracledb from 'oracledb';
|
|
3
|
+
export {oracledb};
|
|
4
|
+
|
|
1
5
|
// server
|
|
2
|
-
export {getVersion} from './
|
|
6
|
+
export {getVersion} from './version.js';
|
|
3
7
|
export {createServer, startServer, loadConfig, startServerConfig} from './server/server.js';
|
|
4
8
|
export * from './util/shutdown.js';
|
|
5
9
|
|
package/src/server/config.js
CHANGED
package/types/index.d.ts
CHANGED
|
@@ -1,4 +1,5 @@
|
|
|
1
|
-
export {
|
|
1
|
+
export { oracledb };
|
|
2
|
+
export { getVersion } from "./version.js";
|
|
2
3
|
export * from "./util/shutdown.js";
|
|
3
4
|
export * from "./util/oracle.js";
|
|
4
5
|
export * from "./util/file.js";
|
|
@@ -6,4 +7,5 @@ export { handlerWebPlSql } from "./handler/plsql/handlerPlSql.js";
|
|
|
6
7
|
export { handlerLogger } from "./handler/handlerLogger.js";
|
|
7
8
|
export { handlerUpload } from "./handler/handlerUpload.js";
|
|
8
9
|
export { handlerMetrics } from "./handler/handlerMetrics.js";
|
|
10
|
+
import oracledb from 'oracledb';
|
|
9
11
|
export { createServer, startServer, loadConfig, startServerConfig } from "./server/server.js";
|
|
File without changes
|