Merge branch 'dev-2.0'

This commit is contained in:
Christopher Jones 2017-12-14 10:53:33 +11:00
commit 33331413c5
255 changed files with 42636 additions and 25546 deletions

30
.github/SUPPORT.md vendored Normal file
View File

@ -0,0 +1,30 @@
# Node-oracledb Support
Node-oracledb is an Open Source project.
Searching and reading may be the quickest way to resolve a problem.
## Node-oracledb Installation issues
Read the [Installation instructions](https://github.com/oracle/node-oracledb/blob/master/INSTALL.md) and see [Troubleshooting](https://github.com/oracle/node-oracledb/blob/master/INSTALL.md#troubleshooting)
## SQL and PL/SQL Questions
Ask SQL and PL/SQL questions at [AskTOM](https://asktom.oracle.com/)
Try out SQL and find code snippets on our hosted database with [LIVE SQL](https://livesql.oracle.com/)
## Database and other Oracle Issues
Ask Database, network connectivity, or other Oracle issues on an [OTN Forum](https://community.oracle.com/community/database/)
## Node-oracledb Documentation
The Node API documentation is divided into [API documentation](https://github.com/oracle/node-oracledb/blob/master/doc/api.md) and a [User Guide](https://github.com/oracle/node-oracledb/blob/master/doc/api.md#connectionhandling)
## Got a Node-oracledb question?
Ask at [GitHub](https://github.com/oracle/node-oracledb/issues)
When opening a new issue, fill in the template that will be shown.
Include enough information for people to understand your problem.

View File

@ -1,4 +1,4 @@
*Delete irrelevant parts of this template.*
*Delete unnecessary parts of this template.*
### For general questions:
@ -7,44 +7,36 @@ Use the questions at the bottom of this template as a guide.
Use Markdown syntax, particularly for code blocks: see https://help.github.com/articles/basic-writing-and-formatting-syntax/#quoting-code
Use a gist for screen output and logs: see https://gist.github.com/ **Do not paste long output into this issue**.
### For security issues:
See https://www.oracle.com/support/assurance/vulnerability-remediation/reporting-security-vulnerabilities.html for how to report security issues.
### For installation issues:
Use a gist for screen output and logs: see https://gist.github.com/
**Do not paste long output into this issue**
- Review the install instructions https://github.com/oracle/node-oracledb/blob/master/INSTALL.md
Review the install instructions at https://github.com/oracle/node-oracledb/blob/master/INSTALL.md
Use `npm install --verbose oracledb`. Review your output and logs.
Try to install in a different way. **Google anything that looks like an error.** Try some potential solutions.
For Node 4 onwards, you need a compiler with C++11 support. On Linux use GCC 4.7 or later.
Did the error indicate a network connection issue? Do you need to set `http_proxy`?
Try running `npm cache clean` and deleting the `node_modules/oracledb` directory.
Do you have an old version of `node-gyp` installed? Try updating it. Also try deleting `$HOME/.node-gyp` or equivalent.
- Review the troubleshooting tips https://github.com/oracle/node-oracledb/blob/master/INSTALL.md#troubleshooting
#### Answer the following questions:
1. What is your version of Node.js? Run examples/version.js to find versions.
1. What is your Node.js version? Is it 64-bit or 32-bit? Run `version.js` from https://github.com/oracle/node-oracledb/blob/master/examples/version.js
2. What version of node-oracledb are you using?
2. What is your node-oracledb version?
3. What is the version of your Oracle client (e.g. Instant Client)? How was it installed? Where it is installed?
3. What is your Oracle client (e.g. Instant Client) version? Is it 64-bit or 32-bit? How was it installed? Where is it installed?
4. What is the version of Oracle Database?
4. What is your Oracle Database version?
5. What is your OS and version?
6. What compiler version did you use? For example, with GCC, run `gcc --version`
6. What is your compiler version? For example, with GCC, run `gcc --version`
7. What environment variables did you set? How *exactly* did you set them?
7. What Oracle environment variables did you set? How *exactly* did you set them?
8. What *exact* command caused the problem (e.g. what command did you try to install with)? Who were you logged in as?
8. What is the `PATH` environment variable (on Windows) or `LD_LIBRARY_PATH` (on Linux) set to? On macOS, what is in `~/lib`?
9. What error(s) you are seeing?
9. What *exact* command caused the problem (e.g. what command did you try to install with)? Who were you logged in as?
10. What error(s) you are seeing?

View File

@ -4,6 +4,8 @@ Before submitting PRs for node-oracledb you must have your signed *Oracle Contri
If the problem solved is small, you may find it easier to open an Issue describing the problem and its cause so we can create the fix.
**Note that the ODPI-C submodule does not accept PRs.** Any required changes to ODPI-C should be submitted in the form of a problem description at https://github.com/oracle/odpi/issues before submitting a node-oracledb PR.
The bottom of your commit message must have the following line using your name and e-mail address as it appears in the OCA Signatories list.
```

5
.gitignore vendored
View File

@ -14,7 +14,9 @@ node_modules
/examples/lobselectout.jpg
/examples/lobbindsout1.txt
/examples/lobbindsout2.txt
/odpi
/package/SHASUMS256.txt
/package/*.gz
package-lock.json
# Oracle Ignores
sqlnet.log
@ -24,3 +26,4 @@ oraaccess.xml
instantclient
instantclient_11_2
instantclient_12_1
instantclient_12_2

3
.gitmodules vendored Normal file
View File

@ -0,0 +1,3 @@
[submodule "odpi"]
path = odpi
url = https://github.com/oracle/odpi

View File

@ -1,4 +1,6 @@
.github
.editorconfig
.gitmodules
INSTALL.md
CONTRIBUTING.md
/doc
@ -7,6 +9,16 @@ CONTRIBUTING.md
/build
/node_modules
/oracle_private
/.github
/package/*.gz
/package/SHASUMS256.*
oracledb-*.tgz
staging-oracledb-*.tgz
.npmignore
/odpi/Makefile
/odpi/Makefile.win32
/odpi/doc
/odpi/samples
/odpi/test
/odpi/.git
/odpi/.github
/odpi/.gitattributes

View File

@ -1,5 +1,372 @@
# Change Log
## node-oracledb v2.0.15 (15 Dec 2017) changes since node-oracledb version 1
- Release testing is now done for Node.js 4, 6, 8 and 9.
- Node-oracledb now uses the [ODPI-C](https://github.com/oracle/odpi)
database abstraction library.
- Upgraded [NAN](https://github.com/nodejs/nan) build dependency to 2.8.
- Installation has significantly improved. Some pre-built binaries
are available for convenience, or the add-on can be continue to built
from source code. Refer to
[INSTALL.md](https://github.com/oracle/node-oracledb/blob/master/INSTALL.md).
- Added utilities to /package for building binaries for
distribution, and for installing them.
- When building from source code:
- Oracle header files are no longer needed.
- The `OCI_LIB_DIR` and `OCI_INC_DIR` environment variables are not needed.
- A single node-oracledb binary now works with any of the Oracle
11.2, 12.1 or 12.2 clients. This improves portability when the
node-oracledb add-on is copied between machines. Applications
should be tested with their target environment to make sure
expected Oracle functionality is available.
- At run time, users of macOS must put the Oracle client libraries
in `~/lib` or `/usr/local/lib`. Linux users of Instant Client
RPMs must always set `LD_LIBRARY_PATH` or use ldconfig - the
previous RPATH linking option is not available. Other Linux users
should continue to use `LD_LIBRARY_PATH` or ldconfig. Windows
users should continue to put Oracle client libraries in `PATH`.
- On non-Windows platforms, if Oracle client libraries are not
located in the system library search path
(e.g. `LD_LIBRARY_PATH`), then node-oracledb attempts to use
libraries in `$ORACLE_HOME/lib`.
- A new [Troubleshooting
section](https://github.com/oracle/node-oracledb/blob/master/INSTALL.md#troubleshooting)
was add to INSTALL.
- Improvements were made to `require('oracledb')` failure messages
to help users resolve problems.
- Changed the installation message prefix in binding.gyp from
'node-oracledb' to 'oracledb'.
- Improved query handling:
- Enhanced direct fetches to allow an unlimited number of rows to be
fetched. This occurs when `oracledb.maxRows = 0`
- Changed the default value of `oracledb.maxRows` to 0, meaning
unlimited.
- Replaced `prefetchRows` (used for internal fetch buffering and
tuning) with a new property `fetchArraySize`. This affects direct
fetches, ResultSet `getRow()` and `queryStream()`.
- `getRows(numRows,...)` internal fetch buffering is now only tuned
by the `numRows` value.
- Implemented `getRow()` in JavaScript for better performance.
- Tightened up checking on in-use ResultSets and Lobs to avoid leaks
and threading issues by making sure the application has closed them
before connections can be closed. The error DPI-1054 may now be
seen if connections are attempted to be closed too early.
- Added support for fetching columns types LONG (as String) and LONG
RAW (as Buffer). There is no support for streaming these types, so
the value stored in the database may not be able to be completely
fetched if Node.js and V8 memory limits are reached.
- Added support for TIMESTAMP WITH TIME ZONE date type. These are
mapped to a Date object in node-oracledb using LOCAL TIME ZONE.
The TIME ZONE component is not available in the Date object.
- Added support for ROWID data type. Data is fetched as a String.
- Added support for UROWID data type. Data is fetched as a String.
- Added query support for NCHAR and NVARCHAR2 columns. Note binding
these types for DML may not insert data correctly, depending on the
database character set and the database national character set.
- Added query support for NCLOB columns. NCLOB data can be streamed
or fetched as String. Note binding NCLOB for DML may not insert
data correctly, depending on the database character set and the
database national character set.
- Removed node-oracledb size restrictions on LOB `fetchAsString` and
`fetchAsBuffer` queries, and also on LOB binds. Node.js memory
restrictions will still prevent large LOBs being manipulated in
single chunks.
- In LOB binds, the bind `val` can now be a String when `type` is
CLOB, and `val` can now be a Buffer when `type` is BLOB.
- Improved validation for invalid attribute and parameter values.
- The error parameter of function callbacks is now always null if no
error occurred.
- Database error messages no longer have an extra newline.
- Statements that generate errors are now dropped from the statement
cache. Applications running while table definitions change will no
longer end up with unusable SQL statements due to stale cache
entries. Note that Oracle best-practice is never to change table
definitions while applications are executing.
- Prevent use of NaN with Oracle numbers to avoid data corruption.
- For LOB streaming, make sure 'close' is the very last event, and
doesn't occur before an 'error' event.
- Fix duplicate 'close' event for error conditions when streaming LOBs
in Node 8.
- `connection.createLob()` now uses Oracle Call Interface's (OCI)
underlying 'cache' mode.
- `Lob.close()` now marks LOBs invalid immediately rather than during
the asynchronous portion of the `close()` method, so that all other
attempts are no-ops.
- Relaxed the restriction preventing `oracledb.connnectionClass` being
used with dedicated connections; it previously gave ORA-56609. Now
DRCP can now be used with dedicated connections but the
`CLIENT_DRIVER` value in `V$SESSION_CONNECT_INFO` will not be set in
this case. The recommendation is still to use a session pool when
using DRCP.
- Fixed a crash with LOB out binds in DML RETURNING statements when the
number of rows returned exceeds the number of rows originally
allocated internally.
- Empty arrays can now be used in PL/SQL Collection Associative Array
(Index-by) binds.
- Some NJS and DPI error messages and numbers have changed. This is
particularly true of DPI errors due to the use of ODPI-C.
- Many new tests have been created.
- Updated examples for new functionality.
- Documentation has been updated and improved.
## node-oracledb v2.0.15 (15 Dec 2017)
- The stated compatibility is now for Node.js 4, 6, 8 and 9.
- Improved query handling:
- Enhanced direct fetches to allow an unlimited number of rows to be
fetched. This occurs when `oracledb.maxRows = 0`
- Changed the default value of `oracledb.maxRows` to 0, meaning
unlimited.
- Replaced `prefetchRows` (used for internal fetch buffering and
tuning) with a new property `fetchArraySize`. This affects direct
fetches, ResultSet `getRow()` and `queryStream()`.
- `getRows(numRows,...)` internal fetch buffering is now only tuned
by the `numRows` value.
- Implemented `getRow()` in JavaScript for better performance.
- Moved operations on REF CURSORS out of the main thread in order to
improve performance and memory usage.
- Fixed proxy support in the binary installer.
- Ensured the callback error parameter is null, not undefined, when no
error occurred.
- Improvements were made to `require('oracledb')` failure messages to
help users resolve installation and usage problems.
- Fixed compiler deprecation warnings regarding `Nan::ForceSet`.
## node-oracledb v2.0.14 Development (20 Nov 2017)
- Added infrastructure to /package for creating binary installs.
Updated INSTALL.md.
- Improved validation for invalid attribute and parameter values.
- In LOB binds, the bind "val" can now be a String when "type" is
CLOB, and "val" can now be a Buffer when "type" is BLOB.
- Changed binding.gyp message prefix from 'node-oracledb' to 'oracledb'.
- Fix compiler warning with va_start
- Eliminate memory leak when processing result sets containing LOBs
that require more than one fetch operation (regression from v1).
- Move fetch buffer allocation to reduce memory use for Result Sets
(regression from v1).
- Upgraded NAN dependency from 2.5 to 2.8.
- Updated ODPI-C submodule:
- Reinstate safe size limit for LOB bind to PL/SQL (node-oracledb regression from v1).
- Fix valgrind byte overrun when loading `libclntsh` from `$ORACLE_HOME`.
- Do not prevent connections from being explicitly closed when a fatal error has taken place.
- Eliminate race condition on initialization. Add finalization code.
- Eliminate use of OCI wrappers for use of mutexes, which improves performance (now uses native threading, e.g. pthreads).
- Prevent use of NaN with Oracle numbers to avoid data corruption.
- Prevent ORA-1010 during connection ping to pre 10g Oracle Database.
- Improve debug trace output format.
- Prevent crash for DML RETURNING of variables that require dynamic binding.
- Updated examples to avoid "DPI-1054: connection cannot be closed
when open statements or LOBs exist" and to avoid duplicate callbacks
on stream errors.
- Check for JavaScript exceptions and if one is found, ensure that the
error is passed correctly to the callback and is not raised when the
C++ method has finished.
- Added code to handle invalid object properties.
- Make sure 'close' is the very last event, and doesn't occur before
an 'error' event. Also emit 'close' after 'error' event for
`queryStream()`
- Changed default sample connect string to `"localhost/orclpdb"` which
is the Oracle Database 12.2 default for pluggable databases.
- Moved NJS code from `/src/njs/src` to `/src` to remove obsolete
directory nesting.
- Perform error cleanup as soon as possible in order to avoid possible
race conditions when errors take place.
- Move operations on REF CURSORS out of the main thread in order to
improve performance and memory usage.
- Relaxed the restriction preventing `oracledb.connnectionClass` being
used with dedicated connections; it previously gave ORA-56609. Now
DRCP can now be used with dedicated connections but the
`CLIENT_DRIVER` value in `V$SESSION_CONNECT_INFO` will not be set in
this case. The recommendation is still to use a session pool when
using DRCP.
- Tighten up checking on in-use ResultSets and Lobs to avoid leaks and
threading issues by making sure the application has closed them
before connections can be closed. The error DPI-1054 may now be
seen if connections are attempted to be closed too early.
- On Windows, disable ODPI-C thread cleanup to resolve a thread timing
issue, since Node.js creates all threads at startup and never
terminates them.
- Added extra message text to NJS-045 to give potential causes for
`require('oracledb')` failures when the ODPI-C layer can't detect
the issue.
- Updated ODPI-C submodule: various changes including improved
initialization error messages, and runtime-enabled debug tracing.
- Fix duplicate 'close' event for error conditions when streaming Lobs
in Node 8.
- Fix LOB streaming 'close' and 'end' event order (regression from v1).
- Fixed crash with LOB out binds in DML RETURNING statements when the
number of rows returned exceeds the number of rows originally
allocated internally.
- Improve handling of invalid `externalAuth`, `fetchAsString`, and
`fetchAsBuffer` attribute values.
- Fix support for `connectionClass` (regression from v1).
## node-oracledb v2.0.13 Development (19 Jun 2017)
- Node-oracledb now uses the [ODPI-C](https://github.com/oracle/odpi)
database abstraction library.
- Installation instructions have changed. Refer to
[INSTALL.md](https://github.com/oracle/node-oracledb/blob/master/INSTALL.md).
Distribution is still via source code.
Oracle header files are no longer needed. The `OCI_LIB_DIR` and
`OCI_INC_DIR` environment variables are not needed.
At run time, Oracle 11.2, 12.1 or 12.2 client libraries should still
be in `PATH` (for Windows) or `LD_LIBRARY_PATH` (for Linux) or
similar platform library loading path. Users of macOS must put the
Oracle client libraries in `~/lib` or `/usr/local/lib`. Linux users
of Instant Client RPMs must always set `LD_LIBRARY_PATH` or use
ldconfig - the previous RPATH linking option is not available.
On non-Windows platforms, if Oracle client libraries are not located
in the system library search path (e.g. `LD_LIBRARY_PATH`), then
node-oracledb attempts to use libraries in `$ORACLE_HOME/lib`.
A single node-oracledb binary now works with any of the Oracle
client 11.2, 12.1 or 12.2 libraries. This improves portability when
node-oracledb builds are copied between machines.
- `Lob.close()` now marks LOBs invalid immediately rather than during
the asynchronous portion of the `close()` method, so that all other
attempts are no-ops.
- Incorrect application logic in version 1 that attempted to close a
connection while certain LOB, ResultSet or other database operations
were still occurring gave an NJS-030, NJS-031 or NJS-032 "connection
cannot be released" error. Now in version 2 the connection will be
closed but any operation that relied on the connection being open
will fail.
- Some NJS and DPI error messages and numbers have changed. This is
particularly true of DPI errors due to the use of ODPI-C.
- Stated compatibility is now for Node.js 4, 6 and 8.
- Added support for fetching columns types LONG (as String) and LONG
RAW (as Buffer). There is no support for streaming these types, so
the value stored in the DB may not be able to be completely fetched
if Node.js and V8 memory limits are reached.
- Added support for TIMESTAMP WITH TIME ZONE date type. These are
mapped to a Date object in node-oracledb using LOCAL TIME ZONE.
The TIME ZONE component is not available in the Date object.
- Added support for ROWID data type. Data is fetched as a String.
- Added support for UROWID data type. Data is fetched as a String.
- Added query support for NCHAR and NVARCHAR2 columns. Binding for
DML may not insert data correctly, depending on the database
character set and the database national character set.
- Added query support for NCLOB columns. NCLOB data can be streamed
or fetched as String. Binding for DML may not insert data
correctly, depending on the database character set and the database
national character set.
- Removed node-oracledb size restrictions on LOB `fetchAsString` and
`fetchAsBuffer` queries, and also on LOB binds. Node.js and V8
memory restrictions will still prevent large LOBs being manipulated
in single chunks.
- Statements that generate errors are now dropped from the statement
cache. Applications running while table definitions change will no
longer end up with unusable SQL statements due to stale cache
entries. Note that Oracle best-practice is never to change table
definitions while applications are executing.
- Empty arrays can now be used in PL/SQL Collection Associative Array
(Index-by) binds.
- `connection.createLob()` now uses OCI's underlying 'cache' mode.
- Database errors no longer have an extra newline.
- Upgraded NAN dependency from 2.5 to 2.6.
## node-oracledb v1.13.1 (12 Apr 2017)
- Fix regression with NULL values to PL/SQL procedures with multiple parameters.

1794
INSTALL.md

File diff suppressed because it is too large Load Diff

139
README.md
View File

@ -1,90 +1,80 @@
# node-oracledb version 1.13
# node-oracledb version 2.0
## <a name="about"></a> About node-oracledb
The node-oracledb add-on for Node.js powers high performance Oracle
Database applications.
Use node-oracledb to connect Node.js 4, 6 and 7 to Oracle Database.
Use node-oracledb to connect Node.js 4, 6, 8 and 9 to Oracle Database.
The add-on is stable, well documented, and has a comprehensive test suite.
The node-oracledb project is open source and maintained by Oracle Corp. The home page is on the
[Oracle Technology Network](http://www.oracle.com/technetwork/database/database-technologies/scripting-languages/node_js/).
The node-oracledb project is open source and maintained by Oracle Corp.
### Node-oracledb supports:
- [Promises](https://github.com/oracle/node-oracledb/blob/master/doc/api.md#promiseoverview), [Callbacks](https://github.com/oracle/node-oracledb/blob/master/doc/api.md#intro) and [Streams](https://github.com/oracle/node-oracledb/blob/master/doc/api.md#querystream)
- [SQL and PL/SQL execution](https://github.com/oracle/node-oracledb/blob/master/doc/api.md#sqlexecution)
- [REF CURSORs](https://github.com/oracle/node-oracledb/blob/master/doc/api.md#refcursors)
- [Large Objects: CLOBs and BLOBs as Streams or Strings and Buffers](https://github.com/oracle/node-oracledb/blob/master/doc/api.md#lobhandling)
- [Oracle Database 12c JSON datatype](https://github.com/oracle/node-oracledb/blob/master/doc/api.md#jsondatatype)
- [Query results as JavaScript objects or arrays](https://github.com/oracle/node-oracledb/blob/master/doc/api.md#queryoutputformats)
- [Smart mapping between JavaScript and Oracle types with manual override available](https://github.com/oracle/node-oracledb/blob/master/doc/api.md#typemap)
- [Data binding using JavaScript types, objects or arrays](https://github.com/oracle/node-oracledb/blob/master/doc/api.md#bind)
- [Transaction Management](https://github.com/oracle/node-oracledb/blob/master/doc/api.md#transactionmgt)
- [Inbuilt Connection Pool with Queueing, Aliasing and Liveness checking](https://github.com/oracle/node-oracledb/blob/master/doc/api.md#connpooling)
- [Database Resident Connection Pooling (DRCP)](https://github.com/oracle/node-oracledb/blob/master/doc/api.md#drcp)
- [External Authentication](https://github.com/oracle/node-oracledb/blob/master/doc/api.md#extauth)
- [Row Prefetching](https://github.com/oracle/node-oracledb/blob/master/doc/api.md#rowprefetching)
- [Statement Caching](https://github.com/oracle/node-oracledb/blob/master/doc/api.md#stmtcache)
- [Client Result Caching](https://docs.oracle.com/database/122/ADFNS/performance-and-scalability.htm#ADFNS464)
- [End-to-end Tracing, Mid-tier Authentication, and Auditing](https://github.com/oracle/node-oracledb/blob/master/doc/api.md#endtoend)
- [Async/Await][2], [Promises][3], [Callbacks][4] and [Streams][5]
- [SQL and PL/SQL execution][6]
- [REF CURSORs][7]
- [Large Objects: CLOBs and BLOBs as Streams or Strings and Buffers][8]
- [Oracle Database 12c JSON datatype][9]
- [Query results as JavaScript objects or arrays][10]
- [Smart mapping between JavaScript and Oracle types with manual override available][11]
- [Data binding using JavaScript types, objects or arrays][12]
- [Transaction Management][13]
- [Inbuilt Connection Pool with Queuing, Aliasing and Liveness checking][14]
- [Database Resident Connection Pooling (DRCP)][15]
- [External Authentication][16]
- [Array Fetches][17]
- [Statement Caching][18]
- [Client Result Caching][19]
- [End-to-end Tracing, Mid-tier Authentication, and Auditing][20]
- Oracle High Availability Features
- [Fast Application Notification (FAN)](https://docs.oracle.com/database/122/ADFNS/high-availability.htm#ADFNS538)
- [Runtime Load Balancing (RLB)](https://docs.oracle.com/database/122/ADFNS/connection_strategies.htm#ADFNS515)
- [Transparent Application Failover (TAF)](https://docs.oracle.com/database/122/ADFNS/high-availability.htm#ADFNS-GUID-96599425-9BDA-483C-9BA2-4A4D13013A37)
- [Fast Application Notification (FAN)][21]
- [Runtime Load Balancing (RLB)][22]
- [Transparent Application Failover (TAF)][23]
We are actively working on supporting the best Oracle Database
features, and on functionality requests from
[users involved in the project](https://github.com/oracle/node-oracledb/issues).
features, and on functionality requests from [users involved in the
project][24].
## <a name="start"></a> Getting Started
See [Getting Started with Node-oracledb][1].
## <a name="installation"></a> Installation
Prerequisites:
- [Python 2.7](https://www.python.org/downloads/)
- C Compiler with support for C++ 11 (Xcode, gcc, Visual Studio or similar)
- Oracle 11.2, 12.1 or 12.2 client libraries. Use the small, free [Oracle Instant Client](http://www.oracle.com/technetwork/database/features/instant-client/index-100365.html) "basic" and "SDK" packages if your database is remote. Or use the libraries and headers from a locally installed database such as the free [Oracle XE](http://www.oracle.com/technetwork/database/database-technologies/express-edition/overview/index.html) release.
Oracle's standard client-server network compatibility applies: Oracle Client 12.2 can connect to Oracle Database 11.2 or greater. Oracle Client 12.1 can connect to Oracle Database 10.2 or greater. Oracle Client 11.2 can connect to Oracle Database 9.2 or greater.
- Set `OCI_LIB_DIR` and `OCI_INC_DIR` during installation if the Oracle libraries and headers are in a non-default location
Run `npm install oracledb` to install from the [npm registry](https://www.npmjs.com/package/oracledb).
See [INSTALL](https://github.com/oracle/node-oracledb/tree/master/INSTALL.md) for details.
See [Quick Start Node-oracledb Installation][37].
## <a name="examples"></a> Examples
See the
[examples](https://github.com/oracle/node-oracledb/tree/master/examples) directory.
Start
with
[examples/select1.js](https://github.com/oracle/node-oracledb/blob/master/examples/select1.js#L35).
See the [examples][30] directory. Start with
[examples/select1.js][31].
## <a name="doc"></a> Documentation
See [Documentation for the Oracle Database Node.js Add-on](https://github.com/oracle/node-oracledb/tree/master/doc/api.md).
See [Documentation for the Oracle Database Node.js Add-on][32].
## <a name="help"></a> Help
Issues and questions can be raised with the node-oracledb community on [GitHub](https://github.com/oracle/node-oracledb/issues).
Issues and questions can be raised with the node-oracledb community on
[GitHub][24].
## <a name="changes"></a> Changes
See [CHANGELOG](https://github.com/oracle/node-oracledb/tree/master/CHANGELOG.md).
See [CHANGELOG][33].
## <a name="testing"></a> Tests
To run the test suite see [test/README](https://github.com/oracle/node-oracledb/tree/master/test/README.md).
To run the test suite see [test/README][34].
## <a name="contrib"></a> Contributing
Node-oracledb is an open source project. See
[CONTRIBUTING](https://github.com/oracle/node-oracledb/tree/master/CONTRIBUTING.md)
for details.
Node-oracledb is an open source project. See [CONTRIBUTING][35] for
details.
Oracle gratefully acknowledges the contributions to node-oracledb that have been made by the community.
Oracle gratefully acknowledges the contributions to node-oracledb that
have been made by the community.
## <a name="license"></a> License
@ -94,11 +84,50 @@ 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.
[http://www.apache.org/licenses/LICENSE-2.0][36]. 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.
[1]: https://github.com/oracle/node-oracledb/blob/master/doc/api.md#getstarted
[2]: https://github.com/oracle/node-oracledb/blob/master/doc/api.md#asyncawaitoverview
[3]: https://github.com/oracle/node-oracledb/blob/master/doc/api.md#promiseoverview
[4]: https://github.com/oracle/node-oracledb/blob/master/doc/api.md#intro
[5]: https://github.com/oracle/node-oracledb/blob/master/doc/api.md#querystream
[6]: https://github.com/oracle/node-oracledb/blob/master/doc/api.md#sqlexecution
[7]: https://github.com/oracle/node-oracledb/blob/master/doc/api.md#refcursors
[8]: https://github.com/oracle/node-oracledb/blob/master/doc/api.md#lobhandling
[9]: https://github.com/oracle/node-oracledb/blob/master/doc/api.md#jsondatatype
[10]: https://github.com/oracle/node-oracledb/blob/master/doc/api.md#queryoutputformats
[11]: https://github.com/oracle/node-oracledb/blob/master/doc/api.md#typemap
[12]: https://github.com/oracle/node-oracledb/blob/master/doc/api.md#bind
[13]: https://github.com/oracle/node-oracledb/blob/master/doc/api.md#transactionmgt
[14]: https://github.com/oracle/node-oracledb/blob/master/doc/api.md#connpooling
[15]: https://github.com/oracle/node-oracledb/blob/master/doc/api.md#drcp
[16]: https://github.com/oracle/node-oracledb/blob/master/doc/api.md#extauth
[17]: https://github.com/oracle/node-oracledb/blob/master/doc/api.md#propdbfetcharraysize
[18]: https://github.com/oracle/node-oracledb/blob/master/doc/api.md#stmtcache
[19]: https://docs.oracle.com/database/122/ADFNS/performance-and-scalability.htm#ADFNS464
[20]: https://github.com/oracle/node-oracledb/blob/master/doc/api.md#endtoend
[21]: https://docs.oracle.com/database/122/ADFNS/high-availability.htm#ADFNS538
[22]: https://docs.oracle.com/database/122/ADFNS/connection_strategies.htm#ADFNS515
[23]: https://docs.oracle.com/database/122/ADFNS/high-availability.htm#ADFNS-GUID-96599425-9BDA-483C-9BA2-4A4D13013A37
[24]: https://github.com/oracle/node-oracledb/issues
[25]: https://www.npmjs.com/package/oracledb
[26]: http://www.oracle.com/technetwork/database/features/instant-client/index-100365.html
[27]: https://github.com/oracle/node-oracledb/blob/master/INSTALL.md#winredists
[28]: http://www.oracle.com/technetwork/database/database-technologies/express-edition/overview/index.html
[29]: https://github.com/oracle/node-oracledb/blob/master/INSTALL.md
[30]: https://github.com/oracle/node-oracledb/blob/master/examples
[31]: https://github.com/oracle/node-oracledb/blob/master/examples/select1.js#L35
[32]: https://github.com/oracle/node-oracledb/blob/master/doc/api.md
[33]: https://github.com/oracle/node-oracledb/blob/master/CHANGELOG.md
[34]: https://github.com/oracle/node-oracledb/blob/master/test/README.md
[35]: https://github.com/oracle/node-oracledb/blob/master/CONTRIBUTING.md
[36]: http://www.apache.org/licenses/LICENSE-2.0
[37]: https://github.com/oracle/node-oracledb/blob/master/INSTALL.md#quickstart

View File

@ -3,97 +3,83 @@
{
"target_name" : "oracledb",
"sources" : [
"src/njs/src/njsOracle.cpp",
"src/njs/src/njsPool.cpp",
"src/njs/src/njsConnection.cpp",
"src/njs/src/njsResultSet.cpp",
"src/njs/src/njsMessages.cpp",
"src/njs/src/njsIntLob.cpp",
"src/dpi/src/dpiEnv.cpp",
"src/dpi/src/dpiEnvImpl.cpp",
"src/dpi/src/dpiException.cpp",
"src/dpi/src/dpiExceptionImpl.cpp",
"src/dpi/src/dpiConnImpl.cpp",
"src/dpi/src/dpiDateTimeArrayImpl.cpp",
"src/dpi/src/dpiPoolImpl.cpp",
"src/dpi/src/dpiStmtImpl.cpp",
"src/dpi/src/dpiUtils.cpp",
"src/dpi/src/dpiLob.cpp",
"src/dpi/src/dpiCommon.cpp"
"src/njsCommon.cpp",
"src/njsOracle.cpp",
"src/njsPool.cpp",
"src/njsConnection.cpp",
"src/njsResultSet.cpp",
"src/njsMessages.cpp",
"src/njsIntLob.cpp",
"odpi/src/dpiConn.c",
"odpi/src/dpiContext.c",
"odpi/src/dpiData.c",
"odpi/src/dpiDebug.c",
"odpi/src/dpiDeqOptions.c",
"odpi/src/dpiEnqOptions.c",
"odpi/src/dpiEnv.c",
"odpi/src/dpiError.c",
"odpi/src/dpiGen.c",
"odpi/src/dpiGlobal.c",
"odpi/src/dpiHandlePool.c",
"odpi/src/dpiLob.c",
"odpi/src/dpiMsgProps.c",
"odpi/src/dpiObjectAttr.c",
"odpi/src/dpiObject.c",
"odpi/src/dpiObjectType.c",
"odpi/src/dpiOci.c",
"odpi/src/dpiOracleType.c",
"odpi/src/dpiPool.c",
"odpi/src/dpiRowid.c",
"odpi/src/dpiStmt.c",
"odpi/src/dpiSubscr.c",
"odpi/src/dpiUtils.c",
"odpi/src/dpiVar.c"
],
"conditions" : [
[
'OS=="linux"', {
"variables" : {
"oci_inc_dir%" : "<!(INSTURL=\"https://github.com/oracle/node-oracledb/blob/master/INSTALL.md\"; ERR=\"node-oracledb ERR! Error:\"; if [ -z $OCI_INC_DIR ]; then OCI_LIB_DIR=`ls -d /usr/lib/oracle/*/client*/lib/libclntsh.* 2> /dev/null | tail -1 | sed -e 's#/libclntsh[^/]*##'`; if [ -z $OCI_LIB_DIR ]; then if [ -z \"$ORACLE_HOME\" ]; then if [ -f /opt/oracle/instantclient/sdk/include/oci.h ]; then echo \"/opt/oracle/instantclient/sdk/include/\"; else echo \"$ERR Cannot find Oracle client header files.\" >&2; echo \"$ERR See $INSTURL\" >&2; echo \"\" >&2; fi; else if [ -f $ORACLE_HOME/rdbms/public/oci.h ]; then echo $ORACLE_HOME/rdbms/public; else echo \"$ERR Cannot find \$ORACLE_HOME/rdbms/public/oci.h\" >&2; echo \"$ERR See $INSTURL\" >&2; echo \"\" >&2; fi; fi; else OCI_INC_DIR=`echo $OCI_LIB_DIR | sed -e 's!^/usr/lib/oracle/\(.*\)/client\([64]*\)*/lib[/]*$!/usr/include/oracle/\\1/client\\2!'`; if [ -z $OCI_INC_DIR ]; then if [ -f /opt/oracle/instantclient/sdk/include/oci.h ]; then echo \"/opt/oracle/instantclient/sdk/include/\"; else echo \"$ERR Cannot find Oracle client header files.\" >&2; echo \"$ERR See $INSTURL\" >&2; echo \"\" >&2; fi; else if [ -f \"$OCI_INC_DIR/oci.h\" ]; then echo $OCI_INC_DIR; else echo \"$ERR Cannot find \$OCI_INC_DIR/oci.h\" >&2; echo \"$ERR See $INSTURL\" >&2; echo \"\" >&2; fi; fi; fi; else if [ -f \"$OCI_INC_DIR/oci.h\" ]; then echo $OCI_INC_DIR; else echo \"$ERR Cannot find \$OCI_INC_DIR/oci.h\" >&2; echo \"$ERR See $INSTURL\" >&2; echo \"\" >&2; fi; fi;)",
"oci_lib_dir%" : "<!(INSTURL=\"https://github.com/oracle/node-oracledb/blob/master/INSTALL.md\"; ERR=\"node-oracledb ERR! Error:\"; if [ -z $OCI_LIB_DIR ]; then OCI_LIB_DIR=`ls -d /usr/lib/oracle/*/client*/lib/libclntsh.* 2> /dev/null | tail -1 | sed -e 's#/libclntsh[^/]*##'`; if [ -z $OCI_LIB_DIR ]; then if [ -z \"$ORACLE_HOME\" ]; then if [ -f /opt/oracle/instantclient/libclntsh.so ]; then echo \"/opt/oracle/instantclient/\"; else echo \"$ERR Cannot find Oracle library libclntsh.so\" >&2; echo \"$ERR See $INSTURL\" >&2; echo \"\" >&2; fi; else if [ -f \"$ORACLE_HOME/lib/libclntsh.so\" ]; then echo $ORACLE_HOME/lib; else echo \"$ERR Cannot find \$ORACLE_HOME/lib/libclntsh.so\" >&2; echo \"$ERR See $INSTURL\" >&2; echo \"\" >&2; fi; fi; else if [ -f \"$OCI_LIB_DIR/libclntsh.so\" ]; then echo $OCI_LIB_DIR; else echo \"$ERR Cannot find \$OCI_LIB_DIR/libclntsh.so\" >&2; echo \"$ERR See $INSTURL\" >&2; echo \"\" >&2; fi; fi; else if [ -f \"$OCI_LIB_DIR/libclntsh.so\" ]; then echo $OCI_LIB_DIR; else echo \"$ERR Cannot find \$OCI_LIB_DIR/libclntsh.so\" >&2; echo \"$ERR See $INSTURL\" >&2; echo \"\" >&2; fi; fi;)",
"oci_rpath%" : "<!(if [ -z $OCI_LIB_DIR ]; then OCI_LIB_DIR=`ls -d /usr/lib/oracle/*/client*/lib/libclntsh.* 2> /dev/null | tail -1 | sed -e 's#/libclntsh[^/]*##'`; if [ -z $OCI_LIB_DIR ]; then if [ -d \"$ORACLE_HOME\" ]; then if [ -z \"${FORCE_RPATH+x}\" ]; then echo \"\"; else echo \"-Wl,-rpath,$ORACLE_HOME/lib\"; fi; else if [ -z \"${FORCE_RPATH+x}\" ]; then echo \"\"; else echo \"-Wl,-rpath,/opt/oracle/instantclient\"; fi; fi; else echo \"-Wl,-rpath,$OCI_LIB_DIR\"; fi; else if [ -z \"${FORCE_RPATH+x}\" ]; then echo \"\"; else echo \"-Wl,-rpath,$OCI_LIB_DIR\"; fi; fi;)",
"dpi_check%" : "<!(INSTURL=\"https://github.com/oracle/node-oracledb/blob/master/INSTALL.md#github\"; ERR=\"oracledb ERR! Error:\"; if [ -f odpi/include/dpi.h ]; then echo \"Has dpi.h\"; else echo \"$ERR Cannot find odpi/include/dpi.h. For GitHub ZIP downloads you must separately download the odpi subdirectory from GitHub.\" >&2; echo \"$ERR See $INSTURL\" >&2; echo \"\" >&2; fi;)"
},
"cflags" : ['-fexceptions'],
"cflags_cc" : ['-fexceptions'],
"libraries" : ["-lclntsh"],
"link_settings" : {
"libraries" : ['-L<(oci_lib_dir) <(oci_rpath)']
}
"libraries" : ['-ldl', '-lpthread'],
}
],
[
'OS=="mac"', {
"variables" : {
"dpi_check%" : "<!(INSTURL=\"https://github.com/oracle/node-oracledb/blob/master/INSTALL.md#github\"; ERR=\"oracledb ERR! Error:\"; if [ -f odpi/include/dpi.h ]; then echo \"Has dpi.h\"; else echo \"$ERR Cannot find odpi/include/dpi.h. For GitHub ZIP downloads you must separately download the odpi subdirectory from GitHub.\" >&2; echo \"$ERR See $INSTURL\" >&2; echo \"\" >&2; fi;)"
},
"xcode_settings": {
"GCC_ENABLE_CPP_EXCEPTIONS": "YES",
"GCC_ENABLE_CPP_RTTI": "YES"
},
"variables" : {
"oci_inc_dir%" : "<!(INSTURL=\"https://github.com/oracle/node-oracledb/blob/master/INSTALL.md#instosx\"; ERR=\"node-oracledb ERR! Error:\"; if [ -z $OCI_INC_DIR ]; then if [ -f /opt/oracle/instantclient/sdk/include/oci.h ]; then echo \"/opt/oracle/instantclient/sdk/include/\"; else echo \"$ERR Cannot find Oracle client header files.\" >&2; echo \"$ERR See $INSTURL\" >&2; echo \"\" >&2; fi; else if [ -f \"$OCI_INC_DIR/oci.h\" ]; then echo $OCI_INC_DIR; else echo \"$ERR Cannot find \$OCI_INC_DIR/oci.h\" >&2; echo \"$ERR See $INSTURL\" >&2; echo \"\" >&2; fi; fi;)",
"oci_lib_dir%" : "<!(INSTURL=\"https://github.com/oracle/node-oracledb/blob/master/INSTALL.md#instosx\"; ERR=\"node-oracledb ERR! Error:\"; if [ -z $OCI_LIB_DIR ]; then if [ -f /opt/oracle/instantclient/libclntsh.dylib ]; then echo \"/opt/oracle/instantclient/\"; else echo \"$ERR Cannot find /opt/oracle/instantclient/libclntsh.dylib\" >&2; echo \"$ERR Do you need to run 'cd /opt/oracle/instantclient && ln -s libclntsh.dylib.* libclntsh.dylib'?\" >&2; echo \"$ERR See $INSTURL\" >&2; echo \"\" >&2; fi; else if [ -f \"$OCI_LIB_DIR/libclntsh.dylib\" ]; then echo $OCI_LIB_DIR; else echo \"$ERR Cannot find \$OCI_LIB_DIR/libclntsh.dylib\" >&2; echo \"$ERR Do you need to run 'cd \$OCI_LIB_DIR && ln -s libclntsh.dylib.* libclntsh.dylib'?\" >&2; echo \"$ERR See $INSTURL\" >&2; echo \"\" >&2; fi; fi;)",
},
"cflags" : ['-fexceptions'],
"cflags_cc" : ['-fexceptions'],
"libraries" : ["-lclntsh"],
"link_settings" : {
"libraries" : ['-L<(oci_lib_dir) -Wl,-rpath,<(oci_lib_dir)']
}
"libraries" : ['-ldl', '-lpthread']
}
],
[
'OS=="aix"', {
"variables" : {
"oci_inc_dir%" : '<!(echo ${OCI_INC_DIR:="/opt/oracle/instantclient/sdk/include/"})',
"oci_lib_dir%" : '<!(echo ${OCI_LIB_DIR:="/opt/oracle/instantclient/"})',
},
"libraries" : ["-lclntsh"],
"cflags" : ['-fexceptions', '-fsigned-char'],
"cflags_cc" : ['-fexceptions', '-fsigned-char'],
"link_settings" : {
"libraries" : ['-L<(oci_lib_dir)']
}
"dpi_check%" : "<!(INSTURL=\"https://github.com/oracle/node-oracledb/blob/master/INSTALL.md#github\"; ERR=\"oracledb ERR! Error:\"; if [ -f odpi/include/dpi.h ]; then echo \"Has dpi.h\"; else echo \"$ERR Cannot find odpi/include/dpi.h. For GitHub ZIP downloads you must separately download the odpi subdirectory from GitHub.\" >&2; echo \"$ERR See $INSTURL\" >&2; echo \"\" >&2; fi;)"
},
"cflags" : ['-fexceptions', '-fsigned-char'],
"cflags_cc" : ['-fexceptions', '-fsigned-char'],
"libraries" : ['-ldl', '-lpthread'],
}
],
[
'OS=="solaris"', {
"variables" : {
"oci_inc_dir%" : "<!(INSTURL=\"https://github.com/oracle/node-oracledb/blob/master/INSTALL.md\"; ERR=\"node-oracledb ERR! Error:\"; if [ -z $OCI_INC_DIR ]; then if [ -f /opt/oracle/instantclient/sdk/include/oci.h ]; then echo \"/opt/oracle/instantclient/sdk/include/\"; else echo \"$ERR Cannot find Oracle client header files.\" >&2; echo \"$ERR See $INSTURL\" >&2; echo \"\" >&2; fi; else if [ -f \"$OCI_INC_DIR/oci.h\" ]; then echo $OCI_INC_DIR; else echo \"$ERR Cannot find \$OCI_INC_DIR/oci.h\" >&2; echo \"$ERR See $INSTURL\" >&2; echo \"\" >&2; fi; fi;)",
"oci_lib_dir%" : "<!(INSTURL=\"https://github.com/oracle/node-oracledb/blob/master/INSTALL.md\"; ERR=\"node-oracledb ERR! Error:\"; if [ -z $OCI_LIB_DIR ]; then if [ -f /opt/oracle/instantclient/libclntsh.so ]; then echo \"/opt/oracle/instantclient/\"; else echo \"$ERR Cannot find /opt/oracle/instantclient/libclntsh.so\" >&2; echo \"$ERR Do you need to run 'cd /opt/oracle/instantclient && ln -s libclntsh.so.* libclntsh.so'?\" >&2; echo \"$ERR See $INSTURL\" >&2; echo \"\" >&2; fi; else if [ -f \"$OCI_LIB_DIR/libclntsh.so\" ]; then echo $OCI_LIB_DIR; else echo \"$ERR Cannot find \$OCI_LIB_DIR/libclntsh.so\" >&2; echo \"$ERR Do you need to run 'cd \$OCI_LIB_DIR && ln -s libclntsh.so.* libclntsh.so'?\" >&2; echo \"$ERR See $INSTURL\" >&2; echo \"\" >&2; fi; fi;)",
},
"libraries" : ["-lclntsh"],
"cflags" : ['-fexceptions'],
"cflags_cc" : ['-fexceptions'],
"link_settings" : {
"libraries" : ['-L<(oci_lib_dir)']
}
"dpi_check%" : "<!(INSTURL=\"https://github.com/oracle/node-oracledb/blob/master/INSTALL.md#github\"; ERR=\"oracledb ERR! Error:\"; if [ -f odpi/include/dpi.h ]; then echo \"Has dpi.h\"; else echo \"$ERR Cannot find odpi/include/dpi.h. For GitHub ZIP downloads you must separately download the odpi subdirectory from GitHub.\" >&2; echo \"$ERR See $INSTURL\" >&2; echo \"\" >&2; fi;)"
},
"cflags" : ['-fexceptions'],
"cflags_cc" : ['-fexceptions'],
"libraries" : ['-ldl', '-lpthread'],
}
],
[
"OS=='win'", {
"variables" : {
"oci_lib_dir%": "<!(IF DEFINED OCI_LIB_DIR (echo %OCI_LIB_DIR%) ELSE (echo C:\oracle\instantclient\sdk\lib\msvc))",
"oci_inc_dir%": "<!(IF DEFINED OCI_INC_DIR (echo %OCI_INC_DIR%) ELSE (echo C:\oracle\instantclient\sdk\include))",
},
"link_settings": {
"libraries": [
"-loci",
]
},
"configurations" : {
"Release" : {
"msvs_settings": {
@ -125,9 +111,6 @@
"OptimizeReferences": 2,
"EnableCOMDATFolding": 2,
"LinkIncremental": 1,
"AdditionalLibraryDirectories": [
"<(oci_lib_dir)"
]
}
}
},
@ -150,9 +133,6 @@
"VCLinkerTool": {
"LinkTimeCodeGeneration": 1,
"LinkIncremental": 1,
"AdditionalLibraryDirectories": [
"<(oci_lib_dir)"
]
}
}
}
@ -160,9 +140,8 @@
}
],
],
"include_dirs" : [ "<(oci_inc_dir)",
"src/dpi/src/",
"src/dpi/include/",
"include_dirs" : [ "odpi/src/",
"odpi/include/",
"<!(node -e \"require('nan')\")"
],
}

2549
doc/api.md

File diff suppressed because it is too large Load Diff

39
examples/README.md Normal file
View File

@ -0,0 +1,39 @@
# Node-oracledb Examples
This directory contains [node-oracledb](https://www.npmjs.com/package/oracledb) examples.
To run the examples:
- [Install node-oracledb](https://github.com/oracle/node-oracledb/blob/master/INSTALL.md).
- Use `demo.sql` to create schema objects used by the samples. For
example, to load them in the HR schema run:
```
sqlplus hr/welcome@localhost/orclpdb @demo.sql
```
- Edit `dbconfig.js` and set your username, password and the database
connection string:
```
module.exports = {
user: "hr",
password: "welcome",
connectString:"localhost/orclpdb"
};
```
- Then run the samples like:
```
node select1.js
```
The demonstration objects can be dropped with `demodrop.sql`:
```
sqlplus hr/welcome@localhost/orclpdb @demodrop.sql
```

View File

@ -57,10 +57,10 @@ function init() {
// Create HTTP server and listen on port 'httpPort'
http
.createServer(function(request, response) {
handleRequest(request, response);
})
.listen(httpPort);
.createServer(function(request, response) {
handleRequest(request, response);
})
.listen(httpPort);
console.log("Server running. Try requesting: http://localhost:" + httpPort + "/getimage");
});
@ -140,13 +140,13 @@ function handleRequest(request, response) {
}
process
.on('SIGTERM', function() {
console.log("\nTerminating");
process.exit(0);
})
.on('SIGINT', function() {
console.log("\nTerminating");
process.exit(0);
});
.on('SIGTERM', function() {
console.log("\nTerminating");
process.exit(0);
})
.on('SIGINT', function() {
console.log("\nTerminating");
process.exit(0);
});
init();

View File

@ -1,4 +1,4 @@
/* Copyright (c) 2015, 2016, Oracle and/or its affiliates. All rights reserved. */
/* Copyright (c) 2015, 2017, Oracle and/or its affiliates. All rights reserved. */
/******************************************************************************
*
@ -50,17 +50,17 @@ var dorelease = function(conn) {
var docleanup = function (conn, cb) {
conn.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;",
`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;`,
function(err) {
return cb(err, conn);
});

View File

@ -1,4 +1,4 @@
/* Copyright (c) 2015, Oracle and/or its affiliates. All rights reserved. */
/* Copyright (c) 2015, 2017, Oracle and/or its affiliates. All rights reserved. */
/******************************************************************************
*
@ -34,7 +34,7 @@
* [//]host_name[:port][/service_name][:server_type][/instance_name]
*
* Commonly just the host_name and service_name are needed
* e.g. "localhost/orcl" or "localhost/XE"
* e.g. "localhost/orclpdb" or "localhost/XE"
*
* If using a tnsnames.ora file, the file can be in a default
* location such as $ORACLE_HOME/network/admin/tnsnames.ora or
@ -76,7 +76,7 @@ module.exports = {
// For information on connection strings see:
// https://github.com/oracle/node-oracledb/blob/master/doc/api.md#connectionstrings
connectString : process.env.NODE_ORACLEDB_CONNECTIONSTRING || "localhost/orcl",
connectString : process.env.NODE_ORACLEDB_CONNECTIONSTRING || "localhost/orclpdb",
// Setting externalAuth is optional. It defaults to false. See:
// https://github.com/oracle/node-oracledb/blob/master/doc/api.md#extauth

View File

@ -1,4 +1,4 @@
/* Copyright (c) 2015, 2016, Oracle and/or its affiliates. All rights reserved. */
/* Copyright (c) 2015, 2017, Oracle and/or its affiliates. All rights reserved. */
/******************************************************************************
*
@ -65,10 +65,10 @@ var enableDbmsOutput = function (conn, cb) {
var createDbmsOutput = function (conn, cb) {
conn.execute(
"BEGIN " +
"DBMS_OUTPUT.PUT_LINE('Hello, Oracle!');" +
"DBMS_OUTPUT.PUT_LINE('Hello, Node!');" +
"END;",
`BEGIN
DBMS_OUTPUT.PUT_LINE('Hello, Oracle!');
DBMS_OUTPUT.PUT_LINE('Hello, Node!');
END;`,
function(err) { return cb(err, conn); });
};

View File

@ -1,4 +1,4 @@
/* Copyright (c) 2015, 2016, Oracle and/or its affiliates. All rights reserved. */
/* Copyright (c) 2015, 2017, Oracle and/or its affiliates. All rights reserved. */
/******************************************************************************
*
@ -68,7 +68,8 @@ var doit = function(pool) {
enableDbmsOutput,
createDbmsOutput,
fetchDbmsOutput,
printDbmsOutput
printDbmsOutput,
closeRS
],
function (err, conn) {
if (err) { console.error("In waterfall error cb: ==>", err, "<=="); }
@ -84,10 +85,10 @@ var enableDbmsOutput = function (conn, cb) {
var createDbmsOutput = function (conn, cb) {
conn.execute(
"BEGIN " +
"DBMS_OUTPUT.PUT_LINE('Hello, Oracle!');" +
"DBMS_OUTPUT.PUT_LINE('Hello, Node!');" +
"END;",
`BEGIN
DBMS_OUTPUT.PUT_LINE('Hello, Oracle!');
DBMS_OUTPUT.PUT_LINE('Hello, Node!');
END;`,
function(err) { return cb(err, conn); });
};
@ -118,12 +119,18 @@ var fetchRowsFromRS = function(conn, resultSet, numRows, cb) {
numRows,
function (err, rows) {
if (err) {
return cb(err, conn);
return cb(err, conn, resultSet);
} else if (rows.length > 0) {
console.log(rows);
return fetchRowsFromRS(conn, resultSet, numRows, cb);
} else {
return cb(null, conn);
return cb(null, conn, resultSet);
}
});
};
var closeRS = function(conn, resultSet, cb) {
resultSet.close(function(err) {
return cb(err, conn);
});
};

View File

@ -1,4 +1,4 @@
/* Copyright (c) 2015, 2016, Oracle and/or its affiliates. All rights reserved. */
/* Copyright (c) 2015, 2017, Oracle and/or its affiliates. All rights reserved. */
/******************************************************************************
*
@ -60,7 +60,9 @@ END;
SHOW ERRORS
-- For plsqlarray.js example for PL/SQL 'INDEX BY' array binds
DROP TABLE waveheight;
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
@ -107,24 +109,29 @@ END;
SHOW ERRORS
-- For selectjson.js example of JSON datatype. Requires Oracle Database 12.1.0.2
DROP TABLE j_purchaseorder;
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 selectjsonclob.js example of JSON datatype. Requires Oracle Database 12.1.0.2
DROP TABLE j_purchaseorder_c;
CREATE TABLE j_purchaseorder_c (po_document CLOB 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
DROP TABLE dmlrupdtab;
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');
COMMIT;
-- For LOB examples
DROP TABLE mylobs;
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
@ -173,5 +180,6 @@ END;
SHOW ERRORS
-- For raw1.js
DROP TABLE myraw;
BEGIN EXECUTE IMMEDIATE 'DROP TABLE myraw'; EXCEPTION WHEN OTHERS THEN IF SQLCODE <> -942 THEN RAISE; END IF; END;
/
CREATE TABLE myraw (r RAW(64));

View File

@ -1,4 +1,4 @@
/* Copyright (c) 2015, 2016, Oracle and/or its affiliates. All rights reserved. */
/* Copyright (c) 2015, 2017, Oracle and/or its affiliates. All rights reserved. */
/******************************************************************************
*
@ -35,7 +35,7 @@ DROP PACKAGE beachpkg;
DROP TABLE j_purchaseorder;
DROP TABLE j_purchaseorder_c;
DROP TABLE j_purchaseorder_b;
DROP TABLE dmlrupdtab;
@ -49,8 +49,6 @@ DROP TABLE myraw;
DROP TABLE waveheight;
DROP PROCEDURE lob_out;
DROP PROCEDURE lob_in_out;
DROP PROCEDURE lobs_in;

View File

@ -1,4 +1,4 @@
/* Copyright (c) 2015, Oracle and/or its affiliates. All rights reserved. */
/* Copyright (c) 2015, 2017, Oracle and/or its affiliates. All rights reserved. */
/******************************************************************************
*
@ -19,7 +19,11 @@
* dmlrupd1.js
*
* DESCRIPTION
* Example of 'DML Returning' with a single row match
* 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));
@ -47,12 +51,11 @@ oracledb.getConnection(
}
connection.execute(
"UPDATE DMLRUPDTAB SET NAME = :name WHERE ID = :id RETURNING ID, NAME INTO :RID, :RNAME",
"UPDATE dmlrupdtab SET name = :name WHERE id = :id RETURNING ROWID INTO :rid",
{
id: 1001,
name: "Krishna",
rid: { type: oracledb.NUMBER, dir: oracledb.BIND_OUT },
rname: { type: oracledb.STRING, dir: oracledb.BIND_OUT }
rid: { type: oracledb.STRING, dir: oracledb.BIND_OUT }
},
{ autoCommit: true },
function(err, result)

View File

@ -1,4 +1,4 @@
/* Copyright (c) 2015, Oracle and/or its affiliates. All rights reserved. */
/* Copyright (c) 2015, 2017, Oracle and/or its affiliates. All rights reserved. */
/******************************************************************************
*
@ -19,7 +19,11 @@
* dmlrupd2.js
*
* DESCRIPTION
* Example of 'DML Returning' with multiple rows matched
* 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));
@ -47,11 +51,13 @@ oracledb.getConnection(
}
connection.execute(
"UPDATE DMLRUPDTAB SET NAME = :name RETURNING ID, NAME INTO :RID, :RNAME",
"UPDATE dmlrupdtab SET name = :name WHERE id IN (:id1, :id2) RETURNING id, ROWID INTO :ids, :rids",
{
id1: 1001,
id2: 1002,
name: "Chris",
rid: { type: oracledb.NUMBER, dir: oracledb.BIND_OUT },
rname: { type: oracledb.STRING, dir: oracledb.BIND_OUT }
ids: { type: oracledb.NUMBER, dir: oracledb.BIND_OUT },
rids: { type: oracledb.STRING, dir: oracledb.BIND_OUT }
},
{ autoCommit: true },
function(err, result)

View File

@ -1,4 +1,4 @@
/* Copyright (c) 2015, 2016, Oracle and/or its affiliates. All rights reserved. */
/* Copyright (c) 2015, 2017, Oracle and/or its affiliates. All rights reserved. */
/******************************************************************************
*
@ -46,13 +46,13 @@ var dorelease = function(conn) {
var dodrop = function (conn, cb) {
conn.execute(
"BEGIN "
+ " EXECUTE IMMEDIATE 'DROP TABLE test'; "
+ " EXCEPTION WHEN OTHERS THEN "
+ " IF SQLCODE <> -942 THEN "
+ " RAISE; "
+ " END IF; "
+ "END;",
`BEGIN
EXECUTE IMMEDIATE 'DROP TABLE test';
EXCEPTION WHEN OTHERS THEN
IF SQLCODE <> -942 THEN
RAISE;
END IF;
END;`,
function(err)
{
if (err) {
@ -81,7 +81,7 @@ var docreate = function (conn, cb) {
var doinsert1 = function (conn, cb) {
conn.execute(
"INSERT INTO test VALUES (:id, :nm)",
[1, 'Chris'], // Bind values
{ id : {val: 1 }, nm : {val: 'Chris'} }, // 'bind by name' syntax
function(err, result)
{
if (err) {
@ -96,7 +96,7 @@ var doinsert1 = function (conn, cb) {
var doinsert2 = function (conn, cb) {
conn.execute(
"INSERT INTO test VALUES (:id, :nm)",
[2, 'Alison'], // Bind values
[2, 'Alison'], // 'bind by position' syntax
function(err, result)
{
if (err) {
@ -110,7 +110,9 @@ var doinsert2 = function (conn, cb) {
var doupdate = function (conn, cb) {
conn.execute(
"UPDATE test SET name = 'Bambi'",
"UPDATE test SET name = :nm",
['Bambi'],
{ autoCommit: true }, // commit once for all DML in the script
function(err, result)
{
if (err) {
@ -130,7 +132,7 @@ async.waterfall(
doinsert1,
doinsert2,
doupdate,
dodrop
dodrop // comment this out if you want to verify the data later
],
function (err, conn) {
if (err) { console.error("In waterfall error cb: ==>", err, "<=="); }

View File

@ -1,4 +1,4 @@
/* Copyright (c) 2015, 2016, Oracle and/or its affiliates. All rights reserved. */
/* Copyright (c) 2015, 2017, Oracle and/or its affiliates. All rights reserved. */
/******************************************************************************
*
@ -51,13 +51,13 @@ var dorelease = function(conn) {
var dodrop = function (conn, cb) {
conn.execute(
"BEGIN "
+ " EXECUTE IMMEDIATE 'DROP TABLE test'; "
+ " EXCEPTION WHEN OTHERS THEN "
+ " IF SQLCODE <> -942 THEN "
+ " RAISE; "
+ " END IF; "
+ "END;",
`BEGIN
EXECUTE IMMEDIATE 'DROP TABLE test';
EXCEPTION WHEN OTHERS THEN
IF SQLCODE <> -942 THEN
RAISE;
END IF;
END;`,
function(err)
{
if (err) {

View File

@ -1,4 +1,4 @@
/* Copyright (c) 2016, Oracle and/or its affiliates. All rights reserved. */
/* Copyright (c) 2016, 2017, Oracle and/or its affiliates. All rights reserved. */
/******************************************************************************
*
@ -73,8 +73,7 @@ var query_bind_insert = function (conn, cb) {
conn.execute(
"SELECT c FROM mylobs WHERE id = :id",
{ id: 1 },
function(err, result)
{
function(err, result) {
if (err) {
return cb(err, conn);
}
@ -127,8 +126,7 @@ var plsql_in_as_str_buf = function (conn, cb) {
{ id: 20,
c: {val: bigStr, type: oracledb.STRING, dir: oracledb.BIND_IN},
b: {val: bigBuf, type: oracledb.BUFFER, dir: oracledb.BIND_IN} },
function (err)
{
function (err) {
if (err) {
return cb(err, conn);
}
@ -145,8 +143,7 @@ var plsql_out_as_str_buf = function (conn, cb) {
{ id: 20,
c: {type: oracledb.STRING, dir: oracledb.BIND_OUT, maxSize: 50000},
b: {type: oracledb.BUFFER, dir: oracledb.BIND_OUT, maxSize: 50000} },
function (err /*, result */)
{
function (err /*, result */) {
if (err) {
return cb(err, conn);
}
@ -165,8 +162,7 @@ var query_plsql_inout = function (conn, cb) {
conn.execute(
"SELECT c FROM mylobs WHERE id = :id",
{ id: 1 },
function(err, result)
{
function(err, result) {
if (err) {
return cb(err, conn);
}
@ -189,6 +185,8 @@ var query_plsql_inout = function (conn, cb) {
return cb(err, conn);
}
var errorHandled = false;
var clob2 = result.outBinds.ciobv;
if (clob2 === null) {
return cb(new Error('plsql_out_inout(): NULL clob2 found'), conn);
@ -199,34 +197,38 @@ var query_plsql_inout = function (conn, cb) {
clob2.setEncoding('utf8'); // set the encoding so we get a 'string' not a 'buffer'
clob2.on(
'error',
function(err)
{
function(err) {
// console.log("clob2.on 'error' event");
return cb(err);
if (!errorHandled) {
errorHandled = true;
return cb(err);
}
});
clob2.on(
'end',
function()
{
function() {
// console.log("clob2.on 'end' event");
});
clob2.on(
'close',
function()
{
function() {
// console.log("clob2.on 'close' event");
console.log (" Completed");
return cb(null, conn);
if (!errorHandled) {
return cb(null, conn);
}
});
var outStream = fs.createWriteStream(clobOutFileName1);
outStream.on(
'error',
function(err)
{
function(err) {
// console.log("outStream.on 'error' event");
return cb(err);
if (!errorHandled) {
errorHandled = true;
return cb(err);
}
});
// Switch into flowing mode and push the LOB to the file
@ -244,8 +246,7 @@ var plsql_out_inout = function (conn, cb) {
{ idbv: 1,
cobv: {type: oracledb.CLOB, dir: oracledb.BIND_OUT},
bobv: {type: oracledb.BLOB, dir: oracledb.BIND_OUT} }, // not used in this demo; it will be NULL anyway
function(err, result)
{
function(err, result) {
if (err) {
return cb(err, conn);
}
@ -266,6 +267,8 @@ var plsql_out_inout = function (conn, cb) {
return cb(err, conn);
}
var errorHandled = false;
var clob2 = result.outBinds.ciobv;
if (clob2 === null) {
return cb(new Error('plsql_out_inout(): NULL clob2 found'), conn);
@ -276,33 +279,37 @@ var plsql_out_inout = function (conn, cb) {
clob2.setEncoding('utf8'); // set the encoding so we get a 'string' not a 'buffer'
clob2.on(
'error',
function(err)
{
function(err) {
// console.log("clob2.on 'error' event");
return cb(err);
if (!errorHandled) {
errorHandled = true;
return cb(err);
}
});
clob2.on(
'end',
function()
{
function() {
// console.log("clob2.on 'end' event");
});
clob2.on(
'close',
function()
{
function() {
// console.log("clob2.on 'close' event");
console.log (" Completed");
return cb(null, conn);
if (!errorHandled) {
console.log (" Completed");
return cb(null, conn);
}
});
var outStream = fs.createWriteStream(clobOutFileName2);
outStream.on(
'error',
function(err)
{
function(err) {
// console.log("outStream.on 'error' event");
return cb(err);
if (!errorHandled) {
errorHandled = true;
return cb(err);
}
});
// Switch into flowing mode and push the LOB to the file

View File

@ -1,4 +1,4 @@
/* Copyright (c) 2015, 2016, Oracle and/or its affiliates. All rights reserved. */
/* Copyright (c) 2015, 2017, Oracle and/or its affiliates. All rights reserved. */
/******************************************************************************
*
@ -24,10 +24,9 @@
*
* "Small" amounts of data can be bound directly for INSERT into LOB
* columns. Larger amounts should be streamed, see lobinssert2.js.
* The boundary between 'small' and 'large' has a hard limit
* determined by the version of the Oracle client libraries, and a
* soft limit restricted by available memory. See node-oracledb
* documentation.
* The boundary between 'small' and 'large' depends on how Node.js
* 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:

View File

@ -1,4 +1,4 @@
/* Copyright (c) 2015, 2016, Oracle and/or its affiliates. All rights reserved. */
/* Copyright (c) 2015, 2017, Oracle and/or its affiliates. All rights reserved. */
/******************************************************************************
*
@ -42,59 +42,69 @@ oracledb.getConnection(
password : dbConfig.password,
connectString : dbConfig.connectString
},
function(err, connection)
{
function(err, connection) {
if (err) { console.error(err.message); return; }
connection.execute(
"INSERT INTO mylobs (id, c) VALUES (:id, EMPTY_CLOB()) RETURNING c INTO :lobbv",
{ id: 4, lobbv: {type: oracledb.CLOB, dir: oracledb.BIND_OUT} },
{ autoCommit: false }, // a transaction needs to span the INSERT and pipe()
function(err, result)
{
function(err, result) {
if (err) { console.error(err.message); return; }
if (result.rowsAffected != 1 || result.outBinds.lobbv.length != 1) {
console.error('Error getting a LOB locator');
return;
}
var errorHandled = false;
var lob = result.outBinds.lobbv[0];
lob.on(
'close',
function()
{
function() {
console.log("lob.on 'close' event");
connection.commit(
function(err)
{
if (err)
console.error(err.message);
else
console.log("Text inserted successfully.");
connection.close(function(err) {
if (err) console.error(err);
});
if (!errorHandled) {
errorHandled = true;
if (err) {
console.error(err);
} else {
console.log("Text inserted successfully.");
}
connection.close(function(err) {
if (err)
console.error(err);
});
}
});
});
lob.on(
'error',
function(err)
{
function(err) {
console.log("lob.on 'error' event");
console.error(err);
connection.close(function(err) {
if (err) console.error(err.message);
});
if (!errorHandled) {
errorHandled = true;
console.error(err);
lob.close(function(err) {
if (err) {
console.error(err.message);
}
});
}
});
console.log('Reading from ' + inFileName);
var inStream = fs.createReadStream(inFileName);
inStream.on(
'error',
function(err)
{
function(err) {
console.log("inStream.on 'error' event");
if (err) console.error(err);
if (!errorHandled) {
errorHandled = true;
console.error(err);
}
});
inStream.pipe(lob); // copies the text to the LOB

View File

@ -1,4 +1,4 @@
/* Copyright (c) 2016, Oracle and/or its affiliates. All rights reserved. */
/* Copyright (c) 2016, 2017, Oracle and/or its affiliates. All rights reserved. */
/******************************************************************************
*
@ -75,6 +75,9 @@ var docreatetemplob = function (conn, cb) {
var doloadtemplob = function (conn, templob, cb) {
console.log('Streaming from the text file into the temporary LOB');
var errorHandled = false;
templob.on(
'close',
function()
@ -87,7 +90,10 @@ var doloadtemplob = function (conn, templob, cb) {
function(err)
{
console.log("templob.on 'error' event");
return cb(err);
if (!errorHandled) {
errorHandled = true;
return cb(err);
}
});
templob.on(
@ -96,7 +102,9 @@ var doloadtemplob = function (conn, templob, cb) {
{
console.log("templob.on 'finish' event");
// The data was loaded into the temporary LOB
return cb(null, conn, templob);
if (!errorHandled) {
return cb(null, conn, templob);
}
});
console.log('Reading from ' + inFileName);
@ -106,7 +114,10 @@ var doloadtemplob = function (conn, templob, cb) {
function(err)
{
console.log("inStream.on 'error' event");
return cb(err);
if (!errorHandled) {
errorHandled = true;
return cb(err);
}
});
inStream.pipe(templob); // copies the text to the temporary LOB

View File

@ -1,4 +1,4 @@
/* Copyright (c) 2016, Oracle and/or its affiliates. All rights reserved. */
/* Copyright (c) 2016, 2017, Oracle and/or its affiliates. All rights reserved. */
/******************************************************************************
*
@ -75,6 +75,9 @@ var createtemplob = function (conn, cb) {
var loadtemplob = function (conn, templob, cb) {
console.log('Streaming from the text file into the temporary LOB');
var errorHandled = false;
templob.on(
'close',
function()
@ -87,7 +90,10 @@ var loadtemplob = function (conn, templob, cb) {
function(err)
{
console.log("templob.on 'error' event");
return cb(err);
if (!errorHandled) {
errorHandled = true;
return cb(err);
}
});
templob.on(
@ -96,7 +102,9 @@ var loadtemplob = function (conn, templob, cb) {
{
console.log("templob.on 'finish' event");
// The data was loaded into the temporary LOB
return cb(null, conn, templob);
if (!errorHandled) {
return cb(null, conn, templob);
}
});
console.log('Reading from ' + inFileName);
@ -106,7 +114,10 @@ var loadtemplob = function (conn, templob, cb) {
function(err)
{
console.log("inStream.on 'error' event");
return cb(err);
if (!errorHandled) {
errorHandled = true;
return cb(err);
}
});
inStream.pipe(templob); // copies the text to the temporary LOB

View File

@ -1,4 +1,4 @@
/* Copyright (c) 2015, 2016, Oracle and/or its affiliates. All rights reserved. */
/* Copyright (c) 2015, 2017, Oracle and/or its affiliates. All rights reserved. */
/******************************************************************************
*
@ -70,34 +70,45 @@ var dostream = function(lob, cb) {
} else {
console.log('Writing a BLOB to ' + outFileName);
}
var errorHandled = false;
lob.on(
'error',
function(err)
{
// console.log("lob.on 'error' event");
return cb(err);
function(err) {
console.log("lob.on 'error' event");
if (!errorHandled) {
errorHandled = true;
lob.close(function() {
return cb(err);
});
}
});
lob.on(
'end',
function()
{
// console.log("lob.on 'end' event");
function() {
console.log("lob.on 'end' event");
});
lob.on(
'close',
function()
{
function() {
// console.log("lob.on 'close' event");
return cb(null);
if (!errorHandled) {
return cb(null);
}
});
var outStream = fs.createWriteStream(outFileName);
outStream.on(
'error',
function(err)
{
// console.log("outStream.on 'error' event");
return cb(err);
function(err) {
console.log("outStream.on 'error' event");
if (!errorHandled) {
errorHandled = true;
lob.close(function() {
return cb(err);
});
}
});
// Switch into flowing mode and push the LOB to the file
@ -107,8 +118,7 @@ var dostream = function(lob, cb) {
var doquery = function(cb) {
conn.execute(
sql,
function(err, result)
{
function(err, result) {
if (err) {
return cb(err);
}

View File

@ -1,4 +1,4 @@
/* Copyright (c) 2016, Oracle and/or its affiliates. All rights reserved. */
/* Copyright (c) 2016, 2017, Oracle and/or its affiliates. All rights reserved. */
/******************************************************************************
*
@ -77,21 +77,27 @@ var doquery = function(conn, cb) {
// Stream a CLOB and builds up a String piece-by-piece
var dostream = function(conn, clob, cb) {
clob.setEncoding('utf8'); // set the encoding so we get a 'string' not a 'buffer'
clob.on(
'error',
function(err)
{
console.log("clob.on 'error' event");
return cb(err, conn);
});
var errorHandled = false;
var myclob = ""; // or myblob = Buffer.alloc(0) for BLOBs
// node-oracledb's lob.pieceSize is the number of bytes retrieved
// for each readable 'data' event. The default is lob.chunkSize.
// The recommendation is for it to be a multiple of chunkSize.
// clob.pieceSize = 100; // fetch smaller chunks to demonstrate repeated 'data' events
var myclob = ""; // or myblob = Buffer.alloc(0) for BLOBs
clob.setEncoding('utf8'); // set the encoding so we get a 'string' not a 'buffer'
clob.on(
'error',
function(err)
{
console.log("clob.on 'error' event");
if (!errorHandled) {
errorHandled = true;
clob.close(function() {
return cb(err, conn);
});
}
});
clob.on(
'data',
function(chunk)
@ -112,7 +118,9 @@ var dostream = function(conn, clob, cb) {
function()
{
console.log("clob.on 'close' event");
return cb(null, conn);
if (!errorHandled) {
return cb(null, conn);
}
});
};

View File

@ -1,4 +1,4 @@
/* Copyright (c) 2016, Oracle and/or its affiliates. All rights reserved. */
/* Copyright (c) 2016, 2017, Oracle and/or its affiliates. All rights reserved. */
/******************************************************************************
*
@ -37,9 +37,9 @@ oracledb.getConnection(
})
.then(function(connection) {
return connection.execute(
"SELECT department_id, department_name " +
"FROM departments " +
"WHERE department_id = :did",
`SELECT department_id, department_name
FROM departments
WHERE department_id = :did`,
[180]
)
.then(function(result) {

View File

@ -40,15 +40,6 @@
var oracledb = require('oracledb');
var dbConfig = require('./dbconfig.js');
// Prefetching is a tuning feature for optimizing row transfer from
// the Oracle Database to node-oracledb with Result Sets. The default
// prefetch size is 100. The prefetch size does not affect how, or
// when, rows are returned by node-oracledb to the application.
// Buffering is handled by the underlying Oracle client libraries.
// Benchmark to choose the optimal size for each application or query.
//
//oracledb.prefetchRows = 100;
var numRows = 10; // number of rows to return from each call to getRows()
oracledb.getConnection(
@ -87,9 +78,9 @@ function fetchRowsFromRS(connection, resultSet, numRows)
{
if (err) {
console.log(err);
doClose(connection, resultSet); // always close the result set
} else if (rows.length === 0) { // no rows, or no more rows
doClose(connection, resultSet); // always close the result set
doClose(connection, resultSet); // always close the ResultSet
} else if (rows.length === 0) { // no rows, or no more rows
doClose(connection, resultSet); // always close the ResultSet
} else if (rows.length > 0) {
console.log("fetchRowsFromRS(): Got " + rows.length + " rows");
console.log(rows);

View File

@ -1,4 +1,4 @@
/* Copyright (c) 2016, Oracle and/or its affiliates. All rights reserved. */
/* Copyright (c) 2016, 2017, Oracle and/or its affiliates. All rights reserved. */
/******************************************************************************
*
@ -43,9 +43,9 @@ oracledb.getConnection(
}
connection.execute(
"BEGIN"
+ " OPEN :cursor FOR SELECT department_id, department_name FROM departments;"
+ "END;",
`BEGIN
OPEN :cursor FOR SELECT department_id, department_name FROM departments;
END;`,
{
cursor: { type: oracledb.CURSOR, dir : oracledb.BIND_OUT }
},

View File

@ -1,4 +1,4 @@
/* Copyright (c) 2015, 2016, Oracle and/or its affiliates. All rights reserved. */
/* Copyright (c) 2015, 2017, Oracle and/or its affiliates. All rights reserved. */
/******************************************************************************
*
@ -19,14 +19,26 @@
* resultset1.js
*
* DESCRIPTION
* Executes a query and uses a result set to fetch rows with getRow().
* 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().
*
*****************************************************************************/
var oracledb = require('oracledb');
var dbConfig = require('./dbconfig.js');
// For getRow(), the fetchArraySize property can be adjusted to tune
// data transfer from the Oracle Database to node-oracledb. The value
// of fetchArraySize does not affect how, or when, rows are returned
// by node-oracledb to the application. Buffering is handled by
// node-oracledb. Benchmark to choose the optimal size for each
// application or query.
//
// oracledb.fetchArraySize = 100; // default value is 100
var rowCount = 0;
oracledb.getConnection(
@ -39,12 +51,12 @@ oracledb.getConnection(
{
if (err) { console.error(err.message); return; }
connection.execute(
"SELECT employee_id, last_name " +
"FROM employees " +
"WHERE ROWNUM < 11 " +
"ORDER BY employee_id",
`SELECT employee_id, last_name
FROM employees
WHERE ROWNUM < 11
ORDER BY employee_id`,
[], // no bind variables
{ resultSet: true }, // return a result set. Default is false
{ resultSet: true }, // return a ResultSet. Default is false
function(err, result)
{
if (err) {
@ -64,9 +76,9 @@ function fetchOneRowFromRS(connection, resultSet)
{
if (err) {
console.error(err.message);
doClose(connection, resultSet); // always close the result set
doClose(connection, resultSet); // always close the ResultSet
} else if (!row) { // no rows, or no more rows
doClose(connection, resultSet); // always close the result set
doClose(connection, resultSet); // always close the ResultSet
} else {
rowCount++;
console.log("fetchOneRowFromRS(): row " + rowCount);

View File

@ -1,4 +1,4 @@
/* Copyright (c) 2015, 2016, Oracle and/or its affiliates. All rights reserved. */
/* Copyright (c) 2015, 2017, Oracle and/or its affiliates. All rights reserved. */
/******************************************************************************
*
@ -19,8 +19,8 @@
* resultset2.js
*
* DESCRIPTION
* Executes a query and uses a result set to fetch batches of rows
* with getRows(). Also shows setting the prefetch size.
* 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.
*
*****************************************************************************/
@ -28,16 +28,9 @@
var oracledb = require('oracledb');
var dbConfig = require('./dbconfig.js');
// Prefetching is a tuning feature for optimizing row transfer from
// the Oracle Database to node-oracledb with Result Sets. The default
// prefetch size is 100. The prefetch size does not affect how, or
// when, rows are returned by node-oracledb to the application.
// Buffering is handled by the underlying Oracle client libraries.
// Benchmark to choose the optimal size for each application or query.
//
//oracledb.prefetchRows = 100;
var numRows = 10; // number of rows to return from each call to getRows()
// Number of rows to return from each call to getRows()
var numRows = 10;
oracledb.getConnection(
{
@ -49,14 +42,13 @@ oracledb.getConnection(
{
if (err) { console.error(err.message); return; }
connection.execute(
"SELECT employee_id, last_name " +
"FROM employees " +
"WHERE ROWNUM < 25 " +
"ORDER BY employee_id",
`SELECT employee_id, last_name
FROM employees
WHERE ROWNUM < 25
ORDER BY employee_id`,
[], // no bind variables
{
resultSet: true, // return a result set. Default is false
prefetchRows: 25 // the prefetch size can be set for each query
resultSet: true // return a ResultSet. Default is false
},
function(err, result)
{
@ -78,16 +70,16 @@ function fetchRowsFromRS(connection, resultSet, numRows)
{
if (err) {
console.error(err);
doClose(connection, resultSet); // always close the result set
doClose(connection, resultSet); // always close the ResultSet
} else if (rows.length > 0) {
console.log("fetchRowsFromRS(): Got " + rows.length + " rows");
console.log(rows);
if (rows.length === numRows) // might be more rows
if (rows.length === numRows) // might be more rows
fetchRowsFromRS(connection, resultSet, numRows);
else
doClose(connection, resultSet); // always close the result set
doClose(connection, resultSet); // always close the ResultSet
} else { // no rows
doClose(connection, resultSet); // always close the result set
doClose(connection, resultSet); // always close the ResultSet
}
});
}

View File

@ -43,8 +43,7 @@ oracledb.getConnection(
sql,
[],
{
resultSet: true,
prefetchRows: 25
resultSet: true
},
function(err, result)
{

View File

@ -25,13 +25,11 @@
* Scripts to create the HR schema can be found at:
* https://github.com/oracle/db-sample-schemas/releases
*
* By default, node-oracledb has a maxRows attribute that limits the
* number of records fetched from a query to 100. Although
* adjusting maxRows can be used to control the number of rows
* available to the application, it is more efficient for the
* 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 only to prevent badly
* coded queries from consuming too many Node.js resources.
* coded queries from over-consuming Node.js resources.
*
*****************************************************************************/
@ -45,7 +43,7 @@ var mymaxnumrows = 6; // number of rows to fetch
// They can also be set or overridden at the individual execute() call level
//
// This script sets maxRows in the execute() call but it could be set here instead
// oracledb.maxRows = 150; // Note the default value is 100 and EMPLOYEES has 107 rows
// oracledb.maxRows = 150; // Note the default value is 0, meaning unlimited
oracledb.getConnection(
{

View File

@ -1,4 +1,4 @@
/* Copyright (c) 2015, 2016, Oracle and/or its affiliates. All rights reserved. */
/* Copyright (c) 2015, 2017, Oracle and/or its affiliates. All rights reserved. */
/******************************************************************************
*
@ -50,16 +50,22 @@ oracledb.getConnection(
}
connection.execute(
// The statement to execute
"SELECT department_id, department_name " +
"FROM departments " +
"WHERE department_id = :id",
`SELECT department_id, department_name
FROM departments
WHERE department_id = :id`,
// The "bind value" 180 for the "bind variable" :id
// The "bind value" 180 for the bind variable ":id"
[180],
// Optional execute options argument, such as the query result format
// or whether to get extra metadata
// { outFormat: oracledb.OBJECT, extendedMetaData: true },
// execute() options argument. Since the query only returns one
// row, we can optimize memory usage by reducing the default
// maxRows value. For the complete list of other options see
// the documentation.
{ maxRows: 1
//, outFormat: oracledb.OBJECT // query result format
//, extendedMetaData: true // get extra metadata
//, fetchArraySize: 100 // internal buffer allocation size for tuning
},
// The callback function handles the SQL execution results
function(err, result)

View File

@ -1,4 +1,4 @@
/* Copyright (c) 2015, 2016, Oracle and/or its affiliates. All rights reserved. */
/* Copyright (c) 2015, 2017, Oracle and/or its affiliates. All rights reserved. */
/******************************************************************************
*
@ -26,16 +26,26 @@
* Scripts to create the HR schema can be found at:
* https://github.com/oracle/db-sample-schemas
*
* *****************************************************************************/
******************************************************************************/
var async = require('async');
var oracledb = require('oracledb');
var dbConfig = require('./dbconfig.js');
// Properties are applicable to all connections and SQL executions.
// They can also be set or overridden at the individual execute() call level
// Oracledb properties are applicable to all connections and SQL
// executions. They can also be set or overridden at the individual
// execute() call level
// fetchArraySize can be adjusted to tune the internal data transfer
// from the Oracle Database to node-oracledb. The value does not
// affect how, or when, rows are returned by node-oracledb to the
// application. Buffering is handled internally by node-oracledb.
// Benchmark to choose the optimal size for each application or query.
//
// oracledb.fetchArraySize = 100; // default value is 100
// This script sets outFormat in the execute() call but it could be set here instead:
//
// oracledb.outFormat = oracledb.OBJECT;
var doconnect = function(cb) {
@ -76,7 +86,7 @@ var doquery_object = function (conn, cb) {
conn.execute(
"SELECT location_id, city FROM locations WHERE city LIKE 'S%' ORDER BY city",
{}, // A bind variable parameter is needed to disambiguate the following options parameter
// otherwise you will get Error: ORA-01036: illegal variable name/number
// otherwise you will get Error: ORA-01036: illegal variable name/number
{ outFormat: oracledb.OBJECT }, // outFormat can be OBJECT or ARRAY. The default is ARRAY
function(err, result)
{

View File

@ -1,4 +1,4 @@
/* Copyright (c) 2015, 2016, Oracle and/or its affiliates. All rights reserved. */
/* Copyright (c) 2015, 2017, Oracle and/or its affiliates. All rights reserved. */
/******************************************************************************
*
@ -113,9 +113,9 @@ var dojsonfromrelational = function (conn, cb) {
return cb(null, conn);
} else {
conn.execute(
"SELECT JSON_OBJECT ('deptId' IS d.department_id, 'name' IS d.department_name) department "
+ "FROM departments d "
+ "WHERE department_id < :did",
`SELECT JSON_OBJECT ('deptId' IS d.department_id, 'name' IS d.department_name) department
FROM departments d
WHERE department_id < :did`,
[50],
function(err, result)
{

View File

@ -1,4 +1,4 @@
/* Copyright (c) 2015, 2016, Oracle and/or its affiliates. All rights reserved. */
/* Copyright (c) 2015, 2017, Oracle and/or its affiliates. All rights reserved. */
/******************************************************************************
*
@ -16,10 +16,10 @@
* limitations under the License.
*
* NAME
* selectjsonclob.js
* selectjsonblob.js
*
* DESCRIPTION
* Executes sample queries from a JSON table that uses CLOB storage.
* Executes sample insert and query using a JSON column with BLOB storage.
* Requires Oracle Database 12.1.0.2, which has extensive JSON datatype support.
* See https://docs.oracle.com/database/122/ADJSN/toc.htm
*
@ -50,13 +50,15 @@ var checkver = function (conn, cb) {
}
};
// Insert some data directly.
// Insert some JSON data
var doinsert = function (conn, cb) {
var data = { "userId": 2, "userName": "Bob", "location": "USA" };
var s = JSON.stringify(data);
var b = Buffer.from(s, 'utf8');
conn.execute(
"INSERT INTO j_purchaseorder_c (po_document) VALUES (:lobbv)",
{ lobbv: s },
"INSERT INTO j_purchaseorder_b (po_document) VALUES (:lobbv)",
{ lobbv: b },
// { autoCommit: true }, // uncomment if you want data to persist
function(err)
{
@ -69,13 +71,14 @@ var doinsert = function (conn, cb) {
});
};
// Selecting JSON stored in a CLOB column
// Select JSON stored in a BLOB column
var dojsonquery = function (conn, cb) {
console.log('Selecting JSON stored in a CLOB column');
console.log('Selecting JSON stored in a BLOB column');
conn.execute(
"SELECT po_document FROM j_purchaseorder_c WHERE JSON_EXISTS (po_document, '$.location')",
"SELECT po_document FROM j_purchaseorder_b WHERE JSON_EXISTS (po_document, '$.location')",
[],
{ fetchInfo: { "PO_DOCUMENT": { type: oracledb.STRING} } }, // Fetch as a String instead of a Stream
{ fetchInfo: { "PO_DOCUMENT": { type: oracledb.BUFFER } } }, // Fetch as a Buffer instead of a Stream
function(err, result)
{
if (err)
@ -84,7 +87,7 @@ var dojsonquery = function (conn, cb) {
return cb(new Error('No results'), conn);
console.log('Query results:');
console.log(result.rows);
console.log(result.rows[0][0].toString('utf8'));
return cb(null, conn);
});
};

View File

@ -30,6 +30,8 @@
var oracledb = require('oracledb');
var dbConfig = require('./dbconfig.js');
var rowcount = 0;
oracledb.getConnection(
{
user : dbConfig.user,
@ -44,7 +46,9 @@ oracledb.getConnection(
}
var stream = connection.queryStream(
'SELECT first_name, last_name FROM employees ORDER BY employee_id'
'SELECT first_name, last_name FROM employees ORDER BY employee_id',
[], // no binds
{ fetchArraySize: 150 } // internal buffer size for performance tuning
);
stream.on('error', function (error) {
@ -61,10 +65,12 @@ oracledb.getConnection(
stream.on('data', function (data) {
// console.log("stream 'data' event");
console.log(data);
rowcount++;
});
stream.on('end', function () {
// console.log("stream 'end' event");
console.log('Rows selected: ' + rowcount);
connection.close(
function(err) {
if (err) {

View File

@ -1,4 +1,4 @@
/* Copyright (c) 2015, Oracle and/or its affiliates. All rights reserved. */
/* Copyright (c) 2015, 2017, Oracle and/or its affiliates. All rights reserved. */
/******************************************************************************
*
@ -19,7 +19,7 @@
* version.js
*
* DESCRIPTION
* Shows the oracledb version attributes
* Shows the node-oracledb version attributes
*
*****************************************************************************/
@ -30,13 +30,13 @@ var addonVer, clientVer, serverVer;
var major, minor, update, port, portUpdate;
console.log("Run at: " + new Date());
console.log("Node.js version: " + process.version);
console.log("Node.js version: " + process.version + " (" + process.platform, process.arch + ")");
addonVer = oracledb.version;
major = Math.floor(addonVer / 10000);
minor = Math.floor(addonVer / 100) % 100;
update = addonVer % 100;
console.log("Node-oracledb version: " + addonVer);
//console.log("Node-oracledb version: " + addonVer);
console.log("Node-oracledb text format: " + major + "." + minor + "." + update);
clientVer = oracledb.oracleClientVersion;
@ -45,7 +45,7 @@ minor = Math.floor (clientVer / 1000000) % 100 ;
update = Math.floor (clientVer / 10000) % 100 ;
port = Math.floor (clientVer / 100) % 100 ;
portUpdate = clientVer % 100 ;
console.log("Oracle Client library version: " + clientVer);
//console.log("Oracle Client library version: " + clientVer);
console.log("Oracle Client library text format: " + major + "." + minor + "." + update + "." + port + "." + portUpdate);
oracledb.getConnection(
@ -67,6 +67,6 @@ oracledb.getConnection(
update = Math.floor (serverVer / 10000) % 100 ;
port = Math.floor (serverVer / 100) % 100 ;
portUpdate = serverVer % 100 ;
console.log("Oracle Database version: " + serverVer);
// console.log("Oracle Database version: " + serverVer);
console.log("Oracle Database text format: " + major + "." + minor + "." + update + "." + port + "." + portUpdate);
});

View File

@ -1,4 +1,4 @@
/* Copyright (c) 2015, 2016, Oracle and/or its affiliates. All rights reserved. */
/* Copyright (c) 2015, 2017, Oracle and/or its affiliates. All rights reserved. */
/******************************************************************************
*
@ -112,9 +112,9 @@ function handleRequest(request, response, pool) {
// console.log("Connections in use: " + pool.connectionsInUse);
connection.execute(
"SELECT employee_id, first_name, last_name " +
"FROM employees " +
"WHERE department_id = :id",
`SELECT employee_id, first_name, last_name
FROM employees
WHERE department_id = :id`,
[deptid], // bind variable value
function(err, result) {
if (err) {

View File

@ -1,4 +1,4 @@
/* Copyright (c) 2015, 2016, Oracle and/or its affiliates. All rights reserved. */
/* Copyright (c) 2015, 2017, Oracle and/or its affiliates. All rights reserved. */
/******************************************************************************
*
@ -105,9 +105,9 @@ function handleRequest(request, response, pool) {
// console.log("Connections in use: " + pool.connectionsInUse);
connection.execute(
"SELECT employee_id, first_name, last_name " +
"FROM employees " +
"WHERE department_id = :id",
`SELECT employee_id, first_name, last_name
FROM employees
WHERE department_id = :id`,
[deptid] // bind variable value
)
.then(function(result) {

View File

@ -53,6 +53,10 @@ function queryStream(sql, binding, options) {
stream = new QueryStream(null, self._oracledb);
if (options.fetchArraySize) {
stream._fetchArraySize = options.fetchArraySize;
}
self._execute(sql, binding, options, function(err, result) {
if (err) {
stream._open(err, null);
@ -71,6 +75,7 @@ function queryStream(sql, binding, options) {
function execute(a1, a2, a3, a4) {
var self = this;
var executeCb;
var executeOpts;
var custExecuteCb;
nodbUtil.assert(arguments.length > 1 && arguments.length < 5, 'NJS-009');
@ -103,13 +108,13 @@ function execute(a1, a2, a3, a4) {
// Need to extend resultsets which may come from either the query results
// or outBinds.
if (result.resultSet) {
resultset.extend(result.resultSet, self._oracledb);
resultset.extend(result.resultSet, self._oracledb, executeOpts);
} else if (result.outBinds) {
outBindsKeys = Object.keys(result.outBinds);
for (outBindsIdx = 0; outBindsIdx < outBindsKeys.length; outBindsIdx += 1) {
if (result.outBinds[outBindsKeys[outBindsIdx]] instanceof self._oracledb.ResultSet) {
resultset.extend(result.outBinds[outBindsKeys[outBindsIdx]], self._oracledb);
resultset.extend(result.outBinds[outBindsKeys[outBindsIdx]], self._oracledb, executeOpts);
}
}
}
@ -120,10 +125,12 @@ function execute(a1, a2, a3, a4) {
switch (arguments.length) {
case 4:
executeCb = a4;
executeOpts = a3;
self._execute.call(self, a1, a2, a3, custExecuteCb);
break;
case 3:
executeCb = a3;
executeOpts = a2;
self._execute.call(self, a1, a2, custExecuteCb);
break;
case 2:

View File

@ -1,4 +1,4 @@
/* Copyright (c) 2016, Oracle and/or its affiliates. All rights reserved. */
/* Copyright (c) 2016, 2017, Oracle and/or its affiliates. All rights reserved. */
/******************************************************************************
*
@ -26,7 +26,8 @@ var closePromisified;
util.inherits(Lob, Duplex);
// The Lob class is used to support the streaming of LOB data to/from the database.
// the Lob class is used to support the streaming of LOB data to/from the
// database; the iLob refers to the C++ implementation of the Lob class
function Lob(iLob, opt, oracledb) {
Duplex.call(this, opt);
@ -72,80 +73,57 @@ function Lob(iLob, opt, oracledb) {
});
if (this._autoCloseLob) {
this.once('finish', this._closeSync);
this.once('finish', function() {
this.close(function() {});
});
}
}
// implementation of streaming read; if lob is set to auto-close, the lob is
// automatically closed within the C++ code when an error occurs or when there
// are no more bytes to transfer; all that needs to be done in the JS layer is
// to emit the close and/or error events
Lob.prototype._read = function() {
var self = this;
self.iLob.read(
function(err, str) {
if (err) {
if (self._autoCloseLob) {
// Ignore if any error occurs during close
// Emits 'close' event after closing LOB
self._closeSync();
}
self.emit('error', err);
if (self._autoCloseLob) {
self.emit('close');
}
return;
}
self.push(str);
if (self._autoCloseLob) {
if (!str) {
process.nextTick(function() {
err = self._closeSync(); // Emits 'close' event after closing LOB
if (err) {
self.emit('error', err);
return;
}
});
}
if (self._autoCloseLob && !str) {
process.nextTick(function() {
self.emit('close');
});
}
}
);
};
// implementation of streaming write; if lob is set to auto-close, the lob is
// automatically closed in the "finish" event; all that needs to be done here
// is to emit the close event in the event of an error
Lob.prototype._write = function(data, encoding, cb) {
var self = this;
self.iLob.write(
data,
function(err) {
if (err) {
self._closeSync(); // Ignore if any error occurs during close
cb(err);
return;
if (err && self._autoCloseLob) {
self.emit('close');
}
cb();
cb(err);
}
);
};
// This function will be deprecated in the future
// This internal function used to close the LOB at the end of writable
// stream in synchronus way to avoid race condition between this function and
// application's listener function on 'finish' event.
Lob.prototype._closeSync = function() {
var self = this;
if (self.iLob !== null) {
try {
self.iLob.release();
} catch(err) {
self.iLob = null;
return err;
}
self.emit('close');
}
};
Lob.prototype.close = function(closeCb) {
var self = this;
@ -160,7 +138,9 @@ Lob.prototype.close = function(closeCb) {
}
self.iLob.close(function(err) {
if (!err) {
if (err) {
self.emit('error', err);
} else {
self.emit('close');
}

View File

@ -1,4 +1,4 @@
/* Copyright (c) 2015, 2016, Oracle and/or its affiliates. All rights reserved. */
/* Copyright (c) 2015, 2017, Oracle and/or its affiliates. All rights reserved. */
/******************************************************************************
*
@ -30,22 +30,43 @@ var getConnectionPromisified;
var poolCache = {};
var tempUsedPoolAliases = {};
var defaultPoolAlias = 'default';
var binaryReleasePath = '../build/Release/oracledb.node';
var binaryDebugPath = '../build/Debug/oracledb.node';
// Load the node-oracledb binary add-on that was built when 'npm
// install' invoked node-gyp.
// The Debug version of node-oracledb will only exist if 'npm install
// --debug oracledb' was used. Typically only the maintainers of
// node-oracledb do this.
try {
oracledbCLib = require('../build/Release/oracledb');
oracledbCLib = require(binaryReleasePath);
} catch (err) {
if (err.code !== 'MODULE_NOT_FOUND') {
throw err;
} else {
var nodeInfo = process.versions.node + ' (' + process.platform + ', ' + process.arch +')\n';
var fullReleasePath = require('path').resolve(__dirname, binaryReleasePath);
if (err.code === 'MODULE_NOT_FOUND') {
try {
oracledbCLib = require('../build/Debug/oracledb');
oracledbCLib = require(binaryDebugPath);
} catch (err) {
if (err.code !== 'MODULE_NOT_FOUND') {
throw err;
if (err.code === 'MODULE_NOT_FOUND') {
// Neither Release or Debug binary was found but assume users wanted Release binary
nodeInfo += 'Cannot find module ' + fullReleasePath + '\n' + getInfo();
throw new Error(nodbUtil.getErrorMessage('NJS-045', nodeInfo));
} else {
throw new Error(nodbUtil.getErrorMessage('NJS-045'));
nodeInfo += 'Cannot load ' + binaryDebugPath + '\n';
nodeInfo += 'Node.js require() error was: \n ' + err.message + '\n' + getInfo();
throw new Error(nodbUtil.getErrorMessage('NJS-045', nodeInfo));
}
}
} else {
if (err.message.startsWith('DPI-1047:')) {
// Release add-on binary loaded OK, but ODPI-C can't load Oracle client
nodeInfo += 'Node.js require() error was: \n ' + err.message + '\n';
nodeInfo += 'Node.js require() mapped to ' + fullReleasePath + '\n' + getInfo();
throw new Error(nodbUtil.getErrorMessage('NJS-045', nodeInfo));
} else {
nodeInfo += 'Cannot load ' + fullReleasePath + '\n' + err.message + '\n' + getInfo();
throw new Error(nodbUtil.getErrorMessage('NJS-045', nodeInfo));
}
}
}
@ -53,6 +74,58 @@ oracledbCLib.Oracledb.prototype.newLob = function(iLob) {
return new Lob(iLob, null, oracledbInst);
};
// Return a string with installation usage tips that may be helpful
function getInfo() {
var arch, url, mesg = '';
mesg = 'Node-oracledb installation instructions: ';
mesg += 'https://github.com/oracle/node-oracledb/blob/master/INSTALL.md\n';
if (process.platform === 'linux') {
if (process.arch === 'x64') {
url = 'http://www.oracle.com/technetwork/topics/linuxx86-64soft-092277.html\n';
arch = '64-bit';
} else {
url = 'http://www.oracle.com/technetwork/topics/linuxsoft-082809.html\n';
arch = '32-bit';
}
mesg += 'You must have ' + arch + ' Oracle client libraries in LD_LIBRARY_PATH, or configured with ldconfig.\n';
mesg += 'If you do not have Oracle Database on this computer, then install the Instant Client Basic or Basic Light package from \n';
mesg += url;
} else if (process.platform === 'darwin') {
url = 'http://www.oracle.com/technetwork/topics/intel-macsoft-096467.html';
if (process.arch === 'x64') {
arch = '64-bit';
} else {
arch = '32-bit';
}
mesg += 'You must have the ' + arch + ' Oracle Instant Client Basic or Basic Light package in ~/lib or /usr/local/lib\n';
mesg += 'They can be downloaded from ' + url;
} else if (process.platform === 'win32') {
if (process.arch === 'x64') {
url = 'http://www.oracle.com/technetwork/topics/winx64soft-089540.html\n';
arch = '64-bit';
} else {
url = 'http://www.oracle.com/technetwork/topics/winsoft-085727.html\n';
arch = '32-bit';
}
mesg += 'You must have ' + arch + ' Oracle client libraries in your PATH environment variable.\n';
mesg += 'If you do not have Oracle Database on this computer, then install the Instant Client Basic or Basic Light package from\n';
mesg += url;
mesg += 'A Microsoft Visual Studio Redistributable suitable for your Oracle client library version must be available.\n';
} else {
url = 'http://www.oracle.com/technetwork/database/features/instant-client/index-100365.html\n';
if (process.arch === 'x64') {
arch = '64-bit';
} else {
arch = '32-bit';
}
mesg += 'You must have ' + arch + ' Oracle client libraries in your operating system library search path.\n';
mesg += 'If you do not have Oracle Database on this computer, then install an Instant Client Basic or Basic Light package from: \n';
mesg += url;
}
return mesg;
}
// This createPool function is used the override the createPool method of the
// Oracledb class, which is defined in the C layer. The override allows us to do
// things like extend out the pool instance prior to passing it to the caller.
@ -244,6 +317,10 @@ function extend(oracledb) {
value: 2,
enumerable: true
},
DB_TYPE_LONG: {
value: 8,
enumerable: true
},
DB_TYPE_DATE: {
value: 12,
enumerable: true
@ -252,6 +329,10 @@ function extend(oracledb) {
value: 23,
enumerable: true
},
DB_TYPE_LONG_RAW: {
value: 24,
enumerable: true
},
DB_TYPE_CHAR: {
value: 96,
enumerable: true
@ -288,6 +369,18 @@ function extend(oracledb) {
value: 232,
enumerable: true
},
DB_TYPE_NVARCHAR: {
value : 1001,
enumerable : true
},
DB_TYPE_NCHAR: {
value : 1096,
enumerable : true
},
DB_TYPE_NCLOB: {
value : 1112,
enumerable : true
},
STRING: {
value: 2001,
enumerable: true

View File

@ -51,6 +51,10 @@ function QueryStream(resultSet, oracledb) {
_closed: { // used to track that the stream is closed
value: false,
writable: true
},
_fetchArraySize: { // used to identify the fetch array size
value: oracledb.fetchArraySize,
writable: true
}
}
);
@ -125,7 +129,7 @@ QueryStream.prototype._read = function () {
// errors related to close w/conncurrent operations on resultsets
self._fetching = true;
fetchCount = self._oracledb.maxRows || 100;
fetchCount = self._fetchArraySize;
// Calling the C layer getRows directly to avoid assertions on the public method
self._resultSet._getRows(fetchCount, function(err, rows) {
@ -218,9 +222,7 @@ function close(callback) {
self._resultSet._close(function(err) {
if (err) {
self.emit('error', err);
return;
}
self.emit('close');
});
}

View File

@ -47,7 +47,9 @@ function close(closeCb) {
closePromisified = nodbUtil.promisify(close);
// This getRow function is just a place holder to allow for easier extension later.
// getRow is a JavaScript based wrapper on getRows. It buffers rows in a JavaScript
// array to avoid the trips through the thread pool that would be required if
// implemented in C.
function getRow(getRowCb) {
var self = this;
@ -61,14 +63,32 @@ function getRow(getRowCb) {
self._processingStarted = true;
self._getRow.apply(self, arguments);
if (self._rowCache.length) {
getRowCb(null, self._rowCache.shift());
return;
}
self._getRows(self._fetchArraySize, function(err, rows) {
if (err) {
getRowCb(err);
return;
}
self._rowCache = rows;
getRowCb(null, self._rowCache.shift());
});
}
getRowPromisified = nodbUtil.promisify(getRow);
// This getRows function is just a place holder to allow for easier extension later.
// The JS getRows will first check to see if any rows are in the JS buffer (which
// could result from interspersed calls to getRow and getRows). If no rows are in the
// buffer, the call is just proxied to the C layer. Otherwise, rows are pulled from
// the buffer and potentially concatenated with rows from a call to getRows.
function getRows(numRows, getRowsCb) {
var self = this;
var rowsNeeded;
nodbUtil.assert(arguments.length === 2, 'NJS-009');
nodbUtil.assert(typeof numRows === 'number', 'NJS-006', 1);
@ -81,7 +101,30 @@ function getRows(numRows, getRowsCb) {
self._processingStarted = true;
self._getRows.apply(self, arguments);
if (self._rowCache.length === 0) {
self._getRows.apply(self, arguments);
} else {
rowsNeeded = numRows - self._rowCache.length;
if (rowsNeeded <= 0) {
getRowsCb(null, self._rowCache.splice(0, numRows));
} else {
self._getRows(rowsNeeded, function(err, rows) {
var requestedRows;
if (err) {
getRowsCb(err);
return;
}
requestedRows = self._rowCache.concat(rows);
self._rowCache = [];
getRowsCb(null, requestedRows);
});
}
}
}
getRowsPromisified = nodbUtil.promisify(getRows);
@ -110,7 +153,13 @@ function toQueryStream() {
// The extend method is used to extend the ResultSet instance from the C layer with
// custom properties and method overrides. References to the original methods are
// maintained so they can be invoked by the overriding method at the right time.
function extend(resultSet, oracledb) {
function extend(resultSet, oracledb, executeOpts) {
var fetchArraySize = oracledb.fetchArraySize;
if (executeOpts && executeOpts.fetchArraySize) {
fetchArraySize = executeOpts.fetchArraySize;
}
// Using Object.defineProperties to add properties to the ResultSet instance with
// special properties, such as enumerable but not writable.
Object.defineProperties(
@ -119,6 +168,13 @@ function extend(resultSet, oracledb) {
_oracledb: { // storing a reference to the base instance to avoid circular references with require
value: oracledb
},
_fetchArraySize: { // stores the value of fetchArraySize that was passed to conn.execute (if any)
value: fetchArraySize
},
_rowCache: { // used for storing rows when getRow is used
value: [],
writable: true
},
_processingStarted: { // used to prevent conversion to stream after invoking methods
value: false,
writable: true

View File

@ -41,7 +41,7 @@ var errorMessages = {
'NJS-041': 'NJS-041: cannot convert ResultSet to QueryStream after invoking methods',
'NJS-042': 'NJS-042: cannot invoke ResultSet methods after converting to QueryStream',
'NJS-043': 'NJS-043: ResultSet already converted to QueryStream',
'NJS-045': 'NJS-045: cannot load the oracledb add-on binary',
'NJS-045': 'NJS-045: cannot load the oracledb add-on binary for Node.js %s',
'NJS-046': 'NJS-046: poolAlias "%s" already exists in the connection pool cache',
'NJS-047': 'NJS-047: poolAlias "%s" not found in the connection pool cache'
};

1
odpi Submodule

@ -0,0 +1 @@
Subproject commit 855c898044cc7be20de74da7d42392787dcf8d49

View File

@ -1,6 +1,6 @@
{
"name": "oracledb",
"version": "1.13.1",
"version": "2.0.15",
"description": "Oracle Database driver by Oracle Corp.",
"license": "Apache-2.0",
"homepage": "http://www.oracle.com/technetwork/database/database-technologies/scripting-languages/node_js/",
@ -29,20 +29,20 @@
"url": "git://github.com/oracle/node-oracledb.git"
},
"dependencies": {
"nan": "~2.5.0"
"nan": "~2.8.0"
},
"devDependencies": {
"mocha": "^2.4.5",
"should": "^8.3.1",
"async": "^1.5.0"
"mocha": "^2.4.5",
"should": "^8.3.1",
"async": "^1.5.0"
},
"scripts": {
"test": "mocha --opts test/opts/mocha.opts",
"posttest": "node test/opts/versions.js",
"testwindows": "mocha --opts test\\opts\\mocha.opts && npm run posttest"
"test": "mocha --opts test/opts/mocha.opts",
"posttest": "node test/opts/versions.js",
"testwindows": "mocha --opts test\\opts\\mocha.opts && npm run posttest"
},
"engines": {
"node": ">=0.10.28"
"node": ">=4"
},
"maintainers": [
{

93
package/MAKEPKG.BAT Normal file
View File

@ -0,0 +1,93 @@
@echo off
REM Copyright (c) 2017, Oracle and/or its affiliates. All Rights reserved
REM
REM ******************************************************************************
REM *
REM * You may not use the identified files except in compliance with the Apache
REM * License, Version 2.0 (the "License.")
REM *
REM * You may obtain a copy of the License at
REM * http://www.apache.org/licenses/LICENSE-2.0.
REM *
REM * Unless required by applicable law or agreed to in writing, software
REM * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
REM * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
REM *
REM * See the License for the specific language governing permissions and
REM * limitations under the License.
REM *
REM * NAME
REM * MAKEPKG.BAT
REM *
REM * DESCRIPTION
REM * Create/cleanup of binary package for the current node-oracledb binary.
REM *
REM *****************************************************************************
REM
REM usage: MAKEPKG.BAT [<cmd>]
REM : Possible values for <cmd> are: CLEANUP and CREATEBINARY
REM
REM expected to run this batch file from package sub-directory,
REM where a fresh clone is created.
REM
REM expecting 1 parameter, make sure we have some arguments
if "%1" == "" GOTO usage
REM jump to appropriate sections based on <cmd>
if "%1" == "CLEANUP" GOTO cleanup
if "%1" == "CREATEBINARY" GOTO createbinary
goto usage
REM cleanup section, remove file(s) created by this batch file
:cleanup
echo "cleanup section"
del ..\package-lock.json
del SHASUMS256.txt oracledb-v*-node-*.gz
goto exit
REM compile, package to gz file
:createbinary
echo "createbinary section"
REM Append SHA to LICENSE.MD
git checkout ..\LICENSE.md
setlocal enabledelayedexpansion
REM compose a string with commands to execute one by one
REM start with empty string
set CONCAT_STR=
REM capture SHA
FOR /F "tokens=* USEBACKQ" %%F IN (`git --git-dir=..\.git rev-parse HEAD`) DO (
SET CONCAT_STR=%%F
)
set DATE_STR=
FOR /F "tokens=* USEBACKQ" %%F IN (`DATE /T`) DO ( SET DATE_STR=%%F )
REM append output of other commands
set CMD_STR="git --git-dir=..\odpi\.git rev-parse HEAD && node --version"
for /f %%i in ('%CMD_STR%') do set "CONCAT_STR=!CONCAT_STR! %%i"
set CONCAT_STR=!CONCAT_STR! !DATE_STR!
echo !CONCAT_STR! >> ..\LICENSE.MD
REM Compile node-oracledb
cd ..
CALL npm install
echo "NODE oracledb compiled"
cd package
echo "==> Binary package created for Node.js "
REM create compressed file
node createpackage.js
goto exit
REM display usage string
:usage
echo "usage: MAKEPKG.BAT [<cmd>]
goto exit
REM Exit point
:exit

89
package/Makefile Normal file
View File

@ -0,0 +1,89 @@
# Copyright (c) 2017, 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.
CP=cp
MV=mv
CD=cd
ECHO=echo
DATE=date -u
SED=sed
GREP=grep
RMDIR=rm -rf
RMALL=rm -f
GIT=git
NODE=node
NPM=npm
GITSHA=$(shell $(GIT) --git-dir=../.git rev-parse --verify HEAD)
SUBMOD=$(shell $(GIT) --git-dir=../odpi/.git rev-parse --verify HEAD)
NODEVER=$(shell $(NODE) --version)
BUILDDATE=$(shell $(DATE))
# createpackage.js assumes these paths
BINARY_PATH_LOCAL=../build/Release/oracledb.node
LICENSE_PATH_LOCAL=../LICENSE.md
# Find the node-oracledb version number
MAJ=$(shell $(GREP) '\#define \+NJS_NODE_ORACLEDB_MAJOR' ../src/njsOracle.h | $(SED) -e 's/[^0-9]*//')
MIN=$(shell $(GREP) '\#define \+NJS_NODE_ORACLEDB_MINOR' ../src/njsOracle.h | $(SED) -e 's/[^0-9]*//')
PAT=$(shell $(GREP) '\#define \+NJS_NODE_ORACLEDB_PATCH' ../src/njsOracle.h | $(SED) -e 's/[^0-9]*//')
VER=$(MAJ).$(MIN).$(PAT)
# The staging-oracledb-X.Y.Z.tgz package will try to download binaries from
# https://$NODE_ORACLEDB_PACKAGE_HOSTNAME/$NODE_ORACLEDB_PACKAGE_URL_PATH/vX.Y.Z/
ifndef NODE_ORACLEDB_PACKAGE_HOSTNAME
NODE_ORACLEDB_PACKAGE_HOSTNAME=your-staging-server.example.com
endif
ifndef NODE_ORACLEDB_PACKAGE_URL_PATH
NODE_ORACLEDB_PACKAGE_URL_PATH=/your-url-path-to-directory/
endif
# Create the generic 'npm install' package with a package.json that
# invokes oracledbinstall.js at install time
npmpackage:
$(ECHO) "$(GITSHA) $(BUILDDATE)" > ../lib/rel.txt
$(NPM) pack .. && $(MV) oracledb-$(VER).tgz oracledb-src-$(VER).tgz
@$(ECHO) "==> Created generic GitHub source package for node-oracledb $(VER)"
$(SED) -e "s#'github.com'#'$(NODE_ORACLEDB_PACKAGE_HOSTNAME)'#" oracledbinstall.js > oracledbinstall.js.tmp && $(MV) oracledbinstall.js.tmp oracledbinstall.js
$(SED) -e "s#'/oracle/node-oracledb/releases/download/'#'$(NODE_ORACLEDB_PACKAGE_URL_PATH)'#" oracledbinstall.js > oracledbinstall.js.tmp && $(MV) oracledbinstall.js.tmp oracledbinstall.js
$(CP) package.json ../package.json
$(NPM) pack .. && $(MV) oracledb-$(VER).tgz staging-oracledb-$(VER).tgz
@$(ECHO) "==> Created generic npm staging package for node-oracledb $(VER)"
$(GIT) checkout oracledbinstall.js && $(NPM) pack ..
$(GIT) checkout ../package.json
@$(RMALL) ../lib/rel.txt
@$(ECHO) "==> Created generic npm production package for node-oracledb $(VER)"
# Create a package containing (i) the license file and (ii) the
# node-oracledb binary for the current environment
binarypackage: $(BINARY_PATH_LOCAL) $(LICENSE_PATH_LOCAL)
$(GIT) checkout $(LICENSE_PATH_LOCAL)
$(CP) $(LICENSE_PATH_LOCAL) $(LICENSE_PATH_LOCAL).bk && $(ECHO) "$(GITSHA) $(SUBMOD) $(NODEVER) $(BUILDDATE)" >> $(LICENSE_PATH_LOCAL)
$(NODE) createpackage.js
$(MV) $(LICENSE_PATH_LOCAL).bk $(LICENSE_PATH_LOCAL)
@$(ECHO) "==> Created binary package for Node.js `$(NODE) --version`"
# Build the node-oracledb binary
$(BINARY_PATH_LOCAL): cleanbinary
($(CD) .. && $(NPM) install)
clean: cleanbinary
$(RMALL) ../package-lock.json
$(RMALL) oracledb-$(VER).tgz staging-oracledb-$(VER).tgz SHASUMS256.txt oracledb-v*-node-*.gz
cleanbinary:
$(RMALL) $(BINARY_PATH_LOCAL)

106
package/README.md Normal file
View File

@ -0,0 +1,106 @@
# Overview
This directory contains scripts for building, extracting and
installing binary packages of node-oracledb. Most users do not need
to use anything in this directory (the exception is when doing a
[manual
install](https://github.com/oracle/node-oracledb/blob/master/INSTALL.md#offline)
instead of using `npm`).
The binary install process requires two kinds of package:
- a gzipped tar file like `oracledb-X.Y.Z.tgz` containing JavaScript
and ancillary files suitable for npm to install. This is a generic
file used on all platforms.
- a gzipped package like `oracledb-vZ.Y.Z-node-v57-darwin-x64.gz`
containing the binary add-on. The package uses a custom format with
three components: length bytes (giving the length of the license
file), the license file, and then the node-oracledb binary. Each
Node.js version/architecture needs a unique binary package.
A custom package format is used due to business and technical requirements:
- the license text needs to be included with any binary download.
- Node.js doesn't have a native archive module, and the installer
should be lightweight and not have 3rd party dependencies.
When `npm install oracledb` is executed, the JavaScript package is
first installed by npm. An 'install' script in its `package.json`
invokes `oracledbinstall.js`. This downloads the appropriate
node-oracledb binary package, and then extracts and installs the
binary.
If a suitable binary package is not available, users must compile
source code by installing from GitHub.
Installation is described in [INSTALL](../INSTALL.md).
# Maintainers
- The Makefile is used by node-oracledb maintainers to create the
packages to be uploaded to
[GitHub](https://github.com/oracle/node-oracledb) and
[npm](https://www.npmjs.com/package/oracledb).
- `make npmpackage` makes the main node-oracledb package
containing the general node-oracledb JavaScript files and the
package.json in this directory. This is the package that an
`npm install oracledb` will initially install.
- `make binarypackage` makes a binary package for the current
Node.js / node-oracledb / platform combination and generates a
SHA256 for the binary.
- As part of `npm install`, the `package.json` in this directory
invokes `oracledbinstall.js` that downloads the appropriate binary
package from GitHub. This variant of `package.json` is the copy
bundled for the npm release.
The parent file `../package.json` doesn't have the install target
meaning that node-gyp will be invoked to compile node-oracledb. This
allows installation from source code (via GitHub) when no suitable
pre-built binary is available.
- The `make npmpackage` command creates two variants of the JavaScript bundle:
- `oracledb-X.Y.Z.tgz` which downloads binaries from the
node-oracledb GitHub release page.
- `staging-oracledb-X.Y.Z.tgz` which downloads binaries from a
server of your choice, specified by the environment variables
`NODE_ORACLEDB_PACKAGE_HOSTNAME` (e.g. "your.example.com") and
`NODE_ORACLEDB_PACKAGE_URL_PATH` (e.g. "/yourpath/") which must be set
before running `make`.
- The`staging-oracledb-X.Y.Z.tgz` package can be used to host binaries
on internal networks. Copy `staging-oracledb-X.Y.Z.tgz`, the binary
packages for each desired architectures, and a single SHASUMS256.txt
file (with one line per available binary package) to an
HTTPS-enabled web server to the directory that
https://your.example.com/yourpath/vX.Y.Z/ resolves to. Note if the
web server has a self-signed certificate, then you may need to
bypass some npm checks:
```
export NODE_TLS_REJECT_UNAUTHORIZED=0
npm config set strict-ssl false
npm install https://your.example.com/yourpath/vX.Y.Z/staging-oracledb-X.Y.X.tgz
```
Remember to do `npm config delete strict-ssl` and unset the
environment variable when not testing.
- At install time, setting the environment variable
`NODE_ORACLEDB_TRACE_INSTALL` to `TRUE` will cause `npm install` to
display more tracing information.
- The installer scripts assume GitHub tags have the format "vX.Y.Z".
Other assumptions about GitHub paths are also made in the scripts.
- TODO
- oracledbinstall.js should cache SHASUMS256.txt so it doesn't have to be fetched twice.
- Improve oracledbinstall.js `no_proxy` support for domain names and wildcards.

186
package/createpackage.js Normal file
View File

@ -0,0 +1,186 @@
/* Copyright (c) 2017, 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
* createpackage.js
*
* DESCRIPTION
* Creates a binary package for the current node-oracledb binary. A
* custom package format is used. The package uses a custom format
* with three components: length bytes (giving the length of the
* license file), the license file, and then the node-oracledb
* binary. The package is gzipped.
*
*****************************************************************************/
'use strict';
const fs = require('fs');
const Readable = require('stream').Readable;
const zlib = require('zlib');
const path = require('path');
const util = require('util');
const packageUtil = require('./util.js');
packageUtil.initDynamicProps();
// writeFileToReadable is used to buffer the contents of files to a readable
// stream that can be written out later.
function writeFileToReadable(path, readable) {
return new Promise((resolve, reject) => {
packageUtil.trace('In writeFileToReadable', path, util.inspect(readable, {depth: 0}));
const rs = fs.createReadStream(path);
rs.on('data', chunk => {
readable.push(chunk);
});
rs.on('error', err => {
reject(err);
});
rs.on('close', () => {
resolve();
});
});
}
// createPackage is used to create a custom file that combines the node-oracledb
// binary with the license. This function is meant to be used at the command line.
function createPackage() {
packageUtil.trace('In createPackage');
let binaryPath = packageUtil.BINARY_PATH_LOCAL;
for (let x = 2; x < process.argv.length; x += 1) {
let argParts = process.argv[x].split('=');
let argName = argParts[0];
let argVal = argParts[1];
if (argName === 'path') {
binaryPath = argVal;
}
}
if (!binaryPath.endsWith(packageUtil.BINARY_FILE_NAME)) {
throw new Error('path should resolve to a file named ' + packageUtil.BINARY_FILE_NAME);
}
let binaryStats = fs.statSync(binaryPath);
if (!binaryStats.isFile()) {
throw new Error('path did not resolve to a file');
}
// Requiring in the binary ensures that it matches the version of Node.js currently
// running. This is important as the process variable is used to file naming.
require(path.normalize(binaryPath + '/../../../'));
let licensePath;
if (binaryPath != packageUtil.BINARY_PATH_LOCAL) {
licensePath = path.normalize(binaryPath + '/../../../' + packageUtil.LICENSE_FILE_NAME);
} else {
licensePath = packageUtil.LICENSE_PATH_LOCAL;
}
class TempReadable extends Readable {
constructor(options) {
super(options);
}
_read(size) {} // Must be implemented but not used
}
const tempReadable = new TempReadable({
highWaterMark: 1048576 // 1 MB
});
packageUtil.getSha(binaryPath)
.then(binarySha => {
const newShaLine = binarySha + ' ' + packageUtil.dynamicProps.BINARY_BUILD_NAME;
let shaFileContents;
try {
shaFileContents = fs.readFileSync(packageUtil.SHA_FILE_NAME, {encoding: 'utf8'});
shaFileContents = shaFileContents.split('\n');
let updatedLine = false;
for (let x = 0; x < shaFileContents.length; x += 1) {
const line = shaFileContents[x];
if (line.split(' ')[1] === packageUtil.dynamicProps.BINARY_BUILD_NAME) {
shaFileContents[x] = newShaLine;
updatedLine = true;
break;
}
}
if (!updatedLine) {
shaFileContents.splice(shaFileContents.length - 1, 0, newShaLine);
}
shaFileContents = shaFileContents.join('\n');
} catch (err) {
shaFileContents = newShaLine + '\n';
}
fs.writeFileSync(packageUtil.SHA_FILE_NAME, shaFileContents);
let stats = fs.statSync(licensePath);
let licenseSize = stats.size.toString();
let zerosToAppend = packageUtil.LICENSE_HEADER_BYTES - licenseSize.length;
let paddedZeros = '';
for (let x = 0; x < zerosToAppend; x += 1) {
paddedZeros += '0';
}
licenseSize = paddedZeros + licenseSize;
// The following line generates an error on Node.js 4.0, but not 4.8.5. Not sure
// when the correct API was added.
const licenseSizeBuf = Buffer.from(licenseSize, 'ascii');
tempReadable.push(licenseSizeBuf);
})
.then(() => {
return writeFileToReadable(licensePath, tempReadable);
})
.then(() => {
return writeFileToReadable(binaryPath, tempReadable);
})
.then(() => {
const ws = fs.createWriteStream(packageUtil.dynamicProps.PACKAGE_FILE_NAME);
const gzip = zlib.createGzip();
const filestream = tempReadable.pipe(gzip).pipe(ws);
tempReadable.push(null); // Signal the end of data in
filestream.on('close', () => {
console.log('Package created: ' + packageUtil.dynamicProps.PACKAGE_FILE_NAME);
});
})
.catch(err => {
console.log('Error creating package', err);
})
}
createPackage();

75
package/extractpackage.js Normal file
View File

@ -0,0 +1,75 @@
/* Copyright (c) 2017, 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
* extractpackage.js
*
* DESCRIPTION
* This script is a command-line interface to extract node-oracledb
* binaries from an available binary package, see INSTALL.md.
*
* USAGE
* Run this script like:
* node extractpackage.js path=oracledb-vX.Y.Z-node-vNN-platform-architecture.gz
* For example:
* node extractpackage.js path=oracledb-v2.0.14-node-v57-darwin-x64.gz
*
* The extracted binary can be manually moved to the correct directory.
*
*****************************************************************************/
'use strict';
// This module is meant to be used with Node.js at the command line. It breaks
// apart a custom file that combines the node-oracledb license and binary into
// two separate files.
const fs = require('fs');
const packageUtil = require('./util.js');
let packagePath;
for (let x = 1; x < process.argv.length; x += 1) {
let argParts = process.argv[x].split('=');
let argName = argParts[0];
let argVal = argParts[1];
if (argName === 'path') {
packagePath = argVal;
}
}
if (packagePath === undefined) {
throw new Error('path must be specified: node extractpackage.js path=/path/to/package.gz');
} else {
let stats = fs.statSync(packagePath);
if (!stats.isFile()) {
throw new Error('path did not resolve to a file');
}
}
packageUtil.extract({
packagePath: packagePath,
writeLicense: true
})
.then(() => {
packageUtil.log('Package extracted');
})
.catch(err => {
packageUtil.error('Error extracting package');
packageUtil.error(err.message);
});

460
package/oracledbinstall.js Normal file
View File

@ -0,0 +1,460 @@
/* Copyright (c) 2017, 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
* oracledbinstall.js
*
* DESCRIPTION
* This script is included in the npm bundle of node-oracledb. It
* is invoked by package.json during npm install. It downloads a
* pre-built node-oracleb binary from GitHub if one is available, or
* gives a message on how to compile one from source code.
*
* Set NODE_ORACLEDB_TRACE_INSTALL=TRUE for installation trace output.
*
* MAINTENANCE NOTES
* - This file should run with Node 4 or later.
* - This file should only ever 'require' packages included in core Node.js.
*
*****************************************************************************/
'use strict';
const http = require('http'); // Fails in old Node.js. Use Node 4+
const https = require('https');
const fs = require('fs');
const url = require('url');
const stream = require('stream');
const zlib = require('zlib');
const packageUtil = require('./util.js');
packageUtil.initDynamicProps();
try {
// Requiring here to ensure it's available, actually used in util.js
const crypto = require('crypto');
} catch (err) {
done(new Error('Node.js crypto module required to install from binary'));
return;
}
// Note: the Makefile uses these hostname and path values for the npm
// package but will substitute them for the staging package
const PACKAGE_HOSTNAME = 'github.com';
const PACKAGE_PATH_REMOTE = '/oracle/node-oracledb/releases/download/' + packageUtil.dynamicProps.GITHUB_TAG + '/' + packageUtil.dynamicProps.PACKAGE_FILE_NAME;
const SHA_PATH_REMOTE = '/oracle/node-oracledb/releases/download/' + packageUtil.dynamicProps.GITHUB_TAG + '/' + packageUtil.SHA_FILE_NAME;
const PORT = 443;
// getProxyConfig gets the proxy configuration for a given hostname. Has basic
// no_proxy support.
function getProxyConfig(hostname) {
packageUtil.trace('In getProxyConfig', hostname);
const proxyConfig = {
useProxy: undefined
};
let proxy = process.env.https_proxy ||
process.env.HTTPS_PROXY ||
process.env.http_proxy ||
process.env.HTTP_PROXY ||
process.env.all_proxy ||
process.env.ALL_PROXY;
if (proxy) {
proxyConfig.useProxy = true;
if (!proxy.startsWith('http://') && !proxy.startsWith('https://')) {
proxy = 'https://' + proxy;
}
const parsedUrl = url.parse(proxy);
proxyConfig.hostname = parsedUrl.hostname;
proxyConfig.port = parsedUrl.port;
} else {
proxyConfig.useProxy = false;
return proxyConfig;
}
const noProxy = process.env.NO_PROXY ||
process.env.no_PROXY ||
process.env.no_proxy;
if (noProxy === '*') {
packageUtil.trace('noProxy wildcard');
proxyConfig.useProxy = false;
proxyConfig.hostname = undefined;
proxyConfig.hostname = undefined;
} else if (noProxy) {
const noProxies = noProxy.toLowerCase().split(',');
packageUtil.trace('noProxy', noProxies);
if (noProxies.indexOf(hostname.toLowerCase()) > -1) {
proxyConfig.useProxy = false;
proxyConfig.hostname = undefined;
proxyConfig.port = undefined;
}
}
return proxyConfig;
}
// verifyBinary is used to ensure that the SHA of the local binary matches the
// SHA in the remote SHA file.
function verifyBinary() {
return new Promise((resolve, reject) => {
packageUtil.trace('In verifyBinary');
packageUtil.trace('Checking for binary at', packageUtil.BINARY_PATH_LOCAL);
packageUtil.log('Verifying installation');
if (!fs.existsSync(packageUtil.BINARY_PATH_LOCAL)) {
packageUtil.log('Binary not found');
resolve(false);
return;
}
let remoteShaFile = '';
let binarySha;
packageUtil.getSha(packageUtil.BINARY_PATH_LOCAL)
.then((sha) => {
binarySha = sha;
return getRemoteFileReadStream(PACKAGE_HOSTNAME, SHA_PATH_REMOTE);
})
.then(readStream => {
return new Promise((resolve, reject) => {
readStream.setEncoding('utf8');
// Buffer file in memory
readStream.on('data', chunk => {
remoteShaFile += chunk;
});
readStream.on('error', reject);
readStream.on('end', resolve);
});
})
.then(() => {
if (!remoteShaFile.match(packageUtil.dynamicProps.BINARY_BUILD_NAME)) {
packageUtil.log('Build not found in SHASUMS256.txt');
resolve(false);
} else if (!remoteShaFile.match(binarySha + ' ' + packageUtil.dynamicProps.BINARY_BUILD_NAME)) {
packageUtil.log('Binary SHA does not match SHA in SHASUMS256.txt');
resolve(false);
} else {
packageUtil.log('Binary SHA matches SHA in SHASUMS256.txt');
resolve(true);
}
})
.catch(reject);
});
}
// The getRemoteFileReadStream function is used as the starting point for
// fetching remote file streams. It checks the proxy configuration and
// routes the request to the right function accordingly.
function getRemoteFileReadStream(hostname, path) {
packageUtil.trace('In getRemoteFileReadStream', hostname, path);
const proxyConfig = getProxyConfig(hostname);
if (proxyConfig.useProxy) {
return getFileReadStreamByProxy(hostname, path, proxyConfig.hostname, proxyConfig.port)
} else {
return getFileReadStreamBase(hostname, path);
}
}
// getFileReadStreamByProxy connects to a proxy server before calling getFileReadStreamBase
// to retrieve a remote file read stream.
function getFileReadStreamByProxy(hostname, path, proxyHostname, proxyPort) {
return new Promise((resolve, reject) => {
packageUtil.trace('In getFileReadStreamByProxy', hostname, path, proxyHostname, proxyPort);
// Open a proxy tunnel
const req = http.request({
host: proxyHostname,
port: proxyPort,
method: 'CONNECT',
path: hostname + ':' + PORT,
headers: {
'host': hostname + PORT,
}
});
req.on('error', reject);
// When this ends, the transfer will be complete
req.end();
req.on('connect', function(res, socket) {
if (res.statusCode >= 300 && res.statusCode < 400) { // warning: proxy redirection code is untested
const redirectUrl = url.parse(res.headers.location);
proxyHostname = redirectUrl.hostname;
proxyPort = redirectUrl.port;
return getFileReadStreamByProxy(hostname, path, proxyHostname, proxyPort);
} else if (res.statusCode !== 200) {
reject(new Error('Error: HTTP proxy request for ' + hostname + path + ' failed with code ' + res.statusCode));
return;
} else {
getFileReadStreamBase(hostname, path, socket)
.then(fileReadStream => {
resolve(fileReadStream);
})
.catch(reject);
}
});
});
}
// The getFileReadStreamBase function is the main function that retrieves a remote
// file read stream.
function getFileReadStreamBase(hostname, path, socket) {
return new Promise((resolve, reject) => {
packageUtil.trace('In getFileReadStreamBase', hostname, path);
let settled = false;
const req = https.get(
{
host: hostname,
path: path,
socket: socket
},
function(res) {
packageUtil.trace('HTTP statusCode =', res.statusCode);
if (res.statusCode >= 300 && res.statusCode < 400) {
const redirectUrl = url.parse(res.headers.location);
const newHostname = redirectUrl.hostname;
const newPath = redirectUrl.pathname + redirectUrl.search;
getRemoteFileReadStream(newHostname, newPath)
.then(res => {
if (!settled) {
resolve(res);
settled = true;
}
})
.catch(err => {
if (!settled) {
reject(err);
settled = true;
}
});
} else if (res.statusCode !== 200) {
if (!settled) {
reject(new Error('Error: HTTPS request for https://' + hostname + path + ' failed with code ' + res.statusCode));
settled = true;
}
} else {
if (!settled) {
resolve(res);
settled = true;
}
}
}
);
req.on('error', err => {
if (!settled) {
reject(err);
settled = true;
}
});
});
}
// installBinary creates the directories for the binary, downloads the custom
// file, and then extracts the license and the binary.
function installBinary() {
return new Promise((resolve, reject) => {
packageUtil.trace('In installBinary');
// Directories to be created for the binary
const dirs = [
'build',
'build/Release'
];
// Create relative binary directory
try {
dirs.forEach(function(p) {
if (!fs.existsSync(p)) {
fs.mkdirSync(p);
fs.chmodSync(p, '0755');
}
});
} catch(err) {
if (err) {
reject(err);
return;
}
}
// Get the binary
getRemoteFileReadStream(PACKAGE_HOSTNAME, PACKAGE_PATH_REMOTE)
.then(compressedReadstream => {
return packageUtil.extract({
licenseDest: packageUtil.LICENSE_PATH_LOCAL,
writeLicense: true,
binaryDest: packageUtil.BINARY_PATH_LOCAL,
compressedReadstream: compressedReadstream
});
})
.then(() => {
fs.chmodSync(packageUtil.BINARY_PATH_LOCAL, '0755');
resolve();
})
.catch(err => {
reject(err);
});
});
}
// The done function is used to print concluding messages and quit.
function done(err, alreadyInstalled) {
const installUrl = 'https://github.com/oracle/node-oracledb/blob/master/INSTALL.md';
if (err) {
packageUtil.error('NJS-054: Binary build/Release/oracledb.node was not installed from ' + packageUtil.dynamicProps.PACKAGE_FILE_NAME);
packageUtil.error(err.message);
packageUtil.error('If the error is not network or filesystem related, then review ');
packageUtil.error('the Python 2.7 and compiler prerequisites in the installation instructions and');
packageUtil.error('then install from source code with: npm install oracle/node-oracledb.git#' + packageUtil.dynamicProps.GITHUB_TAG);
packageUtil.error('See ' + installUrl, '\n');
process.exit(87);
} else {
let arch;
let clientUrl;
if (process.arch === 'x64') {
arch = '64-bit';
} else {
arch = '32-bit';
}
packageUtil.log('');
packageUtil.log('********************************************************************************');
if (alreadyInstalled) {
packageUtil.log('** Node-oracledb ' + packageUtil.dynamicProps.PACKAGE_JSON_VERSION + ' was already installed for Node.js ' + process.versions.node + ' (' + process.platform + ', ' + process.arch +')');
} else {
packageUtil.log('** Node-oracledb ' + packageUtil.dynamicProps.PACKAGE_JSON_VERSION + ' installation complete for Node.js ' + process.versions.node + ' (' + process.platform + ', ' + process.arch +')');
}
packageUtil.log('**');
packageUtil.log('** To use the installed node-oracledb:');
if (process.platform === 'linux') {
if (process.arch === 'x64') {
clientUrl = 'http://www.oracle.com/technetwork/topics/linuxx86-64soft-092277.html';
} else {
clientUrl = 'http://www.oracle.com/technetwork/topics/linuxsoft-082809.html';
}
packageUtil.log('** - You must have ' + arch + ' Oracle client libraries in LD_LIBRARY_PATH, or configured with ldconfig');
packageUtil.log('** - If you do not already have libraries, install the Instant Client Basic or Basic Light package from ');
packageUtil.log('** ' + clientUrl);
} else if (process.platform === 'darwin') {
clientUrl = 'http://www.oracle.com/technetwork/topics/intel-macsoft-096467.html';
packageUtil.log('** - You need to have the Oracle Instant Client Basic or Basic Light package in ~/lib or /usr/local/lib');
packageUtil.log('** Download from ' + clientUrl);
} else if (process.platform === 'win32') {
if (process.arch === 'x64') {
clientUrl = 'http://www.oracle.com/technetwork/topics/winx64soft-089540.html';
} else {
clientUrl = 'http://www.oracle.com/technetwork/topics/winsoft-085727.html';
}
packageUtil.log('** - You must have ' + arch + ' Oracle client libraries in your PATH environment variable');
packageUtil.log('** - If you do not already have libraries, install the Instant Client Basic or Basic Light package from');
packageUtil.log('** ' + clientUrl);
packageUtil.log('** - A Microsoft Visual Studio Redistributable suitable for your Oracle client library version must be available');
packageUtil.log('** Check ' + installUrl + ' for details');
} else {
clientUrl = 'http://www.oracle.com/technetwork/database/features/instant-client/index-100365.html';
packageUtil.log('** - You must have ' + arch + ' Oracle client libraries in your operating system library search path');
packageUtil.log('** - If you do not already have libraries, install an Instant Client Basic or Basic Light package from: ');
packageUtil.log('** ' + clientUrl);
}
packageUtil.log('**');
packageUtil.log('** Node-oracledb installation instructions: ' + installUrl);
packageUtil.log('********************************************************************************\n');
}
}
// The install function is the main function that installs the binary.
function install() {
packageUtil.trace('In install');
const nodeMajorVersion = Number(process.version.split('.')[0].replace(/^v/, ''));
if (!nodeMajorVersion >= 4) {
done(new Error('Node.js v4.0.0 or higher is required to install from binary'));
return;
}
packageUtil.log('Beginning installation');
verifyBinary() // check if download is necessary for 'npm rebuild'
.then((valid) => {
if (valid) {
done(null, true);
} else {
packageUtil.log('Continuing installation');
return new Promise((resolve, reject) => {
installBinary()
.then(() => {
packageUtil.log('Oracledb installed');
return verifyBinary();
})
.then(valid => {
if (valid) {
done(null, false);
resolve();
} else {
reject(new Error('Verification failed'));
}
})
.catch(reject);
});
}
})
.catch(err => {
done(err, false);
});
}
install();

54
package/package.json Normal file
View File

@ -0,0 +1,54 @@
{
"name": "oracledb",
"version": "2.0.15",
"description": "Oracle Database driver by Oracle Corp.",
"license": "Apache-2.0",
"homepage": "http://www.oracle.com/technetwork/database/database-technologies/scripting-languages/node_js/",
"keywords": [
"Oracle",
"Database",
"official",
"DB",
"SQL",
"JSON",
"PL/SQL",
"OCI",
"API",
"client",
"library",
"driver",
"add-on",
"extension",
"binding",
"interface",
"adapter",
"module"
],
"repository": {
"type": "git",
"url": "git://github.com/oracle/node-oracledb.git"
},
"devDependencies": {
"mocha": "^2.4.5",
"should": "^8.3.1",
"async": "^1.5.0"
},
"scripts": {
"install": "node package/oracledbinstall.js",
"test": "mocha --opts test/opts/mocha.opts",
"posttest": "node test/opts/versions.js",
"testwindows": "mocha --opts test\\opts\\mocha.opts && npm run posttest"
},
"engines": {
"node": ">=4"
},
"maintainers": [
{
"name": "Oracle Corp."
}
],
"bugs": {
"url": "https://github.com/oracle/node-oracledb/issues"
},
"main": "./index.js"
}

286
package/util.js Normal file
View File

@ -0,0 +1,286 @@
/* Copyright (c) 2017, 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.
*
*****************************************************************************/
'use strict';
const fs = require('fs');
const zlib = require('zlib');
const path = require('path');
const util = require('util');
const debug = (process.env.NODE_ORACLEDB_TRACE_INSTALL === 'TRUE') ? true : false;
let crypto;
try {
crypto = require('crypto');
} catch (err) {
// Ignoring this to allow other parts of the module to be used.
}
const LICENSE_FILE_NAME = 'LICENSE.md';
module.exports.LICENSE_FILE_NAME = LICENSE_FILE_NAME;
const LICENSE_PATH_LOCAL = path.normalize(__dirname + '/../') + LICENSE_FILE_NAME;
module.exports.LICENSE_PATH_LOCAL = LICENSE_PATH_LOCAL;
const BINARY_FILE_NAME = 'oracledb.node';
module.exports.BINARY_FILE_NAME = BINARY_FILE_NAME;
const BINARY_PATH_LOCAL = path.normalize(__dirname + '/../build/Release/') + BINARY_FILE_NAME;
module.exports.BINARY_PATH_LOCAL = BINARY_PATH_LOCAL;
const SHA_FILE_NAME = 'SHASUMS256.txt';
module.exports.SHA_FILE_NAME = SHA_FILE_NAME;
const LICENSE_HEADER_BYTES = 10;
module.exports.LICENSE_HEADER_BYTES = LICENSE_HEADER_BYTES;
const dynamicProps = {};
module.exports.dynamicProps = dynamicProps;
// initDynamicProps is used to initalize some properties that are only needed
// during install. This allows the util module to be used by the extract
// module without requiring a package.json.
function initDynamicProps() {
trace('In initDynamicProps');
let packageJSON;
try {
packageJSON = require('../package.json');
} catch (err) {
throw new Error('package.json required to install from binary');
}
const PACKAGE_JSON_VERSION = packageJSON.version;
dynamicProps.PACKAGE_JSON_VERSION = PACKAGE_JSON_VERSION;
let ght;
// Get the package version from package.json
if (packageJSON.version) {
ght = 'v' + packageJSON.version; // assume name format is always the same
} else {
throw new Error('Cannot determine node-oracledb version from package.json');
}
const GITHUB_TAG = ght;
dynamicProps.GITHUB_TAG = GITHUB_TAG;
const BASE_BUILD_NAME = 'oracledb-'+ GITHUB_TAG + '-node-v' + process.versions.modules + '-' + process.platform + '-' + process.arch;
const BINARY_BUILD_NAME = BASE_BUILD_NAME + '-' + BINARY_FILE_NAME;
dynamicProps.BINARY_BUILD_NAME = BINARY_BUILD_NAME;
const PACKAGE_FILE_NAME = BASE_BUILD_NAME + '.gz';
dynamicProps.PACKAGE_FILE_NAME = PACKAGE_FILE_NAME;
trace('dynamicProps =', dynamicProps);
}
module.exports.initDynamicProps = initDynamicProps;
// log is used to log standard output with the 'oracledb' prefix.
function log(message) {
const args = Array.from(arguments);
args.unshift('oracledb');
console.log.apply(console, args);
}
module.exports.log = log;
// trace is used to log trace output when debug is enabled. It combines
// 'oracledb' with a stylized 'TRACE' prefix.
function trace(message) {
if (debug) {
const args = Array.from(arguments);
args.unshift('oracledb \x1b[30m\x1b[45mTRACE\x1b[0m');
console.log.apply(console, args);
}
}
module.exports.trace = trace;
// error is used to log errors. It combines 'oracledb' with a stylized 'ERR'
// prefix.
function error(message) {
const args = Array.from(arguments);
args.unshift('oracledb \x1b[31mERR!\x1b[0m');
console.error.apply(console, args);
}
module.exports.error = error;
// The getSha function is used to get the SHA of a file.
function getSha(path) {
trace('In getSha', path);
return new Promise((resolve, reject) => {
let settled = false;
let hash;
try {
hash = crypto.createHash('sha256');
} catch (err) {
reject(err);
settled = true;
return;
}
const input = fs.createReadStream(path);
input.on('error', err => {
if (!settled) {
reject(err);
settled = true;
}
});
input.on('readable', () => {
const data = input.read();
if (data) {
hash.update(data);
} else {
const sha = hash.digest('hex');
if (!settled) {
trace('sha =', sha);
resolve(sha);
settled = true;
}
}
});
});
}
module.exports.getSha = getSha;
// The extract function is used to extract the license and node-oracledb binary
// from the custom file format that combines both.
function extract(opts) {
return new Promise((resolve, reject) => {
trace('In extract', util.inspect(opts, {depth: 0}));
const binaryDest = opts.binaryDest || process.cwd() + '/' + BINARY_FILE_NAME;
const binaryWriteStream = fs.createWriteStream(binaryDest);
const gunzip = zlib.createGunzip();
let licenseWriteStream;
let compressedReadstream;
let settled = false;
let licenseWritten = false;
let binaryWritten = false;
function checkDone() {
if (!settled && licenseWritten && binaryWritten) {
resolve();
settled = true;
}
}
if (opts.writeLicense === true) {
const licenseDest = opts.licenseDest || process.cwd() + '/' + LICENSE_FILE_NAME;
licenseWriteStream = fs.createWriteStream(licenseDest);
licenseWriteStream.on('error', err => {
if (!settled) {
reject(err);
settled = true;
}
});
licenseWriteStream.on('finish', () => {
licenseWritten = true;
checkDone();
});
} else {
licenseWritten = true;
}
binaryWriteStream.on('error', err => {
if (!settled) {
reject(err);
settled = true;
}
});
binaryWriteStream.on('finish', () => {
binaryWritten = true;
checkDone();
});
if (opts.compressedReadstream) {
compressedReadstream = opts.compressedReadstream;
} else if (opts.packagePath) {
compressedReadstream = fs.createReadStream(opts.packagePath);
}
const unzipedReadStream = compressedReadstream.pipe(gunzip);
let licenseFileSizeBytes;
let licenseFileBytesWritten = 0;
unzipedReadStream.on('close', () => {
binaryWriteStream.end();
});
unzipedReadStream.on('data', chunk => {
let bytesToWriteInThisEvent;
if (licenseFileBytesWritten === 0) { // assumes first chunk size is > LICENSE_HEADER_BYTES
licenseFileSizeBytes = parseInt(chunk.toString('ascii', 0, LICENSE_HEADER_BYTES));
chunk = chunk.slice(LICENSE_HEADER_BYTES);
}
if (licenseFileBytesWritten < licenseFileSizeBytes) {
const remainingLicenseBytesToWrite = licenseFileSizeBytes - licenseFileBytesWritten;
bytesToWriteInThisEvent = (chunk.length > remainingLicenseBytesToWrite) ? remainingLicenseBytesToWrite : chunk.length;
if (opts.writeLicense === true) {
licenseWriteStream.write(chunk.slice(0, bytesToWriteInThisEvent));
}
licenseFileBytesWritten += bytesToWriteInThisEvent;
if (opts.writeLicense === true && licenseFileBytesWritten === licenseFileSizeBytes) {
licenseWriteStream.end();
}
}
if (licenseFileBytesWritten >= licenseFileSizeBytes) {
if (bytesToWriteInThisEvent) {
binaryWriteStream.write(chunk.slice(bytesToWriteInThisEvent));
} else {
binaryWriteStream.write(chunk);
}
}
});
});
}
module.exports.extract = extract;

View File

@ -1,70 +0,0 @@
/* Copyright (c) 2015, 2017, 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
* dpi.h
*
* DESCRIPTION
*
*****************************************************************************/
#ifndef DPI_ORACLE
# define DPI_ORACLE
#define DPI_MAJOR_VERSION 1
#define DPI_MINOR_VERSION 13
#define DPI_PATCH_LEVEL 1
#ifndef DPIEXCEPTION_ORACLE
# include <dpiException.h>
#endif
#ifndef DPIENV_ORACLE
# include <dpiEnv.h>
#endif
#ifndef DPIPOOL_ORACLE
# include <dpiPool.h>
#endif
#ifndef DPICONN_ORACLE
# include <dpiConn.h>
#endif
#ifndef DPISTMT_ORACLE
# include <dpiStmt.h>
#endif
#ifndef DPIDATETIMEARRAY_ORACLE
# include <dpiDateTimeArray.h>
#endif
/*---------------------------------------------------------------------------
COMMON PUBLIC CONSTANTS
---------------------------------------------------------------------------*/
#endif /* DPI_ORACLE */

View File

@ -1,80 +0,0 @@
/* Copyright (c) 2015, 2016, 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
* dpiCommon.h
*
* DESCRIPTION
*
******************************************************************************/
#ifndef DPICOMMON_ORACLE
# define DPICOMMON_ORACLE
namespace dpi
{
/*----------------------------------------------------------------------------
PUBLIC CONSTANTS
----------------------------------------------------------------------------*/
enum HandleType
{
ErrorHandleType = 2 // OCI_HTYPE_ERROR
};
enum DescriptorType
{
LobDescriptorType = 50 // OCI_TYPE_LOB
};
/*----------------------------------------------------------------------------
PUBLIC TYPES
----------------------------------------------------------------------------*/
struct DpiHandle;
struct Descriptor;
/* Utiltiy class containing common functions */
class Common
{
public:
// To obtain the Oracle Client Library Version
static void clientVersion (int *majorv, int *minorv, int *patchv,
int *portv, int *portUpdv );
};
/*----------------------------------------------------------------------------
PUBLIC METHODS
----------------------------------------------------------------------------*/
} // end of namespace dpi
#endif /* DPICOMMON_ORACLE */

View File

@ -1,130 +0,0 @@
/* Copyright (c) 2015, 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
* dpiconn.h
*
* DESCRIPTION
*
*****************************************************************************/
#ifndef DPICONN_ORACLE
# define DPICONN_ORACLE
#ifndef DPILOB_ORACLE
# include <dpiLob.h>
#endif
#ifndef DPISTMT_ORACLE
# include <dpiStmt.h>
#endif
#include <string>
#include <time.h>
namespace dpi
{
using std::string;
/*---------------------------------------------------------------------------
PUBLIC CONSTANTS
---------------------------------------------------------------------------*/
// Enumeration for Database Privileges
typedef enum
{
dbPrivNONE = 0, // None specified
dbPrivSYSDBA, // SYSDBA
} DBPrivileges;
/*---------------------------------------------------------------------------
PUBLIC TYPES
---------------------------------------------------------------------------*/
class Conn
{
public:
// termination
virtual void release( const string &tag = "", boolean retag = false ) = 0;
// properties
virtual void stmtCacheSize(unsigned int stmtCacheSize) = 0;
virtual unsigned int stmtCacheSize() const = 0;
virtual void lobPrefetchSize(unsigned int lobPrefetchSize) = 0;
virtual unsigned int lobPrefetchSize() const = 0;
virtual void clientId(const string &clientId) = 0;
virtual void module(const string &module) = 0;
virtual void action(const string &action) = 0;
// Session Tag
// In case of pooled-connections & tagged sessions, did we get session
// with provided Tag
virtual boolean tagMatched () = 0;
// In case of pooled-connections & tagged sessions, session tag at
// session acquiring time
virtual std::string &tag () = 0;
// methods
virtual Stmt* getStmt (const string &sql="") = 0;
virtual void commit() = 0;
virtual void rollback() = 0;
virtual void breakExecution() = 0;
virtual DpiHandle *getSvch () = 0;
virtual DpiHandle *getErrh () = 0;
virtual unsigned int getServerVersion () = 0;
virtual unsigned int getVarCharByteExpansionRatio () = 0;
virtual unsigned int getLOBCharExpansionRatio () = 0;
virtual void setErrState ( int errNum ) = 0;
protected:
// clients cannot do new and delete
Conn(){};
virtual ~Conn(){};
private:
};
} // end of namespace dpi
#endif /* DPICONN_ORACLE */

View File

@ -1,72 +0,0 @@
/* Copyright (c) 2015, 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
* dpiDateTimeArray.h
*
* DESCRIPTION
*
*****************************************************************************/
#ifndef DPIDATETIMEARRAY_ORACLE
# define DPIDATETIMEARRAY_ORACLE
#include <string>
namespace dpi
{
/*---------------------------------------------------------------------------
PUBLIC CONSTANTS
---------------------------------------------------------------------------*/
/*---------------------------------------------------------------------------
PUBLIC TYPES
---------------------------------------------------------------------------*/
/*************************************************************************
* Name DateTimeArray
*
* DESCRIPTION Interface definiton for DateTime as Array of Descriptors
*
* Methods
* init - to allocate specified number of descritpors
* release - deallocate the descriptors allocated and call the parent
* object to destroy this object also. one time use only.
* getDateTime to return a double value
* setDateTime to set Date/Time from double value
*
************************************************************************/
class DateTimeArray
{
public:
// To allocate an array of descriptors
virtual void* init ( int nCount ) = 0;
// To dealloate the descriptors and this calss
virtual void release () = 0 ;
// Date/time as double value # of seconds from 1970-1-1 00:00:00
virtual long double getDateTime ( const int idx ) = 0;
virtual void setDateTime ( const int idx, long double ms) = 0;
// Destructor
virtual ~DateTimeArray() {};
};
} // namespace dpi
#endif // ifdef DPIDATETIMEARRAY_ORACLE

View File

@ -1,155 +0,0 @@
/* Copyright (c) 2015, 2016, 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
* dpiEnv.h
*
* DESCRIPTION
*
*****************************************************************************/
#ifndef DPIENV_ORACLE
# define DPIENV_ORACLE
#include <string>
#ifndef DPICOMMON_ORACLE
# include <dpiCommon.h>
#endif
#ifndef DPIPOOL_ORACLE
# include <dpiPool.h>
#endif
#ifndef DPICONN_ORACLE
# include <dpiConn.h>
#endif
#define DPI_AL32UTF8 873
namespace dpi
{
using std::string;
class DateTimeArray;
/*---------------------------------------------------------------------------
PUBLIC CONSTANTS
---------------------------------------------------------------------------*/
/*---------------------------------------------------------------------------
PUBLIC TYPES
---------------------------------------------------------------------------*/
class Env
{
public:
// creation/termination
static Env * createEnv( const string &drvName,
unsigned int charset = 0,
unsigned int ncharset = 0);
virtual void terminate() = 0;
// properties
virtual void poolMax(unsigned int poolMax) = 0;
virtual unsigned int poolMax() const = 0;
virtual void poolMin(unsigned int poolMin) = 0;
virtual unsigned int poolMin() const = 0;
virtual void poolIncrement(unsigned int poolMax) = 0;
virtual unsigned int poolIncrement() const = 0;
virtual void poolTimeout(unsigned int poolTimeout) = 0;
virtual unsigned int poolTimeout() const = 0;
virtual void externalAuth(bool externalAuth) = 0;
virtual bool externalAuth() const = 0;
virtual unsigned int clientcharset () const = 0;
virtual unsigned int clientncharset () const = 0 ;
// methods
virtual SPool * createPool(const string &user, const string &password,
const string &connString,
int poolMax = -1, int poolMin = -1,
int poolIncrement = -1,
int poolTimeout = -1,
int stmtCacheSize = -1,
bool externalAuth = false,
bool homogeneous = true,
int poolPingInterval = DPI_NO_PING_INTERVAL ) = 0 ;
// default Ping Interval is assumed to be no-ping
virtual Conn * getConnection(const string &user,
const string &password,
const string &connString,
int stmtCacheSize,
const string &connClass = "",
bool externalAuth = false,
DBPrivileges dbpriv = dbPrivNONE ) = 0;
// DateTime array
virtual DateTimeArray * getDateTimeArray( OCIError *errh ) const = 0;
virtual void releaseDateTimeArray ( DateTimeArray *arr ) const =0;
// handle and descriptor methods
virtual DpiHandle * allocHandle(HandleType handleType) = 0;
static void freeHandle(DpiHandle *handle, HandleType handleType);
virtual Descriptor * allocDescriptor(DescriptorType descriptorType)
= 0;
static void freeDescriptor(Descriptor *descriptor,
DescriptorType descriptorType);
virtual void allocDescriptorArray(DescriptorType descriptorType,
unsigned int arraySize,
Descriptor **descriptorArray) = 0;
static void freeDescriptorArray(Descriptor **descriptorArray,
DescriptorType descriptorType);
virtual DpiHandle * envHandle() const = 0;
protected:
// clients cannot do new and delete
Env();
virtual ~Env();
private:
};
} // end of namespace dpi
#endif /* DPIENV_ORACLE */

View File

@ -1,83 +0,0 @@
/* Copyright (c) 2015, 2016, 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
* dpiException.h
*
* DESCRIPTION
*
*****************************************************************************/
#ifndef DPIEXCEPTION_ORACLE
# define DPIEXCEPTION_ORACLE
#include <exception>
namespace dpi
{
/*----------------------------------------------------------------------------
PUBLIC CONSTANTS
----------------------------------------------------------------------------*/
enum DpiError // error type
{
DpiErrNoError = 0,
DpiErrInternal,
DpiErrUnkOciError,
DpiErrNoEnv,
DpiErrInvalidState,
DpiErrUninitialized,
DpiErrExtAuth,
DpiOciInvalidHandle, // "Invalid OCI Handle/Descriptor or invalid parameter for OCI handle/descriptor allocation call"
DpiErrMemAllocFail, // "Memory allocation failed"
DpiErrNullValue, // "Unexpected NULL value"
};
/*----------------------------------------------------------------------------
PUBLIC TYPES
----------------------------------------------------------------------------*/
class Exception : public std::exception
{
public:
// creation/termination
Exception(){};
virtual ~Exception() throw();
virtual const char * what() const throw() = 0;
virtual int errnum() const throw() = 0;
virtual const char * origin() const throw() = 0;
private:
};
} // end of namespace dpi
#endif /* DPIEXCEPTION_ORACLE */

View File

@ -1,106 +0,0 @@
/* Copyright (c) 2015, 2016, 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
* dpiLob.h - Lob class interface
*
* DESCRIPTION
* This file defines the interface for the Lob class.
*
* NOTES
* The Lob class methods are static functions providing wrappers over the
* corresponding OCI calls.
*
******************************************************************************/
#ifndef DPILOB_ORACLE
# define DPILOB_ORACLE
#ifndef OCI_ORACLE
# include <oci.h>
#endif
#ifndef DPICOMMON_ORACLE
# include <dpiCommon.h>
#endif
namespace dpi
{
/*----------------------------------------------------------------------------
PUBLIC CONSTANTS
----------------------------------------------------------------------------*/
/*----------------------------------------------------------------------------
PUBLIC TYPES
----------------------------------------------------------------------------*/
/*******************************************************************************
* NAME Lob
*
* DESCRIPTION Interface definiton for Lob
*
* METHODS
* read - read the Lob
*
******************************************************************************/
class Lob
{
public:
static void read(DpiHandle *svch, DpiHandle *errh, Descriptor *lobLocator,
unsigned long long &byteAmount,
unsigned long long &charAmount,
unsigned long long offset,
void *buf,
unsigned long long bufl);
static void write(DpiHandle *svch, DpiHandle *errh, Descriptor *lobLocator,
unsigned long long &byteAmount,
unsigned long long &charAmount,
unsigned long long offset,
void *buf,
unsigned long long bufl);
static unsigned int chunkSize(DpiHandle *svch, DpiHandle *errh,
Descriptor *lobLocator);
static unsigned long long length(DpiHandle *svch, DpiHandle *errh,
Descriptor *lobLocator);
static void cacheDescriptor ( DpiHandle *svch, DpiHandle *errh,
Descriptor *srcLocator,
Descriptor **dstLocator );
static void createTempLob ( DpiHandle *svch, DpiHandle *errh,
Descriptor *lobLocator, unsigned char lobType );
static void freeTempLob ( DpiHandle *svch, DpiHandle *errh,
Descriptor *lobLocator );
static boolean isTempLob ( DpiHandle *envh, DpiHandle *errh,
Descriptor *lobLocator );
};
} // namespace dpi
#endif // ifdef DPILOB_ORACLE

View File

@ -1,88 +0,0 @@
/* Copyright (c) 2015, 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
* dpiPool.h
*
* DESCRIPTION
*
*****************************************************************************/
#ifndef DPIPOOL_ORACLE
# define DPIPOOL_ORACLE
#include <string>
#ifndef DPICONN_ORACLE
# include <dpiConn.h>
#endif
// Default value for poolPingInterval parameter, no pinging is done by default
#define DPI_NO_PING_INTERVAL -1
namespace dpi
{
using std::string;
/*---------------------------------------------------------------------------
PUBLIC TYPES
---------------------------------------------------------------------------*/
class SPool
{
public:
// termination
virtual void terminate() = 0;
// readonly properties
virtual unsigned int connectionsOpen() const = 0;
virtual unsigned int connectionsInUse() const = 0;
virtual int poolMax() const = 0 ;
// methods
virtual Conn * getConnection( const std::string &connClass = "",
const std::string &username = "",
const std::string &password = "",
const std::string &tag = "",
const boolean matchAnyTag = false,
const DBPrivileges dbPriv = dbPrivNONE) =0;
protected:
// clients cannot do new and delete
SPool(){};
virtual ~SPool(){};
private:
};
} // end of namespace dpi
#endif /* DPIPOOL_ORACLE */

View File

@ -1,270 +0,0 @@
/* Copyright (c) 2015, 2016, 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
* dpiStmt.h
*
* DESCRIPTION
*
*****************************************************************************/
#ifndef DPISTMT_ORACLE
# define DPISTMT_ORACLE
#ifndef OCI_ORACLE
# include <oci.h>
#endif
#if !defined(OCI_MAJOR_VERSION) || (OCI_MAJOR_VERSION < 11) || \
((OCI_MAJOR_VERSION == 11) && (OCI_MINOR_VERSION < 2))
#error Oracle 11.2 or later client libraries are required for building
#endif
#include <string>
namespace dpi
{
using std::string;
/*---------------------------------------------------------------------------
PUBLIC TYPES
---------------------------------------------------------------------------*/
enum DpiStmtType
{
DpiStmtUnknown = 0,
DpiStmtSelect = 1,
DpiStmtUpdate = 2,
DpiStmtDelete = 3,
DpiStmtInsert = 4,
DpiStmtCreate = 5,
DpiStmtDrop = 6,
DpiStmtAlter = 7,
DpiStmtBegin = 8,
DpiStmtDeclare =9,
DpiStmtCall = 10
};
typedef enum
{
DpiVarChar = 1,
DpiNumber = 2,
DpiInteger = 3, /* external only */
DpiDouble = 4, /* external only */
DpiString = 5, /* external only */
DpiLong = 8,
DpiDate = 12,
DpiRaw = 23,
DpiLongRaw = 24,
DpiUnsignedInteger = 68,
DpiRowid = 104, /* internal only */
DpiFixedChar = 96,
DpiBinaryFloat = 100, /* internal only */
DpiBinaryDouble = 101, /* internal only */
DpiUDT = 108, /* internal only */
DpiRef = 111, /* internal only */
DpiClob = 112,
DpiBlob = 113,
DpiBfile = 114,
DpiRSet = 116,
DpiYearMonth = 182, /* internal only */
DpiDaySecond = 183, /* internal only */
DpiTimestamp = 187, /* internal only */
DpiTimestampTZ = 188, /* internal only */
DpiURowid = 208, /* internal only */
DpiTimestampLTZ = 232, /* internal only */
DpiTypeBase = 33 * 1024,
DpiDateTimeArray, /* external only */
DpiIntervalArray /* external only */
} DpiDataType;
/* OCI Stmt Handle state
* For REFCURSORS state should be DPI_STMT_STATE_EXECUTED
*/
#define DPI_STMT_STATE_UNDEFINED (0) // Undefined
#define DPI_STMT_STATE_INITIALIZED (1) // Initialized
#define DPI_STMT_STATE_EXECUTED (2) // Executed
#define DPI_STMT_STATE_ENDOFFETCH (3) // End of Fetch
/*
* For 11g/12c Compatability BIND/DEFINE calls expect ub8 in 12c & ub4 in 11g
* Using this type makes is compile-time selction of 11g or 12c.
*/
#if OCI_MAJOR_VERSION >= 12
#define DPI_SZ_TYPE sb8
#define DPI_USZ_TYPE ub8
#define DPI_BUFLEN_TYPE ub4
#define DPI_MAX_BUFLEN (1024*1024*1024 - 2) // max for binding: 1GB-2
#define DPIBINDBYPOS OCIBindByPos2
#define DPIBINDBYNAME OCIBindByName2
#define DPIDEFINEBYPOS OCIDefineByPos2
#define DPIATTRROWCOUNT OCI_ATTR_UB8_ROW_COUNT
#define DPILOBREAD OCILobRead2
#define DPILOBWRITE OCILobWrite2
#else
#define DPI_SZ_TYPE sb4
#define DPI_USZ_TYPE ub4
#define DPI_BUFLEN_TYPE ub2
#define DPI_MAX_BUFLEN UB2MAXVAL
#define DPIBINDBYPOS OCIBindByPos
#define DPIBINDBYNAME OCIBindByName
#define DPIDEFINEBYPOS OCIDefineByPos
#define DPIATTRROWCOUNT OCI_ATTR_ROW_COUNT
#define DPILOBREAD OCILobRead
#define DPILOBWRITE OCILobWrite
#endif
// Forward declaration
class Stmt;
// Application (Driver) level callback function prototype
typedef int (*bindcbtype) (void *ctx, DPI_SZ_TYPE nRows, unsigned int bndpos,
unsigned long iter,
unsigned long index, void **bufpp, void **alenp,
void **indpp, unsigned short **rcodepp,
unsigned char *piecep );
// Application (Driver) level callback funciton prototype
typedef int (*definecbtype) ( void *ctx, unsigned long iter,
void **bufpp, void **alenp, void **indpp,
unsigned short **rcodepp );
// Bind-Dynamic Context structure - used for DML RETURNING case.
typedef struct
{
bindcbtype callbackfn; /* Application specific callback */
void* data; /* Data for application specific callback */
unsigned long nrows; /* number of rows affected by this DML */
unsigned long iter; /* iteration - used in Array Bind */
unsigned int bndpos; /* position in the bind array */
short nullInd; /* DML RETURNING: to pass null from inbind cbk */
Stmt *dpistmt; /* DPI Statement Implementation */
} DpiBindCallbackCtx;
// Define-Dynamic Context structure - used for CLOB-as-STRING case
typedef struct
{
definecbtype callbackfn; /* Application specific callback */
void *data; /* Define data for this column */
void *extData; /* Extended data for this colum if any or NULL */
unsigned long prevIter; /* earlier iter, used to detect iter changing */
} DpiDefineCallbackCtx;
typedef struct MetaData
{
unsigned char *colName; // column name
unsigned int colNameLen; // length of column name
unsigned short dbType; // database server type
unsigned short dbSize; // size at database
short precision; // precision
signed char scale; // scale, range starts from -127
unsigned char isNullable; // is the column nullable?
MetaData ()
: colName ( NULL ), colNameLen ( 0 ), dbType ( 0 ), dbSize ( 0 ),
precision ( 0 ), scale ( 0 ), isNullable ( 0 )
{}
} MetaData;
class Stmt
{
public:
// termination
virtual void release() = 0;
// properties
virtual DpiStmtType stmtType() const = 0;
// If NJS layer doesn't set any value, default prefetch is done by OCI.
virtual void prefetchRows ( unsigned int prefetchRows ) = 0;
virtual bool isReturning() = 0 ;
virtual DPI_USZ_TYPE rowsAffected () const = 0;
virtual unsigned int numCols() = 0;
// methods
virtual void bind(unsigned int pos, unsigned short type, void *buf,
DPI_SZ_TYPE bufSize, short *ind, DPI_BUFLEN_TYPE *bufLen,
unsigned int maxarr_len, unsigned int *curelen,
DpiBindCallbackCtx *ctx = NULL) = 0;
virtual void bind(const unsigned char *name, int nameLen,
unsigned int bndpos,
unsigned short type, void *buf, DPI_SZ_TYPE bufSize,
short *ind, DPI_BUFLEN_TYPE *bufLen,
unsigned int maxarr_len, unsigned int *curelen,
DpiBindCallbackCtx *ctx = NULL ) = 0;
virtual void execute ( int numIterations, bool autoCommit = false) = 0;
virtual void define(unsigned int pos, unsigned short type, void *buf,
DPI_SZ_TYPE bufSize, short *ind,
DPI_BUFLEN_TYPE *bufLen,
DpiDefineCallbackCtx *ctx = NULL ) = 0;
virtual void fetch(unsigned int numRows = 1) = 0;
/*
* The returned pointer to MetaData struct should not be freed by the caller
* since this will be freed as part of StmtImpl::release()
*/
virtual const MetaData * getMetaData( bool extendedMetaData ) = 0;
virtual unsigned int rowsFetched() const = 0;
virtual OCIError *getError () = 0;
virtual unsigned int getState () = 0;
virtual ~Stmt(){};
protected:
// clients cannot do new and delete
Stmt(){};
private:
};
} // end of namespace dpi
#endif /* DPISTMT_ORACLE */

View File

@ -1,66 +0,0 @@
/* Copyright (c) 2015, 2016, 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
* dpiCommon.cpp - Common class implementation
*
* DESCRIPTION
* This file implements the Common class which has implementation which
* are independant of any OCI objects.
*
*****************************************************************************/
#ifndef OCI_ORACLE
# include <oci.h>
#endif
#ifndef DPICOMMON_ORACLE
# include <dpiCommon.h>
#endif
#ifndef DPIEXCEPTIONIMPL_ORACLE
# include <dpiExceptionImpl.h>
#endif
/*****************************************************************************/
/*
DESCRIPTION
To obtain Oracle Client Library (OCI) version
PARAMETERS
majorv
minorv
patchv
portv
portUpdv
RETURNS
-NONE-
NOTES:
The values will map as Oracle Version like 12.1.0.2.0 - five component
version of Oracle Client Library
*/
void Common::clientVersion ( int *majorv, int *minorv, int *patchv,
int *portv, int *portUpdv )
{
if ( !majorv || !minorv || !patchv || !portv || !portUpdv )
throw ExceptionImpl ( DpiErrNullValue );
OCIClientVersion ( majorv, minorv, patchv, portv, portUpdv );
}

View File

@ -1,927 +0,0 @@
/* Copyright (c) 2015, 2016, 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
* dpiConnImpl.cpp - ConnImpl class implementation
*
* DESCRIPTION
* This file implements the ConnImpl class which provides the implemenation of
* the Conn abstract class.
*
*****************************************************************************/
#ifndef DPICONNIMPL_ORACLE
# include <dpiConnImpl.h>
#endif
#ifndef DPISTMTIMPL_ORACLE
# include <dpiStmtImpl.h>
#endif
#ifndef DPIUTILS_ORACLE
# include <dpiUtils.h>
#endif
#ifndef DPIEXCEPTIONIMPL_ORACLE
# include <dpiExceptionImpl.h>
#endif
// Error numbers to set the drop_sess flag in sessionRelease()
// Sessions are in an unusable state and needs to be dropped
#define DPI_CONNERR_INVALID_SESS 22
#define DPI_CONNERR_SESS_KILLED 28
#define DPI_CONNERR_SESS_MARKED_KILL 31
#define DPI_CONNERR_SESS_TERM_NO_REPLY 45
#define DPI_CONNERR_ORA_NOT_LOGGED_ON 1012
#define DPI_CONNERR_MAX_IDLE_TIMEOUT 2396
#define DPI_CONNERR_DRCP_ILLEGAL_CALL 56600
#define DPI_MAX_VERSION_SIZE 512
using namespace std;
// Initialize the static member variable
std::string ConnImpl::s_propPingName_ = DPI_TIME_2_PING_NAME ;
/*---------------------------------------------------------------------------
PUBLIC METHODS
---------------------------------------------------------------------------*/
/*****************************************************************************/
/*
DESCRIPTION
Constructor for the ConnImpl class created from an Env object.
PARAMETERS:
env - parent Env object
envh - OCI envh
stmtCacheSize - statement cache size
user - userid
password - password
connString - connect string
connClass - DRCP Connection class string
dbPriv - DB Privileges (SYSDBA or none).
RETURNS:
nothing
*/
ConnImpl::ConnImpl(EnvImpl *env, OCIEnv *envh, bool externalAuth,
unsigned int stmtCacheSize,
const string &user, const string &password,
const string &connString, const string &connClass,
DBPrivileges dbPriv)
try : env_(env), pool_(NULL),
envh_(envh), errh_(NULL), auth_(NULL), svch_(NULL), sessh_(NULL),
hasTxn_(false), csRatio_ (DPI_BEST_CASE_BYTE_CONVERSION_RATIO),
lobCSRatio_(DPI_BEST_CASE_CHAR_CONVERSION_RATIO), srvh_(NULL),
dropConn_(false), inTag_(""), outTag_(""), relTag_(""), retag_(false),
tagMatched_ (false), pingInterval_(DPI_NO_PING_INTERVAL),
lasttick_ ( NULL )
{
this->initConnImpl ( false, externalAuth, connClass,
( OraText * ) connString.c_str (),
( ub4 ) connString.length (), user, password, "",
false, outTag_, tagMatched_, dbPriv );
this->stmtCacheSize(stmtCacheSize);
}
catch (...)
{
cleanup();
throw;
}
/*****************************************************************************/
/*
DESCRIPTION
Constructor for the ConnImpl class created from a Pool object.
PARAMETERS:
pool - parent Pool object
envh - OCI envh
stmtCacheSize - statement cache size
poolName - name of the pool
poolNameLen - length of pool name
connectionClass - connection class.
user - username in case of non-homogenous pool
password - password in case of non-homogenous pool
tag - session tag name
matchAny - Match Tag name as MATCHANY or EXACT
dbPriv - DB privileges (SYSDBA or none)
pingInterval - duration in seconds to elapse before checking
the health of connection being dispensed.
RETURNS:
nothing
NOTES:
This constructor to be used in session-pool scenarios.
For homogeneous pool, user, password should be empty string.
*/
ConnImpl::ConnImpl(PoolImpl *pool, OCIEnv *envh, bool externalAuth,
OraText *poolName, ub4 poolNameLen, const string& connClass,
const string &user, const string &password,
const string &tag, const boolean matchAny,
const DBPrivileges dbPriv, int pingInterval )
try : env_(NULL), pool_(pool),
envh_(envh), errh_(NULL), auth_(NULL),
svch_(NULL), sessh_(NULL), hasTxn_(false),
csRatio_ (DPI_BEST_CASE_BYTE_CONVERSION_RATIO),
lobCSRatio_(DPI_BEST_CASE_CHAR_CONVERSION_RATIO), srvh_(NULL),
dropConn_(false), inTag_ (""), outTag_(""), relTag_(""), retag_ (false),
tagMatched_(false), pingInterval_ (pingInterval), lasttick_ ( NULL )
{
this->initConnImpl ( true, externalAuth, connClass, poolName, poolNameLen,
user, password, tag, matchAny, outTag_, tagMatched_,
dbPriv );
}
catch (...)
{
cleanup ();
throw;
}
/*****************************************************************************/
/*
DESCRIPTION
Destructor for the ConnImpl class.
PARAMETERS:
none
RETURNS:
nothing
NOTES:
*/
ConnImpl::~ConnImpl()
{
cleanup();
}
/*****************************************************************************/
/*
DESCRIPTION
Release the connection.
PARAMETERS:
tag - session tag name
retag - tagCLRTAG, tagNONE
RETURNS:
nothing
NOTES:
*/
void ConnImpl::release( const string &tag, boolean retag )
{
#if OCI_MAJOR_VERSION >= 12
ociCall(OCIAttrGet(sessh_, OCI_HTYPE_SESSION, &hasTxn_, NULL,
OCI_ATTR_TRANSACTION_IN_PROGRESS, errh_), errh_);
#endif
if(hasTxn_)
rollback();
retag_ = retag;
if ( retag )
{
relTag_ = tag; // Update release-tag with given value only if flag is set.
}
if (pool_)
pool_->releaseConnection(this);
else if (env_)
env_->releaseConnection(this);
}
/****************************************************************************
* NAME
* releaseStmt
*
* DESCRIPTION
* To release Stmt object created
*
* PARAMETERS
* stmt - DPI stmt object
*
* RETURNS
* -NONE-
****************************************************************************/
void ConnImpl::releaseStmt ( Stmt *stmt )
{
if (stmt )
{
delete stmt;
}
}
/*****************************************************************************/
/*
DESCRIPTION
Set statement cache size.
PARAMETERS:
stmtCacheSize - statement cache size
RETURNS:
nothing
NOTES:
*/
void ConnImpl::stmtCacheSize(unsigned int stmtCacheSize)
{
ociCall(OCIAttrSet(svch_, OCI_HTYPE_SVCCTX, &stmtCacheSize, 0,
OCI_ATTR_STMTCACHESIZE, errh_), errh_);
}
/*****************************************************************************/
/*
DESCRIPTION
Gets the char expansion ratio for LOBs
PARAMETERS:
-NONE-
RETURNS:
Char expansion ratio (unsigned int)
*/
unsigned int ConnImpl::getLOBCharExpansionRatio ()
{
return lobCSRatio_;
}
/*****************************************************************************/
/*
DESCRIPTION
Get the byte expansion ratio for non-LOB scenarios
PARAMETERS:
-NONE-
RETURNS:
Byte expansion ratio (int)
*/
unsigned int ConnImpl::getVarCharByteExpansionRatio ()
{
return csRatio_;
}
/*****************************************************************************/
/*
DESCRIPTION
Get statement cache size.
PARAMETERS:
none
RETURNS:
statement cache size
NOTES:
*/
unsigned int ConnImpl::stmtCacheSize() const
{
unsigned int stmtCacheSize = 0;
ociCall(OCIAttrGet(svch_, OCI_HTYPE_SVCCTX, &stmtCacheSize, NULL,
OCI_ATTR_STMTCACHESIZE, errh_), errh_);
return stmtCacheSize;
}
/*****************************************************************************/
/*
DESCRIPTION
Set Lob prefetch size.
PARAMETERS
lobPrefetchSize - lob prefetch size
RETURNS
nothing
NOTES:
*/
void ConnImpl::lobPrefetchSize(unsigned int /* lobPrefetchSize */ )
{
// Temporarily disable this attribute.
#if 0
ociCall(OCIAttrSet(sessh_, OCI_HTYPE_SESSION, &lobPrefetchSize, 0,
OCI_ATTR_DEFAULT_LOBPREFETCH_SIZE, errh_), errh_);
#endif
}
/*****************************************************************************/
/*
DESCRIPTION
Get Lob prefetch size..
PARAMETERS
none
RETURNS
lob prefetch size
NOTES:
*/
unsigned int ConnImpl::lobPrefetchSize() const
{
unsigned int lobPrefetchSize = 0;
ociCall(OCIAttrGet(sessh_, OCI_HTYPE_SESSION, &lobPrefetchSize, NULL,
OCI_ATTR_DEFAULT_LOBPREFETCH_SIZE, errh_), errh_);
return lobPrefetchSize;
}
/*****************************************************************************/
/*
DESCRIPTION
Set client id.
PARAMETERS:
clientId - client id
RETURNS:
nothing
NOTES:
*/
void ConnImpl::clientId(const string &clientId)
{
ociCall(OCIAttrSet(sessh_, OCI_HTYPE_SESSION, (void *)clientId.c_str(),
(ub4)clientId.length(), OCI_ATTR_CLIENT_IDENTIFIER, errh_),
errh_);
}
/*****************************************************************************/
/*
DESCRIPTION
Set the module.
PARAMETERS:
module - module
RETURNS:
nothing
NOTES:
*/
void ConnImpl::module(const string &module)
{
ociCall(OCIAttrSet(sessh_, OCI_HTYPE_SESSION, (void *)module.c_str(),
(ub4) module.length(), OCI_ATTR_MODULE, errh_), errh_);
}
/*****************************************************************************/
/*
DESCRIPTION
Set action.
PARAMETERS:
action - action
RETURNS:
nothing
NOTES:
*/
void ConnImpl::action(const string &action)
{
ociCall(OCIAttrSet(sessh_, OCI_HTYPE_SESSION, (void *)action.c_str(),
(ub4) action.length(), OCI_ATTR_ACTION, errh_), errh_);
}
/*****************************************************************************/
/*
DESCRIPTION
Prepare & return the dpiStatement object
PARAMETERS:
sql - SQL statement
RETURNS:
nothing
NOTES:
*/
Stmt* ConnImpl::getStmt (const string &sql)
{
StmtImpl *stmt = new StmtImpl ( envh_, this, svch_, sql);
return stmt;
}
/*****************************************************************************/
/*
DESCRIPTION
Commit the transaction in progress
PARAMETERS:
-NONE-
RETURNS
-NONE_
*/
void ConnImpl::commit ()
{
ociCall (OCITransCommit (svch_, errh_, OCI_DEFAULT), errh_);
}
/*****************************************************************************/
/*
DESCRIPTION
Rollback the transaction in progress
PARAMETERS
-NONE-
RETUNRS:
-NONE_
*/
void ConnImpl::rollback ()
{
ociCall (OCITransRollback (svch_, errh_, OCI_DEFAULT), errh_);
}
/*****************************************************************************/
/*
DESCRIPTION
break (interrupt) the currently executing operation
PARAMETERS
-NONE-
RETURNS:
-NONE_
*/
void ConnImpl::breakExecution()
{
if(svch_)
{
ociCall (OCIBreak (svch_, errh_), errh_);
}
}
/*****************************************************************************/
/*
DESCRIPTION
set the flag if the non-recoverable error happens to connection
PARAMETERS
errNum - Error number
RETURNS:
-NONE_
*/
void ConnImpl::setErrState ( int errNum )
{
/*
* This flag applicable for only Pool, non pooled connection anyway gets
* terminated upon release. This code is NOT thread-safe. But, we are only
* setting the flag to TRUE - multiple threads can try and only will update
* to TRUE only, so it is okay setting this flag.
*/
if ( pool_ )
{
switch ( errNum )
{
// Error numbers to set drop_sess flag
case DPI_CONNERR_INVALID_SESS:
case DPI_CONNERR_SESS_KILLED:
case DPI_CONNERR_SESS_MARKED_KILL:
case DPI_CONNERR_SESS_TERM_NO_REPLY:
case DPI_CONNERR_ORA_NOT_LOGGED_ON:
case DPI_CONNERR_MAX_IDLE_TIMEOUT:
case DPI_CONNERR_DRCP_ILLEGAL_CALL:
dropConn_ = true;
break;
default:
break;
}
}
}
/*****************************************************************************/
/*
DESCRIPTION
To obtain the Oracle Database Server version
PARAMETERS
-None-
RETURNS
version
*/
unsigned int ConnImpl::getServerVersion ()
{
ub4 oraServerVer = 0;
char verbuf[ DPI_MAX_VERSION_SIZE ];
ociCall ( OCIServerRelease ( svch_, errh_, (OraText *)verbuf,
(ub4) sizeof ( verbuf ),
(ub1) OCI_HTYPE_SVCCTX, &oraServerVer ),
errh_ ) ;
return oraServerVer;
}
/*---------------------------------------------------------------------------
PRIVATE METHODS
---------------------------------------------------------------------------*/
/*****************************************************************************/
/*
DESCRIPTION
Constructor for the ConnImpl class created from an Env object.
PARAMETERS:
pool - This flag says whether pool scenario or not
externalAuth - flag for externalAuth
connClass - connClass name
poolNmRconnStr - poolName or connectString
user - userid in case of non-pool scenario
password - password in case of non-pool scenario
tag - session tag name
matchAny - Match session tag name as MATCHANY or MATCHEXACT
dbPriv - DB Privileges (SYSDBA or none)
RETURNS:
nothing
*/
void ConnImpl::initConnImpl ( bool pool, bool externalAuth,
const string& connClass, OraText *poolNmRconnStr,
ub4 nameLen, const string &user, const string &password,
const string &tag, const boolean matchAny,
std::string & curTag, boolean &found, DBPrivileges dbPriv )
{
ub4 mode = OCI_DEFAULT;
ub2 csid = 0;
void *errh = NULL;
void *auth = NULL;
OraText *retTag = NULL ; // To fetch current tag on session
ub4 retTagLen = 0 ; // current tag len
int maxPingRetries = pool ? pool_->poolMax () + 1 : 1 ;
#if ( ( OCI_MAJOR_VERSION < 12 ) || \
( OCI_MAJOR_VERSION == 12 && OCI_MINOR_VERSION < 2 ) )
time_t curTime;
#endif
if ( pool )
mode = externalAuth ? ( OCI_SESSGET_CREDEXT | OCI_SESSGET_SPOOL ) :
OCI_SESSGET_SPOOL;
else
mode = externalAuth ? OCI_SESSGET_CREDEXT : OCI_DEFAULT;
ociCallEnv ( OCIHandleAlloc ( ( void * ) envh_, &errh,
OCI_HTYPE_ERROR, 0, ( dvoid ** ) 0 ), envh_ );
errh_ = ( OCIError * ) errh;
ociCallEnv ( OCIHandleAlloc ( ( void * ) envh_, &auth,
OCI_HTYPE_AUTHINFO, 0, ( dvoid ** ) 0 ),
envh_ );
auth_ = ( OCIAuthInfo * ) auth;
if ( externalAuth && ( !pool ) )
{
if ( password.length () || user.length () )
throw ExceptionImpl ( DpiErrExtAuth );
}
if ( !pool )
{
ociCall ( OCIAttrSet ( ( void * ) auth_, OCI_HTYPE_AUTHINFO,
( void * ) user.c_str (), ( ub4 ) user.length (),
OCI_ATTR_USERNAME, errh_ ), errh_ );
ociCall ( OCIAttrSet ( ( void * ) auth_, OCI_HTYPE_AUTHINFO,
( void * ) password.c_str (),
( ub4 ) password.length (),
OCI_ATTR_PASSWORD, errh_ ), errh_ );
}
switch ( dbPriv )
{
case dbPrivSYSDBA:
mode |= OCI_SESSGET_SYSDBA;
break;
case dbPrivNONE:
default:
break;
}
// If connection class provided, set it on auth handle
if ( connClass.length () )
{
ociCall ( OCIAttrSet ( ( void* ) auth_, OCI_HTYPE_AUTHINFO,
( void * ) connClass.c_str (),
( ub4 ) connClass.length (),
OCI_ATTR_CONNECTION_CLASS, errh_ ), errh_ );
}
/* In case of Pool, we set the driver name on poolAuth_ handle in
* Pool implimentation. For non-pooled connections we set it here.
*/
if ( !pool && !(env_->drvName()).empty() )
{
ociCall ( OCIAttrSet ( (void*) auth_, OCI_HTYPE_AUTHINFO,
(OraText *) ( env_->drvName() ).c_str (),
( ub4 ) ( ( env_->drvName() ).length () ),
OCI_ATTR_DRIVER_NAME, errh_ ), errh_);
}
/*
* Applicable only on Pooled sessions - attempts to return a session with
* specified tag
*
* If matchAny is false - then a session with a different tag is
* never returned
* if matchAny is true - if such a session not available, available
* untagged if no untagged is available, then any
* tagged session is returned. All returned sessions
* are authenticated.
*
* tagMatched_ flag will be true if such a tagged session was returned
* false otherwise.
*/
if ( pool && matchAny )
{
mode |= OCI_SESSGET_SPOOL_MATCHANY;
}
#if ( ( OCI_MAJOR_VERSION < 12 ) || \
( OCI_MAJOR_VERSION == 12 && OCI_MINOR_VERSION < 2 ) )
curTime = time ( NULL ) ; // current tick count
#endif
for (int iter = 0; iter < maxPingRetries; iter ++ )
{
ociCall ( OCISessionGet ( envh_, errh_, &svch_, auth_, poolNmRconnStr,
( ub4 ) nameLen, (OraText*)tag.c_str(),
(ub4) tag.length(),
&retTag,
&retTagLen,
&tagMatched_, mode ),
errh_ );
outTag_ = string ( (char *) retTag, retTagLen ) ;
// session object from svch handle
ociCall ( OCIAttrGet ( svch_, OCI_HTYPE_SVCCTX, &sessh_, 0,
OCI_ATTR_SESSION, errh_ ), errh_ );
#if ( (OCI_MAJOR_VERSION > 12) || \
( OCI_MAJOR_VERSION == 12 && OCI_MINOR_VERSION >= 2 ) )
break;
#else
// For stand alone (non-pooled) connections and pingInterval set to
// no-ping, exit the loop to return the session.
if ( !pool || pingInterval_ < 0 )
break;
//
// PingInterval elapsed implementation is available only for
// pooled-connections and
// pingInterval_ is specified to check (-ve never check)
//
// Use the last stamped time set on the session to check for elapsed
// This implementation is only of client versions < 12.2
if ( pingInterval_ > 0 )
{
// get last tick count if any set from earlier release.
// if none, 0 will be returned.
ociCall ( OCIContextGetValue ( sessh_,
errh_,
(ub1 *)s_propPingName_.c_str(),
(ub1)s_propPingName_.length(),
(void **)&lasttick_ ), errh_ );
// If the session is obtained firstime from pool, context value
// will not be there, in that case, allocate and set it.
if ( !lasttick_ )
{
ociCall ( OCIMemoryAlloc ( sessh_, errh_, (void **)&lasttick_,
OCI_DURATION_SESSION, sizeof (long),
OCI_MEMORY_CLEARED ), errh_ );
sword ret = OCIContextSetValue ( sessh_, errh_, OCI_DURATION_SESSION,
(ub1 *) s_propPingName_.c_str(),
(ub1)s_propPingName_.length(),
(void *) lasttick_ ) ;
// In case if the allocated memory could not be associated with session
// free the memory allocated and return error.
// In case if succeeded, then the allocated memory will be deallocated
// internally by OCI when the session is freed.
if ( ret != OCI_SUCCESS )
{
OCIMemoryFree ( sessh_, errh_, lasttick_ );
ociCall ( ret, errh_ );
}
}
else if ( *lasttick_ > curTime )
{
// If time not elapsed => no need to ping
break;
}
}
// Check for aliveness of session
if ( OCIPing ( svch_, errh_, OCI_DEFAULT ) == OCI_SUCCESS )
break;
// If session is not good, release it and drop from pool too.
ociCall ( OCISessionRelease ( svch_, errh_, (OraText *)"", (sword)0,
OCI_SESSRLS_DROPSESS ), errh_ ) ;
#endif
}
// Initialize the server handle from service handle
ociCall ( OCIAttrGet ( svch_, OCI_HTYPE_SVCCTX, ( void * ) &srvh_, 0,
( ub4 ) OCI_ATTR_SERVER, errh_ ), errh_ );
// Get the DBCHARSET from server
ociCall ( OCIAttrGet ( srvh_, ( ub4 ) OCI_HTYPE_SERVER, ( void * ) &csid,
( ub4 * ) 0, ( ub4 ) OCI_ATTR_CHARSET_ID, errh_ ),
errh_ );
// Client character set is always AL32UTF8
if ( csid != DPI_AL32UTF8 )
{
csRatio_ = DPI_WORST_CASE_BYTE_CONVERSION_RATIO;
}
// Bug in LOB code, alwasy use worst case conversion ratio
lobCSRatio_ = DPI_WORST_CASE_CHAR_CONVERSION_RATIO;
}
/*****************************************************************************/
/*
DESCRIPTION
Cleanup for the ConnImpl class.
PARAMETERS:
none
RETURNS:
nothing
NOTES:
The free OCI handles are set to NULL to so that in case someone tries to
use a release Conn handle, they will get a reproducible seg-fault.
*/
void ConnImpl::cleanup()
{
ub4 relMode = OCI_DEFAULT;
ub4 serverStatus = OCI_SERVER_NORMAL;
if (svch_)
{
if ( pool_ )
{
// Get the connection status
if ( !dropConn_ )
ociCall ( OCIAttrGet ( ( void * ) srvh_, OCI_HTYPE_SERVER,
( void * ) &serverStatus, ( ub4 * ) 0,
OCI_ATTR_SERVER_STATUS, errh_ ), errh_ );
// Remove the session from pool in case of unusable
if ( dropConn_ || ( serverStatus != OCI_SERVER_NORMAL ) )
relMode |= OCI_SESSRLS_DROPSESS;
}
#if ( ( OCI_MAJOR_VERSION < 12 ) || \
( OCI_MAJOR_VERSION == 12 && OCI_MINOR_VERSION < 2 ) )
// The ping Interval and last-stamped-time is used to decide whether
// to explicitly check for aliveness of the connection.
// In 12.2 and above OCI has a different
// light-weight ping mechanism and is always enabled, so this
// implementation is only for Oracle Client library versions <= 12.1
// Set the current time on the session to be used later whether
// this time is elapsed against pingInterval_.
if ( sessh_ )
{
// For Later use, update the session with current time only
// if ping is desired.
if ( pingInterval_ > 0 )
{
time_t curTime = time ( NULL ) ; // Current time in seconds
*lasttick_ = (long) curTime + pingInterval_;
}
}
#endif
// Re-tagging
if( retag_ )
{
relMode |= OCI_SESSRLS_RETAG;
}
/*
* RETAG behavior: (same as in OCI).
* if retag_ is TRUE & relTag_ length is non-zero, then relTag_ is set
* if retag_ is TRUE & relTag_ length is zero, then session-tag is cleared
* if retag_ is FALSE, then no action taken
*/
OCISessionRelease(svch_, errh_, (OraText *)relTag_.c_str (),
(ub4) relTag_.length (), relMode);
svch_ = NULL;
}
if (auth_)
{
OCIHandleFree (auth_, OCI_HTYPE_AUTHINFO);
auth_ = NULL;
}
if (errh_)
{
OCIHandleFree(errh_, OCI_HTYPE_ERROR);
errh_ = NULL;
}
}
/* end of file dpiConnImpl.cpp */

View File

@ -1,202 +0,0 @@
/* Copyright (c) 2015, 2016, 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
* dpiconnImpl.h
*
* DESCRIPTION
*
*****************************************************************************/
#ifndef DPICONNIMPL_ORACLE
# define DPICONNIMPL_ORACLE
#ifndef OCI_ORACLE
# include <oci.h>
#endif
#ifndef DPICONN_ORACLE
# include <dpiConn.h>
#endif
#ifndef DPIENVIMPL_ORACLE
# include <dpiEnvImpl.h>
#endif
#ifndef DPIPOOLIMPL_ORACLE
# include <dpiPoolImpl.h>
#endif
using namespace dpi;
class EnvImpl;
class PoolImpl;
/*
* The maximum byte expansion ratio from any DB character to
* AL32UTF8 is known to be 3-times
*/
#define DPI_WORST_CASE_BYTE_CONVERSION_RATIO 3
/*
* No byte expansion required if DB has AL32UTF8 charset since client is
* always AL32UTF8
*/
#define DPI_BEST_CASE_BYTE_CONVERSION_RATIO 1
/*
* The maximum character expansion ratio from any DB character to
* AL32UTF8 is known to be 4-times for LOBs
*/
#define DPI_WORST_CASE_CHAR_CONVERSION_RATIO 4
/*
* No character expansion required if DB has AL32UTF8 charset since client is
* always AL32UTF8
*/
#define DPI_BEST_CASE_CHAR_CONVERSION_RATIO 1
// Context property name used to store the last-accessed-time of the
// connection. This time and pingInterval are used to decide whether to
// ping or not
#define DPI_TIME_2_PING_NAME "TIME_2_PING"
/*---------------------------------------------------------------------------
PUBLIC TYPES
---------------------------------------------------------------------------*/
class ConnImpl : public Conn
{
public:
// creation/termination
ConnImpl(EnvImpl *env, OCIEnv *envh, bool externalAuth,
unsigned int stmtCacheSize,
const string &user, const string &password,
const string &connString,
const string &connClass,
DBPrivileges dbPriv );
ConnImpl(PoolImpl *pool, OCIEnv *envh, bool externalAuth,
OraText *poolName, ub4 poolNameLen, const string &connClass,
const string &user, const string &password, const string &tag,
const boolean matchAny, const DBPrivileges dbPriv,
int pingInterval = DPI_NO_PING_INTERVAL );
virtual ~ConnImpl();
virtual void release( const string &tag, boolean retag);
// interface properties
virtual void stmtCacheSize(unsigned int stmtCacheSize);
virtual unsigned int stmtCacheSize() const;
virtual void lobPrefetchSize(unsigned int lobPrefetchSize);
virtual unsigned int lobPrefetchSize() const;
virtual void clientId(const string &clientId);
virtual void module(const string &module);
virtual void action(const string &action);
// Connection with requested tag returned or not?
virtual boolean tagMatched () { return tagMatched_; }
// tag associated with connection
virtual std::string& tag () { return outTag_; }
virtual unsigned int getVarCharByteExpansionRatio ();
virtual unsigned int getLOBCharExpansionRatio ();
// interface methods
virtual Stmt* getStmt(const string &sql);
virtual void releaseStmt(Stmt *stmt);
virtual void commit();
virtual void rollback();
virtual void breakExecution();
virtual DpiHandle *getSvch (){return (DpiHandle *)svch_;};
virtual DpiHandle *getErrh (){return (DpiHandle *)errh_;};
virtual void setErrState ( int errNum );
#if OCI_MAJOR_VERSION < 12
inline void hasTxn(boolean connHasTxn)
{
// sets the flag used during connection release.
hasTxn_ = connHasTxn;
}
inline boolean hasTxn()
{
// returns flag to denote active transactions.
return hasTxn_;
}
#endif
virtual unsigned int getServerVersion () ;
private:
void initConnImpl( bool pool, bool externalAuth, const string& connClass,
OraText *poolNmRconnStr, ub4 nameLen,
const string &user, const string &password,
const string &tag, boolean any, std::string &curTag,
boolean &found, DBPrivileges dbPriv );
void cleanup();
EnvImpl *env_; // parent Env object
PoolImpl *pool_; // parent pool object if created from a pool
OCIEnv *envh_; // OCI enviornment handle
OCIError *errh_; // OCI error handle
OCIAuthInfo *auth_; // OCI auth handle
OCISvcCtx *svch_; // OCI service handle
OCISession *sessh_; // OCI Session handle. Do not free this.
boolean hasTxn_; // set if transaction is in progress
int csRatio_; // character expansion ratio
int lobCSRatio_; // character expansion ratio for LOBs
OCIServer *srvh_; // OCI server handle
bool dropConn_; // Set flag in case of unusable connection
string inTag_; // To fetch connections with specified inTag_
string outTag_; // When connection is given, what is tag val
string relTag_; // Release connectih specified tag
boolean retag_; // How to retag? (update, ignore)
boolean tagMatched_; // connection is of same tag as requested?
int pingInterval_; // Time to elapse before checking for aliveness
long *lasttick_; // next ping time if time elapsed.
static string s_propPingName_;// Property name used in Context APIs
};
#endif /* DPICONNIMPL_ORACLE */

View File

@ -1,383 +0,0 @@
/* Copyright (c) 2015, 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
* dpiDateTimeArrayImpl.cpp - DateTimeArrayImpl class Implemenation
*
* DESCRIPTION
* This file implmenets the wrapper over Oracle Database type
* DATE, TIMESTAMP, TIMESTAMP WITH TZ, TIMESTAMP WITH LOCAL TZ.
*
*****************************************************************************/
#include <string.h>
#ifndef DPIUTILS_ORACLE
# include <dpiUtils.h>
#endif
#ifndef DPIDATEIMPL_ORACLE
# include <dpiDateTimeArrayImpl.h>
#endif
#ifndef DPIEXCEPTIONIMPL_ORACLE
# include "dpiExceptionImpl.h"
#endif
#define DPI_UTC_TZ "+00:00"
#define DPI_BASE_YEAR 1970
#define DPI_BASE_MONTH 1
#define DPI_BASE_DATE 1
#define DPI_BASE_HOUR 0
#define DPI_BASE_MIN 0
#define DPI_BASE_SEC 0
#define DPI_BASE_FS 0
#define DPI_MS_DAY 86400000 // 24*60*60*1000
#define DPI_MS_HOUR 3600000 // 60*60*1000
#define DPI_MS_NINUTE 60000 // 60*1000
#define DPI_MS_SECONDS 1000 // ms per sec
#define DPI_FRAC_SEC_MS 1000000 // 1.0E+06
#include <iostream>
using namespace std;
using namespace dpi;
// Static member variable initialization - used to compute diff from
// given date/time. The baseDate_ is 1970-1-1 0:0:0
OCIDateTime * DateTimeArrayImpl::baseDate_ = NULL;
/*---------------------------------------------------------------------------
PUBLIC METHODS
---------------------------------------------------------------------------*/
/****************************************************************************
* NAME DateTimeArrayImpl::DateTimeArrayImpl
*
* DESCRIPTION Constructor of DateTimeArrayImpl
*
* PARAMETERS
* envh OCIEnv handle
* errh OCIError handle
* stmt dpi Stmt object
*
****************************************************************************/
DateTimeArrayImpl::DateTimeArrayImpl (OCIEnv *envh, OCIError *errh,
const Env* env)
: env_(env), envh_ (envh), errh_ (errh), dbdatetime_(NULL)
{
}
/****************************************************************************
* NAME DateTimeArrayImpl::~DateTimeArrayImpl
*
* DESCRIPTION Destructor of DateTimeArrayImpl
*
* PARAMETERS
*
****************************************************************************/
DateTimeArrayImpl::~DateTimeArrayImpl ()
{
if ( dbdatetime_ )
{
// TO release OCI Descriptor handle array and this class too.
this -> release ();
}
}
/****************************************************************************
* NAME DateTimeArrayImpl::init
*
* DESCRIPTION initialization function to allocate OCI Descriptor array
*
* PARAMETERS
* nCount # of descriptors required
*
****************************************************************************/
void *DateTimeArrayImpl::init (int nCount)
{
if ( !dbdatetime_ )
{
// allocate space to hold nCount pointers to OCIDateTime structure
dbdatetime_ = (OCIDateTime**) new OCIDateTime*[nCount];
if( !dbdatetime_ )
{
throw ExceptionImpl ( DpiErrMemAllocFail ) ;
}
sword rc;
rc = OCIArrayDescriptorAlloc ( (dvoid *)envh_, (void **)&dbdatetime_[0],
OCI_DTYPE_TIMESTAMP_LTZ,
nCount, 0, (void **)0);
if ( rc != OCI_SUCCESS )
throw ExceptionImpl ( DpiErrInternal ) ;
}
else
{
/* descriptor array is to be allocated, if for some reason
* it is non-null, then bail out.
*/
throw ExceptionImpl (DpiErrInvalidState);
}
/* NOTE: OCI Descriptor array is returned as void * to be used in
* bind, define calls, and methods of this class is used to set/get
* timestamp
*/
return (void *)dbdatetime_;
}
/****************************************************************************
* NAME DateTimeArrayImpl::release
*
* DESCRIPTION cleanup OCI Descriptor array and this class
*
* PARAMETERS
*
****************************************************************************/
void DateTimeArrayImpl::release ()
{
// destroy OCI descriptor array if already allocated,
// if not allocated, ignore.
if ( dbdatetime_ )
{
OCIArrayDescriptorFree ((dvoid **)dbdatetime_, OCI_DTYPE_TIMESTAMP_LTZ);
delete [] dbdatetime_;
dbdatetime_ = NULL;
}
env_->releaseDateTimeArray ( this ) ;
}
/****************************************************************************
* NAME DateTimeArrayImpl::getDateTime
*
* DESCRIPTION To obtain date/time value from descriptor based on
* given index as long double value
*
* PARAMETERS
* idx index value.
*
****************************************************************************/
long double DateTimeArrayImpl::getDateTime ( const int idx )
{
long double ret = 0;
sword rc = 0;
sb4 dy = 0;
sb4 hr = 0;
sb4 mm = 0;
sb4 ss = 0;
sb4 fsec = 0;
if ( dbdatetime_ )
{
void *interval = NULL ;
rc = OCIDescriptorAlloc ( (dvoid *) envh_, &interval,
OCI_DTYPE_INTERVAL_DS, 0, (dvoid **)0);
if (rc)
{
throw ExceptionImpl ( DpiErrInternal );
}
/* Get diff of date/timestamp */
rc = OCIDateTimeSubtract ( envh_, errh_, dbdatetime_[idx], baseDate_,
( OCIInterval * ) interval );
ociCall ( rc, errh_ ) ;
// Get the Days, hours, minutes, seconds and fractional seconds
ociCall ( OCIIntervalGetDaySecond ( envh_, errh_, &dy, &hr, &mm,
&ss, &fsec,
( OCIInterval * ) interval ), errh_ );
if ( interval )
{
OCIDescriptorFree ( interval, OCI_DTYPE_INTERVAL_DS );
}
}
else
{
// dbdatetime_ has to be allocated by now using init(),
// if not bail out.
throw ExceptionImpl ( DpiErrUninitialized );
}
/*
* dy needs type cast as long double since dy*DPI_MS_DAY crosses sb4 range
* fsec needs type cast as long double to retain fractional seconds
*/
ret = ( ( ( long double ) dy * DPI_MS_DAY ) +
( hr * DPI_MS_HOUR ) +
( mm * DPI_MS_NINUTE ) +
( ss * DPI_MS_SECONDS ) +
( ( long double ) fsec / DPI_FRAC_SEC_MS ) ) ;
return (ret);
}
/****************************************************************************
* NAME DateTimeArrayImpl::setDateTime
*
* DESCRIPTION To set date/time value on descriptor based on
* given index from long double value
*
* PARAMETERS
* idx index value.
*
****************************************************************************/
void DateTimeArrayImpl::setDateTime ( const int idx, long double ms)
{
if ( dbdatetime_ )
{
void *interval = NULL;
sword rc = OCI_SUCCESS ;
sb4 dy = 0;
sb4 hr = 0;
sb4 mm = 0;
sb4 ss = 0;
sb4 fs = 0;
dy = ( sb4 ) ( ms / DPI_MS_DAY ); // Get the days
// dy needs type cast as long double since dy*DPI_MS_DAY crosses sb4 range
ms = ms - ( ( long double ) dy * DPI_MS_DAY );
hr = ( sb4 ) ( ms / DPI_MS_HOUR ); // Get the hours
ms = ms - ( hr * DPI_MS_HOUR );
mm = ( sb4 ) ( ms / DPI_MS_NINUTE ); // Get the minutes
ms = ms - ( mm * DPI_MS_NINUTE );
ss = ( sb4 ) ( ms / DPI_MS_SECONDS ); // Get the seconds
ms = ms - (ss * DPI_MS_SECONDS );
fs = ( sb4 )( ms * DPI_FRAC_SEC_MS ); // Convert the ms into frac sec
rc = OCIDescriptorAlloc ( (dvoid *) envh_, &interval,
OCI_DTYPE_INTERVAL_DS, 0, (dvoid **)0);
if (rc)
{
throw ExceptionImpl ( DpiErrInternal );
}
// Convert the given timestamp in ms into interval
ociCall ( OCIIntervalSetDaySecond ( envh_, errh_, dy, hr, mm,
ss, fs, ( OCIInterval * ) interval),
errh_ );
// Add the interval to the basedate.
ociCall ( OCIDateTimeIntervalAdd ( envh_, errh_, baseDate_,
( OCIInterval * ) interval,
dbdatetime_[idx] ), errh_ ) ;
if ( interval )
{
OCIDescriptorFree ( interval, OCI_DTYPE_INTERVAL_DS );
}
}
else
{
throw ExceptionImpl ( DpiErrUninitialized );
}
}
/****************************************************************************
* NAME DateTimeArrayImpl::initBaseDate
*
* DESCRIPTION To initialize one time initialization of basedate, interval
*
* PARAMETERS
* envh OCI Env Handle
*
* NOTE:
* v8::Date uses # of milliseconds counted from 1970-1-1 0:0:0. To compute
* # of seconds, need to find the difference from basedate, and compute
* to milliseconds. This baseDate is used for execution cycle, instead of
* creating every time, create it one time and use it.
****************************************************************************/
void DateTimeArrayImpl::initBaseDate ( OCIEnv *envh )
{
sword rc = OCI_SUCCESS ;
void *errh = (OCIError *)0;
void *baseDate = NULL;
// If baseDate is not allocated, allocate and init
if ( !baseDate_ )
{
rc = OCIDescriptorAlloc ( (dvoid *)envh, &baseDate,
OCI_DTYPE_TIMESTAMP_LTZ, 0,
(dvoid **)0);
baseDate_ = (OCIDateTime *) baseDate;
if ( !rc ) // OCI_SUCCESS case
{
/*
* NOTE:
* This is one time initialization expected to be done along with
* OCI Env creation(one time). At this point of time, errh is not yet
* created by OCI Env, create a local one, use and destroy
*/
ociCallEnv(OCIHandleAlloc((void *)envh, &errh,
OCI_HTYPE_ERROR, 0, (dvoid **)0), envh);
// Base date is 1970-1-1 00:00:00
ociCall ( OCIDateTimeConstruct (envh, ( OCIError * ) errh, baseDate_,
DPI_BASE_YEAR, DPI_BASE_MONTH,
DPI_BASE_DATE, DPI_BASE_HOUR,
DPI_BASE_MIN, DPI_BASE_SEC, DPI_BASE_FS,
(OraText * )DPI_UTC_TZ,
strlen ( DPI_UTC_TZ ) ),
( OCIError * ) errh);
// Free the allocated error handle
if (errh)
{
OCIHandleFree(errh, OCI_HTYPE_ERROR);
errh = NULL;
}
}
else
{
throw ExceptionImpl ( DpiErrInternal ) ;
}
}
}
/****************************************************************************
* NAME DateTimeArrayImpl::cleanBaseDate
*
* DESCRIPTION To cleanup OCI descriptors for baseDate/interval.
*
* PARAMETERS
*
*
****************************************************************************/
void DateTimeArrayImpl::cleanBaseDate ()
{
if ( baseDate_ )
{
OCIDescriptorFree ( baseDate_, OCI_DTYPE_TIMESTAMP_LTZ );
baseDate_ = NULL ;
}
}
/* end of dpiDateTimeArrayImpl.cpp */

View File

@ -1,87 +0,0 @@
/* Copyright (c) 2015, 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
* dpiDateTimeImpl.h
*
* DESCRIPTION
*
*****************************************************************************/
#ifndef DPIDATETIMEARRAYIMPL_ORACLE
# define DPIDATEARRAYIMPL_ORACLE
#endif
#ifndef DPISTMT_ORACLE
# include <dpiEnv.h>
#endif
#ifndef OCIDATETIMEARRAY_ORACLE
# include <dpiDateTimeArray.h>
#endif
namespace dpi
{
class Env;
/********************************************************************
* Name : DateTimeArrayImpl
*
* Descriptoin : Implementation of DateTimeArray interface
*
* NOTE: One time use only, once release() called the class will be
* destroyed
*/
class DateTimeArrayImpl : public DateTimeArray
{
public:
DateTimeArrayImpl ( OCIEnv *envh, OCIError *err, const Env* env);
virtual ~DateTimeArrayImpl ();
//DateTimeArray methods
virtual void* init (int nCount) ;
virtual void release ();
// Date/Time as double value # of seconds from 1970-1-1 00:00:00
virtual long double getDateTime ( const int idx ) ;
virtual void setDateTime ( const int idx, long double ms);
public:
static void initBaseDate ( OCIEnv *envh);
static void cleanBaseDate ();
private:
static OCIDateTime *baseDate_; // Base date 1970-1-1 0:0:0
private:
// DPI parent object
const Env *env_;
// OCI Handles
OCIEnv *envh_;
OCIError *errh_;
// OCI Descriptor array
OCIDateTime **dbdatetime_;
};
};

View File

@ -1,170 +0,0 @@
/* Copyright (c) 2015, 2016, 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
* dpiEnv.cpp
*
* DESCRIPTION
*
*****************************************************************************/
#ifndef DPIENVIMPL_ORACLE
# include <dpiEnvImpl.h>
#endif
/*---------------------------------------------------------------------------
PUBLIC METHODS
---------------------------------------------------------------------------*/
/*****************************************************************************/
/*
DESCRIPTION
Constructor for the Env class.
PARAMETERS:
none
RETURNS:
nothing
NOTES:
*/
Env::Env()
{
}
/*****************************************************************************/
/*
DESCRIPTION
Destructor for the Env class.
PARAMETERS:
none
RETURNS:
nothing
NOTES:
*/
Env::~Env()
{
}
/*****************************************************************************/
/*
DESCRIPTION
Create the Env object.
PARAMETERS:
drvName - driver name
charset - charset id
ncharset - ncharset id
RETURNS:
nothing
*/
Env * Env::createEnv( const string& drvName,
unsigned int charset, unsigned int ncharset)
{
return EnvImpl::createEnvImpl( drvName, charset, ncharset );
}
/*****************************************************************************/
/*
DESCRIPTION
Free an Dpi handle.
PARAMETERS:
handle - DPI handle to be freed
handleType - Type of DPI handle to be freed
RETURNS:
nothing
NOTES:
*/
void Env::freeHandle(DpiHandle *handle, HandleType handleType)
{
OCIHandleFree(handle, handleType);
}
/*****************************************************************************/
/*
DESCRIPTION
Free an Dpi descriptor.
PARAMETERS:
descriptor - DPI descriptor to be freed
descriptorType - Type of DPI descriptr to be freed
RETURNS:
nothing
NOTES:
*/
void Env::freeDescriptor(Descriptor *descriptor,
DescriptorType descriptorType)
{
OCIDescriptorFree(descriptor, descriptorType);
}
/*****************************************************************************/
/*
DESCRIPTION
Free an Dpi descriptor array.
PARAMETERS:
descriptorArray - DPI descriptor to be freed
descriptorType - Type of DPI descriptr array to be freed
RETURNS:
nothing
NOTES:
*/
void Env::freeDescriptorArray(Descriptor **descriptorArray,
DescriptorType descriptorType)
{
OCIArrayDescriptorFree((void **)descriptorArray, descriptorType);
}
/* end of file dpiEnv.cpp */

View File

@ -1,833 +0,0 @@
/* Copyright (c) 2015, 2016, 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
* dpiEnvImpl.cpp - EnvImpl class implementation
*
* DESCRIPTION
* This file implements the EnvImpl class which provides the implemenation of
* the Env abstract class.
*
*****************************************************************************/
#ifndef DPIENVIMPL_ORACLE
# include <dpiEnvImpl.h>
#endif
#ifndef DPIPOOLIMPL_ORACLE
# include <dpiPoolImpl.h>
#endif
#ifndef DPICONNIMPL_ORACLE
# include <dpiConnImpl.h>
#endif
#ifndef DPIEXCEPTIONIMPL_ORACLE
# include <dpiExceptionImpl.h>
#endif
#ifndef DPIDATETIMEARRAYIMPL_ORACLE
# include <dpiDateTimeArrayImpl.h>
#endif
#ifndef DPIUTILS_ORACLE
# include <dpiUtils.h>
#endif
/*---------------------------------------------------------------------------
PRIVATE CONSTANTS
---------------------------------------------------------------------------*/
static const int kPoolMax = 10;
static const int kPoolMin = 1;
static const int kPoolIncrement = 1;
static const int kPoolTimeout = 120;
static const int kStmtCacheSize = 60;
/*---------------------------------------------------------------------------
PUBLIC METHODS
---------------------------------------------------------------------------*/
/*****************************************************************************/
/*
DESCRIPTION
Constructor for the EnvImpl class.
PARAMETERS:
drvName driver name
charset charset id
ncharset ncharset id
RETURNS:
nothing
NOTES:
*/
EnvImpl::EnvImpl( const string &drvName,
unsigned int charset,
unsigned int ncharset )
try : envh_(NULL), poolMax_(kPoolMax), poolMin_(kPoolMin),
poolIncrement_(kPoolIncrement), poolTimeout_(kPoolTimeout),
externalAuth_(false), stmtCacheSize_(kStmtCacheSize), drvName_(drvName),
charset_ ( charset ), ncharset_ ( ncharset )
{
sword rc = OCIEnvNlsCreate (&envh_, OCI_THREADED | OCI_OBJECT, NULL, NULL,
NULL, NULL, 0, NULL, charset, ncharset);
if (rc)
{
if (envh_)
ociCallEnv(rc, envh_);
else
throw ExceptionImpl(DpiErrNoEnv);
}
DateTimeArrayImpl::initBaseDate ( envh_ ) ;
}
catch (...)
{
cleanup();
throw;
}
/*****************************************************************************/
/*
DESCRIPTION
Destructor for the EnvImpl class.
PARAMETERS:
none
RETURNS:
nothing
NOTES:
*/
EnvImpl::~EnvImpl()
{
cleanup();
}
/*****************************************************************************/
/*
DESCRIPTION
Create the Env object.
PARAMETERS:
envAttrs - environment attributes
RETURNS:
nothing
*/
EnvImpl * EnvImpl::createEnvImpl( const string& drvName,
unsigned int charset,
unsigned int ncharset)
{
return new EnvImpl( drvName, charset, ncharset );
}
/*****************************************************************************/
/*
DESCRIPTION
Terminate the Env object.
PARAMETERS:
none
RETURNS:
nothing
NOTES:
*/
void EnvImpl::terminate()
{
EnvImpl::terminateEnvImpl(this);
}
/*****************************************************************************/
/*
DESCRIPTION
Set the maximum pool size.
PARAMETERS:
poolMax - maximum pool size
RETURNS:
nothing
NOTES:
*/
void EnvImpl::poolMax(unsigned int poolMax)
{
poolMax_ = poolMax;
}
/*****************************************************************************/
/*
DESCRIPTION
Get the maximum pool size.
PARAMETERS:
none
RETURNS:
maximum pool size
NOTES:
*/
unsigned int EnvImpl::poolMax() const
{
return poolMax_;
}
/*****************************************************************************/
/*
DESCRIPTION
Set the minumum pool size.
PARAMETERS:
poolMin - minimum pool size
RETURNS:
nothing
NOTES:
*/
void EnvImpl::poolMin(unsigned int poolMin)
{
poolMin_ = poolMin;
}
/*****************************************************************************/
/*
DESCRIPTION
Get the minimum pool size.
PARAMETERS:
none
RETURNS:
mainimum pool size
NOTES:
*/
unsigned int EnvImpl::poolMin() const
{
return poolMin_;
}
/*****************************************************************************/
/*
DESCRIPTION
Set the pool increment.
PARAMETERS:
poolIncrement - pool increment
RETURNS:
nothing
NOTES:
*/
void EnvImpl::poolIncrement(unsigned int poolIncrement)
{
poolIncrement_= poolIncrement;
}
/*****************************************************************************/
/*
DESCRIPTION
Get the pool increment.
PARAMETERS:
none
RETURNS:
pool increment
NOTES:
*/
unsigned int EnvImpl::poolIncrement() const
{
return poolIncrement_;
}
/*****************************************************************************/
/*
DESCRIPTION
Set the pool timeout.
PARAMETERS:
poolTimeout - pool timeout
RETURNS:
nothing
NOTES:
*/
void EnvImpl::poolTimeout(unsigned int poolTimeout)
{
poolTimeout_ = poolTimeout;
}
/*****************************************************************************/
/*
DESCRIPTION
Get the pool timeout.
PARAMETERS:
none
RETURNS:
pool timeout
NOTES:
*/
unsigned int EnvImpl::poolTimeout() const
{
return poolTimeout_;
}
/*****************************************************************************/
/*
DESCRIPTION
Get the driver name
PARAMETERS:
none
RETURNS:
driver name
NOTES:
*/
const string & EnvImpl::drvName()
{
return drvName_;
}
/*****************************************************************************/
/*
DESCRIPTION
Specify external authentication.
PARAMETERS:
externalAuth - true if using external authentication
false if not useing external authentication
RETURNS:
nothing
NOTES:
*/
void EnvImpl::externalAuth(bool externalAuth)
{
externalAuth_ = externalAuth;
}
/*****************************************************************************/
/*
DESCRIPTION
Is external authentication being used?
PARAMETERS:
none
RETURNS:
true if using external authentication
false otherwise
NOTES:
*/
bool EnvImpl::externalAuth() const
{
return externalAuth_;
}
/*****************************************************************************/
/*
DESCRIPTION
Specify EVENTS mode.
PARAMETERS:
isEventEnabled - true if EVENTS mode enabled
false if EVENTS mode not enabled
RETURNS:
nothing
*/
void EnvImpl::isEventEnabled(bool isEventEnabled)
{
isEventEnabled_ = isEventEnabled;
}
/*****************************************************************************/
/*
DESCRIPTION
Is EVENTS mode enabled?
PARAMETERS:
none
RETURNS:
true if EVENTS mode enabled
false otherwise
NOTES:
*/
bool EnvImpl::isEventEnabled() const
{
return isEventEnabled_;
}
/*****************************************************************************/
/*
DESCRIPTION
returns the charsetid used in this EnvImpl. If none provided at
creation time, could be 0.
PARAMETERS
-NONE-
RETURNS
charset id
*/
unsigned int EnvImpl::clientcharset () const
{
return charset_;
}
/*****************************************************************************/
/*
DESCRIPTION
returns the ncharsetid used in this EnvImpl. If none provided at
creation time, could be 0.
PARAMETERS
-NONE-
RETURNS
ncharset id
*/
unsigned int EnvImpl::clientncharset () const
{
return ncharset_;
}
/*****************************************************************************/
/*
DESCRIPTION
Create the Pool object.
PARAMETERS:
user - userid
password - password
connString - connect string
poolMax - Max number of connections for session pool
poolMin - Min number of connections for session pool
poolIncrement - Increment count for session pool
poolTimeout - Timeout duration after which getConnection will fail
stmtCacheSize - # of statements to cache
externalAuth - external Authentication used or not
homogenous - homongeous pool authentication or not
poolPingInterval - ping Interval used to check for healthiness
RETURNS:
created pool
NOTES:
*/
SPool * EnvImpl::createPool(const string &user, const string &password,
const string &connString,
int poolMax, int poolMin, int poolIncrement,
int poolTimeout, int stmtCacheSize,
bool externalAuth, bool homogenous,
int poolPingInterval)
{
return new PoolImpl(this, envh_, user, password, connString,
(poolMax == -1) ? poolMax_ : poolMax,
(poolMin == -1) ? poolMin_ : poolMin,
(poolIncrement == -1) ? poolIncrement_ :
poolIncrement,
(poolTimeout == -1) ? poolTimeout_ :
poolTimeout,
externalAuth,
(stmtCacheSize == -1) ? stmtCacheSize_ :
stmtCacheSize, homogenous,
poolPingInterval );
}
/*****************************************************************************/
/*
DESCRIPTION
Get connection.
PARAMETERS:
user - userid
password - password
connString - connect string
stmtCacheSize - # statement cached
connClass - DRCP connection class string
externalAuth - external Authentication used or not
dbPriv - DB Privileges (SYSDBA or none).
RETURNS:
created connection
*/
Conn * EnvImpl::getConnection(const string &user, const string &password,
const string &connString,
int stmtCacheSize, const string &connClass,
bool externalAuth, DBPrivileges dbPriv )
{
return (Conn *)new ConnImpl(this, envh_, externalAuth,
(stmtCacheSize == -1) ? stmtCacheSize_ :
stmtCacheSize,
user, password,
connString, connClass, dbPriv);
}
/*****************************************************************************/
/*
DESCRIPTION
Terminated the pool.
PARAMETERS:
pool - connectionpool to be terminated.
RETURNS:
nothing
NOTES:
*/
void EnvImpl::terminatePool(PoolImpl *pool)
{
delete pool;
}
/*****************************************************************************/
/*
DESCRIPTION
Release the connection.
PARAMETERS:
conn - connection to be terminated.
RETURNS:
nothing
NOTES:
*/
void EnvImpl::releaseConnection(ConnImpl *conn)
{
delete conn;
}
/*---------------------------------------------------------------------------
PRIVATE METHODS
---------------------------------------------------------------------------*/
/*****************************************************************************/
/*
DESCRIPTION
Terminated the Env object.
PARAMETERS:
env - Env object to be terminated.
RETURNS:
nothing
NOTES:
*/
void EnvImpl::terminateEnvImpl(EnvImpl *env)
{
DateTimeArrayImpl::cleanBaseDate ();
delete env;
}
/*****************************************************************************/
/*
DESCRIPTION
Cleanup for the EnvImpl class.
PARAMETERS:
none
RETURNS:
nothing
NOTES:
*/
void EnvImpl::cleanup()
{
if (envh_)
{
OCIHandleFree(envh_, OCI_HTYPE_ENV);
envh_ = NULL; // reproducible seg-faults in case someone uses
// a deleted Env
}
}
/****************************************************************************/
/*
NAME
getDateTimeArray
DESCRIPTION
To obtain an DPI class which represents date/timestamp as descriptor
array
RETURNS:
DateTimeArray * -
NOTE:
DatetimeArray uses error object created in StmtImpl instead of creating
separate one, this is ok, as the date/timestamp will be part of SQL
statement execution only.
*/
DateTimeArray* EnvImpl::getDateTimeArray (OCIError *errh) const
{
DateTimeArray *dtmarr = new DateTimeArrayImpl ( envh_, errh, this ) ;
if( !dtmarr )
{
throw ExceptionImpl ( DpiErrMemAllocFail ) ;
}
return dtmarr;
}
/****************************************************************************/
/*
NAME
releaseDateTimeArray
DESCRIPTION
To release datetimeArray object and related resources
RETURNS:
NONE
*/
void EnvImpl::releaseDateTimeArray ( DateTimeArray *arr ) const
{
if ( arr )
delete arr;
}
/*****************************************************************************/
/*
DESCRIPTION
Allocate DPI handle.
PARAMETERS:
handleType - Type of DPI handle to be allocated
RETURNS:
allocated DPI handle
NOTES:
*/
DpiHandle * EnvImpl::allocHandle(HandleType handleType)
{
void *handle = NULL;
ociCallEnv(OCIHandleAlloc(envh_, &handle, handleType, 0, NULL),
envh_);
return (DpiHandle *)handle;
}
/*****************************************************************************/
/*
DESCRIPTION
Allocate DPI descriptor.
PARAMETERS:
descriptorType - Type of DPI descriptor to be allocated
RETURNS:
allocated DPI descriptor
NOTES:
*/
Descriptor * EnvImpl::allocDescriptor(DescriptorType descriptorType)
{
void *descriptor = NULL;
ociCallEnv(OCIDescriptorAlloc(envh_, &descriptor, descriptorType,
0, NULL), envh_);
return (Descriptor *)descriptor;
}
/*****************************************************************************/
/*
DESCRIPTION
Allocate DPI descriptor array.
PARAMETERS:
descriptorType - Type of DPI descriptor to be allocated
arraySize - size of descriptor array
RETURNS:
allocated DPI descriptor array
NOTES:
*/
void EnvImpl::allocDescriptorArray(DescriptorType descriptorType,
unsigned int arraySize,
Descriptor **descriptorArray)
{
ociCallEnv(OCIArrayDescriptorAlloc(envh_, (void **)descriptorArray,
descriptorType, arraySize,
0, NULL), envh_);
}
/*****************************************************************************/
/*
DESCRIPTION
Get the underlying OCI environment handlle.
PARAMETERS:
none
RETURNS:
OCI environment handle
NOTES:
*/
DpiHandle * EnvImpl::envHandle() const
{
return (DpiHandle *)envh_;
}
/* end of file dpiEnvImpl.cpp */

View File

@ -1,164 +0,0 @@
/* Copyright (c) 2015, 2016, 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
* dpiEnvImpl.h
*
* DESCRIPTION
*
*****************************************************************************/
#ifndef DPIENVIMPL_ORACLE
# define DPIENVIMPL_ORACLE
#ifndef OCI_ORACLE
# include <oci.h>
#endif
#ifndef DPIENV_ORACLE
# include <dpiEnv.h>
#endif
#ifndef DPIPOOLIMPL_ORACLE
# include <dpiPoolImpl.h>
#endif
#ifndef DPICONNIMPL_ORACLE
# include <dpiConnImpl.h>
#endif
using namespace dpi;
class ConnImpl;
/*---------------------------------------------------------------------------
PUBLIC TYPES
---------------------------------------------------------------------------*/
class EnvImpl : public Env
{
public:
// creation/termination
EnvImpl( const string &drvName,
unsigned int charset,
unsigned int ncharset);
virtual ~EnvImpl();
static EnvImpl * createEnvImpl( const string& drvName,
unsigned int charset,
unsigned int ncharset);
virtual void terminate();
// interface properties
virtual void poolMax(unsigned int poolMax);
virtual unsigned int poolMax() const;
virtual void poolMin(unsigned int poolMin);
virtual unsigned int poolMin() const;
virtual void poolIncrement(unsigned int poolIncrement);
virtual unsigned int poolIncrement() const;
virtual void poolTimeout(unsigned int poolTimeout);
virtual unsigned int poolTimeout() const;
virtual const string & drvName();
virtual void externalAuth(bool externalAuth);
virtual bool externalAuth() const;
virtual void isEventEnabled(bool isEventEnabled);
virtual bool isEventEnabled() const;
virtual unsigned int clientcharset () const;
virtual unsigned int clientncharset () const;
// interface methods
virtual SPool * createPool(const string &user, const string &password,
const string &connString,
int poolMax, int poolMin,
int poolIncrement,
int poolTimeout,
int stmtCacheSize,
bool externalAuth,
bool homogeneous,
int poolPingInterval );
virtual Conn * getConnection(const string &user, const string &password,
const string &connString, int stmtCacheSize,
const string &connClass,
bool externalAuth, DBPrivileges dbPriv);
// internal methods
virtual void terminatePool(PoolImpl *pool);
virtual void releaseConnection(ConnImpl *conn);
// DateTime array
virtual DateTimeArray* getDateTimeArray ( OCIError *errh ) const ;
virtual void releaseDateTimeArray ( DateTimeArray *arr ) const ;
virtual DpiHandle * allocHandle(HandleType handleType);
virtual Descriptor * allocDescriptor(DescriptorType descriptorType);
virtual void allocDescriptorArray(DescriptorType descriptorType,
unsigned int arraySize,
Descriptor *descriptorArray[]);
virtual DpiHandle * envHandle() const;
private:
static void terminateEnvImpl(EnvImpl *env);
void cleanup();
OCIEnv *envh_; // OCI enviornment handle
unsigned int poolMax_; // max pool size
unsigned int poolMin_; // min pool size
unsigned int poolIncrement_; // pool increment
unsigned int poolTimeout_; // pool timeout
bool externalAuth_; // doing external authentication
bool isEventEnabled_; // EVENTS are enabled
unsigned int stmtCacheSize_; // statement cache size
string drvName_; // driver name
unsigned int charset_; // charset id
unsigned int ncharset_; // ncharset id
};
#endif /* DPIENVIMPL_ORACLE */

View File

@ -1,63 +0,0 @@
/* Copyright (c) 2015, 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
* dpiException.cpp
*
* DESCRIPTION
*
*****************************************************************************/
#ifndef DPIEXCEPTION_ORACLE
# include <dpiException.h>
#endif
using namespace dpi;
/*---------------------------------------------------------------------------
PUBLIC METHODS
---------------------------------------------------------------------------*/
/*****************************************************************************/
/*
DESCRIPTION
Destructor for the Exception class.
PARAMETERS:
none
RETURNS:
nothing
*/
Exception::~Exception() throw ()
{
}
/* end of file dpiException.cpp */

View File

@ -1,216 +0,0 @@
/* Copyright (c) 2015, 2016, 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
* dpiExceptionImpl.cpp - ExceptionImpl class implementation
*
* DESCRIPTION
* This file implements the ExceptionImpl class which provides the
* implemenation of the Exception abstract class.
*
*****************************************************************************/
#include <sstream>
#include <iomanip>
using namespace std;
#ifndef DPIEXCEPTIONIMPL_ORACLE
# include <dpiExceptionImpl.h>
#endif
/*---------------------------------------------------------------------------
PRIVATE DATA
---------------------------------------------------------------------------*/
// don't forget to add comma for previously last message after you add a new
// error message
static const char *dpiErrors[] =
{
"not an error", // DPI-000 - DpiErrNoError
"internal error", // DPI-001 - DpiErrInternal
"could not get OCI error message", // DPI-002 - DpiErrUnkOciError
"no OCI environment handle created", // DPI-003 - DpiErrNoEnv
"invalid state while working with timestamp", // DPI-004 - DpiErrInvalidState
"uninitialized state while working with timestamp", // DPI-005 - DpiErrUninitialized
"user and password should not be set when using external authentication",
// DPI-006 - DpiErrExtAuth
"invalid OCI handle or descriptor", // DPI-007 - DpiOciInvalidHandle
"memory allocation failed", // DPI-008 - DpiErrMemAllocFail
"unexpected NULL value", // DPI-009 - DpiErrNullValue
};
/*---------------------------------------------------------------------------
PUBLIC METHODS
---------------------------------------------------------------------------*/
/*****************************************************************************/
/*
DESCRIPTION
Constructor for the ExceptionImpl class for DPI errors only.
PARAMETERS:
errnum - DPI error number
RETURNS:
nothing
NOTES:
*/
ExceptionImpl::ExceptionImpl(DpiError errnum):
origin_("DPI"), errnum_(errnum)
{
stringstream strstream;
strstream << origin_ << "-" <<setfill('0')<<setw(3)<<errnum_ <<": ";
strstream << dpiErrors[errnum - DpiErrNoError];
message_ = strstream.str();
}
/*****************************************************************************/
/*
DESCRIPTION
Constructor for the ExceptionImpl class.
PARAMETERS:
origin - error origin
errnum - error number
message - error message
RETURNS:
nothing
NOTES:
*/
ExceptionImpl::ExceptionImpl(const char *origin, int errnum,
const char *message):
origin_(origin), errnum_(errnum), message_(message)
{
}
/*****************************************************************************/
/*
DESCRIPTION
Destructor for the ExceptionImpl class.
PARAMETERS:
none
RETURNS:
nothing
NOTES:
*/
ExceptionImpl::~ExceptionImpl() throw ()
{
}
/*****************************************************************************/
/*
DESCRIPTION
Returns error message.
PARAMETERS:
none
RETURNS:
Error message
NOTES:
*/
const char * ExceptionImpl::what() const throw()
{
return message_.c_str ();
}
/*****************************************************************************/
/*
DESCRIPTION
Returns error number.
PARAMETERS:
none
RETURNS:
Error number
NOTES:
*/
int ExceptionImpl::errnum() const throw()
{
return errnum_;
}
/*****************************************************************************/
/*
DESCRIPTION
Returns the origin of the error
PARAMETERS:
none
RETURNS:
Error origin
NOTES:
*/
const char * ExceptionImpl::origin() const throw()
{
return origin_.c_str ();
}
/* end of file dpiExceptionImpl.cpp */

View File

@ -1,71 +0,0 @@
/* Copyright (c) 2015, 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
* dpiExceptionImpl.h
*
* DESCRIPTION
*
*****************************************************************************/
#ifndef DPIEXCEPTIONIMPL_ORACLE
# define DPIEXCEPTIONIMPL_ORACLE
#include <string>
#ifndef DPIEXCEPTION_ORACLE
# include <dpiException.h>
#endif
using namespace dpi;
/*---------------------------------------------------------------------------
PUBLIC TYPES
---------------------------------------------------------------------------*/
class ExceptionImpl : public Exception
{
public:
// creation/termination
ExceptionImpl(DpiError errnum);
ExceptionImpl(const char *origin, int errnum, const char *message);
virtual ~ExceptionImpl() throw();
virtual const char * what() const throw();
virtual int errnum() const throw();
virtual const char * origin() const throw();
private:
std::string origin_;
int errnum_;
std::string message_;
};
#endif /* DPIEXCEPTIONIMPL_ORACLE */

View File

@ -1,316 +0,0 @@
/* Copyright (c) 2015, 2016, 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
* dpiLob.cpp - Lob class Implemenation
*
* DESCRIPTION
* This file implmenets the Lob class.
*
* NOTES
* The Lob class methods are static functions providing wrappers over the
* corresponding OCI calls.
*
*****************************************************************************/
#ifndef DPILOB_ORACLE
# include <dpiLob.h>
#endif
#ifndef DPIUTILS_ORACLE
# include <dpiUtils.h>
#endif
using namespace dpi;
/*----------------------------------------------------------------------------
PUBLIC TYPES
----------------------------------------------------------------------------*/
/*******************************************************************************
DESCRIPTION
Read from the Lob Locator.
PARAMETERS
svch - OCI service handle
errh - OCI error handle
lobLocator - Lob locator to be read
byteAmount (IN/OUT) - IN: number of bytes to read
OUT: number of bytes read
Used for BLOB and BFILE always.
For CLOB, it is used only when charAmount is zero.
charAmount (IN/OUT) - IN: number of characters to read. Set to zero if
interested in byteAmount only.
OUT: number of characters read
Ignored/undefined for BLOB and BFILE.
offset - 1-based absolute offset from the beginning of the
LOB. In bytes for BLOB and BFILE. In characters for
CLOB.
buf (OUT) - buffer where data is read
RETURNS
nothing
NOTES
*/
void Lob::read(DpiHandle *svch, DpiHandle *errh, Descriptor *lobLocator,
unsigned long long &byteAmount, unsigned long long &charAmount,
unsigned long long offset, void *buf, unsigned long long bufl)
{
ociCall(OCILobRead2((OCISvcCtx *)svch, (OCIError *)errh,
(OCILobLocator *)lobLocator,
(oraub8 *)&byteAmount, (oraub8 *)&charAmount,
offset, buf, (oraub8)(byteAmount ? byteAmount : bufl),
OCI_ONE_PIECE, NULL, NULL, 0, SQLCS_IMPLICIT),
(OCIError *)errh);
}
/*******************************************************************************
DESCRIPTION
Write to the Lob Locator.
PARAMETERS
svch - OCI service handle
errh - OCI error handle
lobLocator - Lob locator to be written
byteAmount (IN/OUT) - IN: number of bytes to write
OUT: number of bytes actually written
Used for BLOB and BFILE always.
For CLOB, it is used only when charAmount is zero.
charAmount (IN/OUT) - IN: number of characters to written. Set to zero if
interested in byteAmount only.
OUT: number of characters written
Ignored/undefined for BLOB and BFILE.
offset - 1-based absolute offset from the beginning of the
LOB. In bytes for BLOB and BFILE. In characters for
CLOB.
buf - buffer where data is written from
RETURNS
nothing
NOTES
*/
void Lob::write(DpiHandle *svch, DpiHandle *errh, Descriptor *lobLocator,
unsigned long long &byteAmount, unsigned long long &charAmount,
unsigned long long offset, void *buf, unsigned long long bufl)
{
ociCall(OCILobWrite2((OCISvcCtx *)svch, (OCIError *)errh,
(OCILobLocator *)lobLocator,
(oraub8 *)&byteAmount, (oraub8 *)&charAmount,
offset, buf, (oraub8)(byteAmount ? byteAmount : bufl),
OCI_ONE_PIECE, NULL, NULL, 0, SQLCS_IMPLICIT),
(OCIError *)errh);
}
/*******************************************************************************
DESCRIPTION
Get Lob chunk size
PARAMETERS
svch - OCI service handle
errh - OCI error handle
lobLocator - Lob locator
chunkSize (OUT) - chunk size
RETURNS
nothing
NOTES
*/
unsigned int Lob::chunkSize(DpiHandle *svch, DpiHandle *errh,
Descriptor *lobLocator)
{
unsigned int chunkSize = 0;
ociCall(OCILobGetChunkSize((OCISvcCtx *)svch, (OCIError *)errh,
(OCILobLocator *)lobLocator, &chunkSize),
(OCIError *)errh);
return chunkSize;
}
/*******************************************************************************
DESCRIPTION
Get Lob length
PARAMETERS
svch - OCI service handle
errh - OCI error handle
lobLocator - Lob locator
length (OUT) - length
RETURNS
nothing
NOTES
*/
unsigned long long Lob::length(DpiHandle *svch, DpiHandle *errh,
Descriptor *lobLocator)
{
oraub8 length = 0;
ociCall(OCILobGetLength2((OCISvcCtx *)svch, (OCIError *)errh,
(OCILobLocator *)lobLocator, (oraub8 *)&length),
(OCIError *)errh);
return (unsigned long long)length;
}
/*******************************************************************************
DESCRIPTION
Assigns one LOB locator to another
PARAMETERS
svch - OCI service handle
errh - OCI error handle
srcLocator - The LOB locator to copy from
dstLocator - The LOB locator to copy to
RETURNS
nothing
NOTES
*/
void Lob::cacheDescriptor ( DpiHandle *svch, DpiHandle *errh,
Descriptor *srcLocator, Descriptor **dstLocator )
{
ociCall ( OCILobLocatorAssign ( ( OCISvcCtx * ) svch, ( OCIError * ) errh,
( OCILobLocator * ) srcLocator,
( OCILobLocator ** ) dstLocator ),
( OCIError * ) errh );
}
/*******************************************************************************
DESCRIPTION
Creates a temporary LOB
PARAMETERS
svch - OCI service handle
errh - OCI error handle
lobLocator - Lob locator
lobType - The type of LOB to create.
OCI_TEMP_BLOB - For a temporary BLOB
OCI_TEMP_CLOB - For a temporary CLOB
RETURNS
nothing
*/
void Lob::createTempLob ( DpiHandle *svch, DpiHandle *errh,
Descriptor *lobLocator, unsigned char lobType )
{
ociCall ( OCILobCreateTemporary( ( OCISvcCtx * ) svch, ( OCIError * ) errh,
( OCILobLocator * ) lobLocator,
( ub2 ) OCI_DEFAULT, SQLCS_IMPLICIT,
( ub1 )lobType, false,
OCI_DURATION_SESSION ),
( OCIError * ) errh );
}
/*******************************************************************************
DESCRIPTION
Frees a temporary LOB
PARAMETERS
svch - OCI service handle
errh - OCI error handle
lobLocator - Lob locator
RETURNS
nothing
*/
void Lob::freeTempLob ( DpiHandle *svch, DpiHandle *errh,
Descriptor *lobLocator )
{
ociCall ( OCILobFreeTemporary ( ( OCISvcCtx * ) svch, ( OCIError * ) errh,
( OCILobLocator * ) lobLocator ),
( OCIError * ) errh );
}
/*******************************************************************************
DESCRIPTION
Check whether given LOB is temporary or not
PARAMETERS
envh - OCI ENV handle
errh - OCI error handle
lobLocator - Lob locator
RETURNS
boolean - true if LOB is temporary
false otherwise
*/
boolean Lob::isTempLob ( DpiHandle *envh, DpiHandle *errh,
Descriptor *lobLocator )
{
boolean isTemporary = FALSE;
ociCall ( OCILobIsTemporary ( ( OCIEnv * ) envh, ( OCIError * ) errh,
( OCILobLocator * ) lobLocator, &isTemporary ),
( OCIError * ) errh );
return isTemporary;
}
/* end of dpiDateTimeArrayImpl.cpp */

View File

@ -1,439 +0,0 @@
/* Copyright (c) 2015, 2016, 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
* dpiPoolImpl.cpp - PoolImpl class implementation
*
* DESCRIPTION
* This file implements the PoolImpl class which provides the implemenation
* of the Pool abstract class.
*
*****************************************************************************/
#ifndef DPIENVIMPL_ORACLE
# include <dpiEnvImpl.h>
#endif
#ifndef DPIPOOLIMPL_ORACLE
# include <dpiPoolImpl.h>
#endif
#ifndef DPICONNIMPL_ORACLE
# include <dpiConnImpl.h>
#endif
#ifndef DPIUTILS_ORACLE
# include <dpiUtils.h>
#endif
#ifndef DPIEXCEPTIONIMPL_ORACLE
# include <dpiExceptionImpl.h>
#endif
#include<iostream>
using namespace std;
/*---------------------------------------------------------------------------
PUBLIC METHODS
---------------------------------------------------------------------------*/
/*****************************************************************************/
/*
DESCRIPTION
Constructor for the PoolImpl class.
PARAMETERS:
env - parent Environment object
envh - OCI envh
user - userid
password - password
connString - connect string
poolMax - maximum pool size
poolMin - minimum pool size
poolIncrement - pool increment
poolTimeout - pool timeout
stmtCacheSize - statement cache size
homogeneous - homogeneous or non-homogeneous pool
RETURNS:
nothing
NOTES:
*/
PoolImpl::PoolImpl(EnvImpl *env, OCIEnv *envh,
const string &user, const string &password,
const string &connString, int poolMax,
int poolMin, int poolIncrement,
int poolTimeout, bool externalAuth, int stmtCacheSize,
bool homogeneous, int poolPingInterval )
try : env_(env), externalAuth_(externalAuth), envh_(envh), errh_(NULL),
spoolh_(NULL), poolName_(NULL), poolAuth_(NULL), poolMax_(0),
poolPingInterval_(poolPingInterval)
{
ub4 mode = OCI_DEFAULT;
void *errh = NULL;
void *spoolh = NULL;
void *poolAuth = NULL;
unsigned char spoolMode = OCI_SPOOL_ATTRVAL_NOWAIT; // spoolMode is a ub1
if ( homogeneous )
{
mode |= OCI_SPC_HOMOGENEOUS ;
}
if (externalAuth && (password.length() || user.length()))
throw ExceptionImpl(DpiErrExtAuth);
ociCallEnv(OCIHandleAlloc((void *)envh_, &errh,
OCI_HTYPE_ERROR, 0, (dvoid **)0), envh_);
errh_ = ( OCIError * ) errh;
ociCall(OCIHandleAlloc((void *)envh_, (dvoid **)&spoolh,
OCI_HTYPE_SPOOL, 0, (dvoid **)0), errh_);
spoolh_ = ( OCISPool * ) spoolh;
ociCall ( OCIHandleAlloc ( ( void * ) envh_, ( dvoid ** ) &poolAuth,
OCI_HTYPE_AUTHINFO, 0, ( dvoid ** ) 0 ), errh_ );
poolAuth_ = ( OCIAuthInfo *) poolAuth;
if ( !(env_->drvName()).empty() )
{
ociCall ( OCIAttrSet ( ( void * ) poolAuth_, OCI_HTYPE_AUTHINFO,
( OraText * ) ( env_->drvName() ).c_str (),
( ub4 ) ( ( env_->drvName() ).length () ),
OCI_ATTR_DRIVER_NAME, errh_ ), errh_ );
}
ociCall ( OCIAttrSet ( spoolh_, OCI_HTYPE_SPOOL, poolAuth_, 0,
OCI_ATTR_SPOOL_AUTH, errh_ ), errh_ );
ociCall(OCISessionPoolCreate(envh_, errh_, spoolh_,
&poolName_, &poolNameLen_,
(OraText *)connString.c_str (),
(ub4) connString.length(),
poolMin, poolMax,
poolIncrement,
(OraText *)user.c_str (), (ub4) user.length(),
(OraText *)password.c_str (),
(ub4) password.length(),
mode), errh_ );
this->poolTimeout(poolTimeout);
this->stmtCacheSize(stmtCacheSize);
poolMax_ = poolMax;
/* In case of no free connections available, report error */
ociCall (OCIAttrSet (spoolh_, OCI_HTYPE_SPOOL, &spoolMode,
sizeof (spoolMode), OCI_ATTR_SPOOL_GETMODE, errh_ ),
errh_ ) ;
}
catch (...)
{
cleanup();
throw;
}
/*****************************************************************************/
/*
DESCRIPTION
Destructor for the PoolImpl class.
PARAMETERS:
none
RETURNS:
nothing
NOTES:
*/
PoolImpl::~PoolImpl()
{
cleanup();
}
/*****************************************************************************/
/*
DESCRIPTION
Terminate the Pool object.
PARAMETERS:
none
RETURNS:
nothing
NOTES:
*/
void PoolImpl::terminate()
{
if (poolName_)
{
ociCall( OCISessionPoolDestroy( spoolh_, errh_, OCI_DEFAULT), errh_);
poolName_ = NULL;
}
env_->terminatePool(this);
}
/*****************************************************************************/
/*
DESCRIPTION
Set the pool timeout.
PARAMETERS:
poolTimeout - pool timeout
RETURNS:
nothing
NOTES:
*/
void PoolImpl::poolTimeout(unsigned int poolTimeout)
{
ociCall(OCIAttrSet(spoolh_, OCI_HTYPE_SPOOL, &poolTimeout, 0,
OCI_ATTR_SPOOL_TIMEOUT, errh_), errh_);
}
/*****************************************************************************/
/*
DESCRIPTION
Set statement cache size.
PARAMETERS:
stmtCacheSize - statement cache size
RETURNS:
nothing
NOTES:
*/
void PoolImpl::stmtCacheSize(unsigned int stmtCacheSize)
{
ociCall(OCIAttrSet(spoolh_, OCI_HTYPE_SPOOL, &stmtCacheSize, 0,
OCI_ATTR_SPOOL_STMTCACHESIZE, errh_), errh_);
}
/*****************************************************************************/
/*
DESCRIPTION
Get the number of currently open connections.
PARAMETERS:
none
RETURNS:
number of currently open connections
NOTES:
*/
unsigned int PoolImpl::connectionsOpen() const
{
ub4 openConnections = 0;
ociCall(OCIAttrGet(spoolh_, OCI_HTYPE_SPOOL, &openConnections, 0,
OCI_ATTR_SPOOL_OPEN_COUNT, errh_), errh_);
return openConnections;
}
/*****************************************************************************/
/*
DESCRIPTION
Get the number of currently in use (checked-out) connections.
PARAMETERS:
none
RETURNS:
number of currently in use (checked-out) connections
NOTES:
*/
unsigned int PoolImpl::connectionsInUse() const
{
ub4 inUse = 0;
ociCall(OCIAttrGet(spoolh_, OCI_HTYPE_SPOOL, &inUse, 0,
OCI_ATTR_SPOOL_BUSY_COUNT, errh_), errh_);
return inUse;
}
/*****************************************************************************/
/*
DESCRIPTION
Get the PoolMax specified while creating the session-ppol.
PARAMETERS
-None-
RETURNS
poolMax provided while creating the pool
NOTES:
-None-
*/
int PoolImpl::poolMax () const
{
return poolMax_;
}
/*****************************************************************************/
/*
DESCRIPTION
Get connection.
PARAMETERS:
connectionClass - connection class.
user - user name in case of non-homogeneous pool
password - password in case of non-homogenous pool
tag - session tag name
any - match tag name as MATCHANY or MATCHEXACT
dbPriv - DB Privileges (SYSDBA or none)
RETURNS:
created connection
NOTES:
*/
Conn * PoolImpl::getConnection ( const std::string& connClass,
const std::string& user,
const std::string& password,
const std::string& tag,
const boolean matchAnyTag,
const DBPrivileges dbPriv )
{
Conn *conn = new ConnImpl(this, envh_, externalAuth_, poolName_,
poolNameLen_, connClass, user, password, tag,
matchAnyTag, dbPriv, poolPingInterval_ );
return conn;
}
/*****************************************************************************/
/*
DESCRIPTION
Release the connection.
PARAMETERS:
conn - connection to be release.
RETURNS:
nothing
NOTES:
*/
void PoolImpl::releaseConnection(ConnImpl *conn)
{
delete conn;
}
/*---------------------------------------------------------------------------
PRIVATE METHODS
---------------------------------------------------------------------------*/
/*****************************************************************************/
/*
DESCRIPTION
Cleanup for the PoolImpl class.
PARAMETERS:
none
RETURNS:
nothing
NOTES:
The free OCI handles are set to NULL to so that in case someone tries to
use a released Pool handle, they will get a reproducible seg-fault.
*/
void PoolImpl::cleanup()
{
if ( poolAuth_ )
{
OCIHandleFree (poolAuth_, OCI_HTYPE_AUTHINFO );
poolAuth_ = NULL;
}
if (poolName_)
{
// Ignore errors thrown.
OCISessionPoolDestroy( spoolh_, errh_, OCI_DEFAULT);
poolName_ = NULL;
}
if (spoolh_)
{
OCIHandleFree ( spoolh_, OCI_HTYPE_SPOOL);
spoolh_ = NULL;
}
if (errh_)
{
OCIHandleFree ( errh_, OCI_HTYPE_ERROR );
errh_ = NULL ;
}
}
/* end of file dpiPoolImpl.cpp */

View File

@ -1,109 +0,0 @@
/* Copyright (c) 2015, 2016, 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
* dpiPoolImpl.h
*
* DESCRIPTION
*
*****************************************************************************/
#ifndef DPIPOOLIMPL_ORACLE
# define DPIPOOLIMPL_ORACLE
#ifndef DPIPOOL_ORACLE
# include <dpiPool.h>
#endif
#ifndef DPIENVIMPL_ORACLE
# include <dpiEnvImpl.h>
#endif
#ifndef DPICONNIMPL_ORACLE
# include <dpiConnImpl.h>
#endif
using namespace dpi;
class EnvImpl;
class ConnImpl;
/*---------------------------------------------------------------------------
PUBLIC TYPES
---------------------------------------------------------------------------*/
class PoolImpl : public SPool
{
public:
// creation/termination
PoolImpl(EnvImpl *env, OCIEnv *envh,
const string &user, const string &password,
const string &connString,
int poolMax, int poolMin, int poolIncrement, int poolTimeout,
bool externalAuth, int stmtCacheSize, bool homogeneous,
int poolPingInterval );
virtual ~PoolImpl();
virtual void terminate();
// interface properties
virtual void poolTimeout( unsigned int poolTimeout);
virtual void stmtCacheSize( unsigned int stmtCacheSize );
virtual unsigned int connectionsOpen() const;
virtual unsigned int connectionsInUse() const;
virtual int poolMax() const;
// interface methods
virtual Conn * getConnection( const std::string& connClass,
const std::string& user,
const std::string& password,
const std::string& tag,
const boolean matchAnyTag,
const DBPrivileges dbPriv );
// internal methods
virtual void releaseConnection(ConnImpl *conn);
private:
void cleanup();
EnvImpl *env_; // parent Env object
bool externalAuth_; // doing external authentication
OCIEnv *envh_; // OCI enviornment handle
OCIError *errh_; // OCI error handle
OCISPool *spoolh_; // OCI session pool handle
OraText *poolName_; // pool name
ub4 poolNameLen_; // pool name length
OCIAuthInfo *poolAuth_; // pool Auth handle
int poolMax_; // Maximum sessions in the pool
int poolPingInterval_; // Pool Ping Interval
};
#endif /* DPIPOOLIMPL_ORACLE */

View File

@ -1,826 +0,0 @@
/* Copyright (c) 2015, 2016, 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
* dpiConnImpl.cpp - ConnImpl class implementation
*
* DESCRIPTION
* This file implements the ConnImpl class which provides the implemenation
* of the Conn abstract class.
*
* NOTES
* DPI layer encapsulating OCIStmt object to allow multiple parallel sql
* execution from same connection to go through. Each dpiStmtImpl will have
* its own OCIError object and this will be destroyed at the end of execution
*
*****************************************************************************/
#ifndef DPISTMTIMPL_ORACLE
# include <dpiStmtImpl.h>
#endif
#ifndef DPICONNIMPL_ORACLE
# include <dpiConnImpl.h>
#endif
#ifndef DPIEXCEPTIONIMPL_ORACLE
# include <dpiExceptionImpl.h>
#endif
#ifndef DPIDATETIMEARRAYIMPL_ORACLE
#include <dpiDateTimeArrayImpl.h>
#endif
#ifndef DPIUTILS_ORACLE
# include <dpiUtils.h>
#endif
#include <stdlib.h>
#include <iostream>
using namespace std;
/*---------------------------------------------------------------------------
PUBLIC METHODS
---------------------------------------------------------------------------*/
/*****************************************************************************/
/*
DESCRIPTION
Constructor for StmtImpl class created by Connection object.
PARAMETERS:
envh - OCIEnv handle
conn - parent connImpl object
svch - OCISvcCtx handle
sql - sql statement to execute
RETURN
-NONE-
NOTE:
wrapper of OCIStmt handle to allow multiple executions to go through
single connection parent object from multiple thread(s).
Each StmtImpl creates and uses OCIError handle and this will be destroyed
at the end of the execution.
# of parallel threads can be configured at nodejs level.
*/
StmtImpl::StmtImpl (OCIEnv *envh, ConnImpl *conn,
OCISvcCtx *svch, const string &sql)
try : conn_(conn), errh_(NULL), svch_(svch),
stmth_(NULL), numCols_ (0),meta_(NULL), stmtType_ (DpiStmtUnknown),
isReturning_(false), isReturningSet_(false), refCursor_(false),
state_(DPI_STMT_STATE_UNDEFINED)
{
void *errh = NULL;
void *stmth = NULL;
// create an OCIError object for this execution
ociCallEnv (OCIHandleAlloc ((void *)envh, &errh,
OCI_HTYPE_ERROR, 0, (dvoid **)0), envh);
errh_ = ( OCIError * ) errh;
if(!sql.empty())
{
// Prepare OCIStmt object with given sql statement.
ociCall (OCIStmtPrepare2 (svch_, &stmth_, errh_, (oratext *)sql.c_str(),
(ub4)sql.length(), NULL, 0, OCI_NTV_SYNTAX,
OCI_DEFAULT),
errh_);
}
else
{
// to build empty stmt object used for ref cursors.
ociCall (OCIHandleAlloc ((void *)envh, (dvoid **)&stmth,
OCI_HTYPE_STMT,0, (dvoid **)0), errh_);
stmth_ = ( OCIStmt * ) stmth;
refCursor_ = true;
}
}
catch (...)
{
cleanup ();
throw;
}
/*****************************************************************************/
/*
DESCRIPTION
Destructor for the StmtImpl class.
PARAMETERS
-NONE-
RETURNS:
-NONE_
*/
StmtImpl::~StmtImpl ()
{
cleanup ();
}
/*****************************************************************************/
/*
DESCRIPTION
Get Statement type
PARAMETERS
-NONE_
RETURNS
DpiStmtType enum
*/
DpiStmtType StmtImpl::stmtType () const
{
// Try to query the statement type only once.
if ( stmtType_ == DpiStmtUnknown )
{
ociCall (OCIAttrGet (stmth_, OCI_HTYPE_STMT, (ub2 * )&stmtType_, NULL,
OCI_ATTR_STMT_TYPE, errh_), errh_);
}
return (DpiStmtType)stmtType_;
}
/*****************************************************************************/
/*
DESCRIPTION
Get the numbers of rows affected by the DML operation.
PARAMETERS
-None-
RETURNS:
number of rows affected by the DML operation
*/
DPI_USZ_TYPE StmtImpl::rowsAffected () const
{
DPI_USZ_TYPE rowsAffected = 0;
ociCall (OCIAttrGet (stmth_, OCI_HTYPE_STMT, &rowsAffected, NULL,
DPIATTRROWCOUNT, errh_), errh_);
return rowsAffected;
}
/*****************************************************************************/
/*
DESCRIPTION
Number of columns that will be returned by this statement execution
PARAMETERS
-NONE-
RETURNS
# of columns
*/
unsigned int StmtImpl::numCols ()
{
if (numCols_)
return numCols_;
ociCall (OCIAttrGet (stmth_, OCI_HTYPE_STMT, &numCols_, 0,
OCI_ATTR_PARAM_COUNT, errh_), errh_);
return numCols_;
}
/*****************************************************************************/
/*
DESCRIPTION
Prefetch Rows set on statement handle
PARAMETERS
prefetchRows count
RETURNS
NONE
*/
void StmtImpl::prefetchRows (unsigned int prefetchRows)
{
ociCall(OCIAttrSet(stmth_, OCI_HTYPE_STMT, &prefetchRows, 0,
OCI_ATTR_PREFETCH_ROWS, errh_), errh_);
}
/*****************************************************************************/
/*
DESCRIPTION
bind the variable(s) by position
PARAMETERS
pos - position of the variable 1 based
type - Data type
buf (IN/OUT) - data buffer for the variable's value
bufSize - size of the buffer
ind (OUT) - indicator
bufLen (OUT) - size of data reutnred
maxarr_len - max size of array in case of index-array bind (IN)
curelen - current array length in case of array bind (IN)
ctx - application speficied data for callback if specified.
RETURNS
-NONE-
*/
void StmtImpl::bind (unsigned int pos, unsigned short type, void *buf,
DPI_SZ_TYPE bufSize, short *ind, DPI_BUFLEN_TYPE *bufLen,
unsigned int maxarr_len, unsigned int *curelen,
DpiBindCallbackCtx *ctx)
{
OCIBind *b = (OCIBind *)0;
ociCall (DPIBINDBYPOS (stmth_, &b, errh_, pos,
(ctx ? NULL : (type==DpiRSet) ?
(void *)&(((StmtImpl*)buf)->stmth_) : buf),
(type == DpiRSet) ? 0 : bufSize, type,
(ctx ? NULL : ind),
(ctx ? NULL : bufLen),
NULL, maxarr_len, curelen,
(ctx) ? OCI_DATA_AT_EXEC : OCI_DEFAULT),
errh_);
if ( ctx )
{
// Register callback if app specified data provided.
ociCall (OCIBindDynamic ( b, errh_, (void*)ctx,
StmtImpl::inbindCallback,
(void*)ctx, StmtImpl::outbindCallback ),
errh_ );
}
}
/*****************************************************************************/
/*
DESCRIPTION
Bind the variable by name
PARAMETERS
name - name of the variable
nameLen - len of name.
bndpos - position in array in case of DML Returning.
type - data type
buf (IN/OUT) - data buffer for value
bufSize - size of buffer
ind - indicator
bufLen - returned buffer size
maxarr_len - max array len in case of PL/SQL array binds
curelen - current array len in case of PL/SQL array binds.
ctx - data for application specified callback
*/
void StmtImpl::bind (const unsigned char *name, int nameLen,
unsigned int bndpos,
unsigned short type, void *buf, DPI_SZ_TYPE bufSize,
short *ind, DPI_BUFLEN_TYPE *bufLen,
unsigned int maxarr_len, unsigned int *curelen,
DpiBindCallbackCtx *ctx)
{
OCIBind *b = (OCIBind *)0;
ociCall (DPIBINDBYNAME (stmth_, &b, errh_, name, nameLen,
(ctx ? NULL : (type == DpiRSet) ?
(void *)&((StmtImpl*)buf)->stmth_: buf),
(type == DpiRSet) ? 0 : bufSize, type,
(ctx ? NULL : ind),
(ctx ? NULL : bufLen),
NULL,
maxarr_len, curelen,
(ctx) ? OCI_DATA_AT_EXEC : OCI_DEFAULT), errh_);
if ( ctx )
{
// Register callback if app specified data provided.
ociCall (OCIBindDynamic (b, errh_, (void*)ctx, StmtImpl::inbindCallback,
(void *)ctx, StmtImpl::outbindCallback ),
errh_ );
}
}
/****************************************************************************/
/*
DESCRIPTION
Execute the SQL statement.
PARAMETERS
autoCommit - true/false - autocommit enabled or not
numIterations - iterations to repeat
RETURNS:
-None-
*/
void StmtImpl::execute (int numIterations, bool autoCommit)
{
ub4 mode = autoCommit ? OCI_COMMIT_ON_SUCCESS : OCI_DEFAULT;
ociCall (OCIStmtExecute ( svch_, stmth_, errh_, (ub4)numIterations, (ub4)0,
(OCISnapshot *)NULL, (OCISnapshot *)NULL, mode),
errh_ );
#if OCI_MAJOR_VERSION < 12
// Rollback on connection release for all non-select transactions.
if ( ( stmtType_ != DpiStmtSelect ) && !conn_->hasTxn () )
{
/* Not to be reset, till thread safety is ensured in NJS */
conn_->hasTxn (true );
}
#endif
}
/****************************************************************************/
/*
DESCRIPTION
Release the SQL statement
PARAMETERS
-None-
RETURNS
-None-
*/
void StmtImpl::release ()
{
conn_->releaseStmt ( this ) ;
}
/*****************************************************************************/
/*
DESCRIPTION
Define the variable by pdpition
PARAMETERS
pos - pdpition of the variable
type - data type
buf - data buffer for the value
bufSize - size of the buffer
ind - indicator
bufLen - returned buffer size
ctx - application specified data for callbacks
RETURNS
-None-
*/
void StmtImpl::define (unsigned int pos, unsigned short type, void *buf,
DPI_SZ_TYPE bufSize, short *ind,
DPI_BUFLEN_TYPE *bufLen, DpiDefineCallbackCtx *ctx )
{
OCIDefine *d = (OCIDefine *)0;
ociCall (DPIDEFINEBYPOS (stmth_, &d, errh_, pos, buf, bufSize, type,
(void *)ind, bufLen, NULL,
(ctx ? OCI_DYNAMIC_FETCH : OCI_DEFAULT) ),
errh_);
if ((type == DpiClob) || (type == DpiBlob) || (type == DpiBfile))
{
boolean isLobPrefetchLength = true;
ociCall(OCIAttrSet(d, OCI_HTYPE_DEFINE, &isLobPrefetchLength, 0,
OCI_ATTR_LOBPREFETCH_LENGTH, errh_), errh_);
}
if ( ctx )
{
// Register for callback if application specified data provided
ociCall ( OCIDefineDynamic ( d, errh_, ctx, StmtImpl::defineCallback ),
errh_ );
}
}
/****************************************************************************/
/*
DESCRIPTION
Fetch specified number of rows
PARAMETERS
numRows - number of Rows to fetch
RETURNS
-None-
*/
void StmtImpl::fetch (unsigned int numRows)
{
sword rc = OCIStmtFetch2 (stmth_, errh_, numRows, OCI_FETCH_NEXT, 0,
OCI_DEFAULT);
if ( rc && rc != OCI_NO_DATA )
{
ociCall ( rc, errh_);
}
}
/*****************************************************************************/
/*
DESCRIPTION
To obtain number of rows fetched in the last fetch call
PARAMETERS
-NONE-
RETURNS
unsigned int - # of rows fetched.
*/
unsigned int StmtImpl::rowsFetched () const
{
unsigned int rowsFetched = 0 ;
ociCall (OCIAttrGet (stmth_, OCI_HTYPE_STMT, &rowsFetched,
0, OCI_ATTR_ROWS_FETCHED, errh_), errh_);
return rowsFetched;
}
/*****************************************************************************/
/*
DESCRIPTION
obtains column meta data
PARAMETERS
extendedMetaData - true - all fields are populated
false - only column name, db type, size is populated.
RETURNS
Pointer to MetaData struct.
*/
/*
* The returned pointer to MetaData struct should not be freed by the caller
* since this will be freed as part of StmtImpl::release()
*/
const MetaData* StmtImpl::getMetaData ( bool extendedMetaData )
{
if ( !meta_ )
{
if ( numCols () )
{
ub4 col = 0;
void *colDesc = (OCIParam *) 0;
void *colName = NULL;
meta_ = new MetaData[numCols_];
if ( !meta_ )
{
throw ExceptionImpl ( DpiErrMemAllocFail ) ;
}
while (col < numCols_)
{
ociCall(OCIParamGet((void *)stmth_, OCI_HTYPE_STMT, errh_,
&colDesc, (ub4) (col+1)), errh_ );
ociCall(OCIAttrGet(colDesc, (ub4) OCI_DTYPE_PARAM, &colName,
(ub4 *) &(meta_[col].colNameLen),
(ub4) OCI_ATTR_NAME,errh_ ), errh_ );
meta_[col].colName = (unsigned char *) colName;
ociCall(OCIAttrGet(colDesc, (ub4) OCI_DTYPE_PARAM,
(void*) &(meta_[col].dbType),(ub4 *) 0,
(ub4) OCI_ATTR_DATA_TYPE,
errh_ ), errh_ );
switch ( meta_[col].dbType )
{
case DpiVarChar:
case DpiFixedChar:
case DpiRaw:
// byteSize in case VARCHAR, FIXEDCHAR, RAW columns
ociCall(OCIAttrGet(colDesc, (ub4) OCI_DTYPE_PARAM,
(void*) &(meta_[col].dbSize),(ub4 *) 0,
(ub4) OCI_ATTR_DATA_SIZE,
errh_ ), errh_ );
break;
default:
break;
}
if ( extendedMetaData )
{
ociCall(OCIAttrGet(colDesc, (ub4) OCI_DTYPE_PARAM,
(void*) &(meta_[col].isNullable),(ub4*) 0,
(ub4) OCI_ATTR_IS_NULL,
errh_ ), errh_ );
switch ( meta_[col].dbType )
{
case DpiNumber:
ociCall(OCIAttrGet(colDesc, (ub4) OCI_DTYPE_PARAM,
(void*) &(meta_[col].precision),(ub4* ) 0,
(ub4) OCI_ATTR_PRECISION,
errh_ ), errh_ );
ociCall(OCIAttrGet(colDesc, (ub4) OCI_DTYPE_PARAM,
(void*) &(meta_[col].scale),(ub4*) 0,
(ub4) OCI_ATTR_SCALE,
errh_ ), errh_ );
break;
case DpiTimestamp:
case DpiTimestampTZ:
case DpiTimestampLTZ:
ociCall(OCIAttrGet(colDesc, (ub4) OCI_DTYPE_PARAM,
(void*) &(meta_[col].scale),(ub4*) 0,
(ub4) OCI_ATTR_SCALE,
errh_ ), errh_ );
break;
default:
break;
}
}
OCIDescriptorFree( colDesc, OCI_DTYPE_PARAM);
col++;
}
}
}
return meta_;
}
/*---------------------------------------------------------------------------
PRIVATE METHODS
---------------------------------------------------------------------------*/
/*****************************************************************************/
/*
DESCRIPTION
Cleanup routine for the StmtImpl class.
PARAMETERS
-NONE_
RETURNS
void
*/
void StmtImpl::cleanup ()
{
if(meta_)
{
delete [] meta_;
meta_ = NULL;
}
if ( stmth_)
{
// Release not called for ref cursor.
if ( refCursor_ )
OCIHandleFree ( stmth_, OCI_HTYPE_STMT );
else
ociCall ( OCIStmtRelease (stmth_, errh_, NULL, 0, OCI_DEFAULT), errh_ );
stmth_ = NULL;
}
if ( errh_)
{
OCIHandleFree (errh_, OCI_HTYPE_ERROR);
errh_ = NULL;
}
}
/****************************************************************************/
/*
DESCRIPTION
Callback function for IN binds for Dynamic Binds used for DML Return
This is OCI specific callback.
PARAMETERS
ctxp - context (IN)
bindp - OCIBind pointer (IN)
iter - iteration. (IN)
index - index (rowcount) (IN)
bufpp - buffer pointer (INOUT)
alenpp - actual length (INOUT)
piecep - piece wise flag (INOUT)
indpp - indicator (INOUT)
RETURNS
OCI_CONTINUE
NOTE:
This function is a dummy function, the Dynamic bind concept is not used
for IN binds, and so this function is dummy.
*/
sb4 StmtImpl::inbindCallback ( void *ctxp, OCIBind * /*bindp*/, ub4 /*iter*/,
ub4 /*index*/, void **bufpp, ub4 *alenpp,
ub1 *piecep, void **indpp )
{
DpiBindCallbackCtx *cbCtx = (DpiBindCallbackCtx *)ctxp;
cbCtx->nullInd = -1; /* inbind callback for DML RETURNING myst return null */
*bufpp = (void *)0;
*alenpp = 0;
*indpp = (void *)&(cbCtx->nullInd);
*piecep = OCI_ONE_PIECE;
return OCI_CONTINUE;
}
/****************************************************************************/
/*
DESCRIPTION
Callback function for OUT binds for Dynamic Binds used for DML Return
This is OCI specific callback.
PARAMETERS
ctxp - context (IN)
bindp - OCIBind pointer (IN)
iter - iteration. (IN)
index - index (rowcount) (IN)
bufpp - buffer pointer (INOUT)
alenpp - actual length (INOUT)
piecep - piece wise flag (INOUT)
indpp - indicator (INOUT)
rcodepp - return code pointer (INOUT) - NOT USED
RETURNS
OCI_CONTINUE
NOTE:
This function uses specified callback to allocate and identify blocks
of memory for each cell. ctxp provides the application specific callback
and maxrows.
*/
sb4 StmtImpl::outbindCallback ( void *ctxp, OCIBind *bindp, ub4 iter,
ub4 index, void **bufpp, ub4 **alenp,
ub1 *piecep, void **indpp, ub2 **rcodepp )
{
DpiBindCallbackCtx *cbCtx = (DpiBindCallbackCtx *)ctxp;
ub4 rows = 0;
int cbret = 0;
if ( index == 0 )
{
ub4 sz = sizeof ( rows ) ;
sb4 rc = OCI_SUCCESS ;
OCIError *errh = NULL;
rc = OCIAttrGet ( bindp, OCI_HTYPE_BIND, &rows, (ub4 *)&sz,
OCI_ATTR_ROWS_RETURNED,
((StmtImpl *)cbCtx->dpistmt)->errh_ ) ;
if ( rc != OCI_SUCCESS )
{
errh = ((StmtImpl *)cbCtx->dpistmt)->errh_ ; // preserve err handle
// Cleanup
free ( cbCtx ) ;
cbCtx = NULL;
// bail out
ociCall ( rc, errh ) ;
}
cbCtx->nrows = ( unsigned long ) rows;
cbCtx->iter = iter;
}
/*
Call the application specific callback to allocate and identify
buffer for each row
*/
cbret = (cbCtx->callbackfn)(cbCtx->data, cbCtx->nrows, cbCtx->bndpos,
iter, index, bufpp,
(void **)alenp, indpp, rcodepp, piecep );
/* If the buffer is insufficient for varchar columns, error out */
return (cbret == -1 ) ? OCI_ROWCBK_DONE : OCI_CONTINUE ;
}
/*****************************************************************************/
/*
DESCRIPTION
Callback function for CLOB columns to fetch data as STRING
This is OCI specific callback
PARAMETERS
ctxp (IN) - context for the callback
definep (IN) - OCIDefine pointer
iter (IN) - iteration
bufpp (INOUT)- to provide application specified memory block
alenpp(INOUT)- length of buffer (IN provide max size and OUT data size)
piecep (OUT) - piece wise flag
indpp (INOUT)- to provide buffer for indicator
rcodepp(INOUT) - to provide buffer for return code pointer -NOT USED
RETURNS
OCI_CONTINUE
NOTES:
This function uses specified callback to allocate and identify blocks of
memory for each row.
*/
sb4 StmtImpl::defineCallback ( void *ctxp, OCIDefine *definep, ub4 iter,
void **bufpp, ub4 **alenpp, ub1 *piecep,
void **indpp, ub2 **rcodepp )
{
sb4 rc = OCI_CONTINUE;
int cbret = 0 ;
DpiDefineCallbackCtx *ctx = (DpiDefineCallbackCtx *)ctxp;
cbret = ctx->callbackfn ( ctx, iter, bufpp, (void **) alenpp, (void**)indpp,
rcodepp );
*piecep = OCI_NEXT_PIECE; // always ask for next piece
if ( cbret )
{
/*
* In case of memory allocation failures return error to OCI, which will
* lead to ORA-24343 - user defined callback error.
*/
rc = OCI_ERROR;
}
return rc;
}
/*****************************************************************************/
/*
DESCRIPTION
TO determine if the current SQL statement has RETURNING INTO clause or not
PARAMETERS
-None-
RETURNS
true - if the SQL statement has RETURNING INTO clause, falose otherwise
NOTE:
The OCI is is called only once to determine and the state is cahced.
*/
bool StmtImpl::isReturning ()
{
if ( !isReturningSet_)
{
ub1 isReturning = FALSE;
ociCall ( OCIAttrGet ( stmth_, OCI_HTYPE_STMT, (ub1*)&isReturning, NULL,
OCI_ATTR_STMT_IS_RETURNING, errh_), errh_ );
isReturning_ = ( isReturning == TRUE ) ? true : false;
isReturningSet_ = true;
}
return isReturning_;
}
/*****************************************************************************/
/*
DESCRIPTION
To obtain the OCI statement handle state
PARAMETERS
-None-
RETURNS
One of the possible values DpiStmtState
(DpiStmtStateInitialized, DpiStmtStateExecute, DpiStmtEndOfFetch)
*/
unsigned int StmtImpl::getState ()
{
if ( state_ == DPI_STMT_STATE_UNDEFINED )
{
ociCall (OCIAttrGet (stmth_, OCI_HTYPE_STMT, &state_, NULL,
OCI_ATTR_STMT_STATE, errh_ ), errh_ );
}
return ( unsigned int ) state_;
}
/* end of file dpiStmtImpl.cpp */

View File

@ -1,138 +0,0 @@
/* Copyright (c) 2015, 2016 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
* dpiStmtImpl.h
*
* DESCRIPTION
*
*****************************************************************************/
#ifndef DPISTMTIMPL_ORACLE
# define DPISTMTIMPL_ORACLE
#ifndef DPISTMT_ORACLE
# include <dpiStmt.h>
#endif
#ifndef OCI_ORACLE
# include <oci.h>
#endif
using namespace dpi;
class EnvImpl;
class ConnImpl;
class StmtImpl;
/*---------------------------------------------------------------------------
PUBLIC TYPES
---------------------------------------------------------------------------*/
class StmtImpl : public Stmt
{
public:
// Constructor & Destructor
StmtImpl (OCIEnv *envh, ConnImpl *conn, OCISvcCtx *svch,
const string &sql);
virtual ~StmtImpl ();
// Attributes
virtual DpiStmtType stmtType () const;
virtual DPI_USZ_TYPE rowsAffected () const;
virtual unsigned int numCols() ;
virtual void prefetchRows( unsigned int prefetchRows ) ;
virtual unsigned int rowsFetched () const ;
// Methods
virtual void release ();
virtual void bind (unsigned int pos, unsigned short type, void *buf,
DPI_SZ_TYPE bufSize, short *ind, DPI_BUFLEN_TYPE *bufLen,
unsigned int maxarr_len, unsigned int *curelen,
DpiBindCallbackCtx *ctx);
virtual void bind (const unsigned char *name, int nameLen,
unsigned int bndpos,
unsigned short type, void *buf, DPI_SZ_TYPE bufSize,
short *ind, DPI_BUFLEN_TYPE *bufLen,
unsigned int maxarr_len, unsigned int *curelen,
DpiBindCallbackCtx *ctx);
virtual void execute ( int numIterations, bool autoCommit );
virtual void define (unsigned int pos, unsigned short type, void *buf,
DPI_SZ_TYPE bufSize, short *ind,
DPI_BUFLEN_TYPE *bufLen,
DpiDefineCallbackCtx *ctx );
virtual void fetch (unsigned int numRows = 1);
/*
* The returned pointer to MetaData struct should not be freed by the caller
* since this will be freed as part of StmtImpl::release()
*/
virtual const MetaData *getMetaData ( bool extendedMetaData );
virtual OCIError * getError () { return errh_; }
virtual unsigned int getState ();
virtual bool isReturning ();
// OCI specific Callback to be used for dynamic binding (dummy for IN)
static sb4 inbindCallback ( void *ctxp, OCIBind *bindp, ub4 iter, ub4 index,
void **bufpp, ub4 *alenpp, ub1 *piecep,
void **indpp );
// OCI specific callback to be used for dynamic binding
static sb4 outbindCallback (void *ctxp, OCIBind *bindp, ub4 iter, ub4 index,
void **bufpp, ub4 **alenp, ub1 *piecep,
void **indpp, ub2 **rcodepp );
static sb4 defineCallback ( void *ctxp, OCIDefine *definep, ub4 iter,
void **bufpp, ub4 **alenpp, ub1 *piecep,
void **indpp, ub2 **rcodepp );
private:
void cleanup ();
private:
// DPI objects
ConnImpl *conn_; // parent Connection object
// OCI Objects
OCIError *errh_; // OCI Error object for this stmt execution
OCISvcCtx *svch_; // OCI service handle
OCIStmt *stmth_; // OCI Stmt handle
unsigned int numCols_; // # of cols this stmt execution will return
MetaData *meta_; // Meta data array
unsigned short stmtType_; // Statement Type (Query, DML, ... )
bool isReturning_; // Does the stmt has RETURNING INTO clause?
bool isReturningSet_; // Has isReturning_ flag queried & set.
bool refCursor_; // refCursor or not.
ub4 state_; // OCI Stmt State
};
#endif /* DPISTMTIMPL_ORACLE */

View File

@ -1,145 +0,0 @@
/* Copyright (c) 2015, 2016, 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
* dpiUtils.cpp - ConnImpl class implementation
*
* DESCRIPTION
*
*****************************************************************************/
#include <stdio.h>
#include <string.h>
#ifndef DPIUTILS_ORACLE
# include <dpiUtils.h>
#endif
#ifndef DPIEXCEPTIONIMPL_ORACLE
# include <dpiExceptionImpl.h>
#endif
#ifdef WIN32
#define snprintf _snprintf
#endif
#ifdef OCI_ERROR_MAXMSG_SIZE2
/* A bigger message size is defined from 11.2.0.3 onwards */
#define DPIUTILS_OCI_ERR_MAX_SIZE OCI_ERROR_MAXMSG_SIZE2
#else
#define DPIUTILS_OCI_ERR_MAX_SIZE OCI_ERROR_MAXMSG_SIZE
#endif
/*****************************************************************************/
/*
DESCRIPTION
Wrapper for ociCall and ociCallEnv.
Abstraction for the redundant common functionality.
PARAMETERS:
rc - OCI return code
errh - OCI error hanlde
errType - error type
RETURNS:
nothing
NOTES:
*/
static void ociCallCommon(sword rc, void *handle, ub4 errType)
{
// OCI_SUCCESS_WITH_INFO - warnings are reported in some cases.
// Treat these warnings as success as the OCI call succeeded and
// ignore the error message
if ( (rc == OCI_SUCCESS) || (rc == OCI_SUCCESS_WITH_INFO ) )
return;
if (rc == OCI_INVALID_HANDLE)
throw ExceptionImpl(DpiOciInvalidHandle);
OraText ociErrorMsg[DPIUTILS_OCI_ERR_MAX_SIZE];
sb4 ociErrorNo = 0;
memset(ociErrorMsg, 0, DPIUTILS_OCI_ERR_MAX_SIZE);
rc = OCIErrorGet(handle, 1, NULL, &ociErrorNo, ociErrorMsg,
DPIUTILS_OCI_ERR_MAX_SIZE-1, errType);
if (rc)
throw ExceptionImpl(DpiErrUnkOciError);
else
{
throw ExceptionImpl("ORA", ociErrorNo, (const char *)ociErrorMsg);
}
}
/*---------------------------------------------------------------------------
PUBLIC FUNCTIONS
---------------------------------------------------------------------------*/
/*****************************************************************************/
/*
DESCRIPTION
This routine retrives the error information from the OCI error handle and
throws ExceptionImpl with the information contained in the error handle.
PARAMETERS:
rc - OCI return code
errh - OCI error hanlde
RETURNS:
nothing
NOTES:
*/
void ociCall(sword rc, OCIError *errh)
{
ociCallCommon(rc, errh, OCI_HTYPE_ERROR);
}
/*****************************************************************************/
/*
DESCRIPTION
This routine retrives the error information from the OCI environment
handle and throws ExceptionImpl with the information contained in the
error handle.
PARAMETERS:
rc - OCI return code
envh - OCI environment hanlde
RETURNS:
nothing
NOTES:
*/
void ociCallEnv(sword rc, OCIEnv *envh)
{
ociCallCommon(rc, envh, OCI_HTYPE_ENV);
}
/* end of file dpiUtils.cpp */

View File

@ -1,53 +0,0 @@
/* Copyright (c) 2015, 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
* dpiUtils.h
*
* DESCRIPTION
*
*****************************************************************************/
#ifndef DPIUTILS_ORACLE
# define DPIUTILS_ORACLE
#ifndef OCI_ORACLE
# include <oci.h>
#endif
/*---------------------------------------------------------------------------
PUBLIC CONSTANTS AND MACROS
---------------------------------------------------------------------------*/
/*---------------------------------------------------------------------------
PUBLIC TYPES
---------------------------------------------------------------------------*/
/*---------------------------------------------------------------------------
PUBLIC FUNCTIONS
---------------------------------------------------------------------------*/
void ociCall(sword rc, OCIError *errh);
void ociCallEnv(sword rc, OCIEnv *envh);
#endif /* DPIUTILS_ORACLE */

File diff suppressed because it is too large Load Diff

View File

@ -1,862 +0,0 @@
/* Copyright (c) 2015, 2017, 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.
*
* This file uses NAN:
*
* Copyright (c) 2015 NAN contributors
*
* NAN contributors listed at https://github.com/rvagg/nan#contributors
*
* Permission is hereby granted, free of charge, to any person obtaining
* a copy of this software and associated documentation files (the
* "Software"), to deal in the Software without restriction, including
* without limitation the rights to use, copy, modify, merge, publish,
* distribute, sublicense, and/or sell copies of the Software, and to
* permit persons to whom the Software is furnished to do so, subject to
* the following conditions:
*
* The above copyright notice and this permission notice shall be
* included in all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
* NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
* LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
* OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
* WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
*
* NAME
* njsConnection.h
*
* DESCRIPTION
* Connection class
*
*****************************************************************************/
#ifndef __NJSCONNECTION_H__
#define __NJSCONNECTION_H__
#include <node.h>
#include <string>
#include <vector>
#include "dpi.h"
#include "njsUtils.h"
#include "njsOracle.h"
using namespace v8;
using namespace node;
using namespace dpi;
class Connection;
class ProtoILob;
// Max number of bytes allowed for PLSQL STRING/BUFFER arguments
#define NJS_THRESHOLD_SIZE_PLSQL_STRING_ARG 32767
// Extended bind type
typedef enum
{
NJS_EXTBIND_DEFAULT = 0, /* Default case no data yet to determine */
NJS_EXTBIND_REFCURSOR = 1, /* REFCURSOR case, OUT Bind */
NJS_EXTBIND_LOB = 2, /* LOB Bind IN case -large data - temp lob case */
NJS_EXTBIND_DMLRETCB = 3, /* DML Returning case context used for callback */
} ExtBindType;
// Enumeration to identify which struct of union is used in ExtDefine.
typedef enum
{
NJS_EXTDEFINE_UNDEFINED = 0, /* Not defined yet */
NJS_EXTDEFINE_CONVERT_LOB = 1, /* Used as part of lob As String/buffer */
} ExtDefineType;
/**
* Structure used for binds
**/
typedef struct Bind
{
std::string key;
void* value;
void* extvalue;
DPI_BUFLEN_TYPE *len; // actual length IN/OUT for bind APIs
unsigned int *len2; // used for DML returning
DPI_SZ_TYPE maxSize;
unsigned short type;
short *ind;
bool isOut;
bool isInOut; // Date/Timestamp needs this info
bool isArray;
unsigned int maxArraySize;
unsigned int curArraySize;
unsigned int rowsReturned; /* number rows returned for
the bind (DML RETURNING) */
dpi::DateTimeArray* dttmarr;
Bind () : key(""), value(NULL), extvalue (NULL), len(NULL), len2(NULL),
maxSize(0), type(0), ind(NULL), isOut(false), isInOut(false),
isArray(false), maxArraySize(0), curArraySize(0),
rowsReturned(0), dttmarr ( NULL )
{}
}Bind;
/**
* Structure used for Query result
**/
typedef struct Define
{
unsigned short fetchType;
DPI_SZ_TYPE maxSize;
void *buf; // will have the values from DB
void *extbuf; // this field will be DPI calls
DPI_BUFLEN_TYPE *len;
short *ind;
dpi::DateTimeArray *dttmarr; // DPI Date time array of descriptor
Define () :fetchType(0), maxSize(0), buf(NULL), extbuf(NULL),
len(0), ind(0), dttmarr(NULL)
{}
} Define;
/**
* MetaInfo structure, this is parallel structure to Metadata
*
* NOTE:
*
* dbTYpe - database table column data type (SQLT_xxx constants).
* dpiFetchType - data type used with OCI calls after FetchAs/FetInfo rules
* applied used between DB layer and Driver
* njsFetchType - data type reported to the application for this column -
* driver types (Oracledb.constants).
**/
typedef struct MetaInfo
{
std::string name; // DB column name
unsigned short dbType; // DB column type
unsigned short dpiFetchType; // Target fetchType for DPI
short njsFetchType; // Target fetchType for NJS
unsigned short byteSize; // Size In bytes at database
short precision; // Precision
signed char scale; // Scale, range starts from -127
unsigned char isNullable; // Nullable
MetaInfo ()
: name(""), dbType(0), dpiFetchType(0), njsFetchType(NJS_DATATYPE_UNKNOWN),
byteSize(0), precision(0), scale(0), isNullable(false)
{}
} MetaInfo;
/**
* This is a parallel structure to Bind and stores extended bind fields
* in specific cases like refCursor
**/
typedef struct ExtBind
{
ExtBindType extBindType;
union
{
// Specific to REFCURSOR case
struct
{
unsigned int numCols; // number of columns
MetaInfo *mInfo; // MetaInfo structure
} extRefCursor;
// Specific to LOB case
struct
{
void *value; // Stores extra bind reference
bool isStringBuffer2LOB; // Specifies whether string or buffer Converted
// to LOB or not
DPI_SZ_TYPE maxSize; // Size for the OUT or IN OUT bind value
} extLob;
// Specific to DML Returning case, callback ctx
struct
{
DpiBindCallbackCtx *ctx;
} extDMLReturnCbCtx;
} fields;
ExtBind ( ExtBindType extbindType )
{
this->extBindType = extbindType;
switch ( extbindType )
{
case NJS_EXTBIND_REFCURSOR:
this -> fields.extRefCursor.numCols = 0;
this -> fields.extRefCursor.mInfo = 0 ;
break;
case NJS_EXTBIND_LOB:
this -> fields.extLob.value = NULL;
this -> fields.extLob.isStringBuffer2LOB = false;
break;
case NJS_EXTBIND_DMLRETCB:
this -> fields.extDMLReturnCbCtx.ctx = NULL;
break;
default: // Should never hit here!
break;
}
}
} ExtBind;
/**
* Extension to Define struct - to store type specific data here and keep
* Define as generic as possible
*/
typedef struct ExtDefine
{
ExtDefineType extDefType; /* which type of ext-define data used */
// containter for type specific data
union
{
// Fields required for Fetch-Clob-As-String case or Fetch-Blob-As-Buffer
struct
{
void *ctx; /* Context pointer used by the call back */
DPI_BUFLEN_TYPE cLen; /* cummulative length from each callback */
unsigned int *len2; /* size of the buffer for each row */
} extConvertLob ;
} fields;
ExtDefine ( ExtDefineType type )
{
extDefType = type;
if ( type == NJS_EXTDEFINE_CONVERT_LOB )
{
fields.extConvertLob.ctx = NULL ;
fields.extConvertLob.cLen = 0;
fields.extConvertLob.len2 = NULL;
}
}
} ExtDefine;
/*
* RESETEXTDEFINE4NEXTFETCH macro resets one field in ExtDefine struct
* allowing the struct to be reused for subsequent fetch calls. The indexing
* starts with 0 for every fetch and the callback can be called multiple
* times for the same row, based on data-size, a scenario,
* where maxSize is set to 1, and using resultSet Interface (or queryStream),
* the state of extDefine gets confused without this reset
*/
#define RESETEXTDEFINE4NEXTFETCH(extDefine) \
{ \
if ( extDefine ) \
{ \
DpiDefineCallbackCtx *ctx = (DpiDefineCallbackCtx *) \
extDefine->fields.extConvertLob.ctx ; \
ctx->prevIter = -1; \
} \
} \
/**
* FetchInfo structure
**/
typedef struct fetchInfo
{
std::string colName; /* DB Column name or expression name */
DataType njsType; /* Fetch this column as specfieid type */
// Constructor to initialize member variables.
fetchInfo ()
: colName (""), njsType ( NJS_DATATYPE_DEFAULT )
{
}
} FetchInfo;
/**
* LobInfo struct
**/
typedef struct LobInfo
{
Descriptor *lobLocator;
unsigned char lobType;
// Constructor to initialize member variables.
LobInfo ( unsigned char type )
: lobLocator ( NULL ), lobType ( type )
{
}
} LobInfo;
/**
* Baton for Asynchronous Connection methods
**/
typedef struct eBaton
{
uv_work_t req;
std::string sql;
std::string error;
dpi::Env* dpienv;
dpi::Conn* dpiconn;
Connection *njsconn;
DPI_USZ_TYPE rowsAffected;
unsigned int maxRows;
unsigned int prefetchRows;
bool getRS;
bool autoCommit;
unsigned int rowsFetched;
unsigned int outFormat;
unsigned int numCols;
dpi::Stmt *dpistmt;
dpi::DpiStmtType st;
bool stmtIsReturning;
std::vector<Bind*> binds;
std::vector<ExtBind*> extBinds;
unsigned int numOutBinds; // # of out binds used for DML return
Define *defines;
std::vector<ExtDefine*> extDefines;
unsigned int fetchAsStringTypesCount;
DataType *fetchAsStringTypes; // Global by type settings
unsigned int fetchAsBufferTypesCount;
DataType *fetchAsBufferTypes;
unsigned int fetchInfoCount; // Conversion requested count
FetchInfo *fetchInfo; // Conversion meta data
Nan::Persistent<Function> cb;
RefCounter counter;
Nan::Persistent<Object> jsConn;
bool extendedMetaData;
MetaInfo *mInfo;
LobInfo *lobInfo;
std::vector<Nan::Persistent<Object>*>
persistentRefs; // Persistent Refs to JS Objects
eBaton( unsigned int& count, Local<Function> callback,
Local<Object> jsConnObj ) :
sql(""), error(""), dpienv(NULL), dpiconn(NULL), njsconn(NULL),
rowsAffected(0), maxRows(0), prefetchRows(0),
getRS(false), autoCommit(false), rowsFetched(0), outFormat(0),
numCols(0), dpistmt(NULL), st(DpiStmtUnknown),
stmtIsReturning (false), numOutBinds(0), defines(NULL),
fetchAsStringTypesCount (0), fetchAsStringTypes(NULL),
fetchAsBufferTypesCount (0), fetchAsBufferTypes(NULL),
fetchInfoCount(0), fetchInfo(NULL), counter ( count ),
extendedMetaData(false), mInfo(NULL), lobInfo(NULL)
{
cb.Reset( callback );
jsConn.Reset ( jsConnObj );
}
~eBaton ()
{
cb.Reset ();
jsConn.Reset ();
if( !binds.empty() )
{
for( unsigned int index = 0 ;index < binds.size(); index++ )
{
// do not free refcursor type.
if( binds[index]->value && binds[index]->type != DpiRSet )
{
free(binds[index]->value);
}
if ( binds[index]->extvalue )
{
free ( binds[index]->extvalue );
}
if ( binds[index]->ind )
{
free ( binds[index]->ind );
}
if ( binds[index]->len )
{
free ( binds[index]->len );
}
if ( binds[index]->len2 )
{
free ( binds[index]->len2 ) ;
}
delete binds[index];
}
}
if( !extBinds.empty() )
{
for( unsigned int index = 0 ;index < extBinds.size(); index++ )
{
if ( extBinds[index] )
{
switch ( extBinds[index]->extBindType )
{
case NJS_EXTBIND_REFCURSOR:
if ( extBinds[index]->fields.extRefCursor.mInfo )
{
delete [] extBinds[index]->fields.extRefCursor.mInfo;
}
break;
case NJS_EXTBIND_LOB:
if ( extBinds[index]->fields.extLob.value )
{
free ( extBinds[index]->fields.extLob.value );
}
break;
case NJS_EXTBIND_DMLRETCB:
if ( extBinds[index]->fields.extDMLReturnCbCtx.ctx )
{
free ( extBinds[index]->fields.extDMLReturnCbCtx.ctx ) ;
}
break;
case NJS_EXTBIND_DEFAULT:
default:
break;
}
}
delete extBinds[index];
}
extBinds.clear ();
}
if( !persistentRefs.empty() )
{
for( unsigned int index = 0 ;index < persistentRefs.size();
index++ )
{
persistentRefs[index]->Reset ();
delete persistentRefs[index];
}
persistentRefs.clear ();
}
if ( lobInfo )
{
if ( lobInfo->lobLocator )
{
free ( lobInfo->lobLocator );
}
delete lobInfo;
}
if( defines && !getRS ) // To reuse fetch Buffers of ResultSet
{
for( unsigned int i=0; i<numCols; i++ )
{
if ((defines[i].fetchType == DpiClob) ||
(defines[i].fetchType == DpiBlob) ||
(defines[i].fetchType == DpiBfile))
{
for (unsigned int j = 0; j < maxRows; j++)
{
// free all those unused descriptors that were never fetched.
if (((Descriptor **)(defines[i].buf))[j])
Env::freeDescriptor(((Descriptor **)(defines[i].buf))[j],
LobDescriptorType);
}
}
// If Clob data was fetched as String, deallocate each buffer
if ( (defines[i].fetchType == dpi::DpiVarChar) &&
mInfo[i].dbType == dpi::DpiClob )
{
for ( unsigned int j = 0 ; j < maxRows ; j ++ )
{
free ( ((char **)(defines[i].buf))[j] );
}
}
// If Blob data was fetched as Buffer, deallocate each buffer
if ( (defines[i].fetchType == dpi::DpiRaw) &&
mInfo[i].dbType == dpi::DpiBlob )
{
for ( unsigned int j = 0 ; j < maxRows ; j ++ )
{
free ( ((char **)(defines[i].buf))[j] );
}
}
/*
* Buf and indicator will be allocated in all cases.
* len will NOT be allocated for CLOB-as-STRING/BLOB-as-BUFFER
* scenarios. For consistency check all fields before deallocating
*/
if ( defines[i].buf )
{
free(defines[i].buf);
}
if ( defines[i].len )
{
free(defines[i].len);
}
if ( defines[i].ind )
{
free(defines[i].ind);
}
}
delete [] defines;
}
if ( fetchInfo && !getRS )
{
delete [] fetchInfo;
}
if ( fetchAsStringTypes && !getRS )
{
free (fetchAsStringTypes);
}
// Clear the extended-define structures if non-resultset case
if ( extDefines.size() > 0 && !getRS )
{
for ( unsigned int i = 0 ; i < numCols ; i ++ )
{
// If not applicable the it will be NULL
if ( extDefines[i] )
{
// Fetch-Clob-As_string case
if ( extDefines[i]->extDefType == NJS_EXTDEFINE_CONVERT_LOB )
{
free ( extDefines[i]->fields.extConvertLob.ctx );
extDefines[i]->fields.extConvertLob.ctx = NULL ;
free ( extDefines[i]->fields.extConvertLob.len2 );
extDefines[i]->fields.extConvertLob.len2 = NULL ;
delete extDefines[i];
}
}
}
}
if( mInfo && !getRS )
{
delete [] mInfo;
}
}
}eBaton;
class Connection: public Nan::ObjectWrap
{
public:
void setConnection ( dpi::Conn*, Oracledb* oracledb, Local<Object> obj );
static Nan::Persistent<FunctionTemplate> connectionTemplate_s;
static void Init (Handle<Object> target);
static Local<Value> GetRows (eBaton* executeBaton);
static Local<Value> GetMetaData ( const MetaInfo* mInfo,
const unsigned int numCols,
const bool extendedMetaData );
static void DoDefines ( eBaton* executeBaton );
static void DoFetch (eBaton* executeBaton);
static void CopyMetaData ( MetaInfo* mInfo,
eBaton* executeBaton,
const MetaData* meta,
const unsigned int numCols );
bool isValid() { return isValid_; }
dpi::Conn* getDpiConn() { return dpiconn_; }
/*
* Counters to see whether connection is busy or not with LOB, ResultSet or
* DB operations. This counters incremented and decremented for each
* operation and used to prevent releasing busy connection.
*/
inline unsigned int& LOBCount () { return lobCount_; }
inline unsigned int& RSCount () { return rsCount_; }
inline unsigned int& DBCount () { return dbCount_; }
// Reference counter for child temp Lob objects
inline unsigned int* TempLOBCount () { return &tempLobCount_; }
Oracledb* oracledb_;
private:
static NAN_METHOD(New);
// Execute Method on Connection class
static NAN_METHOD(Execute);
static void Async_Execute (uv_work_t *req);
static void Async_AfterExecute (uv_work_t *req);
// Release Method on Connection class
static NAN_METHOD(Release);
static void Async_Release(uv_work_t *req);
static void Async_AfterRelease (uv_work_t *req);
// Commit Method on Connection class
static NAN_METHOD(Commit);
static void Async_Commit (uv_work_t *req);
static void Async_AfterCommit (uv_work_t *req);
// Rollback Method on Connection class
static NAN_METHOD(Rollback);
static void Async_Rollback (uv_work_t *req);
static void Async_AfterRollback (uv_work_t *req);
// BreakMethod on Connection class
static NAN_METHOD(Break);
static void Async_Break(uv_work_t *req);
static void Async_AfterBreak (uv_work_t *req);
// CreateLob Method on Connection class
static NAN_METHOD(CreateLob);
static void Async_CreateLob(uv_work_t *req);
static void Async_AfterCreateLob (uv_work_t *req);
// Define Getter Accessors to properties
static NAN_GETTER(GetStmtCacheSize);
static NAN_GETTER(GetClientId);
static NAN_GETTER(GetModule);
static NAN_GETTER(GetAction);
static NAN_GETTER(GetOracleServerVersion);
// Define Setter Accessors to properties
static NAN_SETTER(SetStmtCacheSize);
static NAN_SETTER(SetClientId);
static NAN_SETTER(SetModule);
static NAN_SETTER(SetAction);
static NAN_SETTER(SetOracleServerVersion);
static void connectionPropertyException(Connection* njsConn,
NJSErrorType errType,
string property);
// Define Connection Constructor
Connection ();
~Connection ();
static void PrepareAndBind (eBaton* executeBaton);
static void ConvertStringOrBuffer2LOB ( eBaton* executeBaton,
unsigned int index );
static void String2CLOB ( eBaton* executeBaton, unsigned int index );
static void Buffer2BLOB ( eBaton* executeBaton, unsigned int index );
static void StringOrBuffer2LOB ( eBaton* executeBaton, unsigned int index,
unsigned char lobType );
static void Descr2StringOrBuffer ( eBaton* executeBaton );
static void CLOB2String ( eBaton* executeBaton, unsigned int index );
static void BLOB2Buffer ( eBaton* executeBaton, unsigned int index );
static void LOB2StringOrBuffer ( eBaton* executeBaton, unsigned int index,
unsigned long long byteAmount,
unsigned long long charAmount );
static void PrepareLOBsForBind ( eBaton* executeBaton, unsigned int index );
static unsigned short SourceDBType2TargetDBType ( unsigned srcType );
static boolean MapByName ( eBaton *executeBaton,
std::string &name,
unsigned short &targetType);
static boolean MapByType ( eBaton *executeBaton, unsigned short &targetType);
static unsigned short GetTargetType ( eBaton *executeBaton,
std::string &name,
unsigned short defaultType);
static void ProcessBinds (Nan::NAN_METHOD_ARGS_TYPE args, unsigned int index,
eBaton* executeBaton);
static void ProcessOptions (Nan::NAN_METHOD_ARGS_TYPE args, unsigned int index,
eBaton* executeBaton);
static void ProcessCallback (Nan::NAN_METHOD_ARGS_TYPE args, unsigned int index,
eBaton* executeBaton);
static void GetExecuteBaton (Nan::NAN_METHOD_ARGS_TYPE args, eBaton* executeBaton);
static void GetOptions (Handle<Object> options, eBaton* executeBaton);
static void GetBinds (Handle<Object> bindobj, eBaton* executeBaton);
static void GetBinds (Handle<Array> bindarray, eBaton* executeBaton);
static void GetBindUnit (Local<Value> bindtypes, Bind* bind, bool array,
eBaton* executeBaton);
static void GetInBindParams(Local<Value> v8val, Bind *bind, eBaton *executeBaton);
static void GetInBindParamsScalar(Local<Value> v8val, Bind *bind, eBaton *executeBaton);
static void GetInBindParamsArray(Local<Array> v8vals, Bind *bind, eBaton *executeBaton);
static bool AllocateBindArray(unsigned short dataType, Bind* bind, eBaton *executeBaton, size_t *arrayElementSize);
static void GetOutBindParams (unsigned short dataType, Bind* bind,
eBaton* executeBaton);
static NJSErrorType Descr2Double ( Define* defines, unsigned int numCols,
unsigned int rowsFetched, bool getRS );
static void Descr2protoILob ( eBaton *executeBaton, unsigned int numCols,
unsigned int rowsFetched );
static v8::Local<v8::Value> GetOutBinds (eBaton* executeBaton);
static v8::Local<v8::Value> GetOutBindArray (eBaton* executeBaton);
static v8::Local<v8::Value> GetOutBindObject (eBaton* executeBaton);
static v8::Local<v8::Value> ToV8ArrayValue (eBaton *executeBaton,
Bind *bind, unsigned long count);
// to convert DB value to v8::Value
static v8::Local<v8::Value> ToV8Value (eBaton *executeBaton,
bool isQuery,
unsigned int index,
unsigned int row = 0);
static v8::Local<v8::Value> Define2V8Value ( eBaton *executeBaton,
unsigned int col,
unsigned int row,
Define *define,
ExtDefine *extDefine );
static v8::Local<v8::Value> Bind2V8Value (
eBaton *executeBaton,
Bind *bind,
unsigned int row ) ;
// for refcursor
static v8::Local<v8::Value> RefCursor2V8Value ( eBaton *executeBaton,
Bind *bind,
ExtBind *extBinds );
// for lobs
static v8::Local<v8::Value> Lob2V8Value (eBaton *executeBaton,
Bind *bind);
static void UpdateDateValue ( eBaton *executeBaton, Bind *bind, unsigned int nRows );
static void v8Date2OraDate(v8::Local<v8::Value> val, Bind *bind);
static ConnectionBusyStatus getConnectionBusyStatus ( Connection *conn );
// Callback/Utility function used to allocate buffer(s) for Bind Structs
static void cbDynBufferAllocate ( void *ctx, bool dmlReturning,
unsigned int nRows,
unsigned int bndpos );
// Callback used in DML-Return SQL statements to
// identify block of memeory for each row.
static int cbDynBufferGet ( void *ctx, DPI_SZ_TYPE nRows,
unsigned int bndpos,
unsigned long iter, unsigned long index,
void **bufpp, void **alenpp, void **indpp,
unsigned short **rcode, unsigned char *piecep );
// Callback used in CLOB-as-STRING/BLOB-as-BUFFER scenarios to dynamically
// allocate memory for each row (in chunks) of this column.
static int cbDynDefine ( void *ctx, unsigned int iter,
void **bufpp, unsigned int **alenpp,
void **indpp, unsigned short **rcodepp );
// Callback used in DML-Return SQL statements to
// identify block of memeory for each row.
static int cbNullInBind ( void *ctx, DPI_SZ_TYPE nRows,
unsigned int bndpos,
unsigned long iter, unsigned long index,
void **bufpp, void **alenpp, void **indpp,
unsigned short **rcode, unsigned char *piecep );
// NewLob Method on Connection class
static v8::Local<v8::Value> NewLob( eBaton* executeBaton,
ProtoILob *protoILob,
bool isAutoCloseLob = true );
/*
* Inline function to identify v8 type from given v8::value
*/
static inline ValueType GetValueType ( v8::Local<v8::Value> v )
{
ValueType type = NJS_VALUETYPE_INVALID;
if ( v->IsUndefined () || v->IsNull () )
{
type = NJS_VALUETYPE_NULL;
}
else if ( v->IsString () )
{
type = NJS_VALUETYPE_STRING;
}
else if ( v->IsInt32 () )
{
type = NJS_VALUETYPE_INTEGER;
}
else if ( v->IsUint32 () )
{
type = NJS_VALUETYPE_UINTEGER;
}
else if ( v->IsNumber () )
{
type = NJS_VALUETYPE_NUMBER;
}
else if ( v->IsDate () )
{
type = NJS_VALUETYPE_DATE;
}
else if ( v->IsObject () )
{
type = NJS_VALUETYPE_OBJECT;
}
return type;
}
/*
* large-value for PL/SQL procedure use tempLob if underling column type
* is LOB, whether to use that feature for this bind or not
*/
static inline bool IsValue2TempLob ( eBaton *executeBaton,
unsigned int index )
{
bool ret = false;
Bind *bind = executeBaton->binds[index];
if ( !bind->isOut && !bind->isInOut ) // IN Bind case
{
// for non-NULL values with provided value len > threshold
if ( ( * ( bind-> ind ) != -1 ) &&
( * ( bind-> len ) > NJS_THRESHOLD_SIZE_PLSQL_STRING_ARG ) )
ret = true;
}
else if ( bind->isOut && !bind->isInOut ) // OUT Bind case
{
// Expected size is greater than threshold
if ( bind -> maxSize > NJS_THRESHOLD_SIZE_PLSQL_STRING_ARG )
{
ret = true;
}
}
else if ( bind->isInOut )
{
// For INOUT bind, either the given value len or expected size is
// greater than threshold
if ( max ( ( DPI_SZ_TYPE ) *( bind->len ), bind->maxSize ) >
NJS_THRESHOLD_SIZE_PLSQL_STRING_ARG )
{
ret = true;
}
}
return ret;
}
dpi::Conn* dpiconn_;
bool isValid_;
unsigned int oracleServerVersion_;
/*
* Counters to see whether connection is busy or not with LOB, ResultSet or
* DB operations. This counters used to prevent releasing busy connection.
*/
unsigned int lobCount_; // LOB operations counter
unsigned int rsCount_; // ResultSet operations counter
unsigned int dbCount_; // Connection or DB operations counter
unsigned int tempLobCount_;// temp LOB counter
Nan::Persistent<Object> jsParent_;
};
#endif /** __NJSCONNECTION_H__ **/

File diff suppressed because it is too large Load Diff

View File

@ -1,266 +0,0 @@
/* Copyright (c) 2015, 2016, 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.
*
* This file uses NAN:
*
* Copyright (c) 2015 NAN contributors
*
* NAN contributors listed at https://github.com/rvagg/nan#contributors
*
* Permission is hereby granted, free of charge, to any person obtaining
* a copy of this software and associated documentation files (the
* "Software"), to deal in the Software without restriction, including
* without limitation the rights to use, copy, modify, merge, publish,
* distribute, sublicense, and/or sell copies of the Software, and to
* permit persons to whom the Software is furnished to do so, subject to
* the following conditions:
*
* The above copyright notice and this permission notice shall be
* included in all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
* NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
* LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
* OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
* WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
*
* NAME
* njsILob.h
*
* DESCRIPTION
* ILob class
* ProtoILob class
*
******************************************************************************/
#ifndef __NJSILOB_H__
#define __NJSILOB_H__
#include <node.h>
#include <string>
#include <vector>
#include "dpi.h"
#include "njsUtils.h"
#include "njsOracle.h"
#include "njsConnection.h"
using namespace v8;
using namespace node;
using namespace dpi;
class ILob;
/**
* Baton for Asynchronous ILob methods
**/
typedef struct LobBaton
{
uv_work_t req;
std::string error;
dpi::Env *dpienv;
dpi::Conn *dpiconn;
ILob *iLob;
char *writebuf;
unsigned long long writelen;
RefCounter counter;
bool errOnActiveOrInvalid;
Nan::Persistent<Function> cb;
Nan::Persistent<Object> lobbuf;
Nan::Persistent<Object> jsLob;
LobBaton( unsigned int& count, Local<Function> callback,
Local<Object> jsLobObj ):
error(""), dpienv(NULL), dpiconn(NULL), iLob(NULL), writebuf(NULL),
writelen(0), counter( count ), errOnActiveOrInvalid(false)
{
cb.Reset( callback );
jsLob.Reset ( jsLobObj );
}
LobBaton( unsigned int& count, Local<Object> buffer_obj,
Local<Function> callback, Local<Object> jsLobObj ):
error(""), dpienv(NULL), dpiconn(NULL), iLob(NULL), writebuf(NULL),
writelen(0), counter( count ), errOnActiveOrInvalid(false)
{
cb.Reset( callback );
lobbuf.Reset(buffer_obj);
jsLob.Reset ( jsLobObj );
}
~LobBaton ()
{
cb.Reset();
lobbuf.Reset();
jsLob.Reset ();
}
} LobBaton;
/******************************************************************************
*
* This is a helper class for ILob's contents to be mostly created in the
* worker thread. Basically, the ProtoILob class is needed to create the
* attributes of the ILob object in the worker thread as there may be some
* issues in creating the ILob object itself in the worker thread. From
* earlier experience, the worker thread could not create JavaScript handles
* which is what an ILob object is.
*
* We want the ProtoILob to be created in the worker thread because it
* allocates the OCI error handle and make other OCI calls such as getting the
* Lob chunk size and Lob length.
*
* If we switch to one OCI error handle per thread using Thread Local Storage
* (TLS), and make getting of chunkSize and Lob length asynchronous calls
* (using the three step procedure where the OCI calls are done in the worker
* thread), then the ProtoILob will not be necessary.
*
******************************************************************************/
class ProtoILob
{
public:
friend class ILob;
ProtoILob(eBaton *executeBaton, Descriptor *lobLocator, unsigned short fetchType);
~ProtoILob();
private:
void cleanup();
Descriptor *lobLocator_;
unsigned short dpiLobType_;
DpiHandle *errh_;
unsigned int chunkSize_;
unsigned long long length_;
bool isTempLob_;
};
class ILob : public Nan::ObjectWrap
{
public:
void setILob ( eBaton *executeBaton, ProtoILob *protoILob,
bool tempLob );
/* Checks whether state and type are good for Bind and set the state to
* NJSBIND_ACTIVE. Check for temp LOB INOUT bind not supported
*/
NJSErrorType preBind ( Bind *bind );
/*
* In case of BIND_INOUT, create a duplicate LOB locator and in case of
* BIND_IN initialize the LOB locator
*/
void doBind ( Bind *bind );
// Process LOB for BIND_IN or BIND_INOUT after passing it to the bind call
void postBind ();
static bool hasILobInstance ( Local<Object> obj );
// Define ILob Constructor
static Nan::Persistent<FunctionTemplate> iLobTemplate_s;
static void Init(Handle<Object> target);
void cleanupDPI ();
void cleanupNJS ();
private:
ILob();
~ILob();
inline NJSErrorType getErrNumber ( bool processBind );
static NAN_METHOD(New);
static NAN_METHOD(Release);
static NAN_METHOD(Close);
static void Async_Close(uv_work_t *req);
static void Async_AfterClose (uv_work_t *req);
static void lobPropertyException(ILob *iLob, NJSErrorType err,
string property);
// Getters for properties
static NAN_GETTER(GetChunkSize);
static NAN_GETTER(GetLength);
static NAN_GETTER(GetPieceSize);
static NAN_GETTER(GetOffset);
static NAN_GETTER(GetType);
static NAN_GETTER(GetIsAutoCloseLob);
static NAN_GETTER(GetIsValid);
// Setters for properties
static NAN_SETTER(SetChunkSize);
static NAN_SETTER(SetLength);
static NAN_SETTER(SetPieceSize);
static NAN_SETTER(SetOffset);
static NAN_SETTER(SetType);
static NAN_SETTER(SetIsAutoCloseLob);
static NAN_SETTER(SetIsValid);
// Read Method on ILob class
static NAN_METHOD(Read);
static void Async_Read (uv_work_t *req);
static void Async_AfterRead (uv_work_t *req);
// Write Method on ILob class
static NAN_METHOD(Write);
static void Async_Write (uv_work_t *req);
static void Async_AfterWrite (uv_work_t *req);
Descriptor *lobLocator_;
unsigned short dpiLobType_;
Connection *njsconn_;
dpi::Conn *dpiconn_;
DpiHandle *svch_;
DpiHandle *errh_;
bool isValid_;
State state_;
char *buf_;
unsigned int bufSize_;
unsigned int chunkSize_;
unsigned long long length_;
unsigned long long offset_;
unsigned long amountRead_;
unsigned long long amountWritten_;
unsigned int njsLobType_;
bool isTempLob_;
unsigned int *tempLobCount_;
bool isAutoCloseLob_;
Nan::Persistent<Object> jsParent_;
};
#endif /** __NJSILOB_H__ **/

View File

@ -1,119 +0,0 @@
/* Copyright (c) 2015, 2016, 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
* njsMessages.cpp
*
* DESCRIPTION
* Static function composes a displayable (error) string with replacements
*
*****************************************************************************/
#include <stdio.h>
#include <stdarg.h>
#include <string>
using namespace std;
#include "njsMessages.h"
// Maximum buffer size to compose error message
#define NJS_MAX_ERROR_MSG_LEN 1024
static const char *errMsg[] =
{
"NJS-000: success", // errSuccess
"NJS-001: expected callback as last parameter", // errMissingCallback
"NJS-002: invalid pool", // errInvalidPool
"NJS-003: invalid connection", // errInvalidConnection
"NJS-004: invalid value for property %s", // errInvalidPropertyValue
"NJS-005: invalid value for parameter %d", // errInvalidParameterValue
"NJS-006: invalid type for parameter %d", // errInvalidParameterType
"NJS-007: invalid value for \"%s\" in parameter %d", // errInvalidPropertyValueInParam
"NJS-008: invalid type for \"%s\" in parameter %d", // errInvalidPropertyTypeInParam
"NJS-009: invalid number of parameters", // errInvalidNumberOfParameters
"NJS-010: unsupported data type in select list", // errUnsupportedDatType
"NJS-011: encountered bind value and type mismatch in parameter %d", // errBindValueAndTypeMismatch
"NJS-012: encountered invalid bind data type in parameter %d", // errInvalidBindDataType
"NJS-013: invalid bind direction", // errInvalidBindDirection
"NJS-014: %s is a read-only property", // errReadOnly
"NJS-015: type was not specified for conversion", // errNoTypeForConversion
"NJS-016: buffer is too small for OUT binds", // errInsufficientBufferForBinds
"NJS-017: concurrent operations on ResultSet are not allowed", // errBusyResultSet
"NJS-018: invalid ResultSet", // errInvalidResultSet
"NJS-019: ResultSet cannot be returned for non-query statements", // errInvalidNonQueryExecution
"NJS-020: empty array was specified to fetch values as string", // errEmptyArrayForFetchAs
"NJS-021: invalid type for conversion specified", // errInvalidTypeForConversion
"NJS-022: invalid Lob", // errInvalidLob
"NJS-023: concurrent operations on a Lob are not allowed", // errBusyLob
"NJS-024: memory allocation failed", // errInsufficientMemory
"NJS-025: overflow when calculating the result area size", // errResultsTooLarge
"NJS-026: maxRows must be greater than zero", // errInvalidmaxRows
"NJS-027: unexpected SQL parsing error", // errSQLSyntaxError
"NJS-028: RAW database type is not supported with DML Returning statements", // errBufferReturningInvalid
"NJS-029: invalid object from JavaScript", // errInvalidJSObject
"NJS-030: connection cannot be released because Lob operations are in progress", // errBusyConnLOB
"NJS-031: connection cannot be released because ResultSet operations are in progress", // errBusyConnRS
"NJS-032: connection cannot be released because a database call is in progress", // errBusyConnDB
"NJS-033: an internal error occurred. [%s][%s]", // errInternalError
"NJS-034: data type is unsupported for array bind", // errInvalidTypeForArrayBind
"NJS-035: maxArraySize is required for IN OUT array bind", // errReqdMaxArraySize
"NJS-036: given array is of size greater than maxArraySize", // errInvalidArraySize
"NJS-037: invalid data type at array index %d for bind \"%s\"", // errIncompatibleTypeArrayBind
"NJS-038: maxArraySize value should be greater than zero", // errInvalidValueArrayBind
"NJS-039: empty array is not allowed for IN bind", // errEmptyArray
"NJS-040: connection request timeout", // errConnRequestTimeout
"NJS-041: cannot convert ResultSet to QueryStream after invoking methods", // errCannotConvertRsToStream
"NJS-042: cannot invoke ResultSet methods after converting to QueryStream", // errCannotInvokeRsMethods
"NJS-043: ResultSet already converted to QueryStream", // errResultSetAlreadyConverted
"NJS-044: named JSON object is not expected in this context", // errNamedJSON
"NJS-045: cannot load the oracledb add-on binary", // errCannotLoadBinary
"NJS-046: pool alias \"%s\" already exists in the connection pool cache", // errPoolWithAliasAlreadyExists
"NJS-047: pool alias \"%s\" not found in the connection pool cache", // errPoolWithAliasNotFound
"NJS-048: operation not permitted while Lob object is active in a bind operation", // errLOBBindActive
"NJS-049: Temporary LOBs were open when the connection was closed", // errBusyConnTEMPLOB
"NJS-050: data must be shorter than %d", // errBindValueTooLarge
"NJS-051: \"%s\" must be less than %d", // errMaxValueTooLarge
"NJS-052: invalid data type at array index %d for bind position %d", // errIncompatibleTypeArrayIndexBind
};
string NJSMessages::getErrorMsg ( NJSErrorType err, ... )
{
char msg[NJS_MAX_ERROR_MSG_LEN + 1]; // buffer to get formatted/substituted error msg
va_list vlist; // variable argument list
std::string str;
if ( err > 0 && err < errMaxErrors )
{
// print all specified arguments
va_start (vlist, err);
if ( vsnprintf (msg, NJS_MAX_ERROR_MSG_LEN, errMsg[err], vlist) <= 0)
{
msg[0] = 0;
}
va_end (vlist);
str = msg;
}
return str;
}
//end of NJSMessages.cpp

View File

@ -1,106 +0,0 @@
/* Copyright (c) 2015, 2016, 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
* njsMessages.h
*
* DESCRIPTION
* Error message consolidation and composing
* All error messages are stored in variable now and is displayed after
* any substitution. These messages can be exported to a text file for
* localization later
*
*****************************************************************************/
#ifndef __NJSMESSAGES_H__
#define __NJSMESSAGES_H__
#include <string>
using namespace std;
typedef enum
{
errSuccess = 0,
errMissingCallback,
errInvalidPool,
errInvalidConnection,
errInvalidPropertyValue,
errInvalidParameterValue,
errInvalidParameterType,
errInvalidPropertyValueInParam,
errInvalidPropertyTypeInParam,
errInvalidNumberOfParameters,
errUnsupportedDatType,
errBindValueAndTypeMismatch,
errInvalidBindDataType,
errInvalidBindDirection,
errReadOnly,
errNoTypeForConversion,
errInsufficientBufferForBinds,
errBusyResultSet,
errInvalidResultSet,
errInvalidNonQueryExecution,
errEmptyArrayForFetchAs,
errInvalidTypeForConversion,
errInvalidLob,
errBusyLob,
errInsufficientMemory,
errResultsTooLarge,
errInvalidmaxRows,
errSQLSyntaxError,
errBufferReturningInvalid,
errInvalidJSObject,
errBusyConnLOB,
errBusyConnRS,
errBusyConnDB,
errInternalError,
errInvalidTypeForArrayBind,
errReqdMaxArraySize,
errInvalidArraySize,
errIncompatibleTypeArrayBind,
errInvalidValueArrayBind,
errEmptyArray,
errConnRequestTimeout,
errCannotConvertRsToStream,
errCannotInvokeRsMethods,
errResultSetAlreadyConverted,
errNamedJSON,
errCannotLoadBinary,
errPoolWithAliasAlreadyExists,
errPoolWithAliasNotFound,
errLOBBindActive,
errBusyConnTEMPLOB,
errBindValueTooLarge,
errMaxValueTooLarge,
errIncompatibleTypeArrayIndexBind,
// New ones should be added here
errMaxErrors // Max # of errors plus one
} NJSErrorType;
class NJSMessages
{
public:
static string getErrorMsg ( NJSErrorType err, ... );
};
#endif /* __NJSMESSAGES_H__ */

File diff suppressed because it is too large Load Diff

View File

@ -1,252 +0,0 @@
/* Copyright (c) 2015, 2017, 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.
*
* This file uses NAN:
*
* Copyright (c) 2015 NAN contributors
*
* NAN contributors listed at https://github.com/rvagg/nan#contributors
*
* Permission is hereby granted, free of charge, to any person obtaining
* a copy of this software and associated documentation files (the
* "Software"), to deal in the Software without restriction, including
* without limitation the rights to use, copy, modify, merge, publish,
* distribute, sublicense, and/or sell copies of the Software, and to
* permit persons to whom the Software is furnished to do so, subject to
* the following conditions:
*
* The above copyright notice and this permission notice shall be
* included in all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
* NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
* LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
* OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
* WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
*
* NAME
* njsOracle.h
*
* DESCRIPTION
* Oracledb class
*
*****************************************************************************/
#ifndef __NJSORACLE_H__
#define __NJSORACLE_H__
#include <v8.h>
#include <node.h>
#include "nan.h"
#include <string>
#include <cstring>
#include <stdlib.h>
#include <stdio.h>
#include "dpi.h"
#include "njsUtils.h"
using namespace node;
using namespace v8;
/* Keep the version in sync with package.json */
#define NJS_NODE_ORACLEDB_MAJOR 1
#define NJS_NODE_ORACLEDB_MINOR 13
#define NJS_NODE_ORACLEDB_PATCH 1
/* Used for Oracledb.version */
#define NJS_NODE_ORACLEDB_VERSION ( (NJS_NODE_ORACLEDB_MAJOR * 10000) + \
(NJS_NODE_ORACLEDB_MINOR * 100) + \
(NJS_NODE_ORACLEDB_PATCH) )
class Oracledb: public Nan::ObjectWrap
{
public:
Nan::Persistent<Object> jsOracledb;
// Oracledb class
static void Init(Handle<Object> target);
dpi::Env* getDpiEnv () const { return dpienv_; }
bool getAutoCommit () const { return autoCommit_; }
unsigned int getOutFormat () const { return outFormat_; }
unsigned int getMaxRows () const { return maxRows_; }
unsigned int getStmtCacheSize () const { return stmtCacheSize_; }
unsigned int getPoolMin () const { return poolMin_; }
unsigned int getPoolMax () const { return poolMax_; }
unsigned int getPoolIncrement () const { return poolIncrement_; }
unsigned int getPoolTimeout () const { return poolTimeout_; }
unsigned int getPrefetchRows () const { return prefetchRows_; }
const std::string& getConnectionClass () const { return connClass_; }
bool getExtendedMetaData () const { return extendedMetaData_;}
const DataType* getFetchAsStringTypes () const;
unsigned int getFetchAsStringTypesCount () const
{ return fetchAsStringTypesCount_ ; }
const DataType* getFetchAsBufferTypes () const ;
unsigned int getFetchAsBufferTypesCount () const
{ return fetchAsBufferTypesCount_ ; }
private:
const string driverName() const;
// Define Oracledb Constructor
static Nan::Persistent<FunctionTemplate> oracledbTemplate_s;
static NAN_METHOD(New);
// Get Connection Methods
static NAN_METHOD(GetConnection);
static void Async_GetConnection(uv_work_t *req);
static void Async_AfterGetConnection(uv_work_t *req);
// Create Pool Methods
static NAN_METHOD(CreatePool);
static void Async_CreatePool (uv_work_t *req );
static void Async_AfterCreatePool (uv_work_t *req);
// Define Getter Accessors to Properties
static NAN_GETTER(GetPoolMin);
static NAN_GETTER(GetPoolMax);
static NAN_GETTER(GetPoolIncrement);
static NAN_GETTER(GetPoolTimeout);
static NAN_GETTER(GetStmtCacheSize);
static NAN_GETTER(GetAutoCommit);
static NAN_GETTER(GetExtendedMetaData);
static NAN_GETTER(GetMaxRows);
static NAN_GETTER(GetOutFormat);
static NAN_GETTER(GetVersion);
static NAN_GETTER(GetConnectionClass);
static NAN_GETTER(GetExternalAuth);
static NAN_GETTER(GetPrefetchRows);
static NAN_GETTER(GetFetchAsString);
static NAN_GETTER(GetFetchAsBuffer);
static NAN_GETTER(GetLobPrefetchSize);
static NAN_GETTER(GetOracleClientVersion);
static NAN_GETTER(GetPoolPingInterval);
// Define Setter Accessors to Properties
static NAN_SETTER(SetPoolMin);
static NAN_SETTER(SetPoolMax);
static NAN_SETTER(SetPoolIncrement);
static NAN_SETTER(SetPoolTimeout);
static NAN_SETTER(SetStmtCacheSize);
static NAN_SETTER(SetAutoCommit);
static NAN_SETTER(SetExtendedMetaData);
static NAN_SETTER(SetMaxRows);
static NAN_SETTER(SetOutFormat);
static NAN_SETTER(SetVersion);
static NAN_SETTER(SetConnectionClass);
static NAN_SETTER(SetExternalAuth);
static NAN_SETTER(SetPrefetchRows);
static NAN_SETTER(SetFetchAsString);
static NAN_SETTER(SetFetchAsBuffer);
static NAN_SETTER(SetLobPrefetchSize);
static NAN_SETTER(SetOracleClientVersion);
static NAN_SETTER(SetPoolPingInterval);
Oracledb();
~Oracledb();
dpi::Env* dpienv_;
unsigned int outFormat_;
bool autoCommit_;
bool extendedMetaData_;
unsigned int maxRows_;
unsigned int stmtCacheSize_;
unsigned int prefetchRows_;
unsigned int poolMin_;
unsigned int poolMax_;
unsigned int poolIncrement_;
unsigned int poolTimeout_;
std::string connClass_;
bool externalAuth_;
DataType *fetchAsStringTypes_;
unsigned int fetchAsStringTypesCount_;
DataType *fetchAsBufferTypes_;
unsigned int fetchAsBufferTypesCount_;
unsigned int lobPrefetchSize_;
unsigned int oraClientVer_;
int poolPingInterval_;
};
/**
* Baton for Asynchronous Get Connection Call
**/
class Pool;
typedef struct connectionBaton
{
uv_work_t req;
std::string user;
std::string pswrd;
std::string connStr;
std::string connClass;
bool externalAuth;
std::string error;
int poolMax;
int poolMin;
int poolIncrement;
int poolTimeout;
int stmtCacheSize;
unsigned int lobPrefetchSize;
unsigned int maxRows;
unsigned int outFormat;
int poolPingInterval;
Nan::Persistent<Function> cb;
dpi::Env* dpienv;
dpi::Conn* dpiconn;
dpi::SPool* dpipool;
Nan::Persistent<Object> jsOradb;
Oracledb *oracledb;
connectionBaton( Local<Function> callback, Local<Object> jsOradbObj ) :
user(""), pswrd(""), connStr(""), connClass(""),
externalAuth(false), error(""),
poolMax(0), poolMin(0), poolIncrement(0),
poolTimeout(0), stmtCacheSize(0), maxRows(0),
outFormat(0), poolPingInterval(DPI_NO_PING_INTERVAL),
dpienv(NULL), dpiconn(NULL), dpipool(NULL)
{
cb.Reset( callback );
jsOradb.Reset ( jsOradbObj );
}
~connectionBaton()
{
cb.Reset();
jsOradb.Reset ();
}
}connectionBaton;
#endif /* __NJSORACLE_H__ */

View File

@ -1,700 +0,0 @@
/* Copyright (c) 2015, 2016, 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.
*
* This file uses NAN:
*
* Copyright (c) 2015 NAN contributors
*
* NAN contributors listed at https://github.com/rvagg/nan#contributors
*
* Permission is hereby granted, free of charge, to any person obtaining
* a copy of this software and associated documentation files (the
* "Software"), to deal in the Software without restriction, including
* without limitation the rights to use, copy, modify, merge, publish,
* distribute, sublicense, and/or sell copies of the Software, and to
* permit persons to whom the Software is furnished to do so, subject to
* the following conditions:
*
* The above copyright notice and this permission notice shall be
* included in all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
* NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
* LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
* OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
* WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
*
* NAME
* njsPool.cpp
*
* DESCRIPTION
* Pool class implementation.
*
*****************************************************************************/
#include "node.h"
#include <string>
#include "njsOracle.h"
#include "njsPool.h"
#include "njsConnection.h"
#include "njsUtils.h"
using namespace std;
using namespace node;
using namespace v8;
//peristent Pool class handle
Nan::Persistent<FunctionTemplate> Pool::poolTemplate_s;
Pool::Pool(){}
Pool::~Pool(){}
/*****************************************************************************/
/*
DESCRIPTION
Store the config in pool instance.
*/
void Pool::setPool( dpi::SPool *dpipool, Oracledb* oracledb,
unsigned int poolMax, unsigned int poolMin,
unsigned int poolIncrement, unsigned int poolTimeout,
unsigned stmtCacheSize, unsigned int lobPrefetchSize,
int pingInterval, Local<Object> jsOradb )
{
this->dpipool_ = dpipool;
this->isValid_ = true;
this->oracledb_ = oracledb;
this->poolMax_ = poolMax;
this->poolMin_ = poolMin;
this->poolIncrement_ = poolIncrement;
this->poolTimeout_ = poolTimeout;
this->stmtCacheSize_ = stmtCacheSize;
this->lobPrefetchSize_ = lobPrefetchSize;
this->pingInterval_ = pingInterval;
this->jsParent_.Reset ( jsOradb );
}
/*****************************************************************************/
/*
DESCRIPTION
Init function of the Pool class.
Initiates and maps the functions and properties of Pool class.
*/
void Pool::Init(Handle<Object> target)
{
Nan::HandleScope scope;
Local<FunctionTemplate> temp = Nan::New<FunctionTemplate>(New);
temp->InstanceTemplate()->SetInternalFieldCount(1);
temp->SetClassName(Nan::New<v8::String>("Pool").ToLocalChecked());
Nan::SetPrototypeMethod(temp, "terminate", Terminate);
Nan::SetPrototypeMethod(temp, "getConnection", GetConnection);
Nan::SetAccessor(temp->InstanceTemplate(),
Nan::New<v8::String>("poolMax").ToLocalChecked(),
Pool::GetPoolMax,
Pool::SetPoolMax );
Nan::SetAccessor(temp->InstanceTemplate(),
Nan::New<v8::String>("poolMin").ToLocalChecked(),
Pool::GetPoolMin,
Pool::SetPoolMin );
Nan::SetAccessor(temp->InstanceTemplate(),
Nan::New<v8::String>("poolIncrement").ToLocalChecked(),
Pool::GetPoolIncrement,
Pool::SetPoolIncrement );
Nan::SetAccessor(temp->InstanceTemplate(),
Nan::New<v8::String>("poolTimeout").ToLocalChecked(),
Pool::GetPoolTimeout,
Pool::SetPoolTimeout );
Nan::SetAccessor(temp->InstanceTemplate(),
Nan::New<v8::String>("connectionsOpen").ToLocalChecked(),
Pool::GetConnectionsOpen,
Pool::SetConnectionsOpen );
Nan::SetAccessor(temp->InstanceTemplate(),
Nan::New<v8::String>("connectionsInUse").ToLocalChecked(),
Pool::GetConnectionsInUse,
Pool::SetConnectionsInUse );
Nan::SetAccessor(temp->InstanceTemplate(),
Nan::New<v8::String>("stmtCacheSize").ToLocalChecked(),
Pool::GetStmtCacheSize,
Pool::SetStmtCacheSize );
Nan::SetAccessor(temp->InstanceTemplate(),
Nan::New<v8::String>("poolPingInterval").ToLocalChecked(),
Pool::GetPoolPingInterval,
Pool::SetPoolPingInterval );
poolTemplate_s.Reset( temp );
Nan::Set(target, Nan::New<v8::String>("Pool").ToLocalChecked(),
temp->GetFunction());
}
/*****************************************************************************/
/*
DESCRIPTION
Invoked when new of pool is called from JS
*/
NAN_METHOD(Pool::New)
{
Pool *njsPool = new Pool();
njsPool->Wrap(info.Holder());
info.GetReturnValue().Set(info.Holder());
}
/*****************************************************************************/
/*
DESCRIPTION
Abstraction to all getter accessors of properties
*/
Local<Primitive> Pool::getPoolProperty(Pool* njsPool, unsigned int poolProperty)
{
Nan::EscapableHandleScope scope;
if(!njsPool->isValid_)
{
string msg = NJSMessages::getErrorMsg(errInvalidPool);
NJS_SET_EXCEPTION ( msg.c_str() );
return scope.Escape ( Nan::Undefined() ) ;
}
else
{
return scope.Escape ( Nan::New<v8::Integer>(poolProperty) ) ;
}
return scope.Escape ( Nan::Undefined() ) ;
}
/*****************************************************************************/
/*
DESCRIPTION
Abstraction to all getter accessors of properties
*/
Local<Primitive> Pool::getPoolProperty(Pool* njsPool, int poolProperty)
{
Nan::EscapableHandleScope scope;
if(!njsPool->isValid_)
{
string msg = NJSMessages::getErrorMsg(errInvalidPool);
NJS_SET_EXCEPTION ( msg.c_str() );
return scope.Escape ( Nan::Undefined() ) ;
}
else
{
return scope.Escape ( Nan::New<v8::Integer>(poolProperty) ) ;
}
return scope.Escape ( Nan::Undefined() ) ;
}
/*****************************************************************************/
/*
DESCRIPTION
Get Accessor of poolMin Property
*/
NAN_GETTER(Pool::GetPoolMin)
{
Pool* njsPool = Nan::ObjectWrap::Unwrap<Pool>(info.Holder());
NJS_CHECK_OBJECT_VALID2(njsPool, info);
info.GetReturnValue().Set(getPoolProperty( njsPool, njsPool->poolMin_));
}
/*****************************************************************************/
/*
DESCRIPTION
Get Accessor of poolMax Property
*/
NAN_GETTER(Pool::GetPoolMax)
{
Pool* njsPool = Nan::ObjectWrap::Unwrap<Pool>(info.Holder());
NJS_CHECK_OBJECT_VALID2(njsPool, info);
info.GetReturnValue().Set(getPoolProperty( njsPool, njsPool->poolMax_));
}
/*****************************************************************************/
/*
DESCRIPTION
Get Accessor of poolIncrement Property
*/
NAN_GETTER(Pool::GetPoolIncrement)
{
Pool* njsPool = Nan::ObjectWrap::Unwrap<Pool>(info.Holder());
NJS_CHECK_OBJECT_VALID2(njsPool, info);
info.GetReturnValue().Set(getPoolProperty( njsPool, njsPool->poolIncrement_));
}
/*****************************************************************************/
/*
DESCRIPTION
Get Accessor of poolTimeout Property
*/
NAN_GETTER(Pool::GetPoolTimeout)
{
Pool* njsPool = Nan::ObjectWrap::Unwrap<Pool>(info.Holder());
NJS_CHECK_OBJECT_VALID2(njsPool, info);
info.GetReturnValue().Set(getPoolProperty( njsPool, njsPool->poolTimeout_));
}
/*****************************************************************************/
/*
DESCRIPTION
Get Accessor of connectionsOpen Property
*/
NAN_GETTER(Pool::GetConnectionsOpen)
{
Pool* njsPool = Nan::ObjectWrap::Unwrap<Pool>(info.Holder());
NJS_CHECK_OBJECT_VALID2(njsPool, info);
if(!njsPool->isValid_)
{
string msg = NJSMessages::getErrorMsg(errInvalidPool);
NJS_SET_EXCEPTION ( msg.c_str() );
info.GetReturnValue().SetUndefined();
return;
}
try
{
info.GetReturnValue().Set(njsPool->dpipool_->connectionsOpen());
return;
}
catch(dpi::Exception &e)
{
NJS_SET_CONN_ERR_STATUS ( e.errnum(), NULL );
NJS_SET_EXCEPTION ( e.what() );
}
info.GetReturnValue().SetUndefined();
}
/*****************************************************************************/
/*
DESCRIPTION
Get Accessor of connectionsInUse Property
*/
NAN_GETTER(Pool::GetConnectionsInUse)
{
Pool* njsPool = Nan::ObjectWrap::Unwrap<Pool>(info.Holder());
NJS_CHECK_OBJECT_VALID2(njsPool, info);
if(!njsPool->isValid_)
{
string error = NJSMessages::getErrorMsg ( errInvalidPool );
NJS_SET_EXCEPTION ( error.c_str() );
info.GetReturnValue().SetUndefined();
return;
}
try
{
info.GetReturnValue().Set(njsPool->dpipool_->connectionsInUse());
return;
}
catch(dpi::Exception &e)
{
NJS_SET_CONN_ERR_STATUS ( e.errnum(), NULL );
NJS_SET_EXCEPTION ( e.what() );
}
info.GetReturnValue().SetUndefined();
}
/*****************************************************************************/
/*
DESCRIPTION
Get Accessor of stmtCacheSize Property
*/
NAN_GETTER(Pool::GetStmtCacheSize)
{
Pool* njsPool = Nan::ObjectWrap::Unwrap<Pool>(info.Holder());
NJS_CHECK_OBJECT_VALID2(njsPool, info);
info.GetReturnValue().Set(getPoolProperty( njsPool, njsPool->stmtCacheSize_));
}
/*****************************************************************************/
/*
DESCRIPTION
GetAccessor of poolPingInterval property
*/
NAN_GETTER(Pool::GetPoolPingInterval)
{
Pool *njsPool = Nan::ObjectWrap::Unwrap<Pool>( info.Holder() );
NJS_CHECK_OBJECT_VALID2(njsPool, info ) ;
info.GetReturnValue().Set(getPoolProperty (njsPool,
njsPool->pingInterval_));
}
/*****************************************************************************/
/*
DESCRIPTION
Abstraction to all setter accessors of properties
*/
void Pool::setPoolProperty (Pool* njsPool, string property)
{
Nan::HandleScope scope;
NJS_CHECK_OBJECT_VALID(njsPool);
string msg;
if(!njsPool->isValid_)
msg = NJSMessages::getErrorMsg(errInvalidPool);
else
msg = NJSMessages::getErrorMsg(errReadOnly, property.c_str());
NJS_SET_EXCEPTION ( msg.c_str() );
}
/*****************************************************************************/
/*
DESCRIPTION
Set Accessor of poolMin Property - throws error
*/
NAN_SETTER(Pool::SetPoolMin)
{
setPoolProperty(Nan::ObjectWrap::Unwrap<Pool>(info.Holder()), "poolMin");
}
/*****************************************************************************/
/*
DESCRIPTION
Set Accessor of poolMax Property - throws error
*/
NAN_SETTER(Pool::SetPoolMax)
{
setPoolProperty(Nan::ObjectWrap::Unwrap<Pool>(info.Holder()), "poolMax");
}
/*****************************************************************************/
/*
DESCRIPTION
Set Accessor of poolIncrement Property - throws error
*/
NAN_SETTER(Pool::SetPoolIncrement)
{
setPoolProperty(Nan::ObjectWrap::Unwrap<Pool>(info.Holder()), "poolIncrement");
}
/*****************************************************************************/
/*
DESCRIPTION
Set Accessor of poolTimeout Property - throws error
*/
NAN_SETTER(Pool::SetPoolTimeout)
{
setPoolProperty(Nan::ObjectWrap::Unwrap<Pool>(info.Holder()), "poolTimeout");
}
/*****************************************************************************/
/*
DESCRIPTION
Set Accessor of connectionsOpen Property - throws error
*/
NAN_SETTER(Pool::SetConnectionsOpen)
{
setPoolProperty(Nan::ObjectWrap::Unwrap<Pool>(info.Holder()), "connectionsOpen");
}
/*****************************************************************************/
/*
DESCRIPTION
Set Accessor of connectionsInUse Property - throws error
*/
NAN_SETTER(Pool::SetConnectionsInUse)
{
setPoolProperty(Nan::ObjectWrap::Unwrap<Pool>(info.Holder()), "connectionsInUse");
}
/*****************************************************************************/
/*
DESCRIPTION
Set Accessor of stmtCacheSize Property - throws error
*/
NAN_SETTER(Pool::SetStmtCacheSize)
{
setPoolProperty(Nan::ObjectWrap::Unwrap<Pool>(info.Holder()),
"stmtCacheSize");
}
/*****************************************************************************/
/*
DESCRIPTION
Set Accessor of poolPingInterval property.
*/
NAN_SETTER(Pool::SetPoolPingInterval)
{
setPoolProperty ( Nan::ObjectWrap::Unwrap<Pool>(info.Holder()),
"poolPingInterval" );
}
/*****************************************************************************/
/*
DESCRIPTION
Get Connection method on Pool class.
PARAMETERS:
Arguments - Callback
*/
NAN_METHOD(Pool::GetConnection)
{
Local<Function> callback;
NJS_GET_CALLBACK ( callback, info );
Pool *njsPool = Nan::ObjectWrap::Unwrap<Pool>(info.Holder());
poolBaton *connBaton = new poolBaton ( callback, info.Holder() );
NJS_CHECK_OBJECT_VALID3 ( njsPool, connBaton->error, exitGetConnection);
NJS_CHECK_NUMBER_OF_ARGS ( connBaton->error, info, 1, 1, exitGetConnection );
if(!njsPool->isValid_)
{
connBaton->error = NJSMessages::getErrorMsg ( errInvalidPool );
goto exitGetConnection;
}
connBaton->njspool = njsPool;
connBaton->connClass = njsPool->oracledb_->getConnectionClass ();
connBaton->lobPrefetchSize = njsPool->lobPrefetchSize_;
exitGetConnection:
connBaton->req.data = (void *)connBaton;
int status = uv_queue_work(uv_default_loop(), &connBaton->req,
Async_GetConnection,
(uv_after_work_cb)Async_AfterGetConnection);
// delete the Baton if uv_queue_work fails
if ( status )
{
delete connBaton;
string error = NJSMessages::getErrorMsg ( errInternalError,
"uv_queue_work",
"GetConnection" );
NJS_SET_EXCEPTION ( error.c_str() );
}
info.GetReturnValue().SetUndefined();
}
/*****************************************************************************/
/*
DESCRIPTION
Worker function of Get Connection method
PARAMETERS:
UV queue work block
NOTES:
DPI call execution.
*/
void Pool::Async_GetConnection(uv_work_t *req)
{
poolBaton *connBaton = (poolBaton *)req->data;
if(!(connBaton->error).empty()) goto exitAsyncGetConnection;
try
{
connBaton->dpiconn = connBaton-> njspool -> dpipool_ ->
getConnection ( connBaton-> connClass );
connBaton->dpiconn->lobPrefetchSize(connBaton->lobPrefetchSize);
}
catch (dpi::Exception &e)
{
NJS_SET_CONN_ERR_STATUS ( e.errnum(), NULL );
connBaton->error = std::string (e.what());
}
exitAsyncGetConnection:
;
}
/*****************************************************************************/
/*
DESCRIPTION
Callback function of Get Connection method
PARAMETERS:
UV queue work block
status - expected to be non-zero.
NOTES:
Connection handle is formed and handed over to JS.
*/
void Pool::Async_AfterGetConnection(uv_work_t *req)
{
Nan::HandleScope scope;
poolBaton *connBaton = (poolBaton*)req->data;
Nan::TryCatch tc;
Local<Value> argv[2];
if(!(connBaton->error).empty())
{
argv[0] = v8::Exception::Error(
Nan::New<v8::String>(connBaton->error).ToLocalChecked());
argv[1] = Nan::Undefined();
}
else
{
argv[0] = Nan::Undefined();
Local<Object> connection = Nan::NewInstance (
Local<Function>::Cast (
Nan::GetFunction (
Nan::New<FunctionTemplate> (
Connection::connectionTemplate_s )).ToLocalChecked () )).ToLocalChecked ();
(Nan::ObjectWrap::Unwrap<Connection> (connection))->
setConnection( connBaton->dpiconn,
connBaton->njspool->oracledb_,
Nan::New( connBaton->jsPool ) );
argv[1] = connection;
}
Local<Function> callback = Nan::New<Function>(connBaton->cb);
delete connBaton;
Nan::MakeCallback( Nan::GetCurrentContext()->Global(),
callback, 2, argv );
if(tc.HasCaught())
{
Nan::FatalException(tc);
}
}
/*****************************************************************************/
/*
DESCRIPTION
Terminate method
PARAMETERS:
Arguments - Callback
*/
NAN_METHOD(Pool::Terminate)
{
Local<Function> callback;
NJS_GET_CALLBACK ( callback, info );
Pool *njsPool = Nan::ObjectWrap::Unwrap<Pool>(info.Holder());
poolBaton *terminateBaton = new poolBaton ( callback, info.Holder() );
NJS_CHECK_OBJECT_VALID3 (njsPool, terminateBaton->error, exitTerminate);
NJS_CHECK_NUMBER_OF_ARGS ( terminateBaton->error, info, 1, 1, exitTerminate );
if(!njsPool->isValid_)
{
terminateBaton->error = NJSMessages::getErrorMsg( errInvalidPool );
goto exitTerminate;
}
terminateBaton->njspool = njsPool;
exitTerminate:
terminateBaton->req.data = (void *)terminateBaton;
int status = uv_queue_work(uv_default_loop(), &terminateBaton->req,
Async_Terminate,
(uv_after_work_cb)Async_AfterTerminate);
// delete the Baton if uv_queue_work fails
if ( status )
{
delete terminateBaton;
string error = NJSMessages::getErrorMsg ( errInternalError,
"uv_queue_work", "Terminate" );
NJS_SET_EXCEPTION ( error.c_str() );
}
info.GetReturnValue().SetUndefined();
}
/*****************************************************************************/
/*
DESCRIPTION
Worker function of terminate.
PARAMETERS:
UV queue work block
NOTES:
DPI call execution.
*/
void Pool::Async_Terminate(uv_work_t *req)
{
poolBaton *terminateBaton = (poolBaton*)req->data;
if(!terminateBaton->error.empty()) goto exitAsyncTerminate;
try
{
terminateBaton-> njspool-> dpipool_-> terminate ();
}
catch(dpi::Exception& e)
{
NJS_SET_CONN_ERR_STATUS ( e.errnum(), NULL );
terminateBaton->error = std::string(e.what());
}
exitAsyncTerminate:
;
}
/*****************************************************************************/
/*
DESCRIPTION
Callback function of terminate
PARAMETERS:
UV queue work block
*/
void Pool::Async_AfterTerminate(uv_work_t *req)
{
Nan::HandleScope scope;
poolBaton *terminateBaton = (poolBaton*)req->data;
Nan::TryCatch tc;
Local<Value> argv[1];
if(!(terminateBaton->error).empty())
{
argv[0] = v8::Exception::Error(
Nan::New<v8::String>(terminateBaton->error).ToLocalChecked());
}
else
{
argv[0] = Nan::Undefined();
// pool is not valid after terminate succeeds.
terminateBaton-> njspool-> isValid_ = false;
}
/*
* When we release the iLob, we have to clear the reference of
* its parent.
*/
terminateBaton->njspool->jsParent_.Reset ();
Local<Function> callback = Nan::New<Function>(terminateBaton->cb);
delete terminateBaton;
Nan::MakeCallback( Nan::GetCurrentContext()->Global(),
callback, 1, argv );
if(tc.HasCaught())
{
Nan::FatalException(tc);
}
}
/* end of file njsPool.cpp */

View File

@ -1,163 +0,0 @@
/* Copyright (c) 2015, 2016, 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.
*
* This file uses NAN:
*
* Copyright (c) 2015 NAN contributors
*
* NAN contributors listed at https://github.com/rvagg/nan#contributors
*
* Permission is hereby granted, free of charge, to any person obtaining
* a copy of this software and associated documentation files (the
* "Software"), to deal in the Software without restriction, including
* without limitation the rights to use, copy, modify, merge, publish,
* distribute, sublicense, and/or sell copies of the Software, and to
* permit persons to whom the Software is furnished to do so, subject to
* the following conditions:
*
* The above copyright notice and this permission notice shall be
* included in all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
* NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
* LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
* OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
* WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
*
* NAME
* njsPool.h
*
* DESCRIPTION
* Pool class
*
*****************************************************************************/
#ifndef __NJSPOOL_H__
#define __NJSPOOL_H__
#include "dpi.h"
#include <node.h>
#include "nan.h"
#include <string>
using namespace v8;
using namespace node;
class Pool: public Nan::ObjectWrap {
public:
static void Init(Handle<Object> target);
void setPool ( dpi::SPool *, Oracledb* oracledb, unsigned int poolMax,
unsigned int poolMin, unsigned int poolIncrement,
unsigned int poolTimeout, unsigned stmtCacheSize,
unsigned int lobPrefetchSize, int pingInterval,
Local<Object> jsOraDB );
// Define Pool Constructor
static Nan::Persistent<FunctionTemplate> poolTemplate_s ;
private:
static NAN_METHOD(New);
// Get Connection Methods
static NAN_METHOD(GetConnection);
static void Async_GetConnection(uv_work_t* req);
static void Async_AfterGetConnection(uv_work_t* req);
// Terminate Methods
static NAN_METHOD(Terminate);
static void Async_Terminate(uv_work_t* req);
static void Async_AfterTerminate(uv_work_t* req);
// Define Getter Accessors to properties
static NAN_GETTER(GetPoolMax);
static NAN_GETTER(GetPoolMin);
static NAN_GETTER(GetPoolIncrement);
static NAN_GETTER(GetPoolTimeout);
static NAN_GETTER(GetConnectionsOpen);
static NAN_GETTER(GetConnectionsInUse);
static NAN_GETTER(GetStmtCacheSize);
static NAN_GETTER(GetPoolPingInterval);
static Local<Primitive> getPoolProperty(Pool* njsPool,
unsigned int poolProperty);
static Local<Primitive> getPoolProperty(Pool* njsPool, int poolProperty);
// Define Setter Accessors to properties
static NAN_SETTER(SetPoolMax);
static NAN_SETTER(SetPoolMin);
static NAN_SETTER(SetPoolIncrement);
static NAN_SETTER(SetPoolTimeout);
static NAN_SETTER(SetConnectionsOpen);
static NAN_SETTER(SetConnectionsInUse);
static NAN_SETTER(SetStmtCacheSize);
static NAN_SETTER(SetPoolPingInterval);
static void setPoolProperty(Pool* njsPool, string property);
Pool();
~Pool();
dpi::SPool *dpipool_;
bool isValid_;
Oracledb* oracledb_;
unsigned int poolMin_;
unsigned int poolMax_;
unsigned int poolIncrement_;
unsigned int poolTimeout_;
unsigned int stmtCacheSize_;
unsigned int lobPrefetchSize_;
int pingInterval_;
Nan::Persistent<Object> jsParent_;
};
typedef struct poolBaton
{
uv_work_t req;
std::string error;
std::string connClass;
Nan::Persistent<Function> cb;
dpi::Conn* dpiconn;
Pool* njspool;
unsigned int lobPrefetchSize;
Nan::Persistent<Object> jsPool;
poolBaton( Local<Function> callback, Local<Object> poolObj ) :
error(""), connClass(""),
dpiconn(NULL), njspool(NULL), lobPrefetchSize(0)
{
cb.Reset( callback );
jsPool.Reset ( poolObj );
}
~poolBaton()
{
cb.Reset();
jsPool.Reset ();
}
}poolBaton;
#endif /* __NJSPOOL_H__ */

View File

@ -1,767 +0,0 @@
/* Copyright (c) 2015, 2017, 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.
*
* This file uses NAN:
*
* Copyright (c) 2015 NAN contributors
*
* NAN contributors listed at https://github.com/rvagg/nan#contributors
*
* Permission is hereby granted, free of charge, to any person obtaining
* a copy of this software and associated documentation files (the
* "Software"), to deal in the Software without restriction, including
* without limitation the rights to use, copy, modify, merge, publish,
* distribute, sublicense, and/or sell copies of the Software, and to
* permit persons to whom the Software is furnished to do so, subject to
* the following conditions:
*
* The above copyright notice and this permission notice shall be
* included in all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
* NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
* LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
* OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
* WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
*
* NAME
* njsResultSet.cpp
*
* DESCRIPTION
* ResultSet class implementation.
*
*****************************************************************************/
#include "node.h"
#include <string>
#include "njsResultSet.h"
#include "njsConnection.h"
#include <iostream>
using namespace std;
using namespace node;
using namespace v8;
//peristent ResultSet class handle
Nan::Persistent<FunctionTemplate> ResultSet::resultSetTemplate_s;
/*****************************************************************************/
/*
DESCRIPTION
Store the config in pool instance.
PARAMETERS
stmt - dpi statement
executeBaton - eBaton structure
numCols - number of columns
mInfo - an array of structs representing column info
*/
void ResultSet::setResultSet ( dpi::Stmt *stmt, eBaton *executeBaton,
const unsigned int numCols,
const MetaInfo *mInfo )
{
this->dpistmt_ = stmt;
this->dpienv_ = executeBaton->dpienv;
this->njsconn_ = executeBaton->njsconn;
this->numCols_ = numCols;
this->jsParent_.Reset ( executeBaton->jsConn );
/*
* stmt can be NULL in REFCURSOR case, when the stored procedure
* did not return a valid stmt handle
*/
this->state_ = ( stmt ) ? NJS_INACTIVE : NJS_INVALID;
this->outFormat_ = executeBaton->outFormat;
this->fetchRowCount_ = 0;
this->rsEmpty_ = false;
this->defineBuffers_ = NULL;
this->extDefines_.resize ( 0 ) ;
this->extendedMetaData_ = executeBaton->extendedMetaData;
this->mInfo_ = new MetaInfo [ this->numCols_ ];
if ( !this->mInfo_ )
{
executeBaton->error = NJSMessages::getErrorMsg ( errInsufficientMemory );
goto exitSetResultSet;
}
// In refCursor case mInfo can be NULL
if ( mInfo )
{
for ( unsigned int col = 0; col < this->numCols_; col++ )
{
this->mInfo_[col] = mInfo[col];
}
}
exitSetResultSet:
if ( !executeBaton->error.empty () )
{
if ( this->mInfo_ )
{
delete [] this -> mInfo_ ;
this -> mInfo_ = NULL ;
}
}
}
/*****************************************************************************/
/*
DESCRIPTION
Init function of the ResultSet class.
Initiates and maps the functions and properties of ResultSet class.
*/
void ResultSet::Init(Handle<Object> target)
{
Nan::HandleScope scope;
Local<FunctionTemplate> temp = Nan::New<FunctionTemplate>(New);
temp->InstanceTemplate()->SetInternalFieldCount(1);
temp->SetClassName(Nan::New<v8::String>("ResultSet").ToLocalChecked());
Nan::SetPrototypeMethod(temp, "close", Close);
Nan::SetPrototypeMethod(temp, "getRow", GetRow);
Nan::SetPrototypeMethod(temp, "getRows", GetRows);
Nan::SetAccessor(temp->InstanceTemplate(),
Nan::New<v8::String>("metaData").ToLocalChecked(),
ResultSet::GetMetaData,
ResultSet::SetMetaData );
resultSetTemplate_s.Reset( temp);
Nan::Set(target, Nan::New<v8::String>("ResultSet").ToLocalChecked(),
temp->GetFunction());
}
/*****************************************************************************/
/*
DESCRIPTION
Invoked when new of connection is called from JS
*/
NAN_METHOD(ResultSet::New)
{
ResultSet *resultSet = new ResultSet();
resultSet->Wrap(info.Holder());
info.GetReturnValue().Set(info.Holder());
}
/*****************************************************************************/
/*
DESCRIPTION
Get Accessor of metaData Property
*/
NAN_GETTER(ResultSet::GetMetaData)
{
ResultSet* njsResultSet = Nan::ObjectWrap::Unwrap<ResultSet>(info.Holder());
string msg;
NJS_CHECK_OBJECT_VALID2(njsResultSet, info);
if(!njsResultSet->njsconn_->isValid())
{
msg = NJSMessages::getErrorMsg ( errInvalidConnection );
NJS_SET_EXCEPTION ( msg.c_str() );
info.GetReturnValue().SetUndefined();
return;
}
else if(njsResultSet->state_ == NJS_INVALID)
{
msg = NJSMessages::getErrorMsg ( errInvalidResultSet );
NJS_SET_EXCEPTION ( msg.c_str() );
info.GetReturnValue().SetUndefined();
return;
}
Local<Value> meta = Connection::GetMetaData(
njsResultSet->mInfo_,
njsResultSet->numCols_,
njsResultSet->extendedMetaData_ );
info.GetReturnValue().Set(meta);
}
/*****************************************************************************/
/*
DESCRIPTION
Set Accessor of metaData Property - throws error
*/
NAN_SETTER(ResultSet::SetMetaData)
{
ResultSet* njsResultSet = Nan::ObjectWrap::Unwrap<ResultSet>(info.Holder());
string msg;
NJS_CHECK_OBJECT_VALID(njsResultSet);
if(!njsResultSet->njsconn_->isValid())
msg = NJSMessages::getErrorMsg ( errInvalidConnection );
else if(njsResultSet->state_ == NJS_INVALID)
msg = NJSMessages::getErrorMsg(errInvalidResultSet);
else
msg = NJSMessages::getErrorMsg(errReadOnly, "metaData");
NJS_SET_EXCEPTION ( msg.c_str() );
}
/*****************************************************************************/
/*
DESCRIPTION
Get Row method on Result Set class.
PARAMETERS:
info - callback
*/
NAN_METHOD(ResultSet::GetRow)
{
Local<Function> callback;
NJS_GET_CALLBACK ( callback, info );
ResultSet *njsResultSet = Nan::ObjectWrap::Unwrap<ResultSet>(info.Holder());
/* If njsResultSet is invalid from JS, then throw an exception */
NJS_CHECK_OBJECT_VALID2 ( njsResultSet, info );
Local<Object> jsConn = Nan::New ( njsResultSet->jsParent_ );
rsBaton *getRowsBaton = new rsBaton ( njsResultSet->njsconn_->RSCount (),
callback, info.Holder(), jsConn );
getRowsBaton->njsRS = njsResultSet;
if(njsResultSet->state_ == NJS_INVALID)
{
getRowsBaton->error = NJSMessages::getErrorMsg ( errInvalidResultSet );
// donot alter the state while exiting
getRowsBaton->errOnActiveOrInvalid = true;
goto exitGetRow;
}
if(njsResultSet->state_ == NJS_ACTIVE)
{
getRowsBaton->error = NJSMessages::getErrorMsg ( errBusyResultSet );
// donot alter the state while exiting
getRowsBaton->errOnActiveOrInvalid = true;
goto exitGetRow;
}
njsResultSet->state_ = NJS_ACTIVE;
NJS_CHECK_NUMBER_OF_ARGS ( getRowsBaton->error, info, 1, 1, exitGetRow );
getRowsBaton->numRows = 1;
exitGetRow:
ResultSet::GetRowsCommon(getRowsBaton);
info.GetReturnValue().SetUndefined();
}
/*****************************************************************************/
/*
DESCRIPTION
Get Rows method on Result Set class.
PARAMETERS:
info - numRows, callback
*/
NAN_METHOD(ResultSet::GetRows)
{
Local<Function> callback;
NJS_GET_CALLBACK ( callback, info );
ResultSet *njsResultSet = Nan::ObjectWrap::Unwrap<ResultSet>(info.Holder());
/* If njsResultSet is invalid from JS, then throw an exception */
NJS_CHECK_OBJECT_VALID2 ( njsResultSet, info );
Local<Object> jsConn = Nan::New ( njsResultSet->jsParent_ );
rsBaton *getRowsBaton = new rsBaton ( njsResultSet->njsconn_->RSCount (),
callback, info.Holder(), jsConn );
getRowsBaton->njsRS = njsResultSet;
if(njsResultSet->state_ == NJS_INVALID)
{
getRowsBaton->error = NJSMessages::getErrorMsg ( errInvalidResultSet );
// donot alter the state while exiting
getRowsBaton->errOnActiveOrInvalid = true;
goto exitGetRows;
}
else if(njsResultSet->state_ == NJS_ACTIVE)
{
getRowsBaton->error = NJSMessages::getErrorMsg ( errBusyResultSet );
// donot alter the state while exiting
getRowsBaton->errOnActiveOrInvalid = true;
goto exitGetRows;
}
njsResultSet->state_ = NJS_ACTIVE;
NJS_CHECK_NUMBER_OF_ARGS ( getRowsBaton->error, info, 2, 2, exitGetRows );
NJS_GET_ARG_V8UINT ( getRowsBaton->numRows, getRowsBaton->error,
info, 0, exitGetRows );
if(!getRowsBaton->numRows)
{
getRowsBaton->error = NJSMessages::getErrorMsg (
errInvalidParameterValue, 1);
goto exitGetRows;
}
getRowsBaton->fetchMultiple = true;
exitGetRows:
ResultSet::GetRowsCommon(getRowsBaton);
info.GetReturnValue().SetUndefined();
}
/*****************************************************************************/
/*
DESCRIPTION
Common method for GetRow and GetRows method
PARAMETERS:
getRowsBaton - resultset baton
*/
void ResultSet::GetRowsCommon(rsBaton *getRowsBaton)
{
ResultSet *njsRS;
eBaton *ebaton;
if(!(getRowsBaton->error).empty()) goto exitGetRowsCommon;
if(!getRowsBaton->njsRS->njsconn_->isValid())
{
getRowsBaton->error = NJSMessages::getErrorMsg ( errInvalidConnection );
goto exitGetRowsCommon;
}
ebaton = getRowsBaton->ebaton;
njsRS = getRowsBaton->njsRS;
ebaton->maxRows = getRowsBaton->numRows;
ebaton->dpistmt = njsRS->dpistmt_;
ebaton->getRS = true;
ebaton->dpienv = njsRS->njsconn_->oracledb_->getDpiEnv();
ebaton->outFormat = njsRS->outFormat_;
ebaton->njsconn = njsRS->njsconn_;
ebaton->dpiconn = njsRS->njsconn_->getDpiConn();
ebaton->numCols = njsRS->numCols_;
ebaton->mInfo = njsRS->mInfo_;
exitGetRowsCommon:
getRowsBaton->req.data = (void *)getRowsBaton;
int status = uv_queue_work(uv_default_loop(), &getRowsBaton->req,
Async_GetRows, (uv_after_work_cb)Async_AfterGetRows);
// delete the Baton if uv_queue_work fails
if ( status )
{
delete getRowsBaton;
string error = NJSMessages::getErrorMsg ( errInternalError,
"uv_queue_work",
"GetRowsCommon" );
NJS_SET_EXCEPTION ( error.c_str() );
}
}
/*****************************************************************************/
/*
DESCRIPTION
Worker function of GetRows method
PARAMETERS:
req - UV queue work block
NOTES:
DPI call execution.
*/
void ResultSet::Async_GetRows(uv_work_t *req)
{
rsBaton *getRowsBaton = (rsBaton*)req->data;
ResultSet *njsRS = getRowsBaton->njsRS;
eBaton *ebaton = getRowsBaton->ebaton;
if(!(getRowsBaton->error).empty()) goto exitAsyncGetRows;
if(njsRS->rsEmpty_)
{
ebaton->rowsFetched = 0;
goto exitAsyncGetRows;
}
try
{
// Allocate if not already done, or need more buffer
if( !njsRS->defineBuffers_ ||
njsRS->fetchRowCount_ < getRowsBaton->numRows )
{
if( njsRS->defineBuffers_ )
{
njsRS -> clearFetchBuffer( njsRS->fetchRowCount_ );
}
Connection::DoDefines( ebaton );
if ( !ebaton->error.empty () )
{
getRowsBaton->error = ebaton->error;
goto exitAsyncGetRows;
}
njsRS->fetchRowCount_ = getRowsBaton->numRows;
njsRS->defineBuffers_ = ebaton->defines;
njsRS->extDefines_.resize ( ebaton->numCols, NULL ) ;
for ( unsigned int col = 0 ; col < ebaton->numCols ; col ++ )
{
njsRS->extDefines_[col] = ebaton->extDefines[col];
}
}
else
{
// Buffers are reused except for LOB columns
for (unsigned int col = 0; col < njsRS->numCols_; col++)
{
// In case of LOB column, descriptor would have been wrapped by
// ProtoILob & njsIntLob and set the element to NULL, so reallocate
switch( njsRS->mInfo_[col].dbType )
{
case dpi::DpiClob:
case dpi::DpiBlob:
case dpi::DpiBfile:
for (unsigned int j = 0; j < ebaton->maxRows; j++)
{
if ( !( ((Descriptor **)(njsRS->defineBuffers_[col].buf))[j] ) )
{
((Descriptor **)(njsRS->defineBuffers_[col].buf))[j] =
ebaton->dpienv->allocDescriptor(LobDescriptorType);
}
}
break;
default:
break;
}
}
}
ebaton->defines = njsRS->defineBuffers_;
ebaton->extDefines.resize ( ebaton->numCols, NULL ) ;
for ( unsigned int col = 0 ; col < ebaton->numCols ; col ++ )
{
ebaton->extDefines[col] = njsRS->extDefines_[col];
RESETEXTDEFINE4NEXTFETCH(ebaton->extDefines[col]);
}
Connection::DoFetch(ebaton);
if ( !ebaton->error.empty () )
{
getRowsBaton->error = ebaton->error;
goto exitAsyncGetRows;
}
if(ebaton->rowsFetched != getRowsBaton->numRows)
njsRS->rsEmpty_ = true;
}
catch (dpi::Exception &e)
{
NJS_SET_CONN_ERR_STATUS ( e.errnum(), njsRS->njsconn_->getDpiConn() );
getRowsBaton->error = std::string (e.what());
}
exitAsyncGetRows:
;
}
/*****************************************************************************/
/*
DESCRIPTION
Callback function of GetRows method
PARAMETERS:
req - UV queue work block
*/
void ResultSet::Async_AfterGetRows(uv_work_t *req)
{
Nan::HandleScope scope;
rsBaton *getRowsBaton = (rsBaton*)req->data;
Nan::TryCatch tc;
Local<Value> argv[2];
if(!(getRowsBaton->error).empty())
{
argv[0] = v8::Exception::Error(
Nan::New<v8::String>(getRowsBaton->error).ToLocalChecked());
argv[1] = Nan::Undefined();
}
else
{
argv[0] = Nan::Undefined();
eBaton* ebaton = getRowsBaton->ebaton;
ebaton->outFormat = getRowsBaton->njsRS->outFormat_;
Local<Value> rowsArray = Nan::New<v8::Array>(0),
rowsArrayValue = Nan::Null();
if(ebaton->rowsFetched)
{
rowsArray = Connection::GetRows(ebaton);
if(!(ebaton->error).empty())
{
argv[0] = v8::Exception::Error(
Nan::New<v8::String>(ebaton->error).ToLocalChecked());
argv[1] = Nan::Undefined();
goto exitAsyncAfterGetRows;
}
rowsArrayValue = Local<Array>::Cast(rowsArray)->Get(0);
}
argv[1] = (getRowsBaton->fetchMultiple) ? rowsArray : rowsArrayValue;
}
exitAsyncAfterGetRows:
if(!getRowsBaton->errOnActiveOrInvalid)
{
getRowsBaton->njsRS->state_ = NJS_INACTIVE;
}
Local<Function> callback = Nan::New(getRowsBaton->ebaton->cb);
delete getRowsBaton;
Nan::MakeCallback(Nan::GetCurrentContext()->Global(),
callback, 2, argv);
if(tc.HasCaught())
{
Nan::FatalException(tc);
}
}
/*****************************************************************************/
/*
DESCRIPTION
Close method
PARAMETERS:
info - Callback
*/
NAN_METHOD(ResultSet::Close)
{
Local<Function> callback;
NJS_GET_CALLBACK ( callback, info );
ResultSet *njsResultSet = Nan::ObjectWrap::Unwrap<ResultSet>(info.Holder());
/* If njsResultSet is invalid from JS, then throw an exception */
NJS_CHECK_OBJECT_VALID2 ( njsResultSet, info );
Local<Object> jsConn = Nan::New ( njsResultSet->jsParent_ );
rsBaton *closeBaton = new rsBaton ( njsResultSet->njsconn_->RSCount (),
callback, info.Holder(), jsConn );
closeBaton->njsRS = njsResultSet;
if(njsResultSet->state_ == NJS_INVALID)
{
closeBaton->error = NJSMessages::getErrorMsg ( errInvalidResultSet );
// donot alter the state while exiting
closeBaton->errOnActiveOrInvalid = true;
goto exitClose;
}
else if(njsResultSet->state_ == NJS_ACTIVE)
{
closeBaton->error = NJSMessages::getErrorMsg ( errBusyResultSet );
// donot alter the state while exiting
closeBaton->errOnActiveOrInvalid = true;
goto exitClose;
}
njsResultSet->state_ = NJS_ACTIVE;
NJS_CHECK_NUMBER_OF_ARGS ( closeBaton->error, info, 1, 1, exitClose );
if(!njsResultSet->njsconn_->isValid())
{
closeBaton->error = NJSMessages::getErrorMsg ( errInvalidConnection );
goto exitClose;
}
exitClose:
closeBaton->req.data = (void *)closeBaton;
int status = uv_queue_work(uv_default_loop(), &closeBaton->req,
Async_Close, (uv_after_work_cb)Async_AfterClose);
// delete the Baton if uv_queue_work fails
if ( status )
{
delete closeBaton;
string error = NJSMessages::getErrorMsg ( errInternalError,
"uv_queue_work",
"ResultSetClose" );
NJS_SET_EXCEPTION ( error.c_str() );
}
info.GetReturnValue().SetUndefined();
}
/*****************************************************************************/
/*
DESCRIPTION
Worker function of close.
PARAMETERS:
req - UV queue work block
NOTES:
DPI call execution.
*/
void ResultSet::Async_Close(uv_work_t *req)
{
rsBaton *closeBaton = (rsBaton*)req->data;
if(!closeBaton->error.empty()) goto exitAsyncClose;
try
{
closeBaton-> njsRS-> dpistmt_-> release ();
Define* defineBuffers = closeBaton-> njsRS-> defineBuffers_;
if(defineBuffers)
{
closeBaton -> njsRS -> clearFetchBuffer(
closeBaton-> njsRS-> fetchRowCount_);
}
if ( closeBaton-> njsRS-> mInfo_ )
{
delete [] closeBaton->njsRS->mInfo_;
closeBaton->njsRS->mInfo_ = NULL;
}
}
catch(dpi::Exception& e)
{
NJS_SET_CONN_ERR_STATUS ( e.errnum(),
closeBaton->njsRS->njsconn_->getDpiConn() );
closeBaton->error = std::string(e.what());
}
exitAsyncClose:
;
}
/*****************************************************************************/
/*
DESCRIPTION
Callback function of close
PARAMETERS:
req - UV queue work block
*/
void ResultSet::Async_AfterClose(uv_work_t *req)
{
Nan::HandleScope scope;
rsBaton *closeBaton = (rsBaton*)req->data;
Nan::TryCatch tc;
Local<Value> argv[1];
if(!(closeBaton->error).empty())
{
argv[0] = v8::Exception::Error(
Nan::New<v8::String>(closeBaton->error).ToLocalChecked());
if(!closeBaton->errOnActiveOrInvalid)
{
closeBaton->njsRS->state_ = NJS_INACTIVE;
}
}
else
{
argv[0] = Nan::Undefined();
// resultset is not valid after close succeeds.
closeBaton-> njsRS-> state_ = NJS_INVALID;
}
/*
* When we close the resultSet, we have to clear the reference of
* its parent.
*/
closeBaton->njsRS->jsParent_.Reset ();
Local<Function> callback = Nan::New(closeBaton->ebaton->cb);
delete closeBaton;
Nan::MakeCallback( Nan::GetCurrentContext()->Global(), callback, 1, argv );
if(tc.HasCaught())
{
Nan::FatalException(tc);
}
}
/*****************************************************************************/
/*
DESCRIPTION
Free FetchBuffers
PARAMETERS:
defineBuffers - Define bufferes from njsResultSet,
numCols - # of columns
*/
void ResultSet::clearFetchBuffer( unsigned int numRows )
{
for( unsigned int i=0; i<numCols_; i++ )
{
if ( defineBuffers_[i].dttmarr )
{
/* Date/Timestamp columns */
defineBuffers_[i].dttmarr->release ();
defineBuffers_[i].extbuf = NULL;
}
else if ( ( defineBuffers_[i].fetchType == DpiClob ) ||
( defineBuffers_[i].fetchType == DpiBlob ) ||
( defineBuffers_[i].fetchType == DpiBfile ) )
{
/* Lob columns */
for (unsigned int j = 0; j < numRows; j++)
{
if (((Descriptor **)(defineBuffers_[i].buf))[j])
{
Env::freeDescriptor(((Descriptor **)(defineBuffers_[i].buf))[j],
LobDescriptorType);
}
}
}
else if ( ( ( defineBuffers_[i].fetchType == dpi::DpiVarChar ) &&
( mInfo_[i].dbType == dpi::DpiClob ) ) ||
( ( defineBuffers_[i].fetchType == dpi::DpiRaw ) &&
( mInfo_[i].dbType == dpi::DpiBlob ) ) )
{
/* CLOB-as-STRING or BLOB-as-BUFFER case */
for ( unsigned int j = 0 ; j < numRows ; j ++ )
{
if ( ( (char **)defineBuffers_[i].buf)[j] )
{
free ( ( (char **)defineBuffers_[i].buf)[j] );
( ( char **)defineBuffers_[i].buf)[j] = NULL ;
}
}
}
free(defineBuffers_[i].buf);
free(defineBuffers_[i].len);
free(defineBuffers_[i].ind);
if ( extDefines_[i] &&
extDefines_[i]->extDefType == NJS_EXTDEFINE_CONVERT_LOB )
{
free ( extDefines_[i]->fields.extConvertLob.ctx ) ;
free ( extDefines_[i]->fields.extConvertLob.len2 ) ;
delete ( extDefines_[i] );
}
extDefines_.resize ( 0 ) ;
}
delete [] defineBuffers_;
defineBuffers_ = NULL;
extDefines_.clear ();
}
/* end of file njsPool.cpp */

View File

@ -1,160 +0,0 @@
/* Copyright (c) 2015, 2016, 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.
*
* This file uses NAN:
*
* Copyright (c) 2015 NAN contributors
*
* NAN contributors listed at https://github.com/rvagg/nan#contributors
*
* Permission is hereby granted, free of charge, to any person obtaining
* a copy of this software and associated documentation files (the
* "Software"), to deal in the Software without restriction, including
* without limitation the rights to use, copy, modify, merge, publish,
* distribute, sublicense, and/or sell copies of the Software, and to
* permit persons to whom the Software is furnished to do so, subject to
* the following conditions:
*
* The above copyright notice and this permission notice shall be
* included in all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
* NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
* LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
* OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
* WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
*
* NAME
* njsResultSet.h
*
* DESCRIPTION
* ResultSet class
*
*****************************************************************************/
#ifndef __NJSRESULTSET_H__
#define __NJSRESULTSET_H__
#include "dpi.h"
#include <node.h>
#include "nan.h"
#include <v8.h>
#include <string>
#include "njsUtils.h"
#include "njsConnection.h"
using namespace v8;
using namespace node;
class ResultSet;
/**
* Baton for Asynchronous ResultSet methods
**/
typedef struct rsBaton
{
uv_work_t req;
std::string error;
bool fetchMultiple; // set for getRows() method.
bool errOnActiveOrInvalid;
// set if going to exit upon already
// active or invalid
eBaton *ebaton;
unsigned int numRows; // rows to be fetched.
ResultSet* njsRS; // resultset object.
Nan::Persistent<Object> jsRS;
rsBaton( unsigned int& count, Local<Function> callback,
Local<Object> jsRSObj, Local<Object> jsConn )
: error(""), fetchMultiple(false), errOnActiveOrInvalid(false),
numRows(0), njsRS(NULL)
{
jsRS.Reset ( jsRSObj );
ebaton = new eBaton( count, callback, jsConn );
}
~rsBaton()
{
jsRS.Reset ();
if(ebaton)
{
delete ebaton;
}
}
}rsBaton;
//ResultSet Class
class ResultSet: public Nan::ObjectWrap {
public:
ResultSet(){}
~ResultSet(){}
static void Init(Handle<Object> target);
void setResultSet ( dpi::Stmt *dpistmt, eBaton *executebaton,
const unsigned int numCols,
const MetaInfo *mInfo );
// Define ResultSet Constructor
static Nan::Persistent<FunctionTemplate> resultSetTemplate_s ;
private:
static NAN_METHOD(New);
// Get Rows Methods
static NAN_METHOD(GetRow);
static NAN_METHOD(GetRows);
static void Async_GetRows(uv_work_t *req);
static void Async_AfterGetRows(uv_work_t *req);
static void GetRowsCommon(rsBaton*);
// Close Methods
static NAN_METHOD(Close);
static void Async_Close(uv_work_t *req);
static void Async_AfterClose(uv_work_t *req);
// Define Getter Accessors to properties
static NAN_GETTER(GetMetaData);
// Define Setter Accessors to properties
static NAN_SETTER(SetMetaData);
void clearFetchBuffer( unsigned int numRows );
dpi::Stmt *dpistmt_;
dpi::Env *dpienv_;
Connection *njsconn_;
State state_;
bool rsEmpty_;
Define *defineBuffers_;
std::vector<ExtDefine*> extDefines_;
unsigned int numCols_;
unsigned int fetchRowCount_;
unsigned int outFormat_;
bool extendedMetaData_;
Nan::Persistent<Object> jsParent_;
MetaInfo *mInfo_;
};
#endif /* __NJSRESULTSET_H__ */

Some files were not shown because too many files have changed in this diff Show More