diff --git a/javascript/node-oracledb/README.md b/javascript/node-oracledb/README.md index ed2262c8..964dec59 100644 --- a/javascript/node-oracledb/README.md +++ b/javascript/node-oracledb/README.md @@ -1,6 +1,6 @@ # Node-oracledb Examples -This directory contains [node-oracledb 4.0](https://www.npmjs.com/package/oracledb) examples. +This directory contains [node-oracledb 4.1](https://www.npmjs.com/package/oracledb) examples. The node-oracledb add-on for Node.js powers high performance Oracle Database applications. @@ -11,23 +11,15 @@ The node-oracledb add-on for Node.js powers high performance Oracle Database app Issues and questions about node-oracledb can be posted on [GitHub](https://github.com/oracle/node-oracledb/issues) or [Slack](https://node-oracledb.slack.com/) ([link to join -Slack](https://node-oracledb.slack.com/join/shared_invite/enQtNDU4Mjc2NzM5OTA2LTdkMzczODY3OGY3MGI0Yjk3NmQ4NDU4MTI2OGVjNTYzMjE5OGY5YzVkNDY4MWNkNjFiMDM2ZDMwOWRjNWVhNTg). +Slack](https://join.slack.com/t/node-oracledb/shared_invite/enQtNDU4Mjc2NzM5OTA2LWMzY2ZlZDY5MDdlMGZiMGRkY2IzYjI5OGU4YTEzZWM5YjQ3ODUzMjcxNWQyNzE4MzM5YjNkYjVmNDk5OWU5NDM). To run the examples: - [Install node-oracledb](https://oracle.github.io/node-oracledb/INSTALL.html#quickstart). -- Use `demo.sql` to create schema objects used by the samples. For - example, to load them in the HR schema run: - - ``` - sqlplus hr - SQL> @demo.sql - ``` - -- Edit `dbconfig.js` and set your username and the database -connection string: +- Edit `dbconfig.js` and set your username, password and the database +connection string, for example: ``` module.exports = { @@ -35,30 +27,23 @@ connection string: password: process.env.NODE_ORACLEDB_PASSWORD, connectString:"localhost/orclpdb1" }; - ``` -- Set the environment variable `NODE_ORACLEDB_PASSWORD` to your database schema password. - - On Windows: - ``` - set NODE_ORACLEDB_PASSWORD=... ``` - On Linux: - ``` - export NODE_ORACLEDB_PASSWORD=... - ``` + This reads the password from the environment variable + `NODE_ORACLEDB_PASSWORD`, which you must set before running + examples. -- Then run the samples like: +- Review the samples and then run them like: ``` - node select1.js + node example.js ``` -The demonstration objects can be dropped with `demodrop.sql`: +- After running example, the demonstration objects can be dropped with `demodrop.js`: ``` - sqlplus hr/welcome@localhost/orclpdb @demodrop.sql + node demodrop.js ``` ## Example Overview @@ -66,71 +51,71 @@ The demonstration objects can be dropped with `demodrop.sql`: If this is your first time with node-oracledb, start with [`example.js`](example.js). -File Name | Description -----------------------------|---------------------------------------------------------------------------------- -aqoptions.js | Oracle Advanced Queuing (AQ) example setting options and message attributes -aqmulti.js | Oracle Advanced Queuing (AQ) example passing multiple messages -aqobject.js | Oracle Advanced Queuing (AQ) example passing an Oracle Database object -aqraw.js | Basic Oracle Advanced Queuing (AQ) example passing text messages -blobhttp.js | Simple web app that streams an image -calltimeout.js | Shows how to cancel a SQL statement if it doesn't complete in a specified time -connect.js | Basic example for creating a standalone (non-pooled) connection -connectionpool.js | Basic example creating a pool of connections -cqn1.js | Basic Continuous Query Notification (CQN) example -cqn2.js | Continuous Query Notification with notification grouping -date.js | Show some DATE and TIMESTAMP behaviors -dbconfig.js | Common file used by examples for setting connection credentials -dbmsoutputgetline.js | Show fetching DBMS_OUTPUT by binding buffers -dbmsoutputpipe.js | Show fetching DBMS_OUTPUT by using a pipelined table -demo.sql | SQL script to create extra schema objects for the examples -demodrop.sql | SQL script to drop the extra schema objects for the examples -dmlrupd1.js | Example of DML RETURNING with a single row match -dmlrupd2.js | Example of DML RETURNING where multiple rows are matched -em_batcherrors.js | `executeMany()` example showing handling data errors -em_dmlreturn1.js | `executeMany()` example of DML RETURNING that returns single values -em_dmlreturn2.js | `executeMany()` example of DML RETURNING that returns multiple values -em_insert1.js | Array DML example using `executeMany()` with bind-by-name syntax -em_insert2.js | Array DML example using `executeMany()` with bind by position -em_plsql.js | `executeMany()` example calling PL/SQL multiple times with one call -em_rowcounts.js | `executeMany()` example showing how to find the number of rows affected by each input row -endtoend.js | Example showing setting tracing attributes -example.js | Basic example showing creating a table, inserting multiple rows, and querying rows -fetchinfo.js | Show how numbers and dates can be returned as strings using `fetchAsString` and `fetchInfo` -impres.js | Shows PL/SQL 'Implict Results' returning multiple query results from PL/SQL code. -insert1.js | Basic example creating a table and inserting data. Shows DDL and DML -insert2.js | Basic example showing auto commit behavior -lobbinds.js | Demonstrates how to bind and query LOBs -lobinsert1.js | Shows inserting a file into a CLOB column -lobinsert2.js | Inserts text into a CLOB column using the RETURNING INTO method. -lobinserttemp.js | Writes data to a Temporary CLOB and then inserts it into the database -lobplsqltemp.js | Streams data into a Temporary CLOB and then passes it to PL/SQL -lobselect.js | Shows basic, non-streaming CLOB and BLOB queries -lobstream1.js | Shows how to stream LOBs to files -lobstream2.js | Shows using Stream data events to fetch a CLOB -metadata.js | Shows the metadata available after executing SELECT statements -plsqlarray.js | Examples of binding PL/SQL "INDEX BY" tables -plsqlfunc.js | How to call a PL/SQL function -plsqlproc.js | How to call a PL/SQL procedure -plsqlrecord.js | Shows binding of PL/SQL RECORDS -plsqlvarrayrecord.js | Shows binding a VARRAY of RECORD in PL/SQL -raw1.js | Shows using a Buffer to insert and select a RAW -refcursor.js | Shows using a ResultSet to fetch rows from a REF CURSOR -refcursortoquerystream.js | Converts a REF CURSOR returned from `execute()` to a query stream. -resultset1.js | Executes a query and uses a ResultSet to fetch rows with `getRow()` -resultset2.js | Executes a query and uses a ResultSet to fetch batches of rows with `getRows()` -resultsettoquerystream.js | Converts a ResultSet returned from `execute()` into a Readable Stream. -rowlimit.js | Shows ways to limit the number of records fetched by queries -select1.js | Executes a basic query without using a connection pool or ResultSet -select2.js | Executes queries to show array and object output formats -selectgeometry.js | Insert and query Oracle Spatial geometries -selectjson.js | Shows some JSON features of Oracle Database -selectjsonblob.js | Shows how to use a BLOB as a JSON column store -selectobject.js | Insert and query a named Oracle database object -selectstream.js | Executes a basic query using a Readable Stream -selectvarray.js | Shows inserting and selecting from a VARRAY column -sessionfixup.js | Shows a pooled connection callback to efficiently set session state -sessiontagging1.js | Simple pooled connection tagging for setting session state -sessiontagging2.js | More complex example of pooled connection tagging for setting session state -soda1.js | Basic Simple Oracle Document Access (SODA) example -version.js | Shows the node-oracledb version attributes -webappawait.js | A simple web application using a connection pool +File Name | Description +----------------------------------------------------------|---------------------------------------------------------------------------------- +[`aqmulti.js`](aqmulti.js) | Oracle Advanced Queuing (AQ) example passing multiple messages +[`aqobject.js`](aqobject.js) | Oracle Advanced Queuing (AQ) example passing an Oracle Database object +[`aqoptions.js`](aqoptions.js) | Oracle Advanced Queuing (AQ) example setting options and message attributes +[`aqraw.js`](aqraw.js) | Basic Oracle Advanced Queuing (AQ) example passing text messages +[`blobhttp.js`](blobhttp.js) | Simple web app that streams an image +[`calltimeout.js`](calltimeout.js) | Shows how to cancel a SQL statement if it doesn't complete in a specified time +[`connect.js`](connect.js) | Basic example for creating a standalone (non-pooled) connection +[`connectionpool.js`](connectionpool.js) | Basic example creating a pool of connections +[`cqn1.js`](cqn1.js) | Basic Continuous Query Notification (CQN) example +[`cqn2.js`](cqn2.js) | Continuous Query Notification with notification grouping +[`date.js`](date.js) | Show some DATE and TIMESTAMP behaviors +[`dbconfig.js`](dbconfig.js) | Common file used by examples for setting connection credentials +[`dbmsoutputgetline.js`](dbmsoutputgetline.js) | Show fetching DBMS_OUTPUT by binding buffers +[`dbmsoutputpipe.js`](dbmsoutputpipe.js) | Show fetching DBMS_OUTPUT by using a pipelined table +[`demodrop.js`](demodrop.js) | Drops the schema objects created by the examples +[`demosetup.js`](demosetup.js) | Used to create common schema objects for the examples +[`dmlrupd1.js`](dmlrupd1.js) | Example of DML RETURNING with a single row match +[`dmlrupd2.js`](dmlrupd2.js) | Example of DML RETURNING where multiple rows are matched +[`em_batcherrors.js`](em_batcherrors.js) | `executeMany()` example showing handling data errors +[`em_dmlreturn1.js`](em_dmlreturn1.js) | `executeMany()` example of DML RETURNING that returns single values +[`em_dmlreturn2.js`](em_dmlreturn2.js) | `executeMany()` example of DML RETURNING that returns multiple values +[`em_insert1.js`](em_insert1.js) | Array DML example using `executeMany()` with bind-by-name syntax +[`em_insert2.js`](em_insert2.js) | Array DML example using `executeMany()` with bind by position +[`em_plsql.js`](em_plsql.js) | `executeMany()` example calling PL/SQL multiple times with one call +[`em_rowcounts.js`](em_rowcounts.js) | `executeMany()` example showing how to find the number of rows affected by each input row +[`endtoend.js`](endtoend.js) | Example showing setting tracing attributes +[`example.js`](example.js) | Basic example showing creating a table, inserting multiple rows, and querying rows +[`fetchinfo.js`](fetchinfo.js) | Show how numbers and dates can be returned as strings using `fetchAsString` and `fetchInfo` +[`impres.js`](impres.js) | Shows PL/SQL 'Implict Results' returning multiple query results from PL/SQL code. +[`insert1.js`](insert1.js) | Basic example creating a table and inserting data. Shows DDL and DML +[`insert2.js`](insert2.js) | Basic example showing auto commit behavior +[`lobbinds.js`](lobbinds.js) | Demonstrates how to bind and query LOBs +[`lobinsert1.js`](lobinsert1.js) | Shows inserting a file into a CLOB column +[`lobinsert2.js`](lobinsert2.js) | Inserts text into a CLOB column using the RETURNING INTO method. +[`lobinserttemp.js`](lobinserttemp.js) | Writes data to a Temporary CLOB and then inserts it into the database +[`lobplsqltemp.js`](lobplsqltemp.js) | Streams data into a Temporary CLOB and then passes it to PL/SQL +[`lobselect.js`](lobselect.js) | Shows basic, non-streaming CLOB and BLOB queries +[`lobstream1.js`](lobstream1.js) | Shows how to stream LOBs to files +[`lobstream2.js`](lobstream2.js) | Shows using Stream data events to fetch a CLOB +[`metadata.js`](metadata.js) | Shows the metadata available after executing SELECT statements +[`plsqlarray.js`](plsqlarray.js) | Examples of binding PL/SQL "INDEX BY" tables +[`plsqlfunc.js`](plsqlfunc.js) | How to call a PL/SQL function +[`plsqlproc.js`](plsqlproc.js) | How to call a PL/SQL procedure +[`plsqlrecord.js`](plsqlrecord.js) | Shows binding of PL/SQL RECORDS +[`plsqlvarrayrecord.js`](plsqlvarrayrecord.js) | Shows binding a VARRAY of RECORD in PL/SQL +[`raw.js`](raw.js) | Shows using a Buffer to insert and select a RAW +[`refcursor.js`](refcursor.js) | Shows using a ResultSet to fetch rows from a REF CURSOR +[`refcursortoquerystream.js`](refcursortoquerystream.js) | Converts a REF CURSOR returned from `execute()` to a query stream. +[`resultset1.js`](resultset1.js) | Executes a query and uses a ResultSet to fetch rows with `getRow()` +[`resultset2.js`](resultset2.js) | Executes a query and uses a ResultSet to fetch batches of rows with `getRows()` +[`resultsettoquerystream.js`](resultsettoquerystream.js) | Converts a ResultSet returned from `execute()` into a Readable Stream. +[`rowlimit.js`](rowlimit.js) | Shows ways to limit the number of records fetched by queries +[`select1.js`](select1.js) | Executes a basic query without using a connection pool or ResultSet +[`select2.js`](select2.js) | Executes queries to show array and object output formats +[`selectgeometry.js`](selectgeometry.js) | Insert and query Oracle Spatial geometries +[`selectjson.js`](selectjson.js) | Shows some JSON features of Oracle Database +[`selectjsonblob.js`](selectjsonblob.js) | Shows how to use a BLOB as a JSON column store +[`selectobject.js`](selectobject.js) | Insert and query a named Oracle database object +[`selectstream.js`](selectstream.js) | Executes a basic query using a Readable Stream +[`selectvarray.js`](selectvarray.js) | Shows inserting and selecting from a VARRAY column +[`sessionfixup.js`](sessionfixup.js) | Shows a pooled connection callback to efficiently set session state +[`sessiontagging1.js`](sessiontagging1.js) | Simple pooled connection tagging for setting session state +[`sessiontagging2.js`](sessiontagging2.js) | More complex example of pooled connection tagging for setting session state +[`soda1.js`](soda1.js) | Basic Simple Oracle Document Access (SODA) example +[`version.js`](version.js) | Shows the node-oracledb version attributes +[`webappawait.js`](webappawait.js) | A simple web application using a connection pool diff --git a/javascript/node-oracledb/aqmulti.js b/javascript/node-oracledb/aqmulti.js index ff38797d..9f367e73 100644 --- a/javascript/node-oracledb/aqmulti.js +++ b/javascript/node-oracledb/aqmulti.js @@ -77,6 +77,8 @@ async function deq() { const queue = await connection.getQueue(queueName); queue.deqOptions.visibility = oracledb.AQ_VISIBILITY_IMMEDIATE; // Change the visibility so no explicit commit is required + console.log('Dequeuing messages'); + const messages = await queue.deqMany(5); // get at most 5 messages console.log("Dequeued " + messages.length + " messages"); for (const msg of messages) { diff --git a/javascript/node-oracledb/aqobject.js b/javascript/node-oracledb/aqobject.js index 82fc5c4c..4afccdad 100644 --- a/javascript/node-oracledb/aqobject.js +++ b/javascript/node-oracledb/aqobject.js @@ -22,7 +22,7 @@ * Oracle Advanced Queuing (AQ) example passing an Oracle Database object * * Before running this, a queue allowing an Oracle Database object - * payloads must be created, see + * payload must be created, see * https://oracle.github.io/node-oracledb/doc/api.html#aqobjexample * * This example requires node-oracledb 4 or later. diff --git a/javascript/node-oracledb/blobhttp.js b/javascript/node-oracledb/blobhttp.js index a128d177..e6e1c0f6 100644 --- a/javascript/node-oracledb/blobhttp.js +++ b/javascript/node-oracledb/blobhttp.js @@ -22,12 +22,6 @@ * Listens for an HTTP request and returns an image queried from a BLOB column * Also shows the connection pool's caching using a 'default' pool. * - * Use demo.sql to create the required table or do: - * DROP TABLE mylobs; - * CREATE TABLE mylobs (id NUMBER, c CLOB, b BLOB); - * - * Run lobinsert1.js to load an image before running this example. - * * Start the listener with 'node blobhttp.js' and then use a browser * to load http://localhost:7000/getimage * @@ -35,25 +29,26 @@ * *****************************************************************************/ -var url = require('url'); -var http = require('http'); -var oracledb = require('oracledb'); -var dbConfig = require('./dbconfig.js'); +const url = require('url'); +const http = require('http'); +const oracledb = require('oracledb'); +const dbConfig = require('./dbconfig.js'); +const demoSetup = require('./demosetup.js'); -var httpPort = 7000; +const httpPort = 7000; // Main entry point. Creates a connection pool which becomes the // 'default' pool, and then creates an HTTP server. async function init() { try { - await oracledb.createPool( - { - user: dbConfig.user, - password: dbConfig.password, - connectString: dbConfig.connectString - }); + await oracledb.createPool(dbConfig); console.log('Connection pool started'); + // create the demo table + const connection = await oracledb.getConnection(); + await demoSetup.setupLobs(connection, true); + await connection.close(); + // Create HTTP server and listen on port httpPort const server = http.createServer(); server.on('error', (err) => { @@ -63,7 +58,7 @@ async function init() { handleRequest(request, response); }); await server.listen(httpPort); - console.log("Server running. Try requesting: http://localhost:" + httpPort + "/getimage"); + console.log("Server is running. Try loading http://localhost:" + httpPort + "/getimage"); } catch (err) { console.error('init() error: ' + err.message); @@ -84,14 +79,14 @@ async function handleRequest(request, response) { connection = await oracledb.getConnection(); // gets a connection from the 'default' connection pool const result = await connection.execute( - "SELECT b FROM mylobs WHERE id = :id", // get the image + "SELECT b FROM no_lobs WHERE id = :id", // get the image { id: 2 } ); if (result.rows.length === 0) { - throw new Error("No results. Did you run lobinsert1.js?"); + throw new Error("No data selected from table."); } - var lob = result.rows[0][0]; + const lob = result.rows[0][0]; if (lob === null) { throw new Error("BLOB was NULL"); } @@ -117,6 +112,7 @@ async function handleRequest(request, response) { } catch (err) { console.error(err); + await closePoolAndExit(); } finally { if (connection) { try { @@ -137,9 +133,9 @@ async function closePoolAndExit() { console.log('\nTerminating'); try { // Get the pool from the pool cache and close it when no - // connections are in use, or force it closed after 10 seconds + // connections are in use, or force it closed after 2 seconds // If this hangs, you may need DISABLE_OOB=ON in a sqlnet.ora file - await oracledb.getPool().close(10); + await oracledb.getPool().close(2); console.log('Pool closed'); process.exit(0); } catch(err) { diff --git a/javascript/node-oracledb/calltimeout.js b/javascript/node-oracledb/calltimeout.js index 28d96578..318eb682 100755 --- a/javascript/node-oracledb/calltimeout.js +++ b/javascript/node-oracledb/calltimeout.js @@ -22,8 +22,8 @@ * Shows how to time out long running database calls. * See https://oracle.github.io/node-oracledb/doc/api.html#dbcalltimeouts * - * This example requires node-oracledb 3 or later. - * Node-oracledb must be using Oracle Client 18c libraries, or greater. + * This example requires node-oracledb 3 (or later) and Oracle Client 18c + * libraries (or later). * * This example uses Node 8's async/await syntax. * @@ -40,6 +40,11 @@ async function run() { let connection; try { + + if (oracledb.oracleClientVersion < 1800000000) { + throw new Error("Oracle Client libraries must be 18c or later"); + } + connection = await oracledb.getConnection(dbConfig); connection.callTimeout = timeout * 1000; // milliseconds @@ -66,4 +71,14 @@ async function run() { } } +process + .on('SIGTERM', function() { + console.log("\nTerminating"); + process.exit(0); + }) + .on('SIGINT', function() { + console.log("\nTerminating"); + process.exit(0); + }); + run(); diff --git a/javascript/node-oracledb/connectionpool.js b/javascript/node-oracledb/connectionpool.js index 16c3d93f..0dd4671c 100644 --- a/javascript/node-oracledb/connectionpool.js +++ b/javascript/node-oracledb/connectionpool.js @@ -45,7 +45,7 @@ async function init() { password: dbConfig.password, connectString: dbConfig.connectString // edition: 'ORA$BASE', // used for Edition Based Redefintion - // events: true, // whether to handle Oracle Database FAN and RLB events or support CQN + // events: false, // whether to handle Oracle Database FAN and RLB events or support CQN // externalAuth: false, // whether connections should be established using External Authentication // homogeneous: true, // all connections in the pool have the same credentials // poolAlias: 'default', // set an alias to allow access to the pool via a name. diff --git a/javascript/node-oracledb/cqn1.js b/javascript/node-oracledb/cqn1.js index 86498dd4..2a85bbb3 100644 --- a/javascript/node-oracledb/cqn1.js +++ b/javascript/node-oracledb/cqn1.js @@ -27,7 +27,7 @@ * * Run this script and when the subscription has been created, run * these statements in a SQL*Plus session: - * INSERT INTO CQNTABLE VALUES (101); + * INSERT INTO NO_CQNTABLE VALUES (101); * COMMIT; * * This example requires node-oracledb 2.3 or later. @@ -81,20 +81,40 @@ function myCallback(message) const options = { callback : myCallback, - sql: "SELECT * FROM cqntable WHERE k > :bv", + sql: `SELECT * FROM no_cqntable WHERE k > :bv`, binds: { bv : 100 }, timeout : 60, // Stop after 60 seconds + // ipAddress: '127.0.0.1', // SUBSCR_QOS_QUERY: generate notifications when rows with k > 100 are changed // SUBSCR_QOS_ROWIDS: Return ROWIDs in the notification message qos : oracledb.SUBSCR_QOS_QUERY | oracledb.SUBSCR_QOS_ROWIDS }; +async function setup(connection) { + const stmts = [ + `DROP TABLE no_cqntable`, + + `CREATE TABLE no_cqntable (k NUMBER)` + ]; + + for (const s of stmts) { + try { + await connection.execute(s); + } catch(e) { + if (e.errorNum != 942) + console.error(e); + } + } +} + async function runTest() { let connection; try { connection = await oracledb.getConnection(dbConfig); + await setup(connection); + await connection.subscribe('mysub', options); console.log("Subscription created..."); diff --git a/javascript/node-oracledb/cqn2.js b/javascript/node-oracledb/cqn2.js index b33d2da4..5970d244 100644 --- a/javascript/node-oracledb/cqn2.js +++ b/javascript/node-oracledb/cqn2.js @@ -28,7 +28,7 @@ * * Run this script and when the subscription has been created, run * these statements in a SQL*Plus session: - * INSERT INTO CQNTABLE VALUES (1); + * INSERT INTO NO_CQNTABLE VALUES (1); * COMMIT; * * This example requires node-oracledb 2.3 or later. @@ -40,7 +40,7 @@ const oracledb = require("oracledb"); const dbConfig = require('./dbconfig.js'); -// dbConfig.events = true; // CQN needs events mode, which is true by default in 4.0 +dbConfig.events = true; // CQN needs events mode const interval = setInterval(function() { console.log("waiting..."); @@ -77,7 +77,8 @@ function myCallback(message) const options = { callback : myCallback, - sql: "SELECT * FROM cqntable", + sql: "SELECT * FROM no_cqntable", + // ipAddress: '127.0.0.1', // Stop after 60 seconds timeout : 60, // Return ROWIDs in the notification message @@ -89,12 +90,31 @@ const options = { groupingType : oracledb.SUBSCR_GROUPING_TYPE_SUMMARY }; +async function setup(connection) { + const stmts = [ + `DROP TABLE no_cqntable`, + + `CREATE TABLE no_cqntable (k NUMBER)` + ]; + + for (const s of stmts) { + try { + await connection.execute(s); + } catch(e) { + if (e.errorNum != 942) + console.error(e); + } + } +} + async function runTest() { let connection; try { connection = await oracledb.getConnection(dbConfig); + await setup(connection); + await connection.subscribe('mysub', options); console.log("Subscription created..."); diff --git a/javascript/node-oracledb/date.js b/javascript/node-oracledb/date.js index 7ef55ee8..a6fb3a54 100644 --- a/javascript/node-oracledb/date.js +++ b/javascript/node-oracledb/date.js @@ -47,32 +47,32 @@ async function run() { connection = await oracledb.getConnection(dbConfig); console.log('Creating table'); - await connection.execute( - `BEGIN - DECLARE - e_table_exists EXCEPTION; - PRAGMA EXCEPTION_INIT(e_table_exists, -00942); - BEGIN - EXECUTE IMMEDIATE ('DROP TABLE datetest'); - EXCEPTION - WHEN e_table_exists - THEN NULL; - END; - END;`); - - await connection.execute( - `CREATE TABLE datetest( + + const stmts = [ + `DROP TABLE no_datetab`, + + `CREATE TABLE no_datetab( id NUMBER, timestampcol TIMESTAMP, timestamptz TIMESTAMP WITH TIME ZONE, timestampltz TIMESTAMP WITH LOCAL TIME ZONE, - datecol DATE)`); + datecol DATE)` + ]; + + for (const s of stmts) { + try { + await connection.execute(s); + } catch(e) { + if (e.errorNum != 942) + console.error(e); + } + } // When bound, JavaScript Dates are inserted using TIMESTAMP WITH LOCAL TIMEZONE date = new Date(); console.log('Inserting JavaScript date: ' + date); result = await connection.execute( - `INSERT INTO datetest (id, timestampcol, timestamptz, timestampltz, datecol) + `INSERT INTO no_datetab (id, timestampcol, timestamptz, timestampltz, datecol) VALUES (1, :ts, :tstz, :tsltz, :td)`, { ts: date, tstz: date, tsltz: date, td: date }); console.log('Rows inserted: ' + result.rowsAffected ); @@ -81,7 +81,7 @@ async function run() { result = await connection.execute( `SELECT id, timestampcol, timestamptz, timestampltz, datecol, TO_CHAR(CURRENT_DATE, 'DD-Mon-YYYY HH24:MI') AS CD - FROM datetest + FROM no_datetab ORDER BY id`); console.log(result.rows); @@ -91,7 +91,7 @@ async function run() { date = new Date(); console.log('Inserting JavaScript date: ' + date); result = await connection.execute( - `INSERT INTO datetest (id, timestampcol, timestamptz, timestampltz, datecol) + `INSERT INTO no_datetab (id, timestampcol, timestamptz, timestampltz, datecol) VALUES (2, :ts, :tstz, :tsltz, :td)`, { ts: date, tstz: date, tsltz: date, td: date }); console.log('Rows inserted: ' + result.rowsAffected ); @@ -100,7 +100,7 @@ async function run() { result = await connection.execute( `SELECT id, timestampcol, timestamptz, timestampltz, datecol, TO_CHAR(CURRENT_DATE, 'DD-Mon-YYYY HH24:MI') AS CD - FROM datetest + FROM no_datetab ORDER BY id`); console.log(result.rows); diff --git a/javascript/node-oracledb/dbmsoutputpipe.js b/javascript/node-oracledb/dbmsoutputpipe.js index f8add484..1bf4154f 100644 --- a/javascript/node-oracledb/dbmsoutputpipe.js +++ b/javascript/node-oracledb/dbmsoutputpipe.js @@ -20,23 +20,6 @@ * * DESCRIPTION * Displays PL/SQL DBMS_OUTPUT using a pipelined table. - * Use demo.sql to create the dependencies or do: - * - * CREATE OR REPLACE TYPE dorow AS TABLE OF VARCHAR2(32767); - * / - * SHOW ERRORS - * - * CREATE OR REPLACE FUNCTION mydofetch RETURN dorow PIPELINED IS - * line VARCHAR2(32767); - * status INTEGER; - * BEGIN LOOP - * DBMS_OUTPUT.GET_LINE(line, status); - * EXIT WHEN status = 1; - * PIPE ROW (line); - * END LOOP; - * END; - * / - * SHOW ERRORS * * This example uses Node 8's async/await syntax. * @@ -52,6 +35,38 @@ async function run() { try { connection = await oracledb.getConnection(dbConfig); + // + // Setup + // + + const stmts = [ + `CREATE OR REPLACE TYPE no_dorow AS TABLE OF VARCHAR2(32767)`, + + `CREATE OR REPLACE FUNCTION no_dofetch RETURN no_dorow PIPELINED IS + line VARCHAR2(32767); + status INTEGER; + BEGIN LOOP + DBMS_OUTPUT.GET_LINE(line, status); + EXIT WHEN status = 1; + PIPE ROW (line); + END LOOP; + END;` + + ]; + + for (const s of stmts) { + try { + await connection.execute(s); + } catch(e) { + if (e.errorNum != 942) + console.error(e); + } + } + + // + // Show DBMS_OUTPUT + // + await connection.execute( `BEGIN DBMS_OUTPUT.ENABLE(NULL); @@ -64,7 +79,7 @@ async function run() { END;`); const result = await connection.execute( - `SELECT * FROM TABLE(mydofetch())`); + `SELECT * FROM TABLE(no_dofetch())`); console.log(result.rows); } catch (err) { diff --git a/javascript/node-oracledb/demo.sql b/javascript/node-oracledb/demo.sql deleted file mode 100644 index 2d08ed64..00000000 --- a/javascript/node-oracledb/demo.sql +++ /dev/null @@ -1,262 +0,0 @@ -/* Copyright (c) 2015, 2018, Oracle and/or its affiliates. All rights reserved. */ - -/****************************************************************************** - * - * You may not use the identified files except in compliance with the Apache - * License, Version 2.0 (the "License.") - * - * You may obtain a copy of the License at - * http://www.apache.org/licenses/LICENSE-2.0. - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT - * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * - * See the License for the specific language governing permissions and - * limitations under the License. - * - * NAME - * demo.sql - * - * DESCRIPTION - * Create database objects for the examples in your database user account. - * - * The video https://www.youtube.com/watch?v=WDJacg0NuLo - * shows how to create a new database user. - * - * Scripts to create Oracle Database's traditional sample schemas can - * be found at: https://github.com/oracle/db-sample-schemas - * - *****************************************************************************/ - -SET ECHO ON - --- For plsqlproc.js example for bind parameters -CREATE OR REPLACE PROCEDURE testproc (p_in IN VARCHAR2, p_inout IN OUT VARCHAR2, p_out OUT NUMBER) -AS -BEGIN - p_inout := p_in || p_inout; - p_out := 101; -END; -/ -SHOW ERRORS - --- For plsqlfunc.js example on calling a PL/SQL function -CREATE OR REPLACE FUNCTION testfunc (p1_in IN VARCHAR2, p2_in IN VARCHAR2) RETURN VARCHAR2 -AS -BEGIN - RETURN p1_in || p2_in; -END; -/ -SHOW ERRORS - --- For refcursor.js example of REF CURSORS -CREATE OR REPLACE PROCEDURE get_emp_rs (p_sal IN NUMBER, p_recordset OUT SYS_REFCURSOR) -AS -BEGIN - OPEN p_recordset FOR - SELECT first_name, salary, hire_date - FROM employees - WHERE salary > p_sal; -END; -/ -SHOW ERRORS - --- For plsqlarray.js example for PL/SQL 'INDEX BY' array binds -BEGIN EXECUTE IMMEDIATE 'DROP TABLE waveheight'; EXCEPTION WHEN OTHERS THEN IF SQLCODE <> -942 THEN RAISE; END IF; END; -/ - -CREATE TABLE waveheight (beach VARCHAR2(50), depth NUMBER); - -CREATE OR REPLACE PACKAGE beachpkg IS - TYPE beachType IS TABLE OF VARCHAR2(30) INDEX BY BINARY_INTEGER; - TYPE depthType IS TABLE OF NUMBER INDEX BY BINARY_INTEGER; - PROCEDURE array_in(beaches IN beachType, depths IN depthType); - PROCEDURE array_out(beaches OUT beachType, depths OUT depthType); - PROCEDURE array_inout(beaches IN OUT beachType, depths IN OUT depthType); -END; -/ -SHOW ERRORS - -CREATE OR REPLACE PACKAGE BODY beachpkg IS - - -- Insert array values into a table - PROCEDURE array_in(beaches IN beachType, depths IN depthType) IS - BEGIN - IF beaches.COUNT <> depths.COUNT THEN - RAISE_APPLICATION_ERROR(-20000, 'Array lengths must match for this example.'); - END IF; - FORALL i IN INDICES OF beaches - INSERT INTO waveheight (beach, depth) VALUES (beaches(i), depths(i)); - END; - - -- Return the values from a table - PROCEDURE array_out(beaches OUT beachType, depths OUT depthType) IS - BEGIN - SELECT beach, depth BULK COLLECT INTO beaches, depths FROM waveheight; - END; - - -- Return the arguments sorted - PROCEDURE array_inout(beaches IN OUT beachType, depths IN OUT depthType) IS - BEGIN - IF beaches.COUNT <> depths.COUNT THEN - RAISE_APPLICATION_ERROR(-20001, 'Array lengths must match for this example.'); - END IF; - FORALL i IN INDICES OF beaches - INSERT INTO waveheight (beach, depth) VALUES (beaches(i), depths(i)); - SELECT beach, depth BULK COLLECT INTO beaches, depths FROM waveheight ORDER BY 1; - END; - -END; -/ -SHOW ERRORS - --- For selectjson.js example of JSON datatype. Requires Oracle Database 12.1.0.2 -BEGIN EXECUTE IMMEDIATE 'DROP TABLE j_purchaseorder'; EXCEPTION WHEN OTHERS THEN IF SQLCODE <> -942 THEN RAISE; END IF; END; -/ - --- Note if your applications always insert valid JSON, you may delete --- the IS JSON check to remove its additional validation overhead. -CREATE TABLE j_purchaseorder (po_document VARCHAR2(4000) CHECK (po_document IS JSON)); - --- For selectjsonblob.js example of JSON datatype. Requires Oracle Database 12.1.0.2 -BEGIN EXECUTE IMMEDIATE 'DROP TABLE j_purchaseorder_b'; EXCEPTION WHEN OTHERS THEN IF SQLCODE <> -942 THEN RAISE; END IF; END; -/ -CREATE TABLE j_purchaseorder_b (po_document BLOB CHECK (po_document IS JSON)) LOB (po_document) STORE AS (CACHE); - --- For DML RETURNING aka RETURNING INTO examples -BEGIN EXECUTE IMMEDIATE 'DROP TABLE dmlrupdtab'; EXCEPTION WHEN OTHERS THEN IF SQLCODE <> -942 THEN RAISE; END IF; END; -/ -CREATE TABLE dmlrupdtab (id NUMBER, name VARCHAR2(40)); -INSERT INTO dmlrupdtab VALUES (1001, 'Venkat'); -INSERT INTO dmlrupdtab VALUES (1002, 'Neeharika'); - --- For LOB examples -BEGIN EXECUTE IMMEDIATE 'DROP TABLE mylobs'; EXCEPTION WHEN OTHERS THEN IF SQLCODE <> -942 THEN RAISE; END IF; END; -/ -CREATE TABLE mylobs (id NUMBER, c CLOB, b BLOB); - --- For lobbinds.js: Procedure to show IN bind support for LOBs -CREATE OR REPLACE PROCEDURE lobs_in (p_id IN NUMBER, c_in IN CLOB, b_in IN BLOB) -AS -BEGIN - INSERT INTO mylobs (id, c, b) VALUES (p_id, c_in, b_in); -END; -/ -SHOW ERRORS - --- For lobbinds.js: Procedure to show bind OUT support for LOBs -CREATE OR REPLACE PROCEDURE lobs_out (p_id IN NUMBER, c_out OUT CLOB, b_out OUT BLOB) -AS -BEGIN - SELECT c, b INTO c_out, b_out FROM mylobs WHERE id = p_id; -END; -/ -SHOW ERRORS - --- For lobbinds.js: Procedure to show PL/SQL IN OUT bind support for LOBs -CREATE OR REPLACE PROCEDURE lob_in_out (p_id IN NUMBER, c_inout IN OUT CLOB) -AS -BEGIN - INSERT INTO mylobs (id, c) VALUES (p_id, c_inout); - SELECT 'New LOB: ' || c INTO c_inout FROM mylobs WHERE id = p_id; -END; -/ -SHOW ERRORS - --- For DBMS_OUTPUT example dbmsoutputpipe.js -CREATE OR REPLACE TYPE dorow AS TABLE OF VARCHAR2(32767); -/ -SHOW ERRORS - -CREATE OR REPLACE FUNCTION mydofetch RETURN dorow PIPELINED IS -line VARCHAR2(32767); -status INTEGER; -BEGIN LOOP - DBMS_OUTPUT.GET_LINE(line, status); - EXIT WHEN status = 1; - PIPE ROW (line); -END LOOP; -END; -/ -SHOW ERRORS - --- For raw1.js -BEGIN EXECUTE IMMEDIATE 'DROP TABLE myraw'; EXCEPTION WHEN OTHERS THEN IF SQLCODE <> -942 THEN RAISE; END IF; END; -/ -CREATE TABLE myraw (r RAW(64)); - --- For the executemany*.js examples - -BEGIN EXECUTE IMMEDIATE 'DROP TABLE em_tab'; EXCEPTION WHEN OTHERS THEN IF SQLCODE <> -942 THEN RAISE; END IF; END; -/ -BEGIN EXECUTE IMMEDIATE 'DROP TABLE em_childtab'; EXCEPTION WHEN OTHERS THEN IF SQLCODE <> -942 THEN RAISE; END IF; END; -/ -BEGIN EXECUTE IMMEDIATE 'DROP TABLE em_parenttab'; EXCEPTION WHEN OTHERS THEN IF SQLCODE <> -942 THEN RAISE; END IF; END; -/ - -CREATE TABLE em_tab ( - id NUMBER NOT NULL, - val VARCHAR2(20) -); - -CREATE TABLE em_parenttab ( - parentid NUMBER NOT NULL, - description VARCHAR2(60) NOT NULL, - CONSTRAINT parenttab_pk PRIMARY KEY (parentid) -); - -CREATE TABLE em_childtab ( - childid NUMBER NOT NULL, - parentid NUMBER NOT NULL, - description VARCHAR2(30) NOT NULL, - CONSTRAINT em_childtab_pk PRIMARY KEY (childid), - CONSTRAINT em_childtab_fk FOREIGN KEY (parentid) REFERENCES em_parenttab -); - -INSERT INTO em_parenttab VALUES (10, 'Parent 10'); -INSERT INTO em_parenttab VALUES (20, 'Parent 20'); -INSERT INTO em_parenttab VALUES (30, 'Parent 30'); -INSERT INTO em_parenttab VALUES (40, 'Parent 40'); -INSERT INTO em_parenttab VALUES (50, 'Parent 50'); - -INSERT INTO em_childtab VALUES (1001, 10, 'Child 1001 of Parent 10'); -INSERT INTO em_childtab VALUES (1002, 20, 'Child 1002 of Parent 20'); -INSERT INTO em_childtab VALUES (1003, 20, 'Child 1003 of Parent 20'); -INSERT INTO em_childtab VALUES (1004, 20, 'Child 1004 of Parent 20'); -INSERT INTO em_childtab VALUES (1005, 30, 'Child 1005 of Parent 30'); -INSERT INTO em_childtab VALUES (1006, 30, 'Child 1006 of Parent 30'); -INSERT INTO em_childtab VALUES (1007, 40, 'Child 1007 of Parent 40'); -INSERT INTO em_childtab VALUES (1008, 40, 'Child 1008 of Parent 40'); -INSERT INTO em_childtab VALUES (1009, 40, 'Child 1009 of Parent 40'); -INSERT INTO em_childtab VALUES (1010, 40, 'Child 1010 of Parent 40'); -INSERT INTO em_childtab VALUES (1011, 40, 'Child 1011 of Parent 40'); -INSERT INTO em_childtab VALUES (1012, 50, 'Child 1012 of Parent 50'); -INSERT INTO em_childtab VALUES (1013, 50, 'Child 1013 of Parent 50'); -INSERT INTO em_childtab VALUES (1014, 50, 'Child 1014 of Parent 50'); -INSERT INTO em_childtab VALUES (1015, 50, 'Child 1015 of Parent 50'); - -CREATE OR REPLACE PROCEDURE em_testproc ( - a_num IN NUMBER, - a_outnum OUT NUMBER, - a_outstr OUT VARCHAR2) -AS -BEGIN - a_outnum := a_num * 2; - FOR i IN 1..a_num LOOP - a_outstr := a_outstr || 'X'; - END LOOP; -END; -/ - -COMMIT; - - --- For the cqn*.js examples - --- The DBA must grant access: --- GRANT CHANGE NOTIFICATION TO myuser; - -BEGIN EXECUTE IMMEDIATE 'DROP TABLE cqntable'; EXCEPTION WHEN OTHERS THEN IF SQLCODE <> -942 THEN RAISE; END IF; END; -/ -CREATE TABLE cqntable (k NUMBER); diff --git a/javascript/node-oracledb/demodrop.js b/javascript/node-oracledb/demodrop.js new file mode 100644 index 00000000..19ec39f2 --- /dev/null +++ b/javascript/node-oracledb/demodrop.js @@ -0,0 +1,131 @@ +/* Copyright (c) 2019, Oracle and/or its affiliates. All rights reserved. */ + +/****************************************************************************** + * + * You may not use the identified files except in compliance with the Apache + * License, Version 2.0 (the "License.") + * + * You may obtain a copy of the License at + * http://www.apache.org/licenses/LICENSE-2.0. + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * + * See the License for the specific language governing permissions and + * limitations under the License. + * + * NAME + * demodrop.js + * + * DESCRIPTION + * Cleanup schema objects created by node-oracledb examples + * + *****************************************************************************/ + +const oracledb = require('oracledb'); +const dbConfig = require('./dbconfig.js'); + +async function run() { + let connection; + + console.log('Dropping schema objects'); + + try { + + connection = await oracledb.getConnection(dbConfig); + + const stmts = [ + `DROP PROCEDURE no_proc`, + + `DROP FUNCTION no_func`, + + `DROP PROCEDURE no_get_rs`, + + `DROP PACKAGE no_beachpkg`, + + `DROP TABLE no_banana_farmer PURGE`, + + `DROP TABLE no_farmtab PURGE`, + + `DROP TABLE no_purchaseorder PURGE`, + + `DROP TABLE no_purchaseorder_b PURGE`, + + `DROP TABLE no_dmlrupdtab PURGE`, + + `DROP TABLE no_lobs PURGE`, + + `DROP TYPE no_dorow`, + + `DROP FUNCTION no_dofetch`, + + `DROP TABLE no_raw PURGE`, + + `DROP TABLE no_waveheight PURGE`, + + `DROP PROCEDURE no_lob_in_out`, + + `DROP PROCEDURE no_lobs_in`, + + `DROP PROCEDURE no_lobs_out`, + + `DROP TABLE no_em_tab PURGE`, + + `DROP TABLE no_em_childtab PURGE`, + + `DROP TABLE no_em_parenttab PURGE`, + + `DROP PROCEDURE no_em_proc`, + + `DROP TABLE no_cqntable PURGE`, + + `DROP TABLE no_datetab PURGE`, + + `DROP TABLE no_sports PURGE`, + + `DROP TABLE no_example PURGE`, + + `DROP TABLE no_geometry PURGE`, + + `DROP TABLE no_tab1 PURGE`, + + `DROP TABLE no_tab2 PURGE`, + + `CALL DBMS_AQADM.STOP_QUEUE('DEMO_RAW_QUEUE')`, + + `CALL DBMS_AQADM.DROP_QUEUE('DEMO_RAW_QUEUE')`, + + `CALL DBMS_AQADM.DROP_QUEUE_TABLE('DEMO_RAW_QUEUE_TAB')`, + + `CALL DBMS_AQADM.STOP_QUEUE('ADDR_QUEUE')`, + + `CALL DBMS_AQADM.DROP_QUEUE('ADDR_QUEUE')`, + + `CALL DBMS_AQADM.DROP_QUEUE_TABLE('ADDR_QUEUE_TAB')` + + ]; + + for (const s of stmts) { + try { + console.log(s); + await connection.execute(s); + } catch(e) { + // do nothing + } + } + + } catch (err) { + console.error(err); + } finally { + if (connection) { + try { + await connection.close(); + } catch (err) { + console.error(err); + } + } + } +} + +run(); diff --git a/javascript/node-oracledb/demodrop.sql b/javascript/node-oracledb/demodrop.sql deleted file mode 100644 index 16cbf5c0..00000000 --- a/javascript/node-oracledb/demodrop.sql +++ /dev/null @@ -1,66 +0,0 @@ -/* Copyright (c) 2015, 2018, Oracle and/or its affiliates. All rights reserved. */ - -/****************************************************************************** - * - * You may not use the identified files except in compliance with the Apache - * License, Version 2.0 (the "License.") - * - * You may obtain a copy of the License at - * http://www.apache.org/licenses/LICENSE-2.0. - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT - * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * - * See the License for the specific language governing permissions and - * limitations under the License. - * - * NAME - * demodrop.sql - * - * DESCRIPTION - * Drop example database objects created in demo.sql - * - *****************************************************************************/ - -SET ECHO ON - -DROP PROCEDURE testproc; - -DROP FUNCTION testfunc; - -DROP PROCEDURE get_emp_rs; - -DROP PACKAGE beachpkg; - -DROP TABLE j_purchaseorder; - -DROP TABLE j_purchaseorder_b; - -DROP TABLE dmlrupdtab; - -DROP TABLE mylobs; - -DROP TYPE dorow; - -DROP FUNCTION mydofetch; - -DROP TABLE myraw; - -DROP TABLE waveheight; - -DROP PROCEDURE lob_in_out; - -DROP PROCEDURE lobs_in; - -DROP PROCEDURE lobs_out; - -DROP TABLE em_tab; - -DROP TABLE em_childtab; - -DROP TABLE em_parenttab; - -DROP PROCEDURE em_testproc; - -DROP TABLE cqntable; diff --git a/javascript/node-oracledb/demosetup.js b/javascript/node-oracledb/demosetup.js new file mode 100644 index 00000000..4f79d8c3 --- /dev/null +++ b/javascript/node-oracledb/demosetup.js @@ -0,0 +1,249 @@ +/* Copyright (c) 2019, Oracle and/or its affiliates. All rights reserved. */ + +/****************************************************************************** + * + * You may not use the identified files except in compliance with the Apache + * License, Version 2.0 (the "License.") + * + * You may obtain a copy of the License at + * http://www.apache.org/licenses/LICENSE-2.0. + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * + * See the License for the specific language governing permissions and + * limitations under the License. + * + * NAME + * demosetup.js + * + * DESCRIPTION + * Functions to create schema objects used by some node-oracledb examples + * + *****************************************************************************/ + +const fs = require('fs'); + +// +// Create a table for example queries +// + +async function setupBf(connection) { + + try { + + const stmts = [ + + `ALTER SESSION SET nls_date_format = 'YYYY-MM-DD HH24:MI:SS'`, + + `DROP TABLE no_banana_farmer PURGE`, + + `CREATE TABLE no_banana_farmer ( + id NUMBER NOT NULL, + farmer VARCHAR2(40), + weight NUMBER, + ripeness VARCHAR2(25), + picked DATE + )`, + + `INSERT INTO no_banana_farmer VALUES (1, 'Gita', 100, 'All Green', '2019-07-21 17:00:00')`, + + `INSERT INTO no_banana_farmer VALUES (2, 'Antonio', 90, 'Full Yellow', '2019-07-30 12:00:00')`, + + `INSERT INTO no_banana_farmer VALUES (3, 'Mindy', 92, 'More Yellow than Green', '2019-07-16 14:30:00')`, + + `INSERT INTO no_banana_farmer VALUES (4, 'Bruce', 78, 'More Yellow than Green', '2019-08-01 11:00:00')`, + + ]; + + for (const s of stmts) { + try { + await connection.execute(s); + } catch(e) { + if (e.errorNum != 942) + throw(e); + } + } + await connection.commit(); + + } catch (err) { + console.error(err); + } +} + +// +// Create a table and (optionally) data for LOB examples +// + +async function setupLobs(connection, insertData) { + + const clobInFileName = 'clobexample.txt'; // the file with text to be inserted into the database + const blobInFileName = 'fuzzydinosaur.jpg'; // contains the image to be inserted into the database + + try { + + const stmts = [ + + `DROP TABLE no_lobs PURGE`, + + `CREATE TABLE no_lobs (id NUMBER, c CLOB, b BLOB)`, + + `CREATE OR REPLACE PROCEDURE no_lobs_in (p_id IN NUMBER, c_in IN CLOB, b_in IN BLOB) + AS + BEGIN + INSERT INTO no_lobs (id, c, b) VALUES (p_id, c_in, b_in); + END;`, + + `CREATE OR REPLACE PROCEDURE no_lobs_out (p_id IN NUMBER, c_out OUT CLOB, b_out OUT BLOB) + AS + BEGIN + SELECT c, b INTO c_out, b_out FROM no_lobs WHERE id = p_id; + END;`, + + `CREATE OR REPLACE PROCEDURE no_lob_in_out (p_id IN NUMBER, c_inout IN OUT CLOB) + AS + BEGIN + INSERT INTO no_lobs (id, c) VALUES (p_id, c_inout); + SELECT 'New LOB: ' || c INTO c_inout FROM no_lobs WHERE id = p_id; + END;` + + ]; + + for (const s of stmts) { + try { + await connection.execute(s); + } catch(e) { + if (e.errorNum != 942) + throw(e); + } + } + + if (insertData) { + const str = fs.readFileSync(clobInFileName, 'utf8'); + await connection.execute( + `INSERT INTO no_lobs (id, c) VALUES (:id, :c)`, + { id: 1, c: str } + ); + + const buf = fs.readFileSync(blobInFileName); + await connection.execute( + `INSERT INTO no_lobs (id, b) VALUES (:id, :b)`, + { id: 2, b: buf }, + { autoCommit: true } + ); + } + + } catch (err) { + console.error(err); + } +} + +// +// Create a table for executeMany() examples +// +async function setupEm(connection) { + + try { + + const stmts = [ + + `DROP TABLE no_em_tab PURGE`, + + `DROP TABLE no_em_childtab PURGE`, + + `DROP TABLE no_em_parenttab PURGE`, + + `CREATE TABLE no_em_tab ( + id NUMBER NOT NULL, + val VARCHAR2(20) + )`, + + `CREATE TABLE no_em_parenttab ( + parentid NUMBER NOT NULL, + description VARCHAR2(60) NOT NULL, + CONSTRAINT parenttab_pk PRIMARY KEY (parentid) + )`, + + `CREATE TABLE no_em_childtab ( + childid NUMBER NOT NULL, + parentid NUMBER NOT NULL, + description VARCHAR2(30) NOT NULL, + CONSTRAINT no_em_childtab_pk PRIMARY KEY (childid), + CONSTRAINT no_em_childtab_fk FOREIGN KEY (parentid) REFERENCES no_em_parenttab + )`, + + `CREATE OR REPLACE PROCEDURE no_em_proc ( + a_num IN NUMBER, + a_outnum OUT NUMBER, + a_outstr OUT VARCHAR2) + AS + BEGIN + a_outnum := a_num * 2; + FOR i IN 1..a_num LOOP + a_outstr := a_outstr || 'X'; + END LOOP; + END;`, + + `INSERT INTO no_em_parenttab VALUES (10, 'Parent 10')`, + + `INSERT INTO no_em_parenttab VALUES (20, 'Parent 20')`, + + `INSERT INTO no_em_parenttab VALUES (30, 'Parent 30')`, + + `INSERT INTO no_em_parenttab VALUES (40, 'Parent 40')`, + + `INSERT INTO no_em_parenttab VALUES (50, 'Parent 50')`, + + `INSERT INTO no_em_childtab VALUES (1001, 10, 'Child 1001 of Parent 10')`, + + `INSERT INTO no_em_childtab VALUES (1002, 20, 'Child 1002 of Parent 20')`, + + `INSERT INTO no_em_childtab VALUES (1003, 20, 'Child 1003 of Parent 20')`, + + `INSERT INTO no_em_childtab VALUES (1004, 20, 'Child 1004 of Parent 20')`, + + `INSERT INTO no_em_childtab VALUES (1005, 30, 'Child 1005 of Parent 30')`, + + `INSERT INTO no_em_childtab VALUES (1006, 30, 'Child 1006 of Parent 30')`, + + `INSERT INTO no_em_childtab VALUES (1007, 40, 'Child 1007 of Parent 40')`, + + `INSERT INTO no_em_childtab VALUES (1008, 40, 'Child 1008 of Parent 40')`, + + `INSERT INTO no_em_childtab VALUES (1009, 40, 'Child 1009 of Parent 40')`, + + `INSERT INTO no_em_childtab VALUES (1010, 40, 'Child 1010 of Parent 40')`, + + `INSERT INTO no_em_childtab VALUES (1011, 40, 'Child 1011 of Parent 40')`, + + `INSERT INTO no_em_childtab VALUES (1012, 50, 'Child 1012 of Parent 50')`, + + `INSERT INTO no_em_childtab VALUES (1013, 50, 'Child 1013 of Parent 50')`, + + `INSERT INTO no_em_childtab VALUES (1014, 50, 'Child 1014 of Parent 50')`, + + `INSERT INTO no_em_childtab VALUES (1015, 50, 'Child 1015 of Parent 50')` + + ]; + + for (const s of stmts) { + try { + await connection.execute(s); + } catch(e) { + if (e.errorNum != 942) + throw(e); + } + } + await connection.commit(); + + } catch (err) { + console.error(err); + } +} + +module.exports.setupBf = setupBf; + +module.exports.setupLobs = setupLobs; + +module.exports.setupEm = setupEm; diff --git a/javascript/node-oracledb/dmlrupd1.js b/javascript/node-oracledb/dmlrupd1.js index 77467f14..2d80e9be 100644 --- a/javascript/node-oracledb/dmlrupd1.js +++ b/javascript/node-oracledb/dmlrupd1.js @@ -22,14 +22,6 @@ * Example of 'DML Returning' with a single row match. * The ROWID of the changed record is returned. This is how to get * the 'last insert id'. - * Bind names cannot be reused in the DML section and the RETURNING section. - * - * Use demo.sql to create the required table or do: - * DROP TABLE dmlrupdtab; - * CREATE TABLE dmlrupdtab (id NUMBER, name VARCHAR2(40)); - * INSERT INTO dmlrupdtab VALUES (1001, 'Venkat'); - * INSERT INTO dmlrupdtab VALUES (1002, 'Neeharika'); - * COMMIT; * * This example uses Node 8's async/await syntax. * @@ -45,17 +37,50 @@ async function run() { try { connection = await oracledb.getConnection(dbConfig); + // + // Setup + // + + const stmts = [ + `DROP TABLE no_dmlrupdtab`, + + `CREATE TABLE no_dmlrupdtab (id NUMBER, name VARCHAR2(40))`, + + `INSERT INTO no_dmlrupdtab VALUES (1001, 'Venkat')`, + + `INSERT INTO no_dmlrupdtab VALUES (1002, 'Neeharika')` + ]; + + for (const s of stmts) { + try { + await connection.execute(s); + } catch(e) { + if (e.errorNum != 942) + console.error(e); + } + } + + // + // Show DML Returning + // + + // SQL statement. + // Note bind names cannot be reused in the DML section and the RETURNING section + const sql = + `UPDATE no_dmlrupdtab + SET name = :name + WHERE id = :id + RETURNING ROWID INTO :rid`; + const result = await connection.execute( - `UPDATE dmlrupdtab - SET name = :name - WHERE id = :id - RETURNING ROWID INTO :rid`, + sql, { id: 1001, name: "Krishna", rid: { type: oracledb.STRING, dir: oracledb.BIND_OUT } }, - { autoCommit: true }); + { autoCommit: true } + ); console.log(result.outBinds); diff --git a/javascript/node-oracledb/dmlrupd2.js b/javascript/node-oracledb/dmlrupd2.js index 2affca35..28187a71 100644 --- a/javascript/node-oracledb/dmlrupd2.js +++ b/javascript/node-oracledb/dmlrupd2.js @@ -22,14 +22,6 @@ * Example of 'DML Returning' with multiple rows matched. * The ROWIDs of the changed records are returned. This is how to get * the 'last insert id'. - * Bind names cannot be reused in the DML section and the RETURNING section. - * - * Use demo.sql to create the required table or do: - * DROP TABLE dmlrupdtab; - * CREATE TABLE dmlrupdtab (id NUMBER, name VARCHAR2(40)); - * INSERT INTO dmlrupdtab VALUES (1001, 'Venkat'); - * INSERT INTO dmlrupdtab VALUES (1002, 'Neeharika'); - * COMMIT; * * This example uses Node 8's async/await syntax. * @@ -45,11 +37,43 @@ async function run() { try { connection = await oracledb.getConnection(dbConfig); + // + // Setup + // + + const stmts = [ + `DROP TABLE no_dmlrupdtab`, + + `CREATE TABLE no_dmlrupdtab (id NUMBER, name VARCHAR2(40))`, + + `INSERT INTO no_dmlrupdtab VALUES (1001, 'Venkat')`, + + `INSERT INTO no_dmlrupdtab VALUES (1002, 'Neeharika')` + ]; + + for (const s of stmts) { + try { + await connection.execute(s); + } catch(e) { + if (e.errorNum != 942) + console.error(e); + } + } + + // + // Show DML Returning + // + + // SQL statement. + // Note bind names cannot be reused in the DML section and the RETURNING section + const sql = + `UPDATE no_dmlrupdtab + SET name = :name + WHERE id IN (:id1, :id2) + RETURNING id, ROWID INTO :ids, :rids`; + const result = await connection.execute( - `UPDATE dmlrupdtab - SET name = :name - WHERE id IN (:id1, :id2) - RETURNING id, ROWID INTO :ids, :rids`, + sql, { id1: 1001, id2: 1002, @@ -57,7 +81,8 @@ async function run() { ids: { type: oracledb.NUMBER, dir: oracledb.BIND_OUT }, rids: { type: oracledb.STRING, dir: oracledb.BIND_OUT } }, - { autoCommit: true }); + { autoCommit: true } + ); console.log(result.outBinds); diff --git a/javascript/node-oracledb/em_batcherrors.js b/javascript/node-oracledb/em_batcherrors.js index 1793fe65..c86c8648 100644 --- a/javascript/node-oracledb/em_batcherrors.js +++ b/javascript/node-oracledb/em_batcherrors.js @@ -19,12 +19,11 @@ * em_batcherrors.js * * DESCRIPTION - * Array DML example showing batchErrors behavior. Note, despite the - * autoCommit flag, no commit occurs because of data errors. However - * valid rows are part of a transaction that can be committed if - * desired. - * This example also uses Async/Await of Node 8. - * Use demo.sql to create the required schema. + * Array DML example showing batchErrors behavior. + * + * Note: Despite the autoCommit flag, no commit occurs because of data + * errors. However valid rows are part of a transaction that can be committed + * if desired. * * This example requires node-oracledb 2.2 or later. * @@ -34,8 +33,9 @@ const oracledb = require('oracledb'); const dbConfig = require('./dbconfig.js'); +const demoSetup = require('./demosetup.js'); -const sql = "INSERT INTO em_childtab VALUES (:1, :2, :3)"; +const sql = "INSERT INTO no_em_childtab VALUES (:1, :2, :3)"; const binds = [ [1016, 10, "Child 2 of Parent A"], @@ -63,12 +63,9 @@ async function run() { let connection; try { - connection = await oracledb.getConnection( - { - user : dbConfig.user, - password : dbConfig.password, - connectString : dbConfig.connectString - }); + connection = await oracledb.getConnection(dbConfig); + + await demoSetup.setupEm(connection); // create the demo tables const result = await connection.executeMany(sql, binds, options); console.log("Result is:", result); diff --git a/javascript/node-oracledb/em_dmlreturn1.js b/javascript/node-oracledb/em_dmlreturn1.js index 40a95f15..61fcd5ef 100644 --- a/javascript/node-oracledb/em_dmlreturn1.js +++ b/javascript/node-oracledb/em_dmlreturn1.js @@ -19,9 +19,7 @@ * em_dmlreturn1.js * * DESCRIPTION - * executeMany() example of DML RETURNING that returns single values - * This example also uses Async/Await of Node 8. - * Use demo.sql to create the required schema. + * executeMany() example of DML RETURNING that returns single values. * * This example requires node-oracledb 2.2 or later. * @@ -31,9 +29,9 @@ x *****************************************************************************/ const oracledb = require('oracledb'); const dbConfig = require('./dbconfig.js'); +const demoSetup = require('./demosetup.js'); -const truncateSql = "TRUNCATE TABLE em_tab"; -const insertSql = "INSERT INTO em_tab VALUES (:1, :2) RETURNING ROWID, id, val INTO :3, :4, :5"; +const sql = "INSERT INTO no_em_tab VALUES (:1, :2) RETURNING ROWID, id, val INTO :3, :4, :5"; const binds = [ [1, "Test 1 (One)"], @@ -59,9 +57,9 @@ async function run() { try { connection = await oracledb.getConnection(dbConfig); - await connection.execute(truncateSql); + await demoSetup.setupEm(connection); // create the demo tables - const result = await connection.executeMany(insertSql, binds, options); + const result = await connection.executeMany(sql, binds, options); console.log("rowsAffected is:", result.rowsAffected); console.log("Out binds:"); diff --git a/javascript/node-oracledb/em_dmlreturn2.js b/javascript/node-oracledb/em_dmlreturn2.js index 2653b496..c2088699 100644 --- a/javascript/node-oracledb/em_dmlreturn2.js +++ b/javascript/node-oracledb/em_dmlreturn2.js @@ -20,8 +20,6 @@ * * DESCRIPTION * executeMany() example of DML RETURNING that returns multiple values - * This example also uses Async/Await of Node 8. - * Use demo.sql to create the required schema. * * This example requires node-oracledb 2.2 or later. * @@ -31,9 +29,9 @@ const oracledb = require('oracledb'); const dbConfig = require('./dbconfig.js'); +const demoSetup = require('./demosetup.js'); -const truncateSql = "TRUNCATE TABLE em_tab"; -const insertSql = "INSERT INTO em_tab VALUES (:1, :2)"; +const insertSql = "INSERT INTO no_em_tab VALUES (:1, :2)"; const insertData = [ [1, "Test 1 (One)"], @@ -53,7 +51,7 @@ const insertOptions = { ] }; -const deleteSql = "DELETE FROM em_tab WHERE id < :1 RETURNING id, val INTO :2, :3"; +const deleteSql = "DELETE FROM no_em_tab WHERE id < :1 RETURNING id, val INTO :2, :3"; const deleteData = [ [2], @@ -75,7 +73,7 @@ async function run() { try { connection = await oracledb.getConnection(dbConfig); - await connection.execute(truncateSql); + await demoSetup.setupEm(connection); // create the demo tables await connection.executeMany(insertSql, insertData, insertOptions); diff --git a/javascript/node-oracledb/em_insert1.js b/javascript/node-oracledb/em_insert1.js index 88afee8a..0e30e4a5 100644 --- a/javascript/node-oracledb/em_insert1.js +++ b/javascript/node-oracledb/em_insert1.js @@ -20,8 +20,6 @@ * * DESCRIPTION * Array DML example using executeMany() with bind-by-name syntax. - * This example also uses Async/Await of Node 8. - * Use demo.sql to create the required schema. * * This example requires node-oracledb 2.2 or later. * @@ -31,9 +29,9 @@ const oracledb = require('oracledb'); const dbConfig = require('./dbconfig.js'); +const demoSetup = require('./demosetup.js'); -const truncateSql = "TRUNCATE TABLE em_tab"; -const insertSql = "INSERT INTO em_tab values (:a, :b)"; +const sql = "INSERT INTO no_em_tab values (:a, :b)"; const binds = [ { a: 1, b: "Test 1 (One)" }, @@ -59,9 +57,9 @@ async function run() { try { connection = await oracledb.getConnection(dbConfig); - await connection.execute(truncateSql); + await demoSetup.setupEm(connection); // create the demo tables - const result = await connection.executeMany(insertSql, binds, options); + const result = await connection.executeMany(sql, binds, options); console.log("Result is:", result); } catch (err) { diff --git a/javascript/node-oracledb/em_insert2.js b/javascript/node-oracledb/em_insert2.js index acbbad58..5af60ab1 100644 --- a/javascript/node-oracledb/em_insert2.js +++ b/javascript/node-oracledb/em_insert2.js @@ -20,8 +20,6 @@ * * DESCRIPTION * Array DML example using executeMany() with bind by position. - * This example also uses Async/Await of Node 8. - * Use demo.sql to create the required schema. * * This example requires node-oracledb 2.2 or later. * @@ -31,9 +29,9 @@ const oracledb = require('oracledb'); const dbConfig = require('./dbconfig.js'); +const demoSetup = require('./demosetup.js'); -const truncateSql = "TRUNCATE TABLE em_tab"; -const insertSql = "INSERT INTO em_tab values (:1, :2)"; +const sql = "INSERT INTO no_em_tab values (:1, :2)"; const binds = [ [1, "Test 1 (One)"], @@ -59,9 +57,9 @@ async function run() { try { connection = await oracledb.getConnection(dbConfig); - await connection.execute(truncateSql); + await demoSetup.setupEm(connection); // create the demo tables - const result = await connection.executeMany(insertSql, binds, options); + const result = await connection.executeMany(sql, binds, options); console.log("Result is:", result); } catch (err) { diff --git a/javascript/node-oracledb/em_plsql.js b/javascript/node-oracledb/em_plsql.js index fe0a862f..e10b8fee 100644 --- a/javascript/node-oracledb/em_plsql.js +++ b/javascript/node-oracledb/em_plsql.js @@ -20,8 +20,6 @@ * * DESCRIPTION * executeMany() example calling PL/SQL. - * This example also uses Async/Await of Node 8. - * Use demo.sql to create the required schema. * * This example requires node-oracledb 2.2 or later. * @@ -31,8 +29,9 @@ const oracledb = require('oracledb'); const dbConfig = require('./dbconfig.js'); +const demoSetup = require('./demosetup.js'); -const sql = "BEGIN em_testproc(:1, :2, :3); END;"; +const sql = "BEGIN no_em_proc(:1, :2, :3); END;"; const binds = [ [1], @@ -56,6 +55,8 @@ async function run() { try { connection = await oracledb.getConnection(dbConfig); + await demoSetup.setupEm(connection); // create the demo tables + const result = await connection.executeMany(sql, binds, options); console.log("Result is:", result); diff --git a/javascript/node-oracledb/em_rowcounts.js b/javascript/node-oracledb/em_rowcounts.js index 6e5438a5..953b4c5a 100644 --- a/javascript/node-oracledb/em_rowcounts.js +++ b/javascript/node-oracledb/em_rowcounts.js @@ -21,8 +21,6 @@ * DESCRIPTION * executeMany() example showing dmlRowCounts. * For this example, there no commit so it is re-runnable. - * This example also uses Async/Await of Node 8. - * Use demo.sql to create the required schema. * * This example requires node-oracledb 2.2 or later. * @@ -32,8 +30,9 @@ const oracledb = require('oracledb'); const dbConfig = require('./dbconfig.js'); +const demoSetup = require('./demosetup.js'); -const sql = "DELETE FROM em_childtab WHERE parentid = :1"; +const sql = "DELETE FROM no_em_childtab WHERE parentid = :1"; const binds = [ [20], @@ -49,6 +48,8 @@ async function run() { try { connection = await oracledb.getConnection(dbConfig); + await demoSetup.setupEm(connection); // create the demo tables + const result = await connection.executeMany(sql, binds, options); console.log("Result is:", result); diff --git a/javascript/node-oracledb/endtoend.js b/javascript/node-oracledb/endtoend.js index 2a2a3f57..f737473f 100644 --- a/javascript/node-oracledb/endtoend.js +++ b/javascript/node-oracledb/endtoend.js @@ -19,8 +19,9 @@ * endtoend.js * * DESCRIPTION - * Show setting connection metadata for end-to-end tracing and client authorization. - * While the script sleeps (keeping the connection open), use SQL*Plus as SYSTEM to execute: + * Sets connection metadata for end-to-end tracing and client authorization. + * + * While the script sleeps (keeping the connection open), use SQL*Plus as a privileged user to execute: * SELECT username, client_identifier, action, module FROM v$session WHERE username IS NOT NULL; * The end-to-end tracing attributes are shown in various other DBA views and in Enterprise Manager. * @@ -44,8 +45,8 @@ async function run() { connection.module = "End-to-end example"; connection.action = "Query departments"; - console.log("Use SQL*Plus as SYSTEM to execute the query:"); - console.log("SELECT username, client_identifier, action, module FROM v$session WHERE username = UPPER('" + dbConfig.user +"');"); + console.log("Use SQL*Plus as SYSTEM (or ADMIN for Oracle Cloud databases) to execute the query:"); + console.log(" SELECT username, client_identifier, action, module FROM v$session WHERE username = UPPER('" + dbConfig.user +"');"); // Sleep 10 seconds to keep the connection open. This allows // external queries on V$SESSION to show the connection @@ -65,4 +66,14 @@ async function run() { } } +process + .on('SIGTERM', function() { + console.log("\nTerminating"); + process.exit(0); + }) + .on('SIGINT', function() { + console.log("\nTerminating"); + process.exit(0); + }); + run(); diff --git a/javascript/node-oracledb/example.js b/javascript/node-oracledb/example.js index 16d7b38a..3420058a 100644 --- a/javascript/node-oracledb/example.js +++ b/javascript/node-oracledb/example.js @@ -21,10 +21,9 @@ * DESCRIPTION * A basic node-oracledb example using Node.js 8's async/await syntax. * - * For a connection pool example see connectionpool.js - * For a ResultSet example see resultset2.js + * For connection pool examples see connectionpool.js and webappawait.js + * For a ResultSet example see resultset1.js * For a query stream example see selectstream.js - * For a callback example see select1.js * * This example requires node-oracledb 2.2 or later. * @@ -45,26 +44,36 @@ async function run() { connection = await oracledb.getConnection(dbConfig); + // // Create a table + // - await connection.execute( - `BEGIN - EXECUTE IMMEDIATE 'DROP TABLE mytab'; - EXCEPTION - WHEN OTHERS THEN - IF SQLCODE NOT IN (-00942) THEN - RAISE; - END IF; - END;`); + const stmts = [ + `DROP TABLE no_example`, - await connection.execute( - `CREATE TABLE mytab (id NUMBER, data VARCHAR2(20))`); + `CREATE TABLE no_example (id NUMBER, data VARCHAR2(20))` + ]; - // Insert some data + for (const s of stmts) { + try { + await connection.execute(s); + } catch(e) { + if (e.errorNum != 942) + console.error(e); + } + } + + // + // Insert three rows + // - sql = `INSERT INTO mytab VALUES (:1, :2)`; + sql = `INSERT INTO no_example VALUES (:1, :2)`; - binds = [ [101, "Alpha" ], [102, "Beta" ], [103, "Gamma" ] ]; + binds = [ + [101, "Alpha" ], + [102, "Beta" ], + [103, "Gamma" ] + ]; // For a complete list of options see the documentation. options = { @@ -80,9 +89,11 @@ async function run() { console.log("Number of rows inserted:", result.rowsAffected); + // // Query the data + // - sql = `SELECT * FROM mytab`; + sql = `SELECT * FROM no_example`; binds = {}; @@ -99,7 +110,9 @@ async function run() { console.log("Query results: "); console.log(result.rows); + // // Show the date. The value of ORA_SDTZ affects the output + // sql = `SELECT TO_CHAR(CURRENT_DATE, 'DD-Mon-YYYY HH24:MI') AS CD FROM DUAL`; result = await connection.execute(sql, binds, options); diff --git a/javascript/node-oracledb/fetchinfo.js b/javascript/node-oracledb/fetchinfo.js index 3add2423..13ad237e 100644 --- a/javascript/node-oracledb/fetchinfo.js +++ b/javascript/node-oracledb/fetchinfo.js @@ -21,10 +21,6 @@ * DESCRIPTION * Show how numbers and dates can be returned as strings using fetchAsString * and fetchInfo - * Uses Oracle's sample HR schema. - * - * Scripts to create the HR schema can be found at: - * https://github.com/oracle/db-sample-schemas * * This example uses Node 8's async/await syntax. * @@ -32,9 +28,9 @@ const oracledb = require('oracledb'); const dbConfig = require('./dbconfig.js'); +const demoSetup = require('./demosetup.js'); oracledb.fetchAsString = [ oracledb.NUMBER ]; // any number queried will be returned as a string -//oracledb.fetchAsString = [ oracledb.NUMBER, oracledb.DATE ]; // both date and number can be used async function run() { @@ -43,16 +39,18 @@ async function run() { try { connection = await oracledb.getConnection(dbConfig); + await demoSetup.setupBf(connection); // create the demo table + const result = await connection.execute( - `SELECT last_name, hire_date, salary, commission_pct - FROM employees - WHERE employee_id = :id`, - [178], + `SELECT id, farmer, picked, weight + FROM no_banana_farmer + WHERE id = :id`, + [2], { fetchInfo : { - "HIRE_DATE": { type : oracledb.STRING }, // return the date as a string - "COMMISSION_PCT": { type : oracledb.DEFAULT } // override oracledb.fetchAsString + "PICKED": { type : oracledb.STRING }, // return the date as a string + "WEIGHT": { type : oracledb.DEFAULT } // override oracledb.fetchAsString } }); diff --git a/javascript/node-oracledb/impres.js b/javascript/node-oracledb/impres.js index 1695aa23..736c5c0c 100644 --- a/javascript/node-oracledb/impres.js +++ b/javascript/node-oracledb/impres.js @@ -31,6 +31,7 @@ const oracledb = require('oracledb'); const dbConfig = require('./dbconfig.js'); +const demoSetup = require('./demosetup.js'); oracledb.outFormat = oracledb.OUT_FORMAT_OBJECT; @@ -41,6 +42,8 @@ async function run() { connection = await oracledb.getConnection(dbConfig); + await demoSetup.setupBf(connection); // create the demo table + let result, row; const plsql = ` @@ -48,14 +51,12 @@ async function run() { c1 SYS_REFCURSOR; c2 SYS_REFCURSOR; BEGIN - OPEN c1 FOR SELECT city, postal_code - FROM locations - WHERE location_id < 1500; + OPEN c1 FOR SELECT weight, ripeness + FROM no_banana_farmer; DBMS_SQL.RETURN_RESULT(c1); - OPEN C2 FOR SELECT job_id, employee_id, last_name - FROM employees - WHERE employee_id < 110; + OPEN C2 FOR SELECT sum(weight) AS KILOGRAMS + FROM no_banana_farmer; DBMS_SQL.RETURN_RESULT(c2); END;`; diff --git a/javascript/node-oracledb/insert1.js b/javascript/node-oracledb/insert1.js index 2b2655a5..cf9cba5f 100644 --- a/javascript/node-oracledb/insert1.js +++ b/javascript/node-oracledb/insert1.js @@ -37,36 +37,48 @@ async function run() { try { connection = await oracledb.getConnection(dbConfig); - await connection.execute( - `BEGIN - EXECUTE IMMEDIATE 'DROP TABLE test'; - EXCEPTION WHEN OTHERS THEN - IF SQLCODE <> -942 THEN - RAISE; - END IF; - END;`); - console.log("Table dropped"); + // + // Create a table + // - await connection.execute( - `CREATE TABLE test (id NUMBER, name VARCHAR2(20))`); - console.log("Table created"); + const stmts = [ + `DROP TABLE no_tab1`, + + `CREATE TABLE no_tab1 (id NUMBER, name VARCHAR2(20))` + ]; + + for (const s of stmts) { + try { + await connection.execute(s); + } catch(e) { + if (e.errorNum != 942) + console.error(e); + } + } + + // + // Show several examples of inserting + // // 'bind by name' syntax let result = await connection.execute( - `INSERT INTO test VALUES (:id, :nm)`, - { id : {val: 1 }, nm : {val: 'Chris'} }); + `INSERT INTO no_tab1 VALUES (:id, :nm)`, + { id : {val: 1 }, nm : {val: 'Chris'} } + ); console.log("Rows inserted: " + result.rowsAffected); // 1 // 'bind by position' syntax result = await connection.execute( - `INSERT INTO test VALUES (:id, :nm)`, - [2, 'Alison']); + `INSERT INTO no_tab1 VALUES (:id, :nm)`, + [2, 'Alison'] + ); console.log("Rows inserted: " + result.rowsAffected); // 1 result = await connection.execute( - `UPDATE test SET name = :nm`, + `UPDATE no_tab1 SET name = :nm`, ['Bambi'], - { autoCommit: true }); // commit once for all DML in the script + { autoCommit: true } // commit once for all DML in the script + ); console.log("Rows updated: " + result.rowsAffected); // 2 } catch (err) { diff --git a/javascript/node-oracledb/insert2.js b/javascript/node-oracledb/insert2.js index bfa735ca..b1dfe282 100644 --- a/javascript/node-oracledb/insert2.js +++ b/javascript/node-oracledb/insert2.js @@ -44,30 +44,40 @@ async function run() { let result; - await connection1.execute( - `BEGIN - EXECUTE IMMEDIATE 'DROP TABLE test'; - EXCEPTION WHEN OTHERS THEN - IF SQLCODE <> -942 THEN - RAISE; - END IF; - END;`); - console.log("Table dropped"); - - await connection1.execute( - `CREATE TABLE test (id NUMBER, name VARCHAR2(20))`); - console.log("Table created"); + // + // Create a table + // + + const stmts = [ + `DROP TABLE no_tab2`, + + `CREATE TABLE no_tab2 (id NUMBER, name VARCHAR2(20))` + ]; + + for (const s of stmts) { + try { + await connection1.execute(s); + } catch(e) { + if (e.errorNum != 942) + console.error(e); + } + } + + // + // Show several examples of inserting + // // Insert with autoCommit enabled result = await connection1.execute( - `INSERT INTO test VALUES (:id, :nm)`, + `INSERT INTO no_tab2 VALUES (:id, :nm)`, [1, 'Chris'], // Bind values - { autoCommit: true}); // Override the default, non-autocommit behavior + { autoCommit: true} // Override the default, non-autocommit behavior + ); console.log("Rows inserted: " + result.rowsAffected); // 1 // Insert without committing result = await connection1.execute( - `INSERT INTO test VALUES (:id, :nm)`, + `INSERT INTO no_tab2 VALUES (:id, :nm)`, [2, 'Alison'], // Bind values // { autoCommit: true}, // Since this isn't set, operations using a second connection won't see this row ); @@ -77,7 +87,8 @@ async function run() { // inserting 'Alison' is not commited by default. Uncomment the // autoCommit option above and you will see both rows result = await connection2.execute( - `SELECT * FROM test`); + `SELECT * FROM no_tab2` + ); console.log(result.rows); } catch (err) { diff --git a/javascript/node-oracledb/lobbinds.js b/javascript/node-oracledb/lobbinds.js index 769dc735..06b24bee 100644 --- a/javascript/node-oracledb/lobbinds.js +++ b/javascript/node-oracledb/lobbinds.js @@ -26,9 +26,6 @@ * 4) Querying a LOB and binding using PL/SQL IN OUT bind * 5) PL/SQL OUT bind followed by PL/SQL IN OUT bind * - * Use demo.sql to create the required tables and procedures - * Run lobinsert1.js to load text before running this example - * * This example requires node-oracledb 1.13 or later. * * This example uses Node 8's async/await syntax. @@ -38,6 +35,7 @@ const fs = require('fs'); const oracledb = require('oracledb'); const dbConfig = require('./dbconfig.js'); +const demoSetup = require('./demosetup.js'); const clobOutFileName1 = 'lobbindsout1.txt'; const clobOutFileName2 = 'lobbindsout2.txt'; @@ -50,12 +48,12 @@ async function query_bind_insert(connection) { console.log ("1. query_bind_insert(): Inserting a CLOB using a LOB IN bind for INSERT"); let result = await connection.execute( - `SELECT c FROM mylobs WHERE id = :id`, + `SELECT c FROM no_lobs WHERE id = :id`, { id: 1 } ); if (result.rows.length === 0) { - throw new Error('query_bind_insert(): No results. Did you run lobinsert1.js?'); + throw new Error('query_bind_insert(): No row found'); } const clob1 = result.rows[0][0]; @@ -65,7 +63,7 @@ async function query_bind_insert(connection) { // Insert the value back as a new row result = await connection.execute( - `INSERT INTO mylobs (id, c) VALUES (:id, :c)`, + `INSERT INTO no_lobs (id, c) VALUES (:id, :c)`, { id: 10, c: {val: clob1, type: oracledb.CLOB, dir: oracledb.BIND_IN} @@ -88,7 +86,7 @@ async function plsql_in_as_str_buf(connection) { await connection.execute( `BEGIN - lobs_in(:id, :c, :b); + no_lobs_in(:id, :c, :b); END;`, { id: 20, @@ -107,7 +105,7 @@ async function plsql_out_as_str_buf(connection) { const result = await connection.execute( `BEGIN - lobs_out(:id, :c, :b); + no_lobs_out(:id, :c, :b); END;`, { id: 20, @@ -127,12 +125,12 @@ async function query_plsql_inout(connection) { console.log ("4. query_plsql_inout(): Querying then inserting a CLOB using a PL/SQL IN OUT LOB bind"); let result = await connection.execute( - `SELECT c FROM mylobs WHERE id = :id`, + `SELECT c FROM no_lobs WHERE id = :id`, { id: 1 } ); if (result.rows.length === 0) { - throw new Error('query_plsql_inout(): No results'); + throw new Error('query_plsql_inout(): No row found'); } const clob1 = result.rows[0][0]; @@ -144,7 +142,7 @@ async function query_plsql_inout(connection) { // The returned Lob clob2 will be autoclosed because it is streamed to completion. result = await connection.execute( `BEGIN - lob_in_out(:idbv, :ciobv); + no_lob_in_out(:idbv, :ciobv); END;`, { idbv: 30, @@ -209,7 +207,7 @@ async function plsql_out_inout(connection) { const result1 = await connection.execute( `BEGIN - lobs_out(:idbv, :cobv, :bobv); + no_lobs_out(:idbv, :cobv, :bobv); END;`, { idbv: 1, @@ -227,7 +225,7 @@ async function plsql_out_inout(connection) { // The returned Lob clob2 will be autoclosed because it is streamed to completion. const result2 = await connection.execute( `BEGIN - lob_in_out(:idbv, :ciobv); + no_lob_in_out(:idbv, :ciobv); END;`, { idbv: 50, @@ -305,8 +303,7 @@ async function run() { try { connection = await oracledb.getConnection(dbConfig); - // Cleanup anything other than lobinsert1.js demonstration data - await connection.execute(`DELETE FROM mylobs WHERE id > 2`); + await demoSetup.setupLobs(connection, true); // create the demo table with data await query_bind_insert(connection); await plsql_in_as_str_buf(connection); diff --git a/javascript/node-oracledb/lobinsert1.js b/javascript/node-oracledb/lobinsert1.js index 48cbea6b..2f9c2f5d 100644 --- a/javascript/node-oracledb/lobinsert1.js +++ b/javascript/node-oracledb/lobinsert1.js @@ -21,7 +21,7 @@ * DESCRIPTION * Reads text from clobexample.txt and INSERTs it into a CLOB column. * Reads binary data from fuzzydinosaur.jpg and INSERTs it into a BLOB column. - * Run lobselect.js to query the inserted data. + * After running this, Run lobselect.js to query the inserted data. * * "Small" amounts of data can be bound directly for INSERT into LOB * columns. Larger amounts should be streamed, see lobinssert2.js. @@ -29,11 +29,6 @@ * and V8 handle large data in memory, and on your streaming and * performance requirements. * - * Create clobexample.txt and fuzzydinosaur.jpg before running this example. - * Use demo.sql to create the required table or do: - * DROP TABLE mylobs; - * CREATE TABLE mylobs (id NUMBER, c CLOB, b BLOB); - * * This example requires node-oracledb 1.12 or later. * * This example uses Node 8's async/await syntax. @@ -43,6 +38,7 @@ const fs = require('fs'); const oracledb = require('oracledb'); const dbConfig = require('./dbconfig.js'); +const demoSetup = require('./demosetup.js'); oracledb.autoCommit = true; // for ease of demonstration only @@ -56,16 +52,16 @@ async function run() { try { connection = await oracledb.getConnection(dbConfig); - let result; + await demoSetup.setupLobs(connection, false); // create the demo table without data - // Clean up the table - await connection.execute(`DELETE FROM mylobs`); + let result; // Insert a CLOB const str = fs.readFileSync(clobInFileName, 'utf8'); result = await connection.execute( - `INSERT INTO mylobs (id, c) VALUES (:id, :c)`, - { id: 1, c: str }); + `INSERT INTO no_lobs (id, c) VALUES (:id, :c)`, + { id: 1, c: str } + ); if (result.rowsAffected != 1) throw new Error('CLOB was not inserted'); else @@ -74,8 +70,9 @@ async function run() { // Insert a BLOB const buf = fs.readFileSync(blobInFileName); result = await connection.execute( - `INSERT INTO mylobs (id, b) VALUES (:id, :b)`, - { id: 2, b: buf }); + `INSERT INTO no_lobs (id, b) VALUES (:id, :b)`, + { id: 2, b: buf }, + ); if (result.rowsAffected != 1) throw new Error('BLOB was not inserted'); else diff --git a/javascript/node-oracledb/lobinsert2.js b/javascript/node-oracledb/lobinsert2.js index 58fb09fd..b4851f04 100644 --- a/javascript/node-oracledb/lobinsert2.js +++ b/javascript/node-oracledb/lobinsert2.js @@ -23,20 +23,16 @@ * * For smaller LOBs you will probably prefer the method shown in lobinsert1.js * - * Create clobexample.txt before running this example. - * Use demo.sql to create the required table or do: - * DROP TABLE mylobs; - * CREATE TABLE mylobs (id NUMBER, c CLOB, b BLOB); - * * This example requires node-oracledb 1.12 or later. * *****************************************************************************/ -var fs = require('fs'); -var oracledb = require('oracledb'); -var dbConfig = require('./dbconfig.js'); +const fs = require('fs'); +const oracledb = require('oracledb'); +const dbConfig = require('./dbconfig.js'); +const demoSetup = require('./demosetup.js'); -var inFileName = 'clobexample.txt'; // the file with text to be inserted into the database +const inFileName = 'clobexample.txt'; // the file with text to be inserted into the database async function run() { @@ -45,8 +41,10 @@ async function run() { try { const connection = await oracledb.getConnection(dbConfig); + await demoSetup.setupLobs(connection); // create the demo table + const result = await connection.execute( - `INSERT INTO mylobs (id, c) VALUES (:id, EMPTY_CLOB()) RETURNING c INTO :lobbv`, + `INSERT INTO no_lobs (id, c) VALUES (:id, EMPTY_CLOB()) RETURNING c INTO :lobbv`, { id: 4, lobbv: {type: oracledb.CLOB, dir: oracledb.BIND_OUT} @@ -92,7 +90,7 @@ async function run() { }); console.log('Reading from ' + inFileName); - var inStream = fs.createReadStream(inFileName); + const inStream = fs.createReadStream(inFileName); inStream.on('error', (err) => { // console.log("inStream.on 'error' event"); if (!errorHandled) { diff --git a/javascript/node-oracledb/lobinserttemp.js b/javascript/node-oracledb/lobinserttemp.js index e24223d1..0706aa53 100644 --- a/javascript/node-oracledb/lobinserttemp.js +++ b/javascript/node-oracledb/lobinserttemp.js @@ -25,20 +25,18 @@ * You may prefer the method shown in lobinsert2.js, which inserts * directly into the table. * - * Create clobexample.txt before running this example. - * Use demo.sql to create the required schema. - * * This example requires node-oracledb 1.12 or later. * * This example uses Node 8's async/await syntax. * *****************************************************************************/ -var fs = require('fs'); -var oracledb = require('oracledb'); -var dbConfig = require('./dbconfig.js'); +const fs = require('fs'); +const oracledb = require('oracledb'); +const dbConfig = require('./dbconfig.js'); +const demoSetup = require('./demosetup.js'); -var inFileName = 'clobexample.txt'; // the file with text to be inserted into the database +const inFileName = 'clobexample.txt'; // the file with text to be inserted into the database async function run() { @@ -47,8 +45,7 @@ async function run() { try { connection = await oracledb.getConnection(dbConfig); - // Cleanup anything other than lobinsert1.js demo data - await connection.execute(`DELETE FROM mylobs WHERE id > 2`); + await demoSetup.setupLobs(connection); // create the demo table // Write into a temporary LOB. // An alternative would be to stream into it. @@ -66,7 +63,7 @@ async function run() { try { console.log('Inserting the temporary LOB into the database'); const result = await connection.execute( - `INSERT INTO mylobs (id, c) VALUES (:idbv, :lobbv)`, + `INSERT INTO no_lobs (id, c) VALUES (:idbv, :lobbv)`, { idbv: 3, lobbv: tempLob diff --git a/javascript/node-oracledb/lobplsqltemp.js b/javascript/node-oracledb/lobplsqltemp.js index c6aaf97c..e09ea792 100644 --- a/javascript/node-oracledb/lobplsqltemp.js +++ b/javascript/node-oracledb/lobplsqltemp.js @@ -25,20 +25,18 @@ * Smaller amounts of data can be passed directly to PL/SQL without * needed a temporary LOB. See lobbinds.js * - * Create clobexample.txt before running this example. - * Use demo.sql to create the required schema. - * * This example requires node-oracledb 1.12.1 or later. * * This example uses Node 8's async/await syntax. * *****************************************************************************/ -var fs = require('fs'); -var oracledb = require('oracledb'); -var dbConfig = require('./dbconfig.js'); +const fs = require('fs'); +const oracledb = require('oracledb'); +const dbConfig = require('./dbconfig.js'); +const demoSetup = require('./demosetup.js'); -var inFileName = 'clobexample.txt'; // the file with text to be inserted into the database +const inFileName = 'clobexample.txt'; // the file with text to be inserted into the database async function run() { @@ -47,8 +45,7 @@ async function run() { try { connection = await oracledb.getConnection(dbConfig); - // Cleanup anything other than lobinsert1.js demonstration data - await connection.execute(`DELETE FROM mylobs WHERE id > 2`); + await demoSetup.setupLobs(connection); // create the demo table // Create an empty Temporary Lob const tempLob = await connection.createLob(oracledb.CLOB); @@ -79,7 +76,7 @@ async function run() { }); console.log('Reading from ' + inFileName); - var inStream = fs.createReadStream(inFileName); + const inStream = fs.createReadStream(inFileName); inStream.on('error', (err) => { // console.log("inStream.on 'error' event"); if (!errorHandled) { diff --git a/javascript/node-oracledb/lobselect.js b/javascript/node-oracledb/lobselect.js index ba6971d5..6e74d9f8 100644 --- a/javascript/node-oracledb/lobselect.js +++ b/javascript/node-oracledb/lobselect.js @@ -24,12 +24,6 @@ * * 'Large' LOBs should be streamed as shown in lobstream1.js * - * Use demo.sql to create the required table or do: - * DROP TABLE mylobs; - * CREATE TABLE mylobs (id NUMBER, c CLOB, b BLOB); - * - * Run lobinsert1.js to load data before running this example. - * * This example requires node-oracledb 1.13 or later. * * This example uses Node 8's async/await syntax. @@ -39,6 +33,7 @@ const fs = require('fs'); const oracledb = require('oracledb'); const dbConfig = require('./dbconfig.js'); +const demoSetup = require('./demosetup.js'); const blobOutFileName = 'lobselectout.jpg'; // file to write the BLOB to @@ -55,11 +50,13 @@ async function run() { try { connection = await oracledb.getConnection(dbConfig); + await demoSetup.setupLobs(connection, true); // create the demo table with data + let result; // Fetch a CLOB result = await connection.execute( - `SELECT c FROM mylobs WHERE id = :idbv`, + `SELECT c FROM no_lobs WHERE id = :idbv`, [1] // An alternative to oracledb.fetchAsString is to pass execute() // options and use fetchInfo on the column: @@ -67,7 +64,7 @@ async function run() { ); if (result.rows.length === 0) - throw new Error("No results. Did you run lobinsert1.js?"); + throw new Error("No row found"); const clob = result.rows[0][0]; console.log('The CLOB was: '); @@ -76,14 +73,14 @@ async function run() { // Fetch a BLOB result = await connection.execute( - `SELECT b FROM mylobs WHERE id = :idbv`, + `SELECT b FROM no_lobs WHERE id = :idbv`, [2] // An alternative to oracledb.fetchAsBuffer is to use fetchInfo on the column: // , { fetchInfo: {"B": {type: oracledb.BUFFER}} } ); if (result.rows.length === 0) - throw new Error("No results. Did you run lobinsert1.js?"); + throw new Error("No row found"); const blob = result.rows[0][0]; console.log('Writing BLOB to lobselectout.jpg'); diff --git a/javascript/node-oracledb/lobstream1.js b/javascript/node-oracledb/lobstream1.js index dc7f4d96..e880ff63 100644 --- a/javascript/node-oracledb/lobstream1.js +++ b/javascript/node-oracledb/lobstream1.js @@ -21,21 +21,16 @@ * DESCRIPTION * SELECTs a CLOB and a BLOB and streams to files. * - * Use demo.sql to create the required table or do: - * DROP TABLE mylobs; - * CREATE TABLE mylobs (id NUMBER, c CLOB, b BLOB); - * - * Run lobinsert1.js to load data before running this example. - * * This example requires node-oracledb 1.12 or later. * * This example uses Node 8's async/await syntax. * *****************************************************************************/ -var fs = require('fs'); -var oracledb = require('oracledb'); -var dbConfig = require('./dbconfig.js'); +const fs = require('fs'); +const oracledb = require('oracledb'); +const dbConfig = require('./dbconfig.js'); +const demoSetup = require('./demosetup.js'); // Stream a LOB to a file async function doStream(lob, outFileName) { @@ -94,12 +89,14 @@ async function run() { try { connection = await oracledb.getConnection(dbConfig); + await demoSetup.setupLobs(connection, true); // create the demo table + // // Fetch a CLOB and stream it // - let result = await connection.execute(`SELECT c FROM mylobs WHERE id = 1`); + let result = await connection.execute(`SELECT c FROM no_lobs WHERE id = 1`); if (result.rows.length === 0) { - throw new Error("No results. Did you run lobinsert1.js?"); + throw new Error("No row found"); } let lob = result.rows[0][0]; if (lob === null) { @@ -110,9 +107,9 @@ async function run() { // // Fetch a BLOB and stream it // - result = await connection.execute(`SELECT b FROM mylobs WHERE id = 2`); + result = await connection.execute(`SELECT b FROM no_lobs WHERE id = 2`); if (result.rows.length === 0) { - throw new Error("No results. Did you run lobinsert1.js?"); + throw new Error("No row found"); } lob = result.rows[0][0]; if (lob === null) { diff --git a/javascript/node-oracledb/lobstream2.js b/javascript/node-oracledb/lobstream2.js index b166f9c3..c716d34b 100644 --- a/javascript/node-oracledb/lobstream2.js +++ b/javascript/node-oracledb/lobstream2.js @@ -21,20 +21,15 @@ * DESCRIPTION * SELECTs a CLOB, streams it using 'data' events, and then displays it to the screen * - * Use demo.sql to create the required table or do: - * DROP TABLE mylobs; - * CREATE TABLE mylobs (id NUMBER, c CLOB, b BLOB); - * - * Run lobinsert1.js to load data before running this example. - * * This example requires node-oracledb 1.12 or later. * * This example uses Node 8's async/await syntax. * *****************************************************************************/ -var oracledb = require('oracledb'); -var dbConfig = require('./dbconfig.js'); +const oracledb = require('oracledb'); +const dbConfig = require('./dbconfig.js'); +const demoSetup = require('./demosetup.js'); async function run() { let connection; @@ -42,12 +37,14 @@ async function run() { try { connection = await oracledb.getConnection(dbConfig); + await demoSetup.setupLobs(connection, true); // create the demo table with data + // // Fetch a CLOB and write to the console // - let result = await connection.execute(`SELECT c FROM mylobs WHERE id = 1`); + let result = await connection.execute(`SELECT c FROM no_lobs WHERE id = 1`); if (result.rows.length === 0) { - throw new Error("No results. Did you run lobinsert1.js?"); + throw new Error("No row found"); } const clob = result.rows[0][0]; if (clob === null) { diff --git a/javascript/node-oracledb/metadata.js b/javascript/node-oracledb/metadata.js index b60e2720..9607e6c4 100644 --- a/javascript/node-oracledb/metadata.js +++ b/javascript/node-oracledb/metadata.js @@ -20,10 +20,6 @@ * * DESCRIPTION * Shows default and extended query column metadata - * Uses Oracle's sample HR schema. - * - * Scripts to create the HR schema can be found at: - * https://github.com/oracle/db-sample-schemas * * This example requires node-oracledb 1.10 or later. * @@ -33,6 +29,7 @@ const oracledb = require('oracledb'); const dbConfig = require('./dbconfig.js'); +const demoSetup = require('./demosetup.js'); async function run() { @@ -41,17 +38,19 @@ async function run() { try { connection = await oracledb.getConnection(dbConfig); + await demoSetup.setupBf(connection); // create the demo table + console.log('Default query metadata'); let result = await connection.execute( - `SELECT location_id, city - FROM locations`); + `SELECT id, farmer, picked + FROM no_banana_farmer`); console.log(result.metaData); console.log('Extended query metadata'); result = await connection.execute( - `SELECT location_id, city - FROM locations`, - {}, // no binds + `SELECT id, farmer, picked + FROM no_banana_farmer`, + {}, // no binds { extendedMetaData: true }); // enable the extra metadata console.log(result.metaData); diff --git a/javascript/node-oracledb/plsqlarray.js b/javascript/node-oracledb/plsqlarray.js index 0f725398..11f4ed17 100644 --- a/javascript/node-oracledb/plsqlarray.js +++ b/javascript/node-oracledb/plsqlarray.js @@ -25,8 +25,6 @@ * that table and returns the values. The third procedure accepts * arrays, and returns the values sorted by the beach name. * - * Use demo.sql to create the required tables and package. - * * This example requires node-oracledb 1.6 or later. * * This example uses Node 8's async/await syntax. @@ -43,13 +41,74 @@ async function run() { try { connection = await oracledb.getConnection(dbConfig); + // + // Create table and package + // + + const stmts = [ + `DROP TABLE no_waveheight`, + + `CREATE TABLE no_waveheight (beach VARCHAR2(50), depth NUMBER)`, + + `CREATE OR REPLACE PACKAGE no_beachpkg IS + TYPE beachType IS TABLE OF VARCHAR2(30) INDEX BY BINARY_INTEGER; + TYPE depthType IS TABLE OF NUMBER INDEX BY BINARY_INTEGER; + PROCEDURE array_in(beaches IN beachType, depths IN depthType); + PROCEDURE array_out(beaches OUT beachType, depths OUT depthType); + PROCEDURE array_inout(beaches IN OUT beachType, depths IN OUT depthType); + END;`, + + `CREATE OR REPLACE PACKAGE BODY no_beachpkg IS + + -- Insert array values into a table + PROCEDURE array_in(beaches IN beachType, depths IN depthType) IS + BEGIN + IF beaches.COUNT <> depths.COUNT THEN + RAISE_APPLICATION_ERROR(-20000, 'Array lengths must match for this example.'); + END IF; + FORALL i IN INDICES OF beaches + INSERT INTO no_waveheight (beach, depth) VALUES (beaches(i), depths(i)); + END; + + -- Return the values from a table + PROCEDURE array_out(beaches OUT beachType, depths OUT depthType) IS + BEGIN + SELECT beach, depth BULK COLLECT INTO beaches, depths FROM no_waveheight; + END; + + -- Return the arguments sorted + PROCEDURE array_inout(beaches IN OUT beachType, depths IN OUT depthType) IS + BEGIN + IF beaches.COUNT <> depths.COUNT THEN + RAISE_APPLICATION_ERROR(-20001, 'Array lengths must match for this example.'); + END IF; + FORALL i IN INDICES OF beaches + INSERT INTO no_waveheight (beach, depth) VALUES (beaches(i), depths(i)); + SELECT beach, depth BULK COLLECT INTO beaches, depths FROM no_waveheight ORDER BY 1; + END; + + END;` + ]; + + for (const s of stmts) { + try { + await connection.execute(s); + } catch(e) { + if (e.errorNum != 942) + console.error(e); + } + } + let result; + // // PL/SQL array bind IN parameters: // Pass arrays of values to a PL/SQL procedure + // + await connection.execute( `BEGIN - beachpkg.array_in(:beach_in, :depth_in); + no_beachpkg.array_in(:beach_in, :depth_in); END;`, { beach_in: @@ -60,14 +119,18 @@ async function run() { { type : oracledb.NUMBER, dir: oracledb.BIND_IN, val: [45, 30, 67] } - }); + } + ); console.log('Data was bound in successfully'); + // // PL/SQL array bind OUT parameters: // Fetch arrays of values from a PL/SQL procedure + // + result = await connection.execute( `BEGIN - beachpkg.array_out(:beach_out, :depth_out); + no_beachpkg.array_out(:beach_out, :depth_out); END;`, { beach_out: @@ -78,15 +141,19 @@ async function run() { { type: oracledb.NUMBER, dir: oracledb.BIND_OUT, maxArraySize: 3 } - }); + } + ); console.log("Binds returned:"); console.log(result.outBinds); + // // PL/SQL array bind IN OUT parameters: // Return input arrays sorted by beach name + // + result = await connection.execute( `BEGIN - beachpkg.array_inout(:beach_inout, :depth_inout); + no_beachpkg.array_inout(:beach_inout, :depth_inout); END;`, { beach_inout: @@ -99,7 +166,8 @@ async function run() { dir: oracledb.BIND_INOUT, val: [8, 3, 70], maxArraySize: 6 } - }); + } + ); console.log("Binds returned:"); console.log(result.outBinds); diff --git a/javascript/node-oracledb/plsqlfunc.js b/javascript/node-oracledb/plsqlfunc.js index 7bb1f9bc..7c6bb2f4 100644 --- a/javascript/node-oracledb/plsqlfunc.js +++ b/javascript/node-oracledb/plsqlfunc.js @@ -19,15 +19,7 @@ * plsqlfunc.js * * DESCRIPTION - * Show calling a PL/SQL function - * Use demo.sql to create the required function or do: - * - * CREATE OR REPLACE FUNCTION testfunc (p1_in IN VARCHAR2, p2_in IN VARCHAR2) RETURN VARCHAR2 - * AS - * BEGIN - * RETURN p1_in || p2_in; - * END; - * / + * Shows how to call a PL/SQL function. * * This example uses Node 8's async/await syntax. * @@ -43,16 +35,27 @@ async function run() { try { connection = await oracledb.getConnection(dbConfig); + // Create a PL/SQL stored procedure + + await connection.execute( + `CREATE OR REPLACE FUNCTION no_func + (p1_in IN VARCHAR2, p2_in IN VARCHAR2) RETURN VARCHAR2 + AS + BEGIN + RETURN p1_in || ' ' || p2_in; + END;` + ); + // Invoke the PL/SQL function. // // The equivalent call with PL/SQL named parameter syntax is: // `BEGIN - // :ret := testfunc(p1_in => :p1, p2_in => :p2); + // :ret := no_func(p1_in => :p1, p2_in => :p2); // END;` const result = await connection.execute( `BEGIN - :ret := testfunc(:p1, :p2); + :ret := no_func(:p1, :p2); END;`, { p1: 'Chris', // Bind type is determined from the data. Default direction is BIND_IN diff --git a/javascript/node-oracledb/plsqlproc.js b/javascript/node-oracledb/plsqlproc.js index 2e2736fe..4a0b79b9 100644 --- a/javascript/node-oracledb/plsqlproc.js +++ b/javascript/node-oracledb/plsqlproc.js @@ -19,16 +19,7 @@ * plsqlproc.js * * DESCRIPTION - * Show calling a PL/SQL procedure and binding parameters in various ways - * Use demo.sql to create the required procedure or do: - * - * CREATE OR REPLACE PROCEDURE testproc (p_in IN VARCHAR2, p_inout IN OUT VARCHAR2, p_out OUT NUMBER) - * AS - * BEGIN - * p_inout := p_in || p_inout; - * p_out := 101; - * END; - * / + * Show calling a PL/SQL procedure and binding parameters in various ways. * * This example uses Node 8's async/await syntax. * @@ -44,22 +35,35 @@ async function run() { try { connection = await oracledb.getConnection(dbConfig); - // Invoke the Pl/SQL stored procedure. + // Create a PL/SQL stored procedure + + await connection.execute( + `CREATE OR REPLACE PROCEDURE no_proc + (p_in IN VARCHAR2, p_inout IN OUT VARCHAR2, p_out OUT NUMBER) + AS + BEGIN + p_inout := p_in || p_inout; + p_out := 101; + END;` + ); + + // Invoke the PL/SQL stored procedure. // // The equivalent call with PL/SQL named parameter syntax is: // `BEGIN - // testproc(p_in => :i, p_inout => :io, p_out => :o); + // no_proc(p_in => :i, p_inout => :io, p_out => :o); // END;` const result = await connection.execute( `BEGIN - testproc(:i, :io, :o); + no_proc(:i, :io, :o); END;`, { i: 'Chris', // Bind type is determined from the data. Default direction is BIND_IN io: { val: 'Jones', dir: oracledb.BIND_INOUT }, o: { type: oracledb.NUMBER, dir: oracledb.BIND_OUT } - }); + } + ); console.log(result.outBinds); diff --git a/javascript/node-oracledb/plsqlrecord.js b/javascript/node-oracledb/plsqlrecord.js index 114050ec..a9036882 100644 --- a/javascript/node-oracledb/plsqlrecord.js +++ b/javascript/node-oracledb/plsqlrecord.js @@ -42,25 +42,37 @@ async function run() { connection = await oracledb.getConnection(dbConfig); + // // Create a PL/SQL package that uses a RECORD + // - await connection.execute( + const stmts = [ `CREATE OR REPLACE PACKAGE rectest AS TYPE rectype IS RECORD (name VARCHAR2(40), pos NUMBER); PROCEDURE myproc (p_in IN rectype, p_out OUT rectype); - END rectest;`); + END rectest;`, - await connection.execute( `CREATE OR REPLACE PACKAGE BODY rectest AS PROCEDURE myproc (p_in IN rectype, p_out OUT rectype) AS BEGIN p_out := p_in; p_out.pos := p_out.pos * 2; END; - END rectest;`); + END rectest;` + ]; + + for (const s of stmts) { + try { + await connection.execute(s); + } catch(e) { + console.error(e); + } + } + // // Get the RECORD prototype object + // const RecTypeClass = await connection.getDbObjectClass("RECTEST.RECTYPE"); // console.log(RecTypeClass.prototype); diff --git a/javascript/node-oracledb/plsqlvarrayrecord.js b/javascript/node-oracledb/plsqlvarrayrecord.js index b620d642..fbca68d0 100644 --- a/javascript/node-oracledb/plsqlvarrayrecord.js +++ b/javascript/node-oracledb/plsqlvarrayrecord.js @@ -41,16 +41,12 @@ async function run() { // Create a PL/SQL package that uses a RECORD - let stmts = [ + const stmts = [ `CREATE OR REPLACE PACKAGE netball AS - TYPE playerType IS RECORD (name VARCHAR2(40), position varchar2(20), shirtnumber NUMBER); - TYPE teamType IS VARRAY(10) OF playerType; - PROCEDURE assignShirtNumbers (t_in IN teamType, t_out OUT teamType); - END netball;`, diff --git a/javascript/node-oracledb/raw1.js b/javascript/node-oracledb/raw.js similarity index 79% rename from javascript/node-oracledb/raw1.js rename to javascript/node-oracledb/raw.js index 9d240f88..f99a9e49 100644 --- a/javascript/node-oracledb/raw1.js +++ b/javascript/node-oracledb/raw.js @@ -20,10 +20,6 @@ * * DESCRIPTION * Shows using a Buffer to insert and select a RAW. - * Use demo.sql to create the dependencies or do: - * - * DROP TABLE myraw; - * CREATE TABLE myraw (r RAW(64)); * * This example requires node-oracledb 1.2 or later. * @@ -41,14 +37,41 @@ async function run() { try { connection = await oracledb.getConnection(dbConfig); + // + // Create table + // + + const stmts = [ + `DROP TABLE no_raw`, + + `CREATE TABLE no_raw (r RAW(64))` + ]; + + for (const s of stmts) { + try { + await connection.execute(s); + } catch(e) { + if (e.errorNum != 942) + console.error(e); + } + } + + // + // Insert RAW data + // + const data = [0x48, 0x65, 0x6c, 0x6c, 0x6f, 0x2c, 0x20, 0x4f, 0x72, 0x61, 0x63, 0x6c, 0x65, 0x21]; const inBuf = Buffer.from(data); let result = await connection.execute( - `INSERT INTO myraw VALUES (:r)`, + `INSERT INTO no_raw VALUES (:r)`, { r : { val: inBuf, type: oracledb.BUFFER, dir:oracledb.BIND_IN }}); console.log(result.rowsAffected + " row(s) inserted."); - result = await connection.execute(`SELECT r FROM myraw`); + // + // Fetch RAW data + // + + result = await connection.execute(`SELECT r FROM no_raw`); const outBuf = result.rows[0]; console.log("Buffer queried:"); console.log(outBuf); diff --git a/javascript/node-oracledb/refcursor.js b/javascript/node-oracledb/refcursor.js index d6e364ff..5420abad 100644 --- a/javascript/node-oracledb/refcursor.js +++ b/javascript/node-oracledb/refcursor.js @@ -22,27 +22,15 @@ * Shows using a ResultSet to fetch rows from a REF CURSOR using getRows(). * Streaming is also possible (this is not shown). * - * Uses Oracle's sample HR schema. - * Use demo.sql to create the required procedure or do: - * - * CREATE OR REPLACE PROCEDURE get_emp_rs (p_sal IN NUMBER, p_recordset OUT SYS_REFCURSOR) - * AS - * BEGIN - * OPEN p_recordset FOR - * SELECT first_name, salary, hire_date - * FROM employees - * WHERE salary > p_sal; - * END; - * / - * * This example uses Node 8's async/await syntax. * *****************************************************************************/ const oracledb = require('oracledb'); const dbConfig = require('./dbconfig.js'); +const demoSetup = require('./demosetup.js'); -const numRows = 3; // number of rows to return from each call to getRows() +const numRows = 10; // number of rows to return from each call to getRows() async function run() { @@ -51,23 +39,48 @@ async function run() { try { connection = await oracledb.getConnection(dbConfig); + await demoSetup.setupBf(connection); // create the demo table + + // + // Create a PL/SQL procedure + // + + await connection.execute( + `CREATE OR REPLACE PROCEDURE no_get_rs (p_id IN NUMBER, p_recordset OUT SYS_REFCURSOR) + AS + BEGIN + OPEN p_recordset FOR + SELECT farmer, weight, ripeness + FROM no_banana_farmer + WHERE id < p_id; + END;` + ); + + // + // Get a REF CURSOR result set + // + const result = await connection.execute( `BEGIN - get_emp_rs(:sal, :cursor); + no_get_rs(:id, :cursor); END;`, { - sal: 12000, - cursor: { type: oracledb.CURSOR, dir : oracledb.BIND_OUT } + id: 3, + cursor: { type: oracledb.CURSOR, dir: oracledb.BIND_OUT } }); console.log("Cursor metadata:"); console.log(result.outBinds.cursor.metaData); + // // Fetch rows from the REF CURSOR. + // + // // If getRows(numRows) returns: // Zero rows => there were no rows, or are no more rows to return // Fewer than numRows rows => this was the last set of rows to get // Exactly numRows rows => there may be more rows to fetch + const resultSet = result.outBinds.cursor; let rows; do { diff --git a/javascript/node-oracledb/refcursortoquerystream.js b/javascript/node-oracledb/refcursortoquerystream.js index 2872506d..cd2b200b 100644 --- a/javascript/node-oracledb/refcursortoquerystream.js +++ b/javascript/node-oracledb/refcursortoquerystream.js @@ -23,9 +23,6 @@ * This is an alternative means of processing instead of using * resultSet.getRows(). * - * Scripts to create the HR schema can be found at: - * https://github.com/oracle/db-sample-schemas - * * This example requires node-oracledb 1.9 or later. * * This example uses Node 8's async/await syntax. @@ -34,6 +31,7 @@ const oracledb = require('oracledb'); const dbConfig = require('./dbconfig.js'); +const demoSetup = require('./demosetup.js'); async function run() { let connection; @@ -41,11 +39,14 @@ async function run() { try { connection = await oracledb.getConnection(dbConfig); + await demoSetup.setupBf(connection); // create the demo table + const result = await connection.execute( `BEGIN OPEN :cursor FOR - SELECT department_id, department_name - FROM departments; + SELECT id, farmer + FROM no_banana_farmer + ORDER BY id; END;`, { cursor: { diff --git a/javascript/node-oracledb/resultset1.js b/javascript/node-oracledb/resultset1.js index ac0c60ca..f166853e 100644 --- a/javascript/node-oracledb/resultset1.js +++ b/javascript/node-oracledb/resultset1.js @@ -20,10 +20,6 @@ * * DESCRIPTION * Executes a query and uses a ResultSet to fetch rows with getRow(). - * Uses Oracle's sample HR schema. - * - * Note using queryStream() or getRows() is recommended instead of - * getRow(). * * This example requires node-oracledb 2.0.15 or later. * @@ -33,6 +29,7 @@ const oracledb = require('oracledb'); const dbConfig = require('./dbconfig.js'); +const demoSetup = require('./demosetup.js'); // For getRow(), the fetchArraySize property can be adjusted to tune // data transfer from the Oracle Database to node-oracledb. The value @@ -49,11 +46,12 @@ async function run() { try { connection = await oracledb.getConnection(dbConfig); + await demoSetup.setupBf(connection); // create the demo table + const result = await connection.execute( - `SELECT employee_id, last_name - FROM employees - WHERE ROWNUM < 5 - ORDER BY employee_id`, + `SELECT id, farmer + FROM no_banana_farmer + ORDER BY id`, [], // no bind variables { resultSet: true // return a ResultSet (default is false) @@ -71,6 +69,7 @@ async function run() { // always close the ResultSet await rs.close(); + } catch (err) { console.error(err); } finally { diff --git a/javascript/node-oracledb/resultset2.js b/javascript/node-oracledb/resultset2.js index 8ffc900b..dcce5eb4 100644 --- a/javascript/node-oracledb/resultset2.js +++ b/javascript/node-oracledb/resultset2.js @@ -21,7 +21,6 @@ * DESCRIPTION * Executes a query and uses a ResultSet to fetch batches of rows * with getRows(). Also shows setting the fetch array size. - * Uses Oracle's sample HR schema. * * This example uses Node 8's async/await syntax. * @@ -29,9 +28,10 @@ const oracledb = require('oracledb'); const dbConfig = require('./dbconfig.js'); +const demoSetup = require('./demosetup.js'); // Number of rows to return from each call to getRows() -const numRows = 10; +const numRows = 2; async function run() { let connection; @@ -39,11 +39,12 @@ async function run() { try { connection = await oracledb.getConnection(dbConfig); + await demoSetup.setupBf(connection); // create the demo table + const result = await connection.execute( - `SELECT employee_id, last_name - FROM employees - WHERE ROWNUM < 25 - ORDER BY employee_id`, + `SELECT id, farmer + FROM no_banana_farmer + ORDER BY id`, [], // no bind variables { resultSet: true // return a ResultSet (default is false) diff --git a/javascript/node-oracledb/resultsettoquerystream.js b/javascript/node-oracledb/resultsettoquerystream.js index 178111ae..40604179 100644 --- a/javascript/node-oracledb/resultsettoquerystream.js +++ b/javascript/node-oracledb/resultsettoquerystream.js @@ -22,15 +22,13 @@ * Converts a ResultSet returned from execute() into a Readable Stream. * This is an alternative to using resultset.getRows(). * - * Scripts to create the HR schema can be found at: - * https://github.com/oracle/db-sample-schemas - * * This example uses Node 8's async/await syntax. * *****************************************************************************/ const oracledb = require('oracledb'); const dbConfig = require('./dbconfig.js'); +const demoSetup = require('./demosetup.js'); async function run() { let connection; @@ -38,10 +36,12 @@ async function run() { try { connection = await oracledb.getConnection(dbConfig); + await demoSetup.setupBf(connection); // create the demo table + const result = await connection.execute( - `SELECT employee_id, last_name - FROM employees WHERE ROWNUM < 25 - ORDER BY employee_id`, + `SELECT id, farmer + FROM no_banana_farmer + ORDER BY id`, [], { resultSet: true diff --git a/javascript/node-oracledb/rowlimit.js b/javascript/node-oracledb/rowlimit.js index a6a3d5e2..a59f06cf 100644 --- a/javascript/node-oracledb/rowlimit.js +++ b/javascript/node-oracledb/rowlimit.js @@ -20,16 +20,12 @@ * * DESCRIPTION * Shows ways to limit the number of records fetched by queries. - * Uses Oracle's sample HR schema. * - * Scripts to create the HR schema can be found at: - * https://github.com/oracle/db-sample-schemas/releases - * - * Although adjusting maxRows can be used to control the number of - * rows available to the application, it is more efficient for the - * database if the SQL query syntax limits the number of rows - * returned from the database. Use maxRows to prevent badly coded - * queries from over-consuming Node.js resources. + * Although maxRows can be used to control the number of rows available to the + * application, it is more efficient for the database if the SQL query syntax + * limits the number of rows returned from the database. Use maxRows to + * prevent badly coded queries from over-consuming Node.js resources, or when + * the number of rows to be selected is a known, small value. * * This example uses Node 8's async/await syntax. * @@ -37,9 +33,10 @@ const oracledb = require('oracledb'); const dbConfig = require('./dbconfig.js'); +const demoSetup = require('./demosetup.js'); -const myoffset = 2; // number of rows to skip -const mymaxnumrows = 6; // number of rows to fetch +const myoffset = 1; // number of rows to skip +const mymaxnumrows = 2; // number of rows to fetch async function run() { @@ -48,20 +45,23 @@ async function run() { try { connection = await oracledb.getConnection(dbConfig); - let sql = `SELECT employee_id, last_name FROM employees ORDER BY employee_id`; + await demoSetup.setupBf(connection); // create the demo table + + let sql = `SELECT id, farmer FROM no_banana_farmer ORDER BY id`; if (connection.oracleServerVersion >= 1201000000) { // 12c row-limiting syntax sql += ` OFFSET :offset ROWS FETCH NEXT :maxnumrows ROWS ONLY`; } else { - // Pre-12c syntax [could also customize the original query and use row_number()] + // Pre-12c syntax [you could also customize the original query and use row_number()] sql = `SELECT * FROM (SELECT A.*, ROWNUM AS MY_RNUM FROM ( ${sql} ) A - WHERE ROWNUM <= :maxnumrows + :offset) WHERE MY_RNUM > :offset`; + WHERE ROWNUM <= :maxnumrows + :offset) WHERE MY_RNUM > :offset`; } const result = await connection.execute( sql, - { offset: myoffset, maxnumrows: mymaxnumrows }); + { offset: myoffset, maxnumrows: mymaxnumrows } + ); console.log("Executed: " + sql); console.log("Number of rows returned: " + result.rows.length); diff --git a/javascript/node-oracledb/select1.js b/javascript/node-oracledb/select1.js index 980260c4..01948d9c 100644 --- a/javascript/node-oracledb/select1.js +++ b/javascript/node-oracledb/select1.js @@ -20,10 +20,6 @@ * * DESCRIPTION * Executes a basic query without using a connection pool or ResultSet. - * Uses Oracle's sample HR schema. - * - * Scripts to create the HR schema can be found at: - * https://github.com/oracle/db-sample-schemas * * For a connection pool example see connectionpool.js * For a ResultSet example see resultset2.js @@ -37,6 +33,7 @@ const oracledb = require('oracledb'); const dbConfig = require('./dbconfig.js'); +const demoSetup = require('./demosetup.js'); async function run() { @@ -45,20 +42,18 @@ async function run() { try { // Get a non-pooled connection - connection = await oracledb.getConnection( { - user : dbConfig.user, - password : dbConfig.password, - connectString: dbConfig.connectString - }); + connection = await oracledb.getConnection(dbConfig); + + await demoSetup.setupBf(connection); // create the demo table const result = await connection.execute( // The statement to execute - `SELECT department_id, department_name - FROM departments - WHERE department_id = :id`, + `SELECT farmer, picked, ripeness + FROM no_banana_farmer + where id = :idbv`, - // The "bind value" 180 for the bind variable ":id" - [180], + // The "bind value" 3 for the bind variable ":idbv" + [3], // Options argument. Since the query only returns one // row, we can optimize memory usage by reducing the default @@ -67,19 +62,19 @@ async function run() { { maxRows: 1 //, outFormat: oracledb.OUT_FORMAT_OBJECT // query result format - //, extendedMetaData: true // get extra metadata - //, fetchArraySize: 100 // internal buffer allocation size for tuning + //, extendedMetaData: true // get extra metadata + //, fetchArraySize: 100 // internal buffer allocation size for tuning }); - console.log(result.metaData); // [ { name: 'DEPARTMENT_ID' }, { name: 'DEPARTMENT_NAME' } ] - console.log(result.rows); // [ [ 180, 'Construction' ] ] + console.log(result.metaData); // [ { name: 'FARMER' }, { name: 'PICKED' }, { name: 'RIPENESS' } ] + console.log(result.rows); // [ [ 'Mindy', 2019-07-16T03:30:00.000Z, 'More Yellow than Green' ] ] } catch (err) { console.error(err); } finally { if (connection) { try { - // Note: connections should always be released when not needed + // Connections should always be released when not needed await connection.close(); } catch (err) { console.error(err); diff --git a/javascript/node-oracledb/select2.js b/javascript/node-oracledb/select2.js index 6586bab9..8beb74a9 100644 --- a/javascript/node-oracledb/select2.js +++ b/javascript/node-oracledb/select2.js @@ -21,10 +21,6 @@ * DESCRIPTION * Executes queries to show array and object output formats. * Gets results directly without using a ResultSet. - * Uses Oracle's sample HR schema. - * - * Scripts to create the HR schema can be found at: - * https://github.com/oracle/db-sample-schemas * * This example uses Node 8's async/await syntax. * @@ -34,6 +30,7 @@ const oracledb = require('oracledb'); const dbConfig = require('./dbconfig.js'); +const demoSetup = require('./demosetup.js'); // Oracledb properties are applicable to all connections and SQL // executions. They can also be set or overridden at the individual @@ -58,24 +55,21 @@ async function run() { try { // Get a non-pooled connection - connection = await oracledb.getConnection( { - user : dbConfig.user, - password : dbConfig.password, - connectString: dbConfig.connectString - }); + connection = await oracledb.getConnection(dbConfig); + + await demoSetup.setupBf(connection); // create the demo table // The statement to execute const sql = - `SELECT location_id, city - FROM locations - WHERE city LIKE 'S%' - ORDER BY city`; + `SELECT farmer, picked, ripeness + FROM no_banana_farmer + ORDER BY id`; let result; // Default Array Output Format result = await connection.execute(sql); - console.log("----- Cities beginning with 'S' (default ARRAY output format) --------"); + console.log("----- Banana Farmers (default ARRAY output format) --------"); console.log(result.rows); // Optional Object Output Format @@ -83,7 +77,7 @@ async function run() { sql, {}, // A bind parameter is needed to disambiguate the following options parameter and avoid ORA-01036 { outFormat: oracledb.OUT_FORMAT_OBJECT }); // outFormat can be OBJECT or ARRAY. The default is ARRAY - console.log("----- Cities beginning with 'S' (OBJECT output format) --------"); + console.log("----- Banana Farmers (default OBJECT output format) --------"); console.log(result.rows); } catch (err) { @@ -91,7 +85,7 @@ async function run() { } finally { if (connection) { try { - // Note: connections should always be released when not needed + // Connections should always be released when not needed await connection.close(); } catch (err) { console.error(err); diff --git a/javascript/node-oracledb/selectgeometry.js b/javascript/node-oracledb/selectgeometry.js index d27374d4..23c6909f 100644 --- a/javascript/node-oracledb/selectgeometry.js +++ b/javascript/node-oracledb/selectgeometry.js @@ -43,18 +43,20 @@ async function run() { // // Setup // + const stmts = [ + `DROP TABLE no_geometry`, - await connection.execute( - `BEGIN - EXECUTE IMMEDIATE 'DROP TABLE testgeometry'; - EXCEPTION WHEN OTHERS THEN - IF SQLCODE <> -942 THEN - RAISE; - END IF; - END;`); + `CREATE TABLE no_geometry (id NUMBER, geometry MDSYS.SDO_GEOMETRY)` + ]; - await connection.execute( - `CREATE TABLE testgeometry (id NUMBER, geometry MDSYS.SDO_GEOMETRY)`); + for (const s of stmts) { + try { + await connection.execute(s); + } catch(e) { + if (e.errorNum != 942) + console.error(e); + } + } // // Get a prototype object for the database SDO_GEOMETRY type. @@ -86,7 +88,7 @@ async function run() { ); await connection.execute( - `INSERT INTO testgeometry (id, geometry) VALUES (:id, :g)`, + `INSERT INTO no_geometry (id, geometry) VALUES (:id, :g)`, {id: 1, g: geometry1} ); @@ -96,7 +98,7 @@ async function run() { // await connection.execute( - `INSERT INTO testgeometry (id, geometry) VALUES (:id, :g)`, + `INSERT INTO no_geometry (id, geometry) VALUES (:id, :g)`, { id: 2, g: { type: 'MDSYS.SDO_GEOMETRY', // the name of the top-level database type, case sensitive @@ -104,7 +106,7 @@ async function run() { SDO_GTYPE: 2003, SDO_SRID: null, SDO_POINT: null, - SDO_ELEM_INFO: [ 4, 1003, 3 ], + SDO_ELEM_INFO: [ 1, 1003, 3 ], SDO_ORDINATES: [ 4, 8, 5, 9 ] } } @@ -116,7 +118,7 @@ async function run() { // result = await connection.execute( - `SELECT id, geometry FROM testgeometry`, + `SELECT id, geometry FROM no_geometry`, [], // outFormat determines whether rows will be in arrays or JavaScript objects. // It does not affect how the GEOMETRY column itself is represented. diff --git a/javascript/node-oracledb/selectjson.js b/javascript/node-oracledb/selectjson.js index fc6255ef..75671482 100644 --- a/javascript/node-oracledb/selectjson.js +++ b/javascript/node-oracledb/selectjson.js @@ -20,15 +20,9 @@ * * DESCRIPTION * Shows some JSON features of Oracle Database 12c. - * Requires Oracle Database 12.1.0.2, which has extensive JSON datatype support. - * See https://www.oracle.com/pls/topic/lookup?ctx=dblatest&id=ADJSN - * - * Uses Oracle's sample HR schema. - * Also run demo.sql to create the required extra table or do: * - * DROP TABLE j_purchaseorder; - * CREATE TABLE j_purchaseorder - * (po_document VARCHAR2(4000) CONSTRAINT ensure_json CHECK (po_document IS JSON)); + * Requires at least Oracle Database 12.1.0.2, which has extensive JSON datatype support. + * See https://www.oracle.com/pls/topic/lookup?ctx=dblatest&id=ADJSN * * This example uses Node 8's async/await syntax. * @@ -48,28 +42,48 @@ async function run() { throw new Error('This example only works with Oracle Database 12.1.0.2 or greater'); } + const stmts = [ + `DROP TABLE no_purchaseorder`, + + // Note if your applications always insert valid JSON, you may delete + // the IS JSON check to remove its additional validation overhead. + `CREATE TABLE no_purchaseorder (po_document VARCHAR2(4000) CHECK (po_document IS JSON))` + ]; + + for (const s of stmts) { + try { + await connection.execute(s); + } catch(e) { + if (e.errorNum != 942) + console.error(e); + } + } + let result; console.log('Inserting Data'); const data = { "userId": 1, "userName": "Chris", "location": "Australia" }; const s = JSON.stringify(data); await connection.execute( - `INSERT INTO j_purchaseorder (po_document) VALUES (:bv)`, + `INSERT INTO no_purchaseorder (po_document) VALUES (:bv)`, [s], // bind the JSON string for inserting into the JSON column. - { autoCommit: true }); + { autoCommit: true } + ); console.log('1. Selecting JSON stored in a VARCHAR2 column'); result = await connection.execute( `SELECT po_document - FROM j_purchaseorder - WHERE JSON_EXISTS (po_document, '$.location')`); + FROM no_purchaseorder + WHERE JSON_EXISTS (po_document, '$.location')` + ); const js = JSON.parse(result.rows[0][0]); // just show first record console.log('Query results: ', js); console.log('2. Using JSON_VALUE to extract a value from a JSON column'); result = await connection.execute( `SELECT JSON_VALUE(po_document, '$.location') - FROM j_purchaseorder`); + FROM no_purchaseorder` + ); console.log('Query results: ', result.rows[0][0]); // just show first record if (connection.oracleServerVersion < 1202000000) { @@ -79,15 +93,15 @@ async function run() { console.log('3. Using dot-notation to extract a value from a JSON column'); result = await connection.execute( `SELECT po.po_document.location - FROM j_purchaseorder po`); + FROM no_purchaseorder po` + ); console.log('Query results: ', result.rows[0][0]); // just show first record console.log('4. Using JSON_OBJECT to extract relational data as JSON'); result = await connection.execute( - `SELECT JSON_OBJECT ('deptId' IS d.department_id, 'name' IS d.department_name) department - FROM departments d - WHERE department_id < :did`, - [50]); + `SELECT JSON_OBJECT('key' IS d.dummy) dummy + FROM dual d` + ); for (let row of result.rows) console.log(row[0]); diff --git a/javascript/node-oracledb/selectjsonblob.js b/javascript/node-oracledb/selectjsonblob.js index defd0cd2..8140f45d 100644 --- a/javascript/node-oracledb/selectjsonblob.js +++ b/javascript/node-oracledb/selectjsonblob.js @@ -20,11 +20,10 @@ * * DESCRIPTION * Executes sample insert and query statements using a JSON column with BLOB storage. + * * Requires Oracle Database 12.1.0.2, which has extensive JSON datatype support. * See https://www.oracle.com/pls/topic/lookup?ctx=dblatest&id=ADJSN * - * Use demo.sql to create the required table. - * * This example requires node-oracledb 1.13 or later. * * This example uses Node 8's async/await syntax. @@ -39,7 +38,6 @@ async function run() { let connection; try { - let result; connection = await oracledb.getConnection(dbConfig); @@ -47,21 +45,40 @@ async function run() { throw new Error('This example only works with Oracle Database 12.1.0.2 or greater'); } + const stmts = [ + `DROP TABLE no_purchaseorder_b`, + + `CREATE TABLE no_purchaseorder_b (po_document BLOB CHECK (po_document IS JSON)) LOB (po_document) STORE AS (CACHE)` + ]; + + for (const s of stmts) { + try { + await connection.execute(s); + } catch(e) { + if (e.errorNum != 942) + console.error(e); + } + } + + let result; + console.log('Inserting Data'); const data = { "userId": 2, "userName": "Bob", "location": "USA" }; const s = JSON.stringify(data); const b = Buffer.from(s, 'utf8'); await connection.execute( - `INSERT INTO j_purchaseorder_b (po_document) VALUES (:lobbv)`, - { lobbv: b }); + `INSERT INTO no_purchaseorder_b (po_document) VALUES (:lobbv)`, + { lobbv: b } + ); console.log('Selecting JSON stored in a BLOB column:'); result = await connection.execute( `SELECT po_document - FROM j_purchaseorder_b + FROM no_purchaseorder_b WHERE JSON_EXISTS (po_document, '$.location')`, [], - { fetchInfo: { "PO_DOCUMENT": { type: oracledb.BUFFER } } }); // Fetch as a Buffer instead of a Stream + { fetchInfo: { "PO_DOCUMENT": { type: oracledb.BUFFER } } } // Fetch as a Buffer instead of a Stream + ); if (result.rows.length === 0) throw new Error('No results'); console.log(result.rows[0][0].toString('utf8')); @@ -72,7 +89,8 @@ async function run() { } result = await connection.execute( `SELECT pob.po_document.location - FROM j_purchaseorder_b pob`); + FROM no_purchaseorder_b pob` + ); if (result.rows.length === 0) throw new Error('No results'); console.log(result.rows[0][0]); diff --git a/javascript/node-oracledb/selectobject.js b/javascript/node-oracledb/selectobject.js index 6509bf24..47c28c10 100644 --- a/javascript/node-oracledb/selectobject.js +++ b/javascript/node-oracledb/selectobject.js @@ -45,8 +45,8 @@ async function run() { // Create a table with a named type // - let stmts = [ - `DROP TABLE farmtab`, + const stmts = [ + `DROP TABLE no_farmtab`, `DROP TYPE dbfarmtype`, @@ -58,7 +58,7 @@ async function run() { farmername VARCHAR2(20), harvest dbharvesttype)`, - `CREATE TABLE farmtab (id NUMBER, farm dbfarmtype)` + `CREATE TABLE no_farmtab (id NUMBER, farm dbfarmtype)` ]; for (const s of stmts) { @@ -108,7 +108,7 @@ async function run() { console.log(farm1); await connection.execute( - `INSERT INTO farmtab (id, farm) VALUES (:id, :f)`, + `INSERT INTO no_farmtab (id, farm) VALUES (:id, :f)`, {id: 1, f: farm1} ); @@ -138,7 +138,7 @@ async function run() { console.log(farm2.HARVEST.getValues()); await connection.execute( - `INSERT INTO farmtab (id, farm) VALUES (:id, :f)`, + `INSERT INTO no_farmtab (id, farm) VALUES (:id, :f)`, { id: 2, f: farm2 } ); @@ -149,7 +149,7 @@ async function run() { // await connection.execute( - `INSERT INTO farmtab (id, farm) VALUES (:id, :f)`, + `INSERT INTO no_farmtab (id, farm) VALUES (:id, :f)`, { id: 3, f: { type: FarmType, // pass the prototype object @@ -168,7 +168,7 @@ async function run() { // await connection.execute( - `INSERT INTO farmtab (id, farm) VALUES (:id, :f)`, + `INSERT INTO no_farmtab (id, farm) VALUES (:id, :f)`, { id: 4, f: { type: 'DBFARMTYPE', // the name of the top level database type, case sensitive @@ -187,7 +187,7 @@ async function run() { console.log('\nQuerying:'); result = await connection.execute( - `SELECT id, farm FROM farmtab WHERE id = 1 `, + `SELECT id, farm FROM no_farmtab WHERE id = 1 `, [], // outFormat determines whether rows will be in arrays or JavaScript objects. // It does not affect how the FARM column itself is represented. diff --git a/javascript/node-oracledb/selectstream.js b/javascript/node-oracledb/selectstream.js index 3e04cc02..be2304eb 100644 --- a/javascript/node-oracledb/selectstream.js +++ b/javascript/node-oracledb/selectstream.js @@ -20,10 +20,6 @@ * * DESCRIPTION * Executes a basic query using a Readable Stream. - * Uses Oracle's sample HR schema. - * - * Scripts to create the HR schema can be found at: - * https://github.com/oracle/db-sample-schemas * * This example requires node-oracledb 1.8 or later. * @@ -33,6 +29,7 @@ const oracledb = require('oracledb'); const dbConfig = require('./dbconfig.js'); +const demoSetup = require('./demosetup.js'); async function run() { let connection; @@ -40,13 +37,15 @@ async function run() { try { connection = await oracledb.getConnection(dbConfig); + await demoSetup.setupBf(connection); // create the demo table + const stream = await connection.queryStream( - `SELECT first_name, last_name - FROM employees - ORDER BY employee_id`, + `SELECT farmer, weight + FROM no_banana_farmer + ORDER BY id`, [], // no binds { - fetchArraySize: 150 // internal buffer size used for performance tuning + fetchArraySize: 150 // internal buffer size can be adjusted for performance tuning } ); @@ -70,7 +69,13 @@ async function run() { }); stream.on('end', function() { - // console.log("stream 'end' event"); + // console.log("stream 'end' event"); // all data has been fetched + }); + + stream.on('close', function() { + // console.log("stream 'close' event"); + // The underlying ResultSet has been closed, so the connection can now + // be closed, if desired. Note: do not close connections on 'end'. resolve(rowcount); }); }); diff --git a/javascript/node-oracledb/selectvarray.js b/javascript/node-oracledb/selectvarray.js index 7e193336..cdeb93ec 100644 --- a/javascript/node-oracledb/selectvarray.js +++ b/javascript/node-oracledb/selectvarray.js @@ -41,8 +41,8 @@ async function run() { // Setup - let stmts = [ - `DROP TABLE sports`, + const stmts = [ + `DROP TABLE no_sports`, `DROP TYPE teamtype`, @@ -54,7 +54,7 @@ async function run() { `CREATE TYPE teamtype AS VARRAY(10) OF playertype;`, - `CREATE TABLE sports (sportname VARCHAR2(20), team teamtype)`, + `CREATE TABLE no_sports (sportname VARCHAR2(20), team teamtype)`, ]; for (const s of stmts) { @@ -81,7 +81,7 @@ async function run() { ); await connection.execute( - `INSERT INTO sports (sportname, team) VALUES (:sn, :t)`, + `INSERT INTO no_sports (sportname, team) VALUES (:sn, :t)`, { sn: "Hockey", t: hockeyTeam @@ -90,7 +90,7 @@ async function run() { // Insert with direct bind await connection.execute( - `INSERT INTO sports (sportname, team) VALUES (:sn, :t)`, + `INSERT INTO no_sports (sportname, team) VALUES (:sn, :t)`, { sn: "Badminton", t: { @@ -108,7 +108,7 @@ async function run() { // Query the new data back let result = await connection.execute( - `SELECT sportname, team FROM sports`, + `SELECT sportname, team FROM no_sports`, [], { outFormat: oracledb.OUT_FORMAT_OBJECT diff --git a/javascript/node-oracledb/sessionfixup.js b/javascript/node-oracledb/sessionfixup.js index 046430e2..bd4cfb21 100644 --- a/javascript/node-oracledb/sessionfixup.js +++ b/javascript/node-oracledb/sessionfixup.js @@ -35,15 +35,10 @@ * The function initSession() will be called just once per connection * in the pool. * - * This file uses Node 8's async/await syntax but could be rewritten - * to use callbacks. - * * This example requires node-oracledb 3.1 or later. * * This example uses Node 8's async/await syntax. * - * Also see sessiontagging1.js and sessiontagging2.js - * *****************************************************************************/ const http = require('http'); diff --git a/javascript/node-oracledb/sessiontagging1.js b/javascript/node-oracledb/sessiontagging1.js index 4699537d..3920d7b1 100644 --- a/javascript/node-oracledb/sessiontagging1.js +++ b/javascript/node-oracledb/sessiontagging1.js @@ -38,15 +38,10 @@ * send 20 requests with a concurrency of 4: * ab -n 20 -c 4 http://127.0.0.1:7000/ * - * This file uses Node 8's async/await syntax but could be rewritten - * to use callbacks. - * * This example requires node-oracledb 3.1 or later. * * This example uses Node 8's async/await syntax. * - * Also see sessionfixup.js and sessiontagging2.js - * *****************************************************************************/ const http = require('http'); diff --git a/javascript/node-oracledb/sessiontagging2.js b/javascript/node-oracledb/sessiontagging2.js index 7164c6ab..18600402 100644 --- a/javascript/node-oracledb/sessiontagging2.js +++ b/javascript/node-oracledb/sessiontagging2.js @@ -38,15 +38,10 @@ * send 20 requests with a concurrency of 4: * ab -n 20 -c 4 http://127.0.0.1:7000/ * - * This file uses Node 8's async/await syntax but could be rewritten - * to use callbacks. - * * This example requires node-oracledb 3.1 or later. * * This example uses Node 8's async/await syntax. * - * Also see sessionfixup.js and sessiontagging1.js - * *****************************************************************************/ const http = require('http'); diff --git a/javascript/node-oracledb/soda1.js b/javascript/node-oracledb/soda1.js index 87404fad..625fc65f 100644 --- a/javascript/node-oracledb/soda1.js +++ b/javascript/node-oracledb/soda1.js @@ -21,16 +21,14 @@ * DESCRIPTION * Basic Simple Oracle Document Access (SODA) example. * - * Creates and uses a SODA collection. * Requires Oracle Database and Client 18.3, or higher. * The user must have been granted the SODA_APP and CREATE TABLE privileges. * See https://oracle.github.io/node-oracledb/doc/api.html#sodaoverview * - * This uses Node 8's async/await syntax but could be rewritten to - * use callbacks. - * * This example requires node-oracledb 3.0 or later. * + * This example uses Node 8's async/await syntax. + * *****************************************************************************/ const oracledb = require('oracledb'); diff --git a/javascript/node-oracledb/webappawait.js b/javascript/node-oracledb/webappawait.js index 71e1f081..426ca82c 100644 --- a/javascript/node-oracledb/webappawait.js +++ b/javascript/node-oracledb/webappawait.js @@ -19,21 +19,15 @@ * webappawait.js * * DESCRIPTION - * Shows a web based query using connections from connection pool. + * A web based application displaying banana harvest details. * - * This displays a table of employees in the specified department. - * - * The script creates an HTTP server listening on port 7000 and - * accepts a URL parameter for the department ID, for example: - * http://localhost:7000/90 + * The script creates an HTTP server listening on port 7000 and accepts a URL + * parameter for the banana farmer ID, for example: http://localhost:7000/3 * * In some networks forced pool termination may hang unless you have * 'disable_oob=on' in sqlnet.ora, see * https://oracle.github.io/node-oracledb/doc/api.html#tnsadmin * - * Uses Oracle's sample HR schema. Scripts to create the HR schema - * can be found at: https://github.com/oracle/db-sample-schemas - * * This example requires node-oracledb 3 or later. * * This example uses Node 8's async/await syntax. @@ -43,6 +37,7 @@ const http = require('http'); const oracledb = require('oracledb'); const dbConfig = require('./dbconfig.js'); +const demoSetup = require('./demosetup.js'); const httpPort = 7000; @@ -56,7 +51,7 @@ async function init() { password: dbConfig.password, connectString: dbConfig.connectString // edition: 'ORA$BASE', // used for Edition Based Redefintion - // events: true, // whether to handle Oracle Database FAN and RLB events or support CQN + // events: false, // whether to handle Oracle Database FAN and RLB events or support CQN // externalAuth: false, // whether connections should be established using External Authentication // homogeneous: true, // all connections in the pool have the same credentials // poolAlias: 'default', // set an alias to allow access to the pool via a name. @@ -70,6 +65,11 @@ async function init() { // stmtCacheSize: 30 // number of statements that are cached in the statement cache of each connection }); + // create the demo table + const connection = await oracledb.getConnection(); + await demoSetup.setupBf(connection); + await connection.close(); + // Create HTTP server and listen on port httpPort const server = http.createServer(); server.on('error', (err) => { @@ -79,7 +79,8 @@ async function init() { handleRequest(request, response); }); await server.listen(httpPort); - console.log("Server running at http://localhost:" + httpPort); + console.log("Server is running at http://localhost:" + httpPort); + console.log("Try loading a farmer such as http://localhost:" + httpPort + "/3"); } catch (err) { console.error("init() error: " + err.message); } @@ -87,23 +88,23 @@ async function init() { async function handleRequest(request, response) { const urlparts = request.url.split("/"); - const deptid = urlparts[1]; + const id = urlparts[1]; htmlHeader( response, - "Oracle Database Driver for Node.js", + "Banana Farmer Demonstration", "Example using node-oracledb driver" ); - if (deptid == 'favicon.ico') { + if (id == 'favicon.ico') { // ignore requests for the icon htmlFooter(response); return; } - if (deptid != parseInt(deptid)) { + if (id != parseInt(id)) { handleError( response, - 'URL path "' + deptid + '" is not an integer. Try http://localhost:' + httpPort + '/30', + 'URL path "' + id + '" is not an integer. Try http://localhost:' + httpPort + '/3', null ); @@ -116,13 +117,13 @@ async function handleRequest(request, response) { connection = await oracledb.getConnection(); const result = await connection.execute( - `SELECT employee_id, first_name, last_name - FROM employees - WHERE department_id = :id`, - [deptid] // bind variable value + `SELECT farmer, weight, ripeness, picked + FROM no_banana_farmer + WHERE id = :idbv`, + [id] // bind variable value ); - displayResults(response, result, deptid); + displayResults(response, result, id); } catch (err) { handleError(response, "handleRequest() error", err); @@ -149,8 +150,8 @@ function handleError(response, text, err) { } // Display query results -function displayResults(response, result, deptid) { - response.write("

" + "Employees in Department " + deptid + "

"); +function displayResults(response, result, id) { + response.write("

" + "Harvest details for farmer " + id + "

"); response.write(""); // Column Title @@ -200,6 +201,7 @@ async function closePoolAndExit() { try { // Get the pool from the pool cache and close it when no // connections are in use, or force it closed after 10 seconds + // If this hangs, you may need DISABLE_OOB=ON in a sqlnet.ora file await oracledb.getPool().close(10); console.log("Pool closed"); process.exit(0);