Merge branch 'dev-2.0'
This commit is contained in:
commit
33331413c5
|
@ -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.
|
|
@ -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?
|
||||
|
|
|
@ -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.
|
||||
|
||||
```
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -0,0 +1,3 @@
|
|||
[submodule "odpi"]
|
||||
path = odpi
|
||||
url = https://github.com/oracle/odpi
|
14
.npmignore
14
.npmignore
|
@ -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
|
||||
|
|
367
CHANGELOG.md
367
CHANGELOG.md
|
@ -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
1794
INSTALL.md
File diff suppressed because it is too large
Load Diff
139
README.md
139
README.md
|
@ -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
|
||||
|
|
119
binding.gyp
119
binding.gyp
|
@ -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
2549
doc/api.md
File diff suppressed because it is too large
Load Diff
|
@ -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
|
||||
```
|
|
@ -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();
|
||||
|
|
|
@ -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);
|
||||
});
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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); });
|
||||
};
|
||||
|
||||
|
|
|
@ -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);
|
||||
});
|
||||
};
|
||||
|
|
|
@ -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));
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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)
|
||||
|
|
|
@ -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)
|
||||
|
|
|
@ -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, "<=="); }
|
||||
|
|
|
@ -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) {
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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:
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
});
|
||||
};
|
||||
|
||||
|
|
|
@ -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) {
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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 }
|
||||
},
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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
|
||||
}
|
||||
});
|
||||
}
|
||||
|
|
|
@ -43,8 +43,7 @@ oracledb.getConnection(
|
|||
sql,
|
||||
[],
|
||||
{
|
||||
resultSet: true,
|
||||
prefetchRows: 25
|
||||
resultSet: true
|
||||
},
|
||||
function(err, result)
|
||||
{
|
||||
|
|
|
@ -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(
|
||||
{
|
||||
|
|
|
@ -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)
|
||||
|
|
|
@ -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)
|
||||
{
|
||||
|
|
|
@ -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)
|
||||
{
|
||||
|
|
|
@ -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);
|
||||
});
|
||||
};
|
|
@ -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) {
|
||||
|
|
|
@ -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);
|
||||
});
|
||||
|
|
|
@ -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) {
|
||||
|
|
|
@ -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) {
|
||||
|
|
|
@ -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:
|
||||
|
|
72
lib/lob.js
72
lib/lob.js
|
@ -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');
|
||||
}
|
||||
|
||||
|
|
111
lib/oracledb.js
111
lib/oracledb.js
|
@ -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
|
||||
|
|
|
@ -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');
|
||||
});
|
||||
}
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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'
|
||||
};
|
||||
|
|
|
@ -0,0 +1 @@
|
|||
Subproject commit 855c898044cc7be20de74da7d42392787dcf8d49
|
18
package.json
18
package.json
|
@ -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": [
|
||||
{
|
||||
|
|
|
@ -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
|
|
@ -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)
|
|
@ -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.
|
|
@ -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();
|
|
@ -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);
|
||||
});
|
|
@ -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();
|
|
@ -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"
|
||||
}
|
|
@ -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;
|
|
@ -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 */
|
|
@ -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 */
|
|
@ -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 */
|
|
@ -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
|
|
@ -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 */
|
|
@ -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 */
|
|
@ -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
|
|
@ -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 */
|
|
@ -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 */
|
|
@ -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 );
|
||||
}
|
|
@ -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 */
|
||||
|
|
@ -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 */
|
|
@ -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 */
|
|
@ -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_;
|
||||
|
||||
};
|
||||
|
||||
};
|
|
@ -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 */
|
||||
|
|
@ -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 */
|
||||
|
|
@ -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 */
|
|
@ -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 */
|
||||
|
|
@ -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 */
|
||||
|
|
@ -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 */
|
|
@ -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 */
|
|
@ -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 */
|
||||
|
|
@ -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 */
|
|
@ -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 */
|
|
@ -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 */
|
|
@ -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 */
|
||||
|
|
@ -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
|
@ -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
|
@ -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__ **/
|
|
@ -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
|
||||
|
|
@ -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
|
@ -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__ */
|
||||
|
||||
|
|
@ -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 */
|
||||
|
|
@ -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__ */
|
|
@ -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 */
|
||||
|
|
@ -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
Loading…
Reference in New Issue