Skip to content

Commit 5a83cd1

Browse files
committed
First merge of named Oracle type query and binding support
1 parent 5e70c81 commit 5a83cd1

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

46 files changed

+10018
-1252
lines changed

CHANGELOG.md

Lines changed: 13 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -13,19 +13,30 @@
1313
- The string representation of classes has changed to `[Object Object]` as a consequence of using N-API. Use `Object.getPrototypeOf()` to get class information.
1414
- The C compiler required for building from source code no longer needs C++11 compatibility. The node-oracledb source code is now pure C.
1515

16+
- Added support for querying and binding Oracle Database objects and
17+
collections, see [Oracle Database Objects and
18+
Collections](https://oracle.github.io/node-oracledb/doc/api.html#objects).
19+
1620
- Oracle Advanced Queuing (AQ):
1721

1822
- Added support for "RAW" queues, allowing String and Buffer
1923
messages to be used.
2024

25+
- Added support for object queues, allowing Oracle Database object
26+
messages to be used.
27+
2128
- Added support for notifications with `oracledb.SUBSCR_NAMESPACE_AQ`.
2229

2330
- Added support for Implicit Results, allowing query results to be
2431
returned from PL/SQL without needing parameters or bind variables.
2532

26-
- Added
33+
- Added asynchronous method
2734
[`lob.getData()`](https://oracle.github.io/node-oracledb/doc/api.html#lobgetdata)
28-
to return data from a Lob instance.
35+
to return all data from a Lob readable stream.
36+
37+
- Added a new `dbTypeName` attribute to `extendedMetaData` output. It
38+
contains the name of the type the column has in the database, such
39+
as "VARCHAR2".
2940

3041
- Enhanced BIND_IN of PL/SQL Collection Associative Arrays (Index-by)
3142
so a bind definition object can be omitted (see

binding.gyp

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,7 @@
99
"src/njsAqQueue.c",
1010
"src/njsBaton.c",
1111
"src/njsConnection.c",
12+
"src/njsDbObject.c",
1213
"src/njsErrors.c",
1314
"src/njsLob.c",
1415
"src/njsModule.c",

doc/api.md

Lines changed: 1530 additions & 982 deletions
Large diffs are not rendered by default.

examples/README.md

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -51,6 +51,7 @@ File Name | Description
5151
----------------------------|----------------------------------------------------------------------------------
5252
aqoptions.js | Oracle Advanced Queuing (AQ) example setting options and message attributes
5353
aqmulti.js | Oracle Advanced Queuing (AQ) example passing multiple messages
54+
aqobject.js | Oracle Advanced Queuing (AQ) example passing an Oracle Database object
5455
aqraw.js | Basic Oracle Advanced Queuing (AQ) example passing text messages
5556
blobhttp.js | Simple web app that streams an image
5657
calltimeout.js | Shows how to cancel a SQL statement if it doesn't complete in a specified time
@@ -66,7 +67,7 @@ demo.sql | SQL script to create extra schema objects for the
6667
demodrop.sql | SQL script to drop the extra schema objects for the examples
6768
dmlrupd1.js | Example of DML RETURNING with a single row match
6869
dmlrupd2.js | Example of DML RETURNING where multiple rows are matched
69-
em_batcherrors.js | ``executeMany()`` example showing handling data errors
70+
em_batcherrors.js | `executeMany()` example showing handling data errors
7071
em_dmlreturn1.js | `executeMany()` example of DML RETURNING that returns single values
7172
em_dmlreturn2.js | `executeMany()` example of DML RETURNING that returns multiple values
7273
em_insert1.js | Array DML example using `executeMany()` with bind-by-name syntax
@@ -91,6 +92,7 @@ metadata.js | Shows the metadata available after executing SELEC
9192
plsqlarray.js | Examples of binding PL/SQL "INDEX BY" tables
9293
plsqlfunc.js | How to call a PL/SQL function
9394
plsqlproc.js | How to call a PL/SQL procedure
95+
plsqlrecord.js | Shows binding of PL/SQL RECORDS
9496
raw1.js | Shows using a Buffer to insert and select a RAW
9597
refcursor.js | Shows using a ResultSet to fetch rows from a REF CURSOR
9698
refcursortoquerystream.js | Converts a REF CURSOR returned from `execute()` to a query stream.
@@ -100,9 +102,12 @@ resultsettoquerystream.js | Converts a ResultSet returned from `execute()` int
100102
rowlimit.js | Shows ways to limit the number of records fetched by queries
101103
select1.js | Executes a basic query without using a connection pool or ResultSet
102104
select2.js | Executes queries to show array and object output formats
105+
selectgeometry.js | Insert and query Oracle Spatial geometries
103106
selectjson.js | Shows some JSON features of Oracle Database
104107
selectjsonblob.js | Shows how to use a BLOB as a JSON column store
108+
selectobject.js | Insert and query a named Oracle database object
105109
selectstream.js | Executes a basic query using a Readable Stream
110+
selectvarray.js | Shows inserting and selecting from a VARRAY column
106111
sessionfixup.js | Shows a pooled connection callback to efficiently set session state
107112
sessiontagging1.js | Simple pooled connection tagging for setting session state
108113
sessiontagging2.js | More complex example of pooled connection tagging for setting session state

examples/aqmulti.js

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -40,7 +40,7 @@ async function enq() {
4040

4141
try {
4242
connection = await oracledb.getConnection(dbConfig);
43-
let queue = connection.queue(queueName);
43+
const queue = await connection.queue(queueName);
4444
queue.enqOptions.visibility = oracledb.AQ_VISIBILITY_IMMEDIATE; // Send a message without requiring a commit
4545

4646
console.log('Enqueuing messages');
@@ -74,12 +74,12 @@ async function deq() {
7474

7575
try {
7676
connection = await oracledb.getConnection(dbConfig);
77-
const queue = connection.queue(queueName);
77+
const queue = await connection.queue(queueName);
7878
queue.deqOptions.visibility = oracledb.AQ_VISIBILITY_IMMEDIATE; // Change the visibility so no explicit commit is required
7979

8080
const messages = await queue.deqMany(5); // get at most 5 messages
8181
console.log("Dequeued " + messages.length + " messages");
82-
for (let msg of messages) {
82+
for (const msg of messages) {
8383
console.log(msg.payload.toString());
8484
}
8585

examples/aqobject.js

Lines changed: 94 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,94 @@
1+
/* Copyright (c) 2019, Oracle and/or its affiliates. All rights reserved. */
2+
3+
/******************************************************************************
4+
*
5+
* You may not use the identified files except in compliance with the Apache
6+
* License, Version 2.0 (the "License.")
7+
*
8+
* You may obtain a copy of the License at
9+
* http://www.apache.org/licenses/LICENSE-2.0.
10+
*
11+
* Unless required by applicable law or agreed to in writing, software
12+
* distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
13+
* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14+
*
15+
* See the License for the specific language governing permissions and
16+
* limitations under the License.
17+
*
18+
* NAME
19+
* aqobject.js
20+
*
21+
* DESCRIPTION
22+
* Oracle Advanced Queuing (AQ) example passing an Oracle Database object
23+
*
24+
* Before running this, a queue allowing an Oracle Database object
25+
* payloads must be created, see
26+
* https://oracle.github.io/node-oracledb/doc/api.html#aqobjexample
27+
*
28+
* This example requires node-oracledb 4 or later.
29+
*
30+
* This example uses Node 8's async/await syntax.
31+
*
32+
*****************************************************************************/
33+
34+
const oracledb = require('oracledb');
35+
const dbConfig = require('./dbconfig.js');
36+
37+
const queueName = "ADDR_QUEUE";
38+
39+
async function enq() {
40+
let connection;
41+
42+
// The message to send.
43+
// The attributes correspond to the USER_ADDRESS_TYPE fields.
44+
const addrData = {
45+
NAME: "scott",
46+
ADDRESS: "The Kennel"
47+
};
48+
49+
try {
50+
connection = await oracledb.getConnection(dbConfig);
51+
const queue = await connection.queue(queueName, {payloadType: "USER_ADDRESS_TYPE"});
52+
const message = new queue.payloadTypeClass(addrData);
53+
console.log('Enqueuing: ', addrData);
54+
await queue.enqOne(message);
55+
await connection.commit();
56+
} catch (err) {
57+
console.error(err);
58+
} finally {
59+
if (connection) {
60+
try {
61+
await connection.close();
62+
} catch (err) {
63+
console.error(err);
64+
}
65+
}
66+
}
67+
}
68+
69+
async function deq() {
70+
let connection;
71+
72+
try {
73+
connection = await oracledb.getConnection(dbConfig);
74+
const queue = await connection.queue(queueName, {payloadType: "USER_ADDRESS_TYPE"});
75+
const msg = await queue.deqOne(); // wait for a message
76+
await connection.commit();
77+
if (msg) {
78+
console.log('Dequeued: ', msg.payload);
79+
}
80+
} catch (err) {
81+
console.error(err);
82+
} finally {
83+
if (connection) {
84+
try {
85+
await connection.close();
86+
} catch (err) {
87+
console.error(err);
88+
}
89+
}
90+
}
91+
}
92+
93+
enq();
94+
deq();

examples/aqoptions.js

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -41,7 +41,7 @@ async function enq() {
4141
try {
4242
connection = await oracledb.getConnection(dbConfig);
4343

44-
let queue = connection.queue(queueName);
44+
const queue = await connection.queue(queueName);
4545
queue.enqOptions.visibility = oracledb.AQ_VISIBILITY_IMMEDIATE; // Send a message immediately without requiring a commit
4646

4747
const messageString = 'This is my other message';
@@ -70,7 +70,7 @@ async function deq() {
7070
try {
7171
connection = await oracledb.getConnection(dbConfig);
7272

73-
const queue = connection.queue(queueName);
73+
const queue = await connection.queue(queueName);
7474
Object.assign(
7575
queue.deqOptions,
7676
{

examples/aqraw.js

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -40,7 +40,7 @@ async function enq() {
4040

4141
try {
4242
connection = await oracledb.getConnection(dbConfig);
43-
let queue = connection.queue(queueName);
43+
const queue = await connection.queue(queueName);
4444
const messageString = 'This is my message';
4545
console.log('Enqueuing: ' + messageString);
4646
await queue.enqOne(messageString);
@@ -63,7 +63,7 @@ async function deq() {
6363

6464
try {
6565
connection = await oracledb.getConnection(dbConfig);
66-
const queue = connection.queue(queueName);
66+
const queue = await connection.queue(queueName);
6767
const msg = await queue.deqOne(); // wait for a message
6868
await connection.commit();
6969
if (msg) {

examples/plsqlrecord.js

Lines changed: 131 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,131 @@
1+
/* Copyright (c) 2019, Oracle and/or its affiliates. All rights reserved. */
2+
3+
/******************************************************************************
4+
*
5+
* You may not use the identified files except in compliance with the Apache
6+
* License, Version 2.0 (the "License.")
7+
*
8+
* You may obtain a copy of the License at
9+
* http://www.apache.org/licenses/LICENSE-2.0.
10+
*
11+
* Unless required by applicable law or agreed to in writing, software
12+
* distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
13+
* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14+
*
15+
* See the License for the specific language governing permissions and
16+
* limitations under the License.
17+
*
18+
* NAME
19+
* plsqlrecord.js
20+
*
21+
* DESCRIPTION
22+
* Shows binding of PL/SQL RECORDS
23+
*
24+
* This example requires node-oracledb 4 or later.
25+
*
26+
* This example uses Node 8's async/await syntax.
27+
*
28+
*****************************************************************************/
29+
30+
'use strict';
31+
32+
const oracledb = require('oracledb');
33+
const dbConfig = require('./dbconfig.js');
34+
35+
async function run() {
36+
let connection, binds, options, result, obj;
37+
38+
// The PL/SQL that is called in each example
39+
const plsql = `CALL rectest.myproc(:inbv, :outbv)`;
40+
41+
try {
42+
43+
connection = await oracledb.getConnection(dbConfig);
44+
45+
// Create a PL/SQL package that uses a RECORD
46+
47+
await connection.execute(
48+
`CREATE OR REPLACE PACKAGE rectest AS
49+
TYPE rectype IS RECORD (name VARCHAR2(40), pos NUMBER);
50+
PROCEDURE myproc (p_in IN rectype, p_out OUT rectype);
51+
END rectest;`);
52+
53+
await connection.execute(
54+
`CREATE OR REPLACE PACKAGE BODY rectest AS
55+
PROCEDURE myproc (p_in IN rectype, p_out OUT rectype) AS
56+
BEGIN
57+
p_out := p_in;
58+
p_out.pos := p_out.pos * 2;
59+
END;
60+
END rectest;`);
61+
62+
63+
// Get the RECORD prototype object
64+
65+
const RecTypeClass = await connection.getDbObjectClass("RECTEST.RECTYPE");
66+
// console.log(RecTypeClass.prototype);
67+
68+
69+
//
70+
// Single execution
71+
//
72+
73+
console.log('Using the constructor to create an object:');
74+
obj = new RecTypeClass({ NAME: 'Ship', POS: 12 });
75+
76+
binds = {
77+
inbv: obj,
78+
outbv: { type: RecTypeClass, dir: oracledb.BIND_OUT }
79+
};
80+
81+
result = await connection.execute(plsql, binds);
82+
console.log(result.outBinds.outbv);
83+
84+
console.log('\nBinding the record values directly:');
85+
86+
binds = {
87+
inbv: { type: RecTypeClass, val: { NAME: 'Plane', POS: 34 } },
88+
outbv: { type: RecTypeClass, dir: oracledb.BIND_OUT }
89+
};
90+
91+
result = await connection.execute(plsql, binds);
92+
console.log(result.outBinds.outbv);
93+
94+
//
95+
// executeMany()
96+
//
97+
98+
console.log('\nExample with executeMany():');
99+
100+
binds = [
101+
{ inbv: { NAME: 'Car', POS: 56 } },
102+
{ inbv: { NAME: 'Train', POS: 78 } },
103+
{ inbv: { NAME: 'Bike', POS: 83 } }
104+
];
105+
106+
options = {
107+
bindDefs: {
108+
inbv: { type: RecTypeClass },
109+
outbv: { type: RecTypeClass, dir: oracledb.BIND_OUT },
110+
}
111+
};
112+
113+
result = await connection.executeMany(plsql, binds, options);
114+
for (const b of result.outBinds) {
115+
console.log(b.outbv);
116+
}
117+
118+
} catch (err) {
119+
console.error(err);
120+
} finally {
121+
if (connection) {
122+
try {
123+
await connection.close();
124+
} catch (err) {
125+
console.error(err);
126+
}
127+
}
128+
}
129+
}
130+
131+
run();

0 commit comments

Comments
 (0)