Skip to content

Commit 5c292fa

Browse files
committed
Latest test updates and new examples added
1 parent eb80b7a commit 5c292fa

File tree

5 files changed

+264
-7
lines changed

5 files changed

+264
-7
lines changed

examples/resultset3.js

Lines changed: 109 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,109 @@
1+
/* Copyright (c) 2024, Oracle and/or its affiliates. */
2+
3+
/******************************************************************************
4+
*
5+
* This software is dual-licensed to you under the Universal Permissive License
6+
* (UPL) 1.0 as shown at https://oss.oracle.com/licenses/upl and Apache License
7+
* 2.0 as shown at http://www.apache.org/licenses/LICENSE-2.0. You may choose
8+
* either license.
9+
*
10+
* If you elect to accept the software under the Apache License, Version 2.0,
11+
* the following applies:
12+
*
13+
* Licensed under the Apache License, Version 2.0 (the "License");
14+
* you may not use this file except in compliance with the License.
15+
* You may obtain a copy of the License at
16+
*
17+
* https://www.apache.org/licenses/LICENSE-2.0
18+
*
19+
* Unless required by applicable law or agreed to in writing, software
20+
* distributed under the License is distributed on an "AS IS" BASIS,
21+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
22+
* See the License for the specific language governing permissions and
23+
* limitations under the License.
24+
*
25+
* NAME
26+
* resultset3.js
27+
*
28+
* DESCRIPTION
29+
* Executes a query and uses a ResultSet to fetch batches of rows
30+
* with asyncIterator().
31+
*
32+
*****************************************************************************/
33+
34+
'use strict';
35+
36+
Error.stackTraceLimit = 50;
37+
38+
const oracledb = require('oracledb');
39+
const dbConfig = require('./dbconfig.js');
40+
const demoSetup = require('./demosetup.js');
41+
42+
// This example runs in both node-oracledb Thin and Thick modes.
43+
//
44+
// Optionally run in node-oracledb Thick mode
45+
if (process.env.NODE_ORACLEDB_DRIVER_MODE === 'thick') {
46+
47+
// Thick mode requires Oracle Client or Oracle Instant Client libraries.
48+
// On Windows and macOS Intel you can specify the directory containing the
49+
// libraries at runtime or before Node.js starts. On other platforms (where
50+
// Oracle libraries are available) the system library search path must always
51+
// include the Oracle library path before Node.js starts. If the search path
52+
// is not correct, you will get a DPI-1047 error. See the node-oracledb
53+
// installation documentation.
54+
let clientOpts = {};
55+
// On Windows and macOS Intel platforms, set the environment
56+
// variable NODE_ORACLEDB_CLIENT_LIB_DIR to the Oracle Client library path
57+
if (process.platform === 'win32' || (process.platform === 'darwin' && process.arch === 'x64')) {
58+
clientOpts = { libDir: process.env.NODE_ORACLEDB_CLIENT_LIB_DIR };
59+
}
60+
oracledb.initOracleClient(clientOpts); // enable node-oracledb Thick mode
61+
}
62+
63+
console.log(oracledb.thin ? 'Running in thin mode' : 'Running in thick mode');
64+
65+
async function run() {
66+
let connection;
67+
68+
try {
69+
connection = await oracledb.getConnection(dbConfig);
70+
71+
await demoSetup.setupBf(connection); // create the demo table
72+
73+
const result = await connection.execute(
74+
`SELECT id, farmer
75+
FROM no_banana_farmer
76+
ORDER BY id`,
77+
[], // no bind variables
78+
{
79+
resultSet: true // return a ResultSet (default is false)
80+
}
81+
);
82+
83+
// Fetch rows from the ResultSet using asyncIterator
84+
const rs = result.resultSet;
85+
86+
let rowCount = 0;
87+
console.log('Calling the asyncIterator for the resultSet object...');
88+
for await (const row of rs) {
89+
console.log(row);
90+
rowCount++;
91+
}
92+
console.log("Total rows in the resultset: " + rowCount + " rows");
93+
94+
// always close the ResultSet
95+
await rs.close();
96+
} catch (err) {
97+
console.error(err);
98+
} finally {
99+
if (connection) {
100+
try {
101+
await connection.close();
102+
} catch (err) {
103+
console.error(err);
104+
}
105+
}
106+
}
107+
}
108+
109+
run();

test/dbObject20.js

Lines changed: 113 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -868,9 +868,16 @@ describe('290. dbObject20.js', () => {
868868
const TYPE2 = 'NODB_TEST_INV_OBJ_TBL';
869869
const TYPE3 = 'NODB_TEST_INV_OBJ';
870870
const TYPE4 = 'NODB_TEST_INV_OBJ_TBL_VARCHAR';
871+
872+
// GH issue https://github.com/oracle/node-oracledb/issues/1646
873+
const TYPE5 = 'NODB_TEST_VARCHAR_CHAR';
874+
const TYPE6 = 'NODB_TEST_VARCHAR_BYTE';
875+
871876
const maxVarCharLen = 4;
872877
const maxVarNCharLen = 4;
873878
const maxVarRawLen = 10;
879+
const maxVarChar2CharLen = 100;
880+
const maxVarChar2ByteLen = 100;
874881

875882
before(async () => {
876883
conn = await oracledb.getConnection(dbConfig);
@@ -889,6 +896,12 @@ describe('290. dbObject20.js', () => {
889896
{ type: TYPE3, sql: `CREATE TYPE ${TYPE3} FORCE AS OBJECT (HEADER_ID NUMBER(5,2), TBL ${TYPE2})` },
890897
{
891898
type: TYPE4, sql: `CREATE OR REPLACE TYPE ${TYPE4} IS TABLE OF VARCHAR2 (${maxVarCharLen})`
899+
},
900+
{
901+
type: TYPE5, sql: `CREATE OR REPLACE TYPE ${TYPE5} IS TABLE OF VARCHAR2 (${maxVarChar2CharLen} CHAR)`
902+
},
903+
{
904+
type: TYPE6, sql: `CREATE OR REPLACE TYPE ${TYPE6} IS TABLE OF VARCHAR2 (${maxVarChar2ByteLen} BYTE)`
892905
}
893906
];
894907

@@ -900,6 +913,8 @@ describe('290. dbObject20.js', () => {
900913

901914
after(async () => {
902915
if (conn) {
916+
await testsUtil.dropType(conn, TYPE6);
917+
await testsUtil.dropType(conn, TYPE5);
903918
await testsUtil.dropType(conn, TYPE4);
904919
await testsUtil.dropType(conn, TYPE3);
905920
await testsUtil.dropType(conn, TYPE2);
@@ -1041,6 +1056,104 @@ describe('290. dbObject20.js', () => {
10411056
);
10421057
});
10431058

1059+
it('290.4.4 Verify table of VARCHAR2 with CHAR/BYTE specifier', async () => {
1060+
// Verify table of VARCHAR2 CHAR.
1061+
const dataChar = [
1062+
"1".repeat(maxVarChar2CharLen),
1063+
"A".repeat(maxVarChar2CharLen)
1064+
];
1065+
const charset = await testsUtil.getDBCharSet(conn);
1066+
const isUTF8Charset = (charset === "AL32UTF8");
1067+
if (isUTF8Charset) {
1068+
// push multi byte characters test...
1069+
dataChar.push("Ő".repeat(maxVarChar2CharLen));
1070+
dataChar.push("𠜎".repeat(maxVarChar2CharLen));
1071+
}
1072+
1073+
let pInClass = await conn.getDbObjectClass(TYPE5);
1074+
let pOutClass = await conn.getDbObjectClass(TYPE5);
1075+
let pInObj = new pInClass(dataChar);
1076+
let pOutObj = new pOutClass();
1077+
1078+
// create Procedure.
1079+
let PROC = 'nodb_proc_test2029044';
1080+
let createProc = `
1081+
CREATE OR REPLACE PROCEDURE ${PROC}
1082+
(a IN ${TYPE5}, b IN OUT ${TYPE5}) AS
1083+
BEGIN
1084+
b := a;
1085+
END;
1086+
`;
1087+
let result = await conn.execute(createProc);
1088+
1089+
// Call procedure.
1090+
let plsql = `BEGIN ${PROC} (:pIn, :pOut); END;`;
1091+
let bindVar = {
1092+
pIn: { val: pInObj, dir: oracledb.BIND_IN },
1093+
pOut: { val: pOutObj, dir: oracledb.BIND_INOUT },
1094+
};
1095+
result = await conn.execute(plsql, bindVar);
1096+
1097+
// Verify the result.
1098+
assert.strictEqual(JSON.stringify(dataChar), JSON.stringify(result.outBinds.pOut));
1099+
1100+
if (isUTF8Charset) {
1101+
// Check more than max characters allowed (utf-8 DB charset) but with-in max bytes.
1102+
dataChar.push("Ő".repeat(maxVarChar2CharLen + 1));
1103+
new pInClass(dataChar);
1104+
}
1105+
1106+
// Throw an error if number of characters exceed max bytes storage.
1107+
if (isUTF8Charset) {
1108+
dataChar.push("𠜎".repeat(maxVarChar2CharLen + 1));
1109+
} else {
1110+
dataChar.push("A".repeat(maxVarChar2CharLen + 1));
1111+
}
1112+
assert.throws(
1113+
() => new pInClass(dataChar),
1114+
/NJS-143:/
1115+
);
1116+
1117+
// Verify table of VARCHAR2 BYTE
1118+
const dataBytes = [
1119+
"1".repeat(maxVarChar2ByteLen),
1120+
"A".repeat(maxVarChar2ByteLen)
1121+
];
1122+
1123+
// create Procedure.
1124+
PROC = 'nodb_proc_test2029044_byte';
1125+
createProc = `
1126+
CREATE OR REPLACE PROCEDURE ${PROC}
1127+
(a IN ${TYPE6}, b IN OUT ${TYPE6}) AS
1128+
BEGIN
1129+
b := a;
1130+
END;
1131+
`;
1132+
result = await conn.execute(createProc);
1133+
pInClass = await conn.getDbObjectClass(TYPE6);
1134+
pOutClass = await conn.getDbObjectClass(TYPE6);
1135+
pInObj = new pInClass(dataBytes);
1136+
pOutObj = new pOutClass();
1137+
1138+
// Call procedure.
1139+
plsql = `BEGIN ${PROC} (:pIn, :pOut); END;`;
1140+
bindVar = {
1141+
pIn: { val: pInObj, dir: oracledb.BIND_IN },
1142+
pOut: { val: pOutObj, dir: oracledb.BIND_INOUT },
1143+
};
1144+
result = await conn.execute(plsql, bindVar);
1145+
1146+
// Verify the result.
1147+
assert.strictEqual(JSON.stringify(dataBytes), JSON.stringify(result.outBinds.pOut));
1148+
1149+
// Verify data larger than max size.
1150+
dataBytes.push("A".repeat(maxVarChar2ByteLen + 1));
1151+
assert.throws(
1152+
() => new pInClass(dataBytes),
1153+
/NJS-143:/
1154+
);
1155+
}); // 290.4.4
1156+
10441157
});
10451158

10461159
describe('290.5 Associative Arrays fetch ', function() {

test/list.txt

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -788,7 +788,7 @@ Overview of node-oracledb functional tests
788788
55.3 alternating getRow() & getRows() function
789789
55.3.1 result set
790790
55.3.2 REF Cursor
791-
55.4 automatically close result sets and LOBs when the connection is closed
791+
55.4 automatically close resultSets and LOBs when the connection is closed
792792
55.4.1 resultSet gets closed automatically
793793
55.4.2 REF Cursor gets closed automatically
794794
55.5 the content of resultSet should be consistent
@@ -805,12 +805,14 @@ Overview of node-oracledb functional tests
805805
55.8.1
806806
55.9 calls getRows() once and then close RS before getting more rows
807807
55.9.1
808-
55.10 result set with unsupported data types
808+
55.10 resultSet with unsupported data types
809809
55.10.1 INTERVAL YEAR TO MONTH data type
810810
55.11 bind a cursor BIND_INOUT
811811
55.11.1 has not supported binding a cursor with BIND_INOUT
812812
55.12 Invalid Ref Cursor
813813
55.12.1
814+
55.13 use Resultset asyncIterator
815+
55.13.1
814816

815817
56. fetchAs.js
816818
56.1 property value check
@@ -5627,6 +5629,7 @@ oracledb.OUT_FORMAT_OBJECT and resultSet = true
56275629
290.4.1 Invalid Values for nested property string
56285630
290.4.2 Invalid Values for different datatypes
56295631
290.4.3 Invalid Values for collection
5632+
290.4.4 Verify table of VARCHAR2 with CHAR/BYTE specifier
56305633

56315634
291. dbSchema.js
56325635
291.1 dbSchema and Annotations

test/resultSet2.js

Lines changed: 27 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -159,7 +159,7 @@ describe('55. resultSet2.js', function() {
159159

160160
}); // 55.3
161161

162-
describe('55.4 automatically close result sets and LOBs when the connection is closed', function() {
162+
describe('55.4 automatically close resultSets and LOBs when the connection is closed', function() {
163163
before(async function() {
164164
await setUp(connection, tableName);
165165
});
@@ -430,11 +430,11 @@ describe('55. resultSet2.js', function() {
430430
});
431431
}); // 55.9
432432

433-
describe('55.10 result set with unsupported data types', function() {
433+
describe('55.10 resultSet with unsupported data types', function() {
434434
it('55.10.1 INTERVAL YEAR TO MONTH data type', async function() {
435435
await assert.rejects(async () => {
436436
await connection.execute(
437-
"SELECT dummy, to_yminterval('1-3') FROM dual");
437+
"SELECT dummy, to_yminterval('1-3') FROM dual", [], { resultSet: true });
438438
}, /NJS-010:/);
439439
});
440440

@@ -475,7 +475,7 @@ describe('55. resultSet2.js', function() {
475475

476476
describe('55.12 Invalid Ref Cursor', function() {
477477
const proc =
478-
"CREATE OR REPLACE PROCEDURE get_invalid_refcur ( p OUT SYS_REFCURSOR) " +
478+
"CREATE OR REPLACE PROCEDURE get_invalid_refcur (p OUT SYS_REFCURSOR) " +
479479
" AS " +
480480
" BEGIN " +
481481
" NULL; " +
@@ -500,9 +500,31 @@ describe('55. resultSet2.js', function() {
500500
});
501501
}, /NJS-107:/);
502502

503-
}); // 55.12.1
503+
});
504504
}); // 55.12
505505

506+
describe('55.13 use Resultset asyncIterator', function() {
507+
before(async function() {
508+
await setUp(connection, tableName);
509+
});
510+
511+
after(async function() {
512+
await clearUp(connection, tableName);
513+
});
514+
515+
it('55.13.1 ', async function() {
516+
const result = await connection.execute(
517+
"SELECT * FROM nodb_rs2_emp ORDER BY employees_id",
518+
[],
519+
{ resultSet: true });
520+
const rs = result.resultSet;
521+
for await (const row of rs) {
522+
assert.strictEqual(row.length, 2);
523+
}
524+
await rs.close();
525+
});
526+
}); // 55.13
527+
506528
});
507529

508530

test/testsUtil.js

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -565,3 +565,13 @@ testsUtil.checkAndWait = async function(intervalWait, numIntervals, func) {
565565
err.totalTimeWaited = (intervalWait * numIntervals) / 1000;
566566
throw err;
567567
};
568+
569+
// function to return DBCHARSET
570+
testsUtil.getDBCharSet = async function(conn) {
571+
const res = await conn.execute(`
572+
select value
573+
from nls_database_parameters
574+
where parameter = 'NLS_CHARACTERSET'`
575+
);
576+
return res.rows[0][0];
577+
};

0 commit comments

Comments
 (0)