oracledb 3.0.0 → 3.1.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +135 -8
- package/README.md +6 -4
- package/build/Release/oracledb-abi48-darwin-x64.node +0 -0
- package/build/Release/oracledb-abi48-darwin-x64.node-buildinfo.txt +1 -0
- package/build/Release/oracledb-abi48-linux-x64.node +0 -0
- package/build/Release/oracledb-abi48-linux-x64.node-buildinfo.txt +1 -0
- package/build/Release/oracledb-abi48-win32-x64.node +0 -0
- package/build/Release/oracledb-abi48-win32-x64.node-buildinfo.txt +1 -0
- package/build/Release/oracledb-abi57-darwin-x64.node +0 -0
- package/build/Release/oracledb-abi57-darwin-x64.node-buildinfo.txt +1 -0
- package/build/Release/oracledb-abi57-linux-x64.node +0 -0
- package/build/Release/oracledb-abi57-linux-x64.node-buildinfo.txt +1 -0
- package/build/Release/oracledb-abi57-win32-x64.node +0 -0
- package/build/Release/oracledb-abi57-win32-x64.node-buildinfo.txt +1 -0
- package/build/Release/oracledb-abi64-darwin-x64.node +0 -0
- package/build/Release/oracledb-abi64-darwin-x64.node-buildinfo.txt +1 -0
- package/build/Release/oracledb-abi64-linux-x64.node +0 -0
- package/build/Release/oracledb-abi64-linux-x64.node-buildinfo.txt +1 -0
- package/build/Release/oracledb-abi64-win32-x64.node +0 -0
- package/build/Release/oracledb-abi64-win32-x64.node-buildinfo.txt +1 -0
- package/build/Release/oracledb-abi67-darwin-x64.node +0 -0
- package/build/Release/oracledb-abi67-darwin-x64.node-buildinfo.txt +1 -0
- package/build/Release/oracledb-abi67-linux-x64.node +0 -0
- package/build/Release/oracledb-abi67-linux-x64.node-buildinfo.txt +1 -0
- package/build/Release/oracledb-abi67-win32-x64.node +0 -0
- package/build/Release/oracledb-abi67-win32-x64.node-buildinfo.txt +1 -0
- package/lib/connection.js +18 -4
- package/lib/oracledb.js +44 -92
- package/lib/pool.js +36 -2
- package/lib/sodaCollection.js +1 -1
- package/lib/sodaDatabase.js +1 -1
- package/lib/util.js +82 -5
- package/package/README.md +32 -101
- package/package/install.js +139 -0
- package/package/prunebinaries.js +51 -0
- package/package.json +4 -11
- package/binding.gyp +0 -162
- package/lib/rel.txt +0 -1
- package/odpi/.npmignore +0 -4
- package/odpi/LICENSE.md +0 -218
- package/odpi/README.md +0 -61
- package/odpi/embed/README.md +0 -4
- package/odpi/embed/dpi.c +0 -50
- package/odpi/include/dpi.h +0 -1748
- package/odpi/src/dpiConn.c +0 -2089
- package/odpi/src/dpiContext.c +0 -296
- package/odpi/src/dpiData.c +0 -797
- package/odpi/src/dpiDebug.c +0 -184
- package/odpi/src/dpiDeqOptions.c +0 -370
- package/odpi/src/dpiEnqOptions.c +0 -174
- package/odpi/src/dpiEnv.c +0 -189
- package/odpi/src/dpiError.c +0 -204
- package/odpi/src/dpiErrorMessages.h +0 -86
- package/odpi/src/dpiGen.c +0 -303
- package/odpi/src/dpiGlobal.c +0 -292
- package/odpi/src/dpiHandleList.c +0 -117
- package/odpi/src/dpiHandlePool.c +0 -118
- package/odpi/src/dpiImpl.h +0 -1707
- package/odpi/src/dpiLob.c +0 -506
- package/odpi/src/dpiMsgProps.c +0 -386
- package/odpi/src/dpiObject.c +0 -897
- package/odpi/src/dpiObjectAttr.c +0 -115
- package/odpi/src/dpiObjectType.c +0 -326
- package/odpi/src/dpiOci.c +0 -3527
- package/odpi/src/dpiOracleType.c +0 -492
- package/odpi/src/dpiPool.c +0 -549
- package/odpi/src/dpiRowid.c +0 -136
- package/odpi/src/dpiSodaColl.c +0 -685
- package/odpi/src/dpiSodaCollCursor.c +0 -143
- package/odpi/src/dpiSodaDb.c +0 -432
- package/odpi/src/dpiSodaDoc.c +0 -230
- package/odpi/src/dpiSodaDocCursor.c +0 -143
- package/odpi/src/dpiStmt.c +0 -1797
- package/odpi/src/dpiSubscr.c +0 -674
- package/odpi/src/dpiUtils.c +0 -410
- package/odpi/src/dpiVar.c +0 -1794
- package/package/MAKEPKG.BAT +0 -156
- package/package/Makefile +0 -85
- package/package/createpackage.js +0 -186
- package/package/extractpackage.js +0 -76
- package/package/getversion.js +0 -37
- package/package/oracledbinstall.js +0 -497
- package/package/package.json +0 -54
- package/package/util.js +0 -286
- package/src/njsCommon.cpp +0 -1055
- package/src/njsCommon.h +0 -484
- package/src/njsConnection.cpp +0 -2926
- package/src/njsConnection.h +0 -227
- package/src/njsIntLob.cpp +0 -618
- package/src/njsIntLob.h +0 -179
- package/src/njsMessages.cpp +0 -122
- package/src/njsMessages.h +0 -118
- package/src/njsOracle.cpp +0 -1274
- package/src/njsOracle.h +0 -237
- package/src/njsPool.cpp +0 -482
- package/src/njsPool.h +0 -132
- package/src/njsResultSet.cpp +0 -478
- package/src/njsResultSet.h +0 -120
- package/src/njsSodaCollection.cpp +0 -507
- package/src/njsSodaCollection.h +0 -128
- package/src/njsSodaDatabase.cpp +0 -335
- package/src/njsSodaDatabase.h +0 -108
- package/src/njsSodaDocCursor.cpp +0 -203
- package/src/njsSodaDocCursor.h +0 -94
- package/src/njsSodaDocument.cpp +0 -412
- package/src/njsSodaDocument.h +0 -105
- package/src/njsSodaOperation.cpp +0 -557
- package/src/njsSodaOperation.h +0 -123
- package/src/njsSubscription.cpp +0 -388
- package/src/njsSubscription.h +0 -111
- package/src/njsUtils.cpp +0 -158
- package/src/njsUtils.h +0 -68
package/src/njsConnection.cpp
DELETED
|
@@ -1,2926 +0,0 @@
|
|
|
1
|
-
/* Copyright (c) 2015, 2018, Oracle and/or its affiliates.
|
|
2
|
-
All rights reserved. */
|
|
3
|
-
|
|
4
|
-
/******************************************************************************
|
|
5
|
-
*
|
|
6
|
-
* You may not use the identified files except in compliance with the Apache
|
|
7
|
-
* License, Version 2.0 (the "License.")
|
|
8
|
-
*
|
|
9
|
-
* You may obtain a copy of the License at
|
|
10
|
-
* http://www.apache.org/licenses/LICENSE-2.0.
|
|
11
|
-
*
|
|
12
|
-
* Unless required by applicable law or agreed to in writing, software
|
|
13
|
-
* distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
|
|
14
|
-
* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
15
|
-
*
|
|
16
|
-
* See the License for the specific language governing permissions and
|
|
17
|
-
* limitations under the License.
|
|
18
|
-
*
|
|
19
|
-
* This file uses NAN:
|
|
20
|
-
*
|
|
21
|
-
* Copyright (c) 2015 NAN contributors
|
|
22
|
-
*
|
|
23
|
-
* NAN contributors listed at https://github.com/rvagg/nan#contributors
|
|
24
|
-
*
|
|
25
|
-
* Permission is hereby granted, free of charge, to any person obtaining
|
|
26
|
-
* a copy of this software and associated documentation files (the
|
|
27
|
-
* "Software"), to deal in the Software without restriction, including
|
|
28
|
-
* without limitation the rights to use, copy, modify, merge, publish,
|
|
29
|
-
* distribute, sublicense, and/or sell copies of the Software, and to
|
|
30
|
-
* permit persons to whom the Software is furnished to do so, subject to
|
|
31
|
-
* the following conditions:
|
|
32
|
-
*
|
|
33
|
-
* The above copyright notice and this permission notice shall be
|
|
34
|
-
* included in all copies or substantial portions of the Software.
|
|
35
|
-
*
|
|
36
|
-
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
|
37
|
-
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
|
38
|
-
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
|
39
|
-
* NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
|
|
40
|
-
* LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
|
|
41
|
-
* OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
|
|
42
|
-
* WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
|
43
|
-
*
|
|
44
|
-
* NAME
|
|
45
|
-
* njsConnection.cpp
|
|
46
|
-
*
|
|
47
|
-
* DESCRIPTION
|
|
48
|
-
* Connection class implementation.
|
|
49
|
-
*
|
|
50
|
-
*****************************************************************************/
|
|
51
|
-
|
|
52
|
-
#include "njsConnection.h"
|
|
53
|
-
#include "njsResultSet.h"
|
|
54
|
-
#include "njsSubscription.h"
|
|
55
|
-
#include "njsIntLob.h"
|
|
56
|
-
#include "njsSodaDatabase.h"
|
|
57
|
-
#include <stdlib.h>
|
|
58
|
-
#include <limits>
|
|
59
|
-
|
|
60
|
-
using namespace std;
|
|
61
|
-
|
|
62
|
-
// persistent Connection class handle
|
|
63
|
-
Nan::Persistent<FunctionTemplate> njsConnection::connectionTemplate_s;
|
|
64
|
-
|
|
65
|
-
// default value for bind option maxSize
|
|
66
|
-
#define NJS_MAX_OUT_BIND_SIZE 200
|
|
67
|
-
|
|
68
|
-
// max number of bytes for data converted to string with fetchAsString or fetchInfo
|
|
69
|
-
#define NJS_MAX_FETCH_AS_STRING_SIZE 200
|
|
70
|
-
|
|
71
|
-
//-----------------------------------------------------------------------------
|
|
72
|
-
// njsConnection::Init()
|
|
73
|
-
// Initialization function of Connection class. Maps functions and properties
|
|
74
|
-
// from JS to C++.
|
|
75
|
-
//-----------------------------------------------------------------------------
|
|
76
|
-
void njsConnection::Init(Local<Object> target)
|
|
77
|
-
{
|
|
78
|
-
Nan::HandleScope scope;
|
|
79
|
-
Local<FunctionTemplate> tpl = Nan::New<FunctionTemplate>(New);
|
|
80
|
-
|
|
81
|
-
tpl->InstanceTemplate()->SetInternalFieldCount(1);
|
|
82
|
-
tpl->SetClassName(Nan::New<v8::String>("Connection").ToLocalChecked());
|
|
83
|
-
|
|
84
|
-
Nan::SetPrototypeMethod(tpl, "execute", Execute);
|
|
85
|
-
Nan::SetPrototypeMethod(tpl, "executeMany", ExecuteMany);
|
|
86
|
-
Nan::SetPrototypeMethod(tpl, "getStatementInfo", GetStatementInfo);
|
|
87
|
-
Nan::SetPrototypeMethod(tpl, "close", Close);
|
|
88
|
-
Nan::SetPrototypeMethod(tpl, "commit", Commit);
|
|
89
|
-
Nan::SetPrototypeMethod(tpl, "rollback", Rollback);
|
|
90
|
-
Nan::SetPrototypeMethod(tpl, "break", Break);
|
|
91
|
-
Nan::SetPrototypeMethod(tpl, "createLob", CreateLob);
|
|
92
|
-
Nan::SetPrototypeMethod(tpl, "changePassword", ChangePassword);
|
|
93
|
-
Nan::SetPrototypeMethod(tpl, "ping", Ping);
|
|
94
|
-
Nan::SetPrototypeMethod(tpl, "subscribe", Subscribe);
|
|
95
|
-
Nan::SetPrototypeMethod(tpl, "unsubscribe", Unsubscribe);
|
|
96
|
-
Nan::SetPrototypeMethod(tpl, "getSodaDatabase", GetSodaDatabase);
|
|
97
|
-
|
|
98
|
-
Nan::SetAccessor(tpl->InstanceTemplate(),
|
|
99
|
-
Nan::New<v8::String>("stmtCacheSize").ToLocalChecked(),
|
|
100
|
-
njsConnection::GetStmtCacheSize, njsConnection::SetStmtCacheSize);
|
|
101
|
-
Nan::SetAccessor(tpl->InstanceTemplate(),
|
|
102
|
-
Nan::New<v8::String>("clientId").ToLocalChecked(),
|
|
103
|
-
njsConnection::GetClientId, njsConnection::SetClientId);
|
|
104
|
-
Nan::SetAccessor(tpl->InstanceTemplate(),
|
|
105
|
-
Nan::New<v8::String>("module").ToLocalChecked(),
|
|
106
|
-
njsConnection::GetModule, njsConnection::SetModule);
|
|
107
|
-
Nan::SetAccessor(tpl->InstanceTemplate(),
|
|
108
|
-
Nan::New<v8::String>("action").ToLocalChecked(),
|
|
109
|
-
njsConnection::GetAction, njsConnection::SetAction);
|
|
110
|
-
Nan::SetAccessor(tpl->InstanceTemplate(),
|
|
111
|
-
Nan::New<v8::String>("oracleServerVersion").ToLocalChecked(),
|
|
112
|
-
njsConnection::GetOracleServerVersion,
|
|
113
|
-
njsConnection::SetOracleServerVersion);
|
|
114
|
-
Nan::SetAccessor(tpl->InstanceTemplate(),
|
|
115
|
-
Nan::New<v8::String>("oracleServerVersionString").ToLocalChecked(),
|
|
116
|
-
njsConnection::GetOracleServerVersionString,
|
|
117
|
-
njsConnection::SetOracleServerVersionString);
|
|
118
|
-
Nan::SetAccessor(tpl->InstanceTemplate(),
|
|
119
|
-
Nan::New<v8::String>("callTimeout").ToLocalChecked(),
|
|
120
|
-
njsConnection::GetCallTimeout, njsConnection::SetCallTimeout);
|
|
121
|
-
|
|
122
|
-
connectionTemplate_s.Reset(tpl);
|
|
123
|
-
Nan::Set(target, Nan::New<v8::String>("Connection").ToLocalChecked(),
|
|
124
|
-
tpl->GetFunction());
|
|
125
|
-
}
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
//-----------------------------------------------------------------------------
|
|
129
|
-
// njsConnection::CreateFromBaton()
|
|
130
|
-
// Create a new connection from the baton.
|
|
131
|
-
//-----------------------------------------------------------------------------
|
|
132
|
-
Local<Object> njsConnection::CreateFromBaton(njsBaton *baton)
|
|
133
|
-
{
|
|
134
|
-
Nan::EscapableHandleScope scope;
|
|
135
|
-
njsConnection *connection;
|
|
136
|
-
Local<Function> func;
|
|
137
|
-
Local<Object> obj;
|
|
138
|
-
|
|
139
|
-
func = Nan::GetFunction(
|
|
140
|
-
Nan::New<FunctionTemplate>(connectionTemplate_s)).ToLocalChecked();
|
|
141
|
-
obj = Nan::NewInstance(func).ToLocalChecked();
|
|
142
|
-
connection = Nan::ObjectWrap::Unwrap<njsConnection>(obj);
|
|
143
|
-
connection->dpiConnHandle = baton->dpiConnHandle;
|
|
144
|
-
baton->dpiConnHandle = NULL;
|
|
145
|
-
connection->jsOracledb.Reset(baton->jsOracledb);
|
|
146
|
-
return scope.Escape(obj);
|
|
147
|
-
}
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
//-----------------------------------------------------------------------------
|
|
151
|
-
// njsConnection::ProcessQueryVars()
|
|
152
|
-
// Process query variables on all of the columns in the query. The actual
|
|
153
|
-
// ODPI-C variable will not be created at this point, nor will it be defined.
|
|
154
|
-
// This is deferred until just prior to the fetch.
|
|
155
|
-
//-----------------------------------------------------------------------------
|
|
156
|
-
bool njsConnection::ProcessQueryVars(njsBaton *baton, dpiStmt *dpiStmtHandle,
|
|
157
|
-
njsVariable *vars, uint32_t numVars)
|
|
158
|
-
{
|
|
159
|
-
dpiQueryInfo queryInfo;
|
|
160
|
-
|
|
161
|
-
// populate variables with query metadata
|
|
162
|
-
for (uint32_t i = 0; i < numVars; i++) {
|
|
163
|
-
|
|
164
|
-
// get query information for the specified column
|
|
165
|
-
vars[i].pos = i + 1;
|
|
166
|
-
vars[i].isArray = false;
|
|
167
|
-
vars[i].bindDir = NJS_BIND_OUT;
|
|
168
|
-
if (dpiStmt_getQueryInfo(dpiStmtHandle, vars[i].pos, &queryInfo) < 0) {
|
|
169
|
-
baton->GetDPIError();
|
|
170
|
-
return false;
|
|
171
|
-
}
|
|
172
|
-
vars[i].name = std::string(queryInfo.name, queryInfo.nameLength);
|
|
173
|
-
vars[i].maxArraySize = baton->fetchArraySize;
|
|
174
|
-
vars[i].dbSizeInBytes = queryInfo.typeInfo.dbSizeInBytes;
|
|
175
|
-
vars[i].precision = queryInfo.typeInfo.precision +
|
|
176
|
-
queryInfo.typeInfo.fsPrecision;
|
|
177
|
-
vars[i].scale = queryInfo.typeInfo.scale;
|
|
178
|
-
vars[i].isNullable = queryInfo.nullOk;
|
|
179
|
-
|
|
180
|
-
// determine the type of data
|
|
181
|
-
vars[i].dbTypeNum = queryInfo.typeInfo.oracleTypeNum;
|
|
182
|
-
vars[i].varTypeNum = queryInfo.typeInfo.oracleTypeNum;
|
|
183
|
-
vars[i].nativeTypeNum = queryInfo.typeInfo.defaultNativeTypeNum;
|
|
184
|
-
if (queryInfo.typeInfo.oracleTypeNum != DPI_ORACLE_TYPE_VARCHAR &&
|
|
185
|
-
queryInfo.typeInfo.oracleTypeNum != DPI_ORACLE_TYPE_NVARCHAR &&
|
|
186
|
-
queryInfo.typeInfo.oracleTypeNum != DPI_ORACLE_TYPE_CHAR &&
|
|
187
|
-
queryInfo.typeInfo.oracleTypeNum != DPI_ORACLE_TYPE_NCHAR &&
|
|
188
|
-
queryInfo.typeInfo.oracleTypeNum != DPI_ORACLE_TYPE_ROWID) {
|
|
189
|
-
if (!njsConnection::MapByName(baton, &queryInfo,
|
|
190
|
-
vars[i].varTypeNum))
|
|
191
|
-
njsConnection::MapByType(baton, &queryInfo,
|
|
192
|
-
vars[i].varTypeNum);
|
|
193
|
-
}
|
|
194
|
-
|
|
195
|
-
// validate data type and determine size
|
|
196
|
-
if (vars[i].varTypeNum == DPI_ORACLE_TYPE_VARCHAR ||
|
|
197
|
-
vars[i].varTypeNum == DPI_ORACLE_TYPE_RAW) {
|
|
198
|
-
vars[i].maxSize = NJS_MAX_FETCH_AS_STRING_SIZE;
|
|
199
|
-
vars[i].nativeTypeNum = DPI_NATIVE_TYPE_BYTES;
|
|
200
|
-
} else {
|
|
201
|
-
vars[i].maxSize = 0;
|
|
202
|
-
}
|
|
203
|
-
switch (queryInfo.typeInfo.oracleTypeNum) {
|
|
204
|
-
case DPI_ORACLE_TYPE_VARCHAR:
|
|
205
|
-
case DPI_ORACLE_TYPE_NVARCHAR:
|
|
206
|
-
case DPI_ORACLE_TYPE_CHAR:
|
|
207
|
-
case DPI_ORACLE_TYPE_NCHAR:
|
|
208
|
-
case DPI_ORACLE_TYPE_RAW:
|
|
209
|
-
vars[i].maxSize = queryInfo.typeInfo.clientSizeInBytes;
|
|
210
|
-
if (queryInfo.typeInfo.oracleTypeNum == DPI_ORACLE_TYPE_RAW &&
|
|
211
|
-
vars[i].varTypeNum == DPI_ORACLE_TYPE_VARCHAR)
|
|
212
|
-
vars[i].maxSize *= 2;
|
|
213
|
-
break;
|
|
214
|
-
case DPI_ORACLE_TYPE_DATE:
|
|
215
|
-
case DPI_ORACLE_TYPE_TIMESTAMP:
|
|
216
|
-
case DPI_ORACLE_TYPE_TIMESTAMP_TZ:
|
|
217
|
-
case DPI_ORACLE_TYPE_TIMESTAMP_LTZ:
|
|
218
|
-
if (vars[i].varTypeNum != DPI_ORACLE_TYPE_VARCHAR) {
|
|
219
|
-
vars[i].varTypeNum = DPI_ORACLE_TYPE_TIMESTAMP_LTZ;
|
|
220
|
-
vars[i].nativeTypeNum = DPI_NATIVE_TYPE_DOUBLE;
|
|
221
|
-
}
|
|
222
|
-
break;
|
|
223
|
-
case DPI_ORACLE_TYPE_CLOB:
|
|
224
|
-
case DPI_ORACLE_TYPE_NCLOB:
|
|
225
|
-
if (vars[i].varTypeNum == DPI_ORACLE_TYPE_VARCHAR)
|
|
226
|
-
vars[i].maxSize = (uint32_t) -1;
|
|
227
|
-
break;
|
|
228
|
-
case DPI_ORACLE_TYPE_BLOB:
|
|
229
|
-
if (vars[i].varTypeNum == DPI_ORACLE_TYPE_RAW)
|
|
230
|
-
vars[i].maxSize = (uint32_t) -1;
|
|
231
|
-
break;
|
|
232
|
-
case DPI_ORACLE_TYPE_LONG_VARCHAR:
|
|
233
|
-
case DPI_ORACLE_TYPE_LONG_RAW:
|
|
234
|
-
vars[i].maxSize = (uint32_t) -1;
|
|
235
|
-
break;
|
|
236
|
-
case DPI_ORACLE_TYPE_NUMBER:
|
|
237
|
-
case DPI_ORACLE_TYPE_NATIVE_INT:
|
|
238
|
-
case DPI_ORACLE_TYPE_NATIVE_FLOAT:
|
|
239
|
-
case DPI_ORACLE_TYPE_NATIVE_DOUBLE:
|
|
240
|
-
case DPI_ORACLE_TYPE_ROWID:
|
|
241
|
-
break;
|
|
242
|
-
default:
|
|
243
|
-
baton->error = njsMessages::Get(errUnsupportedDataType,
|
|
244
|
-
queryInfo.typeInfo.oracleTypeNum, i + 1);
|
|
245
|
-
baton->ClearAsyncData();
|
|
246
|
-
return false;
|
|
247
|
-
}
|
|
248
|
-
|
|
249
|
-
}
|
|
250
|
-
|
|
251
|
-
return true;
|
|
252
|
-
}
|
|
253
|
-
|
|
254
|
-
|
|
255
|
-
//-----------------------------------------------------------------------------
|
|
256
|
-
// njsConnection::ProcessVars()
|
|
257
|
-
// Process variables used during binding or fetching. REF cursors must have
|
|
258
|
-
// their query variables defined and LOBs must be initially processed in order
|
|
259
|
-
// to have as much work as possible done in the worker thread and to avoid any
|
|
260
|
-
// round trips.
|
|
261
|
-
//-----------------------------------------------------------------------------
|
|
262
|
-
bool njsConnection::ProcessVars(njsBaton *baton, njsVariable *vars,
|
|
263
|
-
uint32_t numVars, uint32_t numRows)
|
|
264
|
-
{
|
|
265
|
-
for (uint32_t col = 0; col < numVars; col++) {
|
|
266
|
-
njsVariable *var = &vars[col];
|
|
267
|
-
var->buffer.numElements = numRows;
|
|
268
|
-
if (var->bindDir == NJS_BIND_IN)
|
|
269
|
-
continue;
|
|
270
|
-
if (var->dmlReturningBuffers) {
|
|
271
|
-
delete [] var->dmlReturningBuffers;
|
|
272
|
-
var->dmlReturningBuffers = NULL;
|
|
273
|
-
}
|
|
274
|
-
|
|
275
|
-
// for arrays, determine the number of elements in the array
|
|
276
|
-
if (var->isArray) {
|
|
277
|
-
if (dpiVar_getNumElementsInArray(var->dpiVarHandle,
|
|
278
|
-
&var->buffer.numElements) < 0) {
|
|
279
|
-
baton->GetDPIError();
|
|
280
|
-
return false;
|
|
281
|
-
}
|
|
282
|
-
|
|
283
|
-
// for DML returning statements, each row has its own set of rows, so
|
|
284
|
-
// acquire those from ODPI-C and store them in variable buffers for
|
|
285
|
-
// later processing
|
|
286
|
-
} else if (baton->isReturning && var->bindDir == NJS_BIND_OUT) {
|
|
287
|
-
var->dmlReturningBuffers = new njsVariableBuffer[numRows];
|
|
288
|
-
for (uint32_t row = 0; row < numRows; row++) {
|
|
289
|
-
njsVariableBuffer *buffer = &var->dmlReturningBuffers[row];
|
|
290
|
-
if (dpiVar_getReturnedData(var->dpiVarHandle, row,
|
|
291
|
-
&buffer->numElements, &buffer->dpiVarData) < 0) {
|
|
292
|
-
baton->GetDPIError();
|
|
293
|
-
return false;
|
|
294
|
-
}
|
|
295
|
-
if (!ProcessVarBuffer(baton, var, buffer))
|
|
296
|
-
return false;
|
|
297
|
-
}
|
|
298
|
-
}
|
|
299
|
-
|
|
300
|
-
// process the main buffer if DML returning is not in effect
|
|
301
|
-
if (!var->dmlReturningBuffers &&
|
|
302
|
-
!ProcessVarBuffer(baton, var, &var->buffer))
|
|
303
|
-
return false;
|
|
304
|
-
|
|
305
|
-
}
|
|
306
|
-
|
|
307
|
-
return true;
|
|
308
|
-
}
|
|
309
|
-
|
|
310
|
-
|
|
311
|
-
//-----------------------------------------------------------------------------
|
|
312
|
-
// njsConnection::ProcessVarBuffer()
|
|
313
|
-
// Process a variable buffer. REF cursors must have their query variables
|
|
314
|
-
// defined and LOBs must be initially processed in order to have as much work
|
|
315
|
-
// as possible done in the worker thread and avoid any round trips.
|
|
316
|
-
//-----------------------------------------------------------------------------
|
|
317
|
-
bool njsConnection::ProcessVarBuffer(njsBaton *baton, njsVariable *var,
|
|
318
|
-
njsVariableBuffer *buffer)
|
|
319
|
-
{
|
|
320
|
-
dpiStmt *stmt;
|
|
321
|
-
|
|
322
|
-
switch (var->varTypeNum) {
|
|
323
|
-
case DPI_ORACLE_TYPE_CLOB:
|
|
324
|
-
case DPI_ORACLE_TYPE_NCLOB:
|
|
325
|
-
case DPI_ORACLE_TYPE_BLOB:
|
|
326
|
-
if (buffer->lobs)
|
|
327
|
-
delete [] buffer->lobs;
|
|
328
|
-
buffer->lobs = new njsProtoILob[buffer->numElements];
|
|
329
|
-
for (uint32_t i = 0; i < buffer->numElements; i++) {
|
|
330
|
-
njsProtoILob *lob = &buffer->lobs[i];
|
|
331
|
-
lob->dataType = (var->varTypeNum == DPI_ORACLE_TYPE_BLOB) ?
|
|
332
|
-
NJS_DATATYPE_BLOB : NJS_DATATYPE_CLOB;
|
|
333
|
-
lob->isAutoClose = true;
|
|
334
|
-
uint32_t elementIndex = baton->bufferRowIndex + i;
|
|
335
|
-
dpiData *data = &buffer->dpiVarData[elementIndex];
|
|
336
|
-
if (data->isNull)
|
|
337
|
-
continue;
|
|
338
|
-
if (!lob->PopulateFromDPI(baton, data->value.asLOB, true))
|
|
339
|
-
return false;
|
|
340
|
-
}
|
|
341
|
-
break;
|
|
342
|
-
case DPI_ORACLE_TYPE_STMT:
|
|
343
|
-
stmt = buffer->dpiVarData->value.asStmt;
|
|
344
|
-
if (dpiStmt_getNumQueryColumns(stmt, &var->numQueryVars) < 0) {
|
|
345
|
-
baton->GetDPIError();
|
|
346
|
-
return false;
|
|
347
|
-
}
|
|
348
|
-
var->queryVars = new njsVariable[var->numQueryVars];
|
|
349
|
-
if (!ProcessQueryVars(baton, stmt, var->queryVars,
|
|
350
|
-
var->numQueryVars))
|
|
351
|
-
return false;
|
|
352
|
-
break;
|
|
353
|
-
default:
|
|
354
|
-
break;
|
|
355
|
-
}
|
|
356
|
-
return true;
|
|
357
|
-
}
|
|
358
|
-
|
|
359
|
-
|
|
360
|
-
//-----------------------------------------------------------------------------
|
|
361
|
-
// njsConnection::MapByName()
|
|
362
|
-
// Apply "By-Name" rules, if applicable. Returns true if rules were applied
|
|
363
|
-
// (and targetType is set); false otherwise (and targetType is left untouched).
|
|
364
|
-
//-----------------------------------------------------------------------------
|
|
365
|
-
bool njsConnection::MapByName(njsBaton *baton, dpiQueryInfo *queryInfo,
|
|
366
|
-
dpiOracleTypeNum &targetType)
|
|
367
|
-
{
|
|
368
|
-
if (baton->fetchInfo) {
|
|
369
|
-
std::string name = std::string(queryInfo->name, queryInfo->nameLength);
|
|
370
|
-
for (uint32_t i = 0; i < baton->numFetchInfo; i++) {
|
|
371
|
-
if (baton->fetchInfo[i].name.compare(name) == 0) {
|
|
372
|
-
if (baton->fetchInfo[i].type == NJS_DATATYPE_STR) {
|
|
373
|
-
targetType = DPI_ORACLE_TYPE_VARCHAR;
|
|
374
|
-
} else if (baton->fetchInfo[i].type == NJS_DATATYPE_BUFFER) {
|
|
375
|
-
targetType = DPI_ORACLE_TYPE_RAW;
|
|
376
|
-
} else if (baton->fetchInfo[i].type == NJS_DATATYPE_DEFAULT) {
|
|
377
|
-
targetType = queryInfo->typeInfo.oracleTypeNum;
|
|
378
|
-
}
|
|
379
|
-
return true;
|
|
380
|
-
}
|
|
381
|
-
}
|
|
382
|
-
}
|
|
383
|
-
return false;
|
|
384
|
-
}
|
|
385
|
-
|
|
386
|
-
|
|
387
|
-
//-----------------------------------------------------------------------------
|
|
388
|
-
// njsConnection::MapByType()
|
|
389
|
-
// Apply "By-Type" rules, if applicable. Returns true if rules were applied
|
|
390
|
-
// (and targetType is set); false otherwise (and targetType is left untouched).
|
|
391
|
-
//-----------------------------------------------------------------------------
|
|
392
|
-
bool njsConnection::MapByType(njsBaton *baton, dpiQueryInfo *queryInfo,
|
|
393
|
-
dpiOracleTypeNum &targetType)
|
|
394
|
-
{
|
|
395
|
-
uint32_t i;
|
|
396
|
-
|
|
397
|
-
// handle fetchAsString
|
|
398
|
-
for (i = 0; i < baton->numFetchAsStringTypes; i++) {
|
|
399
|
-
switch (queryInfo->typeInfo.oracleTypeNum) {
|
|
400
|
-
case DPI_ORACLE_TYPE_NUMBER:
|
|
401
|
-
case DPI_ORACLE_TYPE_NATIVE_FLOAT:
|
|
402
|
-
case DPI_ORACLE_TYPE_NATIVE_DOUBLE:
|
|
403
|
-
case DPI_ORACLE_TYPE_NATIVE_INT:
|
|
404
|
-
if (baton->fetchAsStringTypes[i] == NJS_DATATYPE_NUM) {
|
|
405
|
-
targetType = DPI_ORACLE_TYPE_VARCHAR;
|
|
406
|
-
return true;
|
|
407
|
-
}
|
|
408
|
-
break;
|
|
409
|
-
case DPI_ORACLE_TYPE_DATE:
|
|
410
|
-
case DPI_ORACLE_TYPE_TIMESTAMP:
|
|
411
|
-
case DPI_ORACLE_TYPE_TIMESTAMP_TZ:
|
|
412
|
-
case DPI_ORACLE_TYPE_TIMESTAMP_LTZ:
|
|
413
|
-
if (baton->fetchAsStringTypes[i] == NJS_DATATYPE_DATE) {
|
|
414
|
-
targetType = DPI_ORACLE_TYPE_VARCHAR;
|
|
415
|
-
return true;
|
|
416
|
-
}
|
|
417
|
-
break;
|
|
418
|
-
case DPI_ORACLE_TYPE_CLOB:
|
|
419
|
-
case DPI_ORACLE_TYPE_NCLOB:
|
|
420
|
-
if (baton->fetchAsStringTypes[i] == NJS_DATATYPE_CLOB) {
|
|
421
|
-
targetType = DPI_ORACLE_TYPE_VARCHAR;
|
|
422
|
-
return true;
|
|
423
|
-
}
|
|
424
|
-
break;
|
|
425
|
-
case DPI_ORACLE_TYPE_RAW:
|
|
426
|
-
if (baton->fetchAsStringTypes[i] == NJS_DATATYPE_BUFFER) {
|
|
427
|
-
targetType = DPI_ORACLE_TYPE_VARCHAR;
|
|
428
|
-
return true;
|
|
429
|
-
}
|
|
430
|
-
break;
|
|
431
|
-
default:
|
|
432
|
-
break;
|
|
433
|
-
}
|
|
434
|
-
}
|
|
435
|
-
|
|
436
|
-
// handle fetchAsBuffer
|
|
437
|
-
for (i = 0; i < baton->numFetchAsBufferTypes; i++) {
|
|
438
|
-
if (queryInfo->typeInfo.oracleTypeNum == DPI_ORACLE_TYPE_BLOB &&
|
|
439
|
-
baton->fetchAsBufferTypes[i] == NJS_DATATYPE_BLOB) {
|
|
440
|
-
targetType = DPI_ORACLE_TYPE_RAW;
|
|
441
|
-
return true;
|
|
442
|
-
}
|
|
443
|
-
}
|
|
444
|
-
|
|
445
|
-
return false;
|
|
446
|
-
}
|
|
447
|
-
|
|
448
|
-
|
|
449
|
-
//-----------------------------------------------------------------------------
|
|
450
|
-
// njsConnection::PrepareAndBind()
|
|
451
|
-
// Prepare statement and bind data to the statement.
|
|
452
|
-
//-----------------------------------------------------------------------------
|
|
453
|
-
bool njsConnection::PrepareAndBind(njsBaton *baton)
|
|
454
|
-
{
|
|
455
|
-
// prepare DPI statement for use
|
|
456
|
-
if (dpiConn_prepareStmt(baton->dpiConnHandle, 0, baton->sql.c_str(),
|
|
457
|
-
(uint32_t) baton->sql.length(), NULL, 0,
|
|
458
|
-
&baton->dpiStmtHandle) < 0) {
|
|
459
|
-
baton->GetDPIError();
|
|
460
|
-
return false;
|
|
461
|
-
}
|
|
462
|
-
|
|
463
|
-
// determine statement information
|
|
464
|
-
dpiStmtInfo stmtInfo;
|
|
465
|
-
if (dpiStmt_getInfo(baton->dpiStmtHandle, &stmtInfo) < 0) {
|
|
466
|
-
baton->GetDPIError();
|
|
467
|
-
return false;
|
|
468
|
-
}
|
|
469
|
-
baton->isPLSQL = (stmtInfo.isPLSQL) ? true : false;
|
|
470
|
-
baton->isReturning = (stmtInfo.isReturning) ? true : false;
|
|
471
|
-
|
|
472
|
-
// result sets are incompatible with non-queries
|
|
473
|
-
if (!stmtInfo.isQuery && baton->getRS) {
|
|
474
|
-
baton->error = njsMessages::Get(errInvalidNonQueryExecution);
|
|
475
|
-
baton->ClearAsyncData();
|
|
476
|
-
return false;
|
|
477
|
-
}
|
|
478
|
-
|
|
479
|
-
// perform any binds necessary
|
|
480
|
-
for (uint32_t i = 0; i < baton->numBindVars; i++) {
|
|
481
|
-
int status;
|
|
482
|
-
njsVariable *var = &baton->bindVars[i];
|
|
483
|
-
if (var->name.empty()) {
|
|
484
|
-
status = dpiStmt_bindByPos(baton->dpiStmtHandle, var->pos,
|
|
485
|
-
var->dpiVarHandle);
|
|
486
|
-
} else {
|
|
487
|
-
status = dpiStmt_bindByName(baton->dpiStmtHandle,
|
|
488
|
-
var->name.c_str(), (uint32_t) var->name.length(),
|
|
489
|
-
var->dpiVarHandle);
|
|
490
|
-
}
|
|
491
|
-
if (status < 0) {
|
|
492
|
-
baton->GetDPIError();
|
|
493
|
-
return false;
|
|
494
|
-
}
|
|
495
|
-
}
|
|
496
|
-
|
|
497
|
-
return true;
|
|
498
|
-
}
|
|
499
|
-
|
|
500
|
-
|
|
501
|
-
//-----------------------------------------------------------------------------
|
|
502
|
-
// njsConnection::GetMetaData()
|
|
503
|
-
// Populate array of metadata for JS from list of variables.
|
|
504
|
-
//-----------------------------------------------------------------------------
|
|
505
|
-
Local<Value> njsConnection::GetMetaData(njsVariable *vars, uint32_t numVars,
|
|
506
|
-
bool extendedMetaData)
|
|
507
|
-
{
|
|
508
|
-
Nan::EscapableHandleScope scope;
|
|
509
|
-
Local<Array> metaArray = Nan::New<Array>(numVars);
|
|
510
|
-
|
|
511
|
-
for (uint32_t i = 0; i < numVars; i++) {
|
|
512
|
-
njsVariable *var = &vars[i];
|
|
513
|
-
Local<Object> column = Nan::New<Object>();
|
|
514
|
-
Nan::Set(column, Nan::New<v8::String>("name").ToLocalChecked(),
|
|
515
|
-
Nan::New<v8::String>(var->name).ToLocalChecked());
|
|
516
|
-
if (extendedMetaData) {
|
|
517
|
-
njsDBType dbType = var->DBType();
|
|
518
|
-
Nan::Set(column,
|
|
519
|
-
Nan::New<v8::String>("fetchType").ToLocalChecked(),
|
|
520
|
-
Nan::New<v8::Number>(var->DataType()));
|
|
521
|
-
Nan::Set(column,
|
|
522
|
-
Nan::New<v8::String>("dbType").ToLocalChecked(),
|
|
523
|
-
Nan::New<v8::Number>(dbType));
|
|
524
|
-
Nan::Set(column,
|
|
525
|
-
Nan::New<v8::String>("nullable").ToLocalChecked(),
|
|
526
|
-
Nan::New<v8::Boolean>(var->isNullable));
|
|
527
|
-
switch (dbType) {
|
|
528
|
-
case NJS_DB_TYPE_VARCHAR:
|
|
529
|
-
case NJS_DB_TYPE_NVARCHAR:
|
|
530
|
-
case NJS_DB_TYPE_CHAR:
|
|
531
|
-
case NJS_DB_TYPE_NCHAR:
|
|
532
|
-
case NJS_DB_TYPE_RAW:
|
|
533
|
-
Nan::Set(column,
|
|
534
|
-
Nan::New<v8::String>("byteSize").ToLocalChecked(),
|
|
535
|
-
Nan::New<v8::Number>(var->dbSizeInBytes));
|
|
536
|
-
break;
|
|
537
|
-
case NJS_DB_TYPE_NUMBER:
|
|
538
|
-
Nan::Set(column,
|
|
539
|
-
Nan::New<v8::String>("precision").ToLocalChecked(),
|
|
540
|
-
Nan::New<v8::Number>(var->precision));
|
|
541
|
-
Nan::Set(column,
|
|
542
|
-
Nan::New<v8::String>("scale").ToLocalChecked(),
|
|
543
|
-
Nan::New<v8::Number>(var->scale) );
|
|
544
|
-
break;
|
|
545
|
-
case NJS_DB_TYPE_TIMESTAMP:
|
|
546
|
-
case NJS_DB_TYPE_TIMESTAMP_TZ:
|
|
547
|
-
case NJS_DB_TYPE_TIMESTAMP_LTZ:
|
|
548
|
-
Nan::Set(column,
|
|
549
|
-
Nan::New<v8::String>("precision").ToLocalChecked(),
|
|
550
|
-
Nan::New<v8::Number>(var->precision));
|
|
551
|
-
break;
|
|
552
|
-
default:
|
|
553
|
-
break;
|
|
554
|
-
}
|
|
555
|
-
}
|
|
556
|
-
Nan::Set(metaArray, i, column);
|
|
557
|
-
}
|
|
558
|
-
return scope.Escape(metaArray);
|
|
559
|
-
}
|
|
560
|
-
|
|
561
|
-
|
|
562
|
-
//-----------------------------------------------------------------------------
|
|
563
|
-
// njsConnection::CreateVarBuffer()
|
|
564
|
-
// Create ODPI-C variables used to hold the bind data.
|
|
565
|
-
//-----------------------------------------------------------------------------
|
|
566
|
-
bool njsConnection::CreateVarBuffer(njsVariable *var, njsBaton *baton)
|
|
567
|
-
{
|
|
568
|
-
// if the variable is not an array use the bind array size
|
|
569
|
-
if (!var->isArray)
|
|
570
|
-
var->maxArraySize = baton->bindArraySize;
|
|
571
|
-
|
|
572
|
-
// if the variable has no data type assume string of size 1
|
|
573
|
-
if (var->bindDataType == NJS_DATATYPE_DEFAULT) {
|
|
574
|
-
var->bindDataType = NJS_DATATYPE_STR;
|
|
575
|
-
var->maxSize = 1;
|
|
576
|
-
}
|
|
577
|
-
|
|
578
|
-
// REF cursors are only supported as out binds currently
|
|
579
|
-
if (var->bindDataType == NJS_DATATYPE_CURSOR &&
|
|
580
|
-
var->bindDir != NJS_BIND_OUT) {
|
|
581
|
-
baton->error = njsMessages::Get(errInvalidPropertyValueInParam,
|
|
582
|
-
"type", 1);
|
|
583
|
-
return false;
|
|
584
|
-
}
|
|
585
|
-
|
|
586
|
-
// max size must be specified for in/out and out binds
|
|
587
|
-
if (!var->maxSize && var->bindDir != NJS_BIND_IN) {
|
|
588
|
-
baton->error = njsMessages::Get(errInvalidPropertyValueInParam,
|
|
589
|
-
"maxSize", 1);
|
|
590
|
-
return false;
|
|
591
|
-
}
|
|
592
|
-
|
|
593
|
-
// determine ODPI-C Oracle type and native type to use
|
|
594
|
-
switch (var->bindDataType) {
|
|
595
|
-
case NJS_DATATYPE_STR:
|
|
596
|
-
var->varTypeNum = DPI_ORACLE_TYPE_VARCHAR;
|
|
597
|
-
var->nativeTypeNum = DPI_NATIVE_TYPE_BYTES;
|
|
598
|
-
break;
|
|
599
|
-
case NJS_DATATYPE_NUM:
|
|
600
|
-
var->varTypeNum = DPI_ORACLE_TYPE_NUMBER;
|
|
601
|
-
var->nativeTypeNum = DPI_NATIVE_TYPE_DOUBLE;
|
|
602
|
-
break;
|
|
603
|
-
case NJS_DATATYPE_INT:
|
|
604
|
-
var->varTypeNum = DPI_ORACLE_TYPE_NUMBER;
|
|
605
|
-
var->nativeTypeNum = DPI_NATIVE_TYPE_INT64;
|
|
606
|
-
break;
|
|
607
|
-
case NJS_DATATYPE_DATE:
|
|
608
|
-
var->varTypeNum = DPI_ORACLE_TYPE_TIMESTAMP_LTZ;
|
|
609
|
-
var->nativeTypeNum = DPI_NATIVE_TYPE_DOUBLE;
|
|
610
|
-
break;
|
|
611
|
-
case NJS_DATATYPE_CURSOR:
|
|
612
|
-
var->varTypeNum = DPI_ORACLE_TYPE_STMT;
|
|
613
|
-
var->nativeTypeNum = DPI_NATIVE_TYPE_STMT;
|
|
614
|
-
break;
|
|
615
|
-
case NJS_DATATYPE_BUFFER:
|
|
616
|
-
var->varTypeNum = DPI_ORACLE_TYPE_RAW;
|
|
617
|
-
var->nativeTypeNum = DPI_NATIVE_TYPE_BYTES;
|
|
618
|
-
break;
|
|
619
|
-
case NJS_DATATYPE_CLOB:
|
|
620
|
-
var->varTypeNum = DPI_ORACLE_TYPE_CLOB;
|
|
621
|
-
var->nativeTypeNum = DPI_NATIVE_TYPE_LOB;
|
|
622
|
-
break;
|
|
623
|
-
case NJS_DATATYPE_BLOB:
|
|
624
|
-
var->varTypeNum = DPI_ORACLE_TYPE_BLOB;
|
|
625
|
-
var->nativeTypeNum = DPI_NATIVE_TYPE_LOB;
|
|
626
|
-
break;
|
|
627
|
-
default:
|
|
628
|
-
baton->error= njsMessages::Get(errInvalidBindDataType, 2);
|
|
629
|
-
return false;
|
|
630
|
-
}
|
|
631
|
-
|
|
632
|
-
// create ODPI-C variable
|
|
633
|
-
if (dpiConn_newVar(baton->dpiConnHandle, var->varTypeNum,
|
|
634
|
-
var->nativeTypeNum, var->maxArraySize, var->maxSize, 1,
|
|
635
|
-
var->isArray, NULL, &var->dpiVarHandle,
|
|
636
|
-
&var->buffer.dpiVarData) < 0) {
|
|
637
|
-
baton->GetDPIError();
|
|
638
|
-
return false;
|
|
639
|
-
}
|
|
640
|
-
|
|
641
|
-
return true;
|
|
642
|
-
}
|
|
643
|
-
|
|
644
|
-
|
|
645
|
-
//-----------------------------------------------------------------------------
|
|
646
|
-
// njsConnection::ProcessExecuteBinds()
|
|
647
|
-
// Process binds passed through to Execute() call.
|
|
648
|
-
//-----------------------------------------------------------------------------
|
|
649
|
-
bool njsConnection::ProcessExecuteBinds(Local<Object> binds, njsBaton *baton)
|
|
650
|
-
{
|
|
651
|
-
Nan::HandleScope scope;
|
|
652
|
-
Local<Array> bindNames;
|
|
653
|
-
|
|
654
|
-
// determine bind names (if binding by name)
|
|
655
|
-
baton->bindArraySize = 1;
|
|
656
|
-
if (!binds->IsUndefined() && !binds->IsArray())
|
|
657
|
-
bindNames = binds->GetOwnPropertyNames();
|
|
658
|
-
|
|
659
|
-
// initialize variables; if there are no variables, nothing further to do!
|
|
660
|
-
if (!InitBindVars(binds, bindNames, baton))
|
|
661
|
-
return false;
|
|
662
|
-
if (baton->numBindVars == 0)
|
|
663
|
-
return true;
|
|
664
|
-
|
|
665
|
-
// scan the execute binds and populate the bind variables
|
|
666
|
-
return ScanExecuteBinds(binds, bindNames, baton);
|
|
667
|
-
}
|
|
668
|
-
|
|
669
|
-
|
|
670
|
-
//-----------------------------------------------------------------------------
|
|
671
|
-
// njsConnection::ScanExecuteBinds()
|
|
672
|
-
// Scan the binds passed through to Execute() and determine the bind
|
|
673
|
-
// type and maximum size (for strings/buffers).
|
|
674
|
-
//-----------------------------------------------------------------------------
|
|
675
|
-
bool njsConnection::ScanExecuteBinds(Local<Object> binds,
|
|
676
|
-
Local<Array> bindNames, njsBaton *baton)
|
|
677
|
-
{
|
|
678
|
-
Nan::HandleScope scope;
|
|
679
|
-
Local<Value> bindName, bindUnit, bindValue;
|
|
680
|
-
Local<Array> byPositionValues;
|
|
681
|
-
njsVariable *var;
|
|
682
|
-
bool byPosition;
|
|
683
|
-
|
|
684
|
-
// determine if binding is by position or by name
|
|
685
|
-
byPosition = (baton->bindVars[0].pos > 0);
|
|
686
|
-
if (byPosition)
|
|
687
|
-
byPositionValues = binds.As<Array>();
|
|
688
|
-
|
|
689
|
-
// scan each column
|
|
690
|
-
for (uint32_t i = 0; i < baton->numBindVars; i++) {
|
|
691
|
-
var = &baton->bindVars[i];
|
|
692
|
-
|
|
693
|
-
// determine bind information and value
|
|
694
|
-
if (byPosition) {
|
|
695
|
-
bindUnit = Nan::Get(byPositionValues, i).ToLocalChecked();
|
|
696
|
-
} else {
|
|
697
|
-
bindName = Nan::Get(bindNames, i).ToLocalChecked();
|
|
698
|
-
if (!Nan::Get(binds, bindName).ToLocal(&bindUnit))
|
|
699
|
-
return false;
|
|
700
|
-
}
|
|
701
|
-
if (bindUnit->IsObject() && !bindUnit->IsDate() &&
|
|
702
|
-
!Buffer::HasInstance(bindUnit) &&
|
|
703
|
-
!njsILob::HasInstance(bindUnit)) {
|
|
704
|
-
if (!ScanExecuteBindUnit(bindUnit.As<Object>(), var, false, baton))
|
|
705
|
-
return false;
|
|
706
|
-
Local<String> key = Nan::New<String>("val").ToLocalChecked();
|
|
707
|
-
bindValue = Nan::Get(bindUnit.As<Object>(), key).ToLocalChecked();
|
|
708
|
-
} else {
|
|
709
|
-
bindValue = bindUnit;
|
|
710
|
-
}
|
|
711
|
-
|
|
712
|
-
// get bind information from value if it has not already been specified
|
|
713
|
-
if (var->bindDataType == NJS_DATATYPE_DEFAULT || !var->maxSize ||
|
|
714
|
-
var->maxSize == NJS_MAX_OUT_BIND_SIZE) {
|
|
715
|
-
njsDataType defaultBindType = NJS_DATATYPE_DEFAULT;
|
|
716
|
-
uint32_t defaultMaxSize = 0;
|
|
717
|
-
if (!GetBindTypeAndSizeFromValue(var, bindValue, &defaultBindType,
|
|
718
|
-
&defaultMaxSize, baton))
|
|
719
|
-
return false;
|
|
720
|
-
if (var->bindDataType == NJS_DATATYPE_DEFAULT)
|
|
721
|
-
var->bindDataType = defaultBindType;
|
|
722
|
-
if (defaultMaxSize > var->maxSize)
|
|
723
|
-
var->maxSize = defaultMaxSize;
|
|
724
|
-
}
|
|
725
|
-
|
|
726
|
-
// for IN binds, maxArraySize is ignored and obtained from the actual
|
|
727
|
-
// array size; for INOUT binds, maxArraySize does need to be specified
|
|
728
|
-
// by the application; for OUT binds, the value from the application
|
|
729
|
-
// must be accepted as is as there is no way to validate it
|
|
730
|
-
if (bindValue->IsArray()) {
|
|
731
|
-
var->isArray = true;
|
|
732
|
-
Local<Array> arrayVal = Local<Array>::Cast(bindValue);
|
|
733
|
-
if (var->bindDir == NJS_BIND_IN) {
|
|
734
|
-
var->maxArraySize = arrayVal->Length();
|
|
735
|
-
if (var->maxArraySize == 0)
|
|
736
|
-
var->maxArraySize = 1;
|
|
737
|
-
} else if (var->maxArraySize == 0) {
|
|
738
|
-
baton->error = njsMessages::Get(errReqdMaxArraySize);
|
|
739
|
-
return false;
|
|
740
|
-
}
|
|
741
|
-
if (var->bindDir == NJS_BIND_INOUT &&
|
|
742
|
-
arrayVal->Length() > var->maxArraySize) {
|
|
743
|
-
baton->error = njsMessages::Get(errInvalidArraySize);
|
|
744
|
-
return false;
|
|
745
|
-
}
|
|
746
|
-
}
|
|
747
|
-
|
|
748
|
-
// create buffer for variable
|
|
749
|
-
if (!CreateVarBuffer(var, baton))
|
|
750
|
-
return false;
|
|
751
|
-
|
|
752
|
-
// process bind value (for all except OUT)
|
|
753
|
-
if (var->bindDir != NJS_BIND_OUT) {
|
|
754
|
-
if (!ProcessBindValue(bindValue, var, baton))
|
|
755
|
-
return false;
|
|
756
|
-
}
|
|
757
|
-
|
|
758
|
-
}
|
|
759
|
-
|
|
760
|
-
return true;
|
|
761
|
-
}
|
|
762
|
-
|
|
763
|
-
|
|
764
|
-
//-----------------------------------------------------------------------------
|
|
765
|
-
// njsConnection::ScanExecuteBindUnit()
|
|
766
|
-
// Scan the execute bind unit for bind information.
|
|
767
|
-
//-----------------------------------------------------------------------------
|
|
768
|
-
bool njsConnection::ScanExecuteBindUnit(Local<Object> bindUnit,
|
|
769
|
-
njsVariable *var, bool inExecuteMany, njsBaton *baton)
|
|
770
|
-
{
|
|
771
|
-
Nan::HandleScope scope;
|
|
772
|
-
|
|
773
|
-
// scan all keys and verify that one of "dir", "type", "maxSize" or "val"
|
|
774
|
-
// is found; if not, the bind information is considered invalid
|
|
775
|
-
Local<Array> keys = bindUnit->GetOwnPropertyNames();
|
|
776
|
-
bool valid = false;
|
|
777
|
-
for (uint32_t i = 0; i < keys->Length(); i++) {
|
|
778
|
-
Local<String> temp =
|
|
779
|
-
Nan::Get(keys, i).ToLocalChecked().As<String>();
|
|
780
|
-
Nan::Utf8String utf8str(temp);
|
|
781
|
-
std::string key =
|
|
782
|
-
std::string(*utf8str, static_cast<size_t>(utf8str.length()));
|
|
783
|
-
if (key.compare("dir") == 0 || key.compare("type") == 0 ||
|
|
784
|
-
key.compare("maxSize") == 0 || key.compare("val") == 0) {
|
|
785
|
-
valid = true;
|
|
786
|
-
break;
|
|
787
|
-
}
|
|
788
|
-
}
|
|
789
|
-
if (!valid) {
|
|
790
|
-
baton->error = njsMessages::Get(errNamedJSON);
|
|
791
|
-
return false;
|
|
792
|
-
}
|
|
793
|
-
|
|
794
|
-
// get and validate bind direction
|
|
795
|
-
uint32_t temp = (uint32_t) var->bindDir;
|
|
796
|
-
if (!baton->GetUnsignedIntFromJSON(bindUnit, "dir", 1, &temp))
|
|
797
|
-
return false;
|
|
798
|
-
var->bindDir = (njsBindDir) temp;
|
|
799
|
-
switch (var->bindDir) {
|
|
800
|
-
case NJS_BIND_OUT:
|
|
801
|
-
case NJS_BIND_IN:
|
|
802
|
-
case NJS_BIND_INOUT:
|
|
803
|
-
break;
|
|
804
|
-
default:
|
|
805
|
-
baton->error = njsMessages::Get(errInvalidBindDirection);
|
|
806
|
-
return false;
|
|
807
|
-
}
|
|
808
|
-
|
|
809
|
-
// get data type
|
|
810
|
-
temp = (uint32_t) var->bindDataType;
|
|
811
|
-
if (!baton->GetUnsignedIntFromJSON(bindUnit, "type", 1, &temp))
|
|
812
|
-
return false;
|
|
813
|
-
if (!temp && inExecuteMany) {
|
|
814
|
-
if (var->pos > 0) {
|
|
815
|
-
baton->error = njsMessages::Get(errMissingTypeByPos, var->pos);
|
|
816
|
-
} else {
|
|
817
|
-
baton->error = njsMessages::Get(errMissingTypeByName,
|
|
818
|
-
var->name.c_str());
|
|
819
|
-
}
|
|
820
|
-
}
|
|
821
|
-
var->bindDataType = (njsDataType) temp;
|
|
822
|
-
|
|
823
|
-
// get maximum size for strings/buffers; this value is only used for
|
|
824
|
-
// IN/OUT and OUT binds in execute() and at all times for executeMany()
|
|
825
|
-
if (var->bindDir != NJS_BIND_IN || inExecuteMany) {
|
|
826
|
-
if (var->bindDir != NJS_BIND_IN)
|
|
827
|
-
var->maxSize = NJS_MAX_OUT_BIND_SIZE;
|
|
828
|
-
if (!baton->GetUnsignedIntFromJSON(bindUnit, "maxSize", 1,
|
|
829
|
-
&var->maxSize))
|
|
830
|
-
return false;
|
|
831
|
-
if (inExecuteMany && var->maxSize == 0) {
|
|
832
|
-
if (var->bindDataType == NJS_DATATYPE_STR ||
|
|
833
|
-
var->bindDataType == NJS_DATATYPE_BUFFER) {
|
|
834
|
-
if (var->pos > 0) {
|
|
835
|
-
baton->error = njsMessages::Get(errMissingMaxSizeByPos,
|
|
836
|
-
var->pos);
|
|
837
|
-
} else {
|
|
838
|
-
baton->error = njsMessages::Get(errMissingMaxSizeByName,
|
|
839
|
-
var->name.c_str());
|
|
840
|
-
}
|
|
841
|
-
return false;
|
|
842
|
-
}
|
|
843
|
-
}
|
|
844
|
-
}
|
|
845
|
-
|
|
846
|
-
// get max array size (for array binds)
|
|
847
|
-
if (!inExecuteMany) {
|
|
848
|
-
if (!baton->GetUnsignedIntFromJSON(bindUnit, "maxArraySize", 1,
|
|
849
|
-
&var->maxArraySize))
|
|
850
|
-
return false;
|
|
851
|
-
if (var->maxArraySize > 0)
|
|
852
|
-
var->isArray = true;
|
|
853
|
-
}
|
|
854
|
-
|
|
855
|
-
return true;
|
|
856
|
-
}
|
|
857
|
-
|
|
858
|
-
|
|
859
|
-
//-----------------------------------------------------------------------------
|
|
860
|
-
// njsConnection::ProcessExecuteManyBinds()
|
|
861
|
-
// Process binds passed through to ExecuteMany() call.
|
|
862
|
-
//-----------------------------------------------------------------------------
|
|
863
|
-
bool njsConnection::ProcessExecuteManyBinds(Local<Array> binds,
|
|
864
|
-
Local<Object> options, njsBaton *baton)
|
|
865
|
-
{
|
|
866
|
-
Nan::HandleScope scope;
|
|
867
|
-
Local<Value> bindDefs, bindName, bindUnit;
|
|
868
|
-
Local<Array> bindNames;
|
|
869
|
-
bool scanRequired;
|
|
870
|
-
|
|
871
|
-
// determine if bind definitions have been specified
|
|
872
|
-
Local<String> key = Nan::New<v8::String>("bindDefs").ToLocalChecked();
|
|
873
|
-
if (!Nan::Get(options, key).ToLocal(&bindDefs))
|
|
874
|
-
return false;
|
|
875
|
-
scanRequired = bindDefs->IsUndefined();
|
|
876
|
-
|
|
877
|
-
// if no bind definitions are specified, the first row is used to determine
|
|
878
|
-
// the number of bind variables and types
|
|
879
|
-
if (scanRequired && !binds.IsEmpty())
|
|
880
|
-
bindDefs = Nan::Get(binds, 0).ToLocalChecked();
|
|
881
|
-
if (!bindDefs->IsUndefined() && !bindDefs->IsArray())
|
|
882
|
-
bindNames = bindDefs.As<Object>()->GetOwnPropertyNames();
|
|
883
|
-
|
|
884
|
-
// initialize variables; if there are no variables, nothing further to do!
|
|
885
|
-
if (!InitBindVars(bindDefs.As<Object>(), bindNames, baton))
|
|
886
|
-
return false;
|
|
887
|
-
if (baton->numBindVars == 0)
|
|
888
|
-
return true;
|
|
889
|
-
|
|
890
|
-
// if no bind definitions are specified, scan the binds to determine type
|
|
891
|
-
// and size
|
|
892
|
-
if (scanRequired) {
|
|
893
|
-
if (!ScanExecuteManyBinds(binds, bindNames, baton))
|
|
894
|
-
return false;
|
|
895
|
-
|
|
896
|
-
// otherwise, use the bind definitions to determine type and size
|
|
897
|
-
} else {
|
|
898
|
-
bool byPosition = (baton->bindVars[0].pos > 0);
|
|
899
|
-
Local<Array> byPositionValues;
|
|
900
|
-
if (byPosition)
|
|
901
|
-
byPositionValues = bindDefs.As<Array>();
|
|
902
|
-
for (uint32_t i = 0; i < baton->numBindVars; i++) {
|
|
903
|
-
njsVariable *var = &baton->bindVars[i];
|
|
904
|
-
if (byPosition) {
|
|
905
|
-
bindUnit = Nan::Get(byPositionValues, i).ToLocalChecked();
|
|
906
|
-
} else {
|
|
907
|
-
bindName = Nan::Get(bindNames, i).ToLocalChecked();
|
|
908
|
-
if (!Nan::Get(bindDefs.As<Object>(),
|
|
909
|
-
bindName).ToLocal(&bindUnit))
|
|
910
|
-
return false;
|
|
911
|
-
}
|
|
912
|
-
if (!ScanExecuteBindUnit(bindUnit.As<Object>(), var, true, baton))
|
|
913
|
-
return false;
|
|
914
|
-
}
|
|
915
|
-
}
|
|
916
|
-
|
|
917
|
-
// create the ODPI-C variables used to hold the data
|
|
918
|
-
for (uint32_t i = 0; i < baton->numBindVars; i++) {
|
|
919
|
-
if (!CreateVarBuffer(&baton->bindVars[i], baton))
|
|
920
|
-
return false;
|
|
921
|
-
}
|
|
922
|
-
|
|
923
|
-
// populate the ODPI-C variables with the data from JavaScript binds
|
|
924
|
-
if (!binds.IsEmpty() && !TransferExecuteManyBinds(binds, bindNames, baton))
|
|
925
|
-
return false;
|
|
926
|
-
|
|
927
|
-
return true;
|
|
928
|
-
}
|
|
929
|
-
|
|
930
|
-
|
|
931
|
-
//-----------------------------------------------------------------------------
|
|
932
|
-
// njsConnection::ScanExecuteManyBinds()
|
|
933
|
-
// Scan the binds passed through to ExecuteMany() and determine the bind
|
|
934
|
-
// type and maximum size (for strings/buffers).
|
|
935
|
-
//-----------------------------------------------------------------------------
|
|
936
|
-
bool njsConnection::ScanExecuteManyBinds(Local<Array> binds,
|
|
937
|
-
Local<Array> bindNames, njsBaton *baton)
|
|
938
|
-
{
|
|
939
|
-
njsDataType defaultBindType;
|
|
940
|
-
uint32_t defaultMaxSize;
|
|
941
|
-
bool byPosition;
|
|
942
|
-
Nan::HandleScope scope;
|
|
943
|
-
Local<Array> byPositionValues;
|
|
944
|
-
Local<Value> bindName, val;
|
|
945
|
-
Local<Object> row;
|
|
946
|
-
njsVariable *var;
|
|
947
|
-
|
|
948
|
-
byPosition = (baton->bindVars[0].pos > 0);
|
|
949
|
-
for (uint32_t i = 0; i < baton->bindArraySize; i++) {
|
|
950
|
-
row = Nan::Get(binds, i).ToLocalChecked().As<Object>();
|
|
951
|
-
|
|
952
|
-
// verify that all rows are by position (array) or by name (object)
|
|
953
|
-
if ((byPosition && !row->IsArray()) ||
|
|
954
|
-
(!byPosition && row->IsArray())) {
|
|
955
|
-
baton->error = njsMessages::Get(errMixedBind);
|
|
956
|
-
return false;
|
|
957
|
-
}
|
|
958
|
-
|
|
959
|
-
// scan each of the columns in the row and determine the bind type and
|
|
960
|
-
// maximum size of the input data
|
|
961
|
-
if (byPosition)
|
|
962
|
-
byPositionValues = row.As<Array>();
|
|
963
|
-
for (uint32_t j = 0; j < baton->numBindVars; j++) {
|
|
964
|
-
var = &baton->bindVars[j];
|
|
965
|
-
if (byPosition) {
|
|
966
|
-
val = Nan::Get(byPositionValues, j).ToLocalChecked();
|
|
967
|
-
} else {
|
|
968
|
-
bindName = Nan::Get(bindNames, j).ToLocalChecked();
|
|
969
|
-
if (!Nan::Get(row, bindName).ToLocal(&val))
|
|
970
|
-
return false;
|
|
971
|
-
}
|
|
972
|
-
if (val->IsUndefined() || val->IsNull())
|
|
973
|
-
continue;
|
|
974
|
-
if (!GetBindTypeAndSizeFromValue(var, val, &defaultBindType,
|
|
975
|
-
&defaultMaxSize, baton, true))
|
|
976
|
-
return false;
|
|
977
|
-
if (var->bindDataType == NJS_DATATYPE_DEFAULT)
|
|
978
|
-
var->bindDataType = defaultBindType;
|
|
979
|
-
if (defaultMaxSize > var->maxSize)
|
|
980
|
-
var->maxSize = defaultMaxSize;
|
|
981
|
-
}
|
|
982
|
-
|
|
983
|
-
}
|
|
984
|
-
|
|
985
|
-
return true;
|
|
986
|
-
}
|
|
987
|
-
|
|
988
|
-
|
|
989
|
-
//-----------------------------------------------------------------------------
|
|
990
|
-
// njsConnection::TransferExecuteManyBinds()
|
|
991
|
-
// Transfer the binds from JavaScript to the ODPI-C variable buffers already
|
|
992
|
-
// created.
|
|
993
|
-
//-----------------------------------------------------------------------------
|
|
994
|
-
bool njsConnection::TransferExecuteManyBinds(Local<Array> binds,
|
|
995
|
-
Local<Array> bindNames, njsBaton *baton)
|
|
996
|
-
{
|
|
997
|
-
bool byPosition;
|
|
998
|
-
Nan::HandleScope scope;
|
|
999
|
-
Local<Array> byPositionValues;
|
|
1000
|
-
Local<Value> bindName, val;
|
|
1001
|
-
Local<Object> row;
|
|
1002
|
-
njsVariable *var;
|
|
1003
|
-
|
|
1004
|
-
// determine if we are binding by position or by name
|
|
1005
|
-
byPosition = (baton->bindVars[0].pos > 0);
|
|
1006
|
-
|
|
1007
|
-
// process each row
|
|
1008
|
-
for (uint32_t i = 0; i < baton->bindArraySize; i++) {
|
|
1009
|
-
row = Nan::Get(binds, i).ToLocalChecked().As<Object>();
|
|
1010
|
-
|
|
1011
|
-
// verify that all rows are by position (array) or by name (object)
|
|
1012
|
-
if ((byPosition && !row->IsArray()) ||
|
|
1013
|
-
(!byPosition && row->IsArray())) {
|
|
1014
|
-
baton->error = njsMessages::Get(errMixedBind);
|
|
1015
|
-
return false;
|
|
1016
|
-
}
|
|
1017
|
-
|
|
1018
|
-
// process each column
|
|
1019
|
-
if (byPosition)
|
|
1020
|
-
byPositionValues = row.As<Array>();
|
|
1021
|
-
for (uint32_t j = 0; j < baton->numBindVars; j++) {
|
|
1022
|
-
var = &baton->bindVars[j];
|
|
1023
|
-
if (byPosition) {
|
|
1024
|
-
val = Nan::Get(byPositionValues, j).ToLocalChecked();
|
|
1025
|
-
} else {
|
|
1026
|
-
bindName = Nan::Get(bindNames, j).ToLocalChecked();
|
|
1027
|
-
if (!Nan::Get(row, bindName).ToLocal(&val))
|
|
1028
|
-
return false;
|
|
1029
|
-
}
|
|
1030
|
-
if (!ProcessScalarBindValue(val, var, i, true, baton))
|
|
1031
|
-
return false;
|
|
1032
|
-
}
|
|
1033
|
-
|
|
1034
|
-
}
|
|
1035
|
-
|
|
1036
|
-
return true;
|
|
1037
|
-
}
|
|
1038
|
-
|
|
1039
|
-
|
|
1040
|
-
//-----------------------------------------------------------------------------
|
|
1041
|
-
// njsConnection::InitBindVars()
|
|
1042
|
-
// Initialize bind variables using the given bind objectd/array as a
|
|
1043
|
-
// template. For binds performed by name, return the bind names as an array.
|
|
1044
|
-
//-----------------------------------------------------------------------------
|
|
1045
|
-
bool njsConnection::InitBindVars(Local<Object> bindObj,
|
|
1046
|
-
Local<Array> bindNames, njsBaton *baton)
|
|
1047
|
-
{
|
|
1048
|
-
bool byPosition = bindObj->IsArray();
|
|
1049
|
-
|
|
1050
|
-
// create bind variables (one for each element of the bind array or each
|
|
1051
|
-
// property of the bind object)
|
|
1052
|
-
if (bindObj->IsUndefined()) {
|
|
1053
|
-
baton->numBindVars = 0;
|
|
1054
|
-
} else if (byPosition) {
|
|
1055
|
-
baton->numBindVars = bindObj.As<Array>()->Length();
|
|
1056
|
-
} else {
|
|
1057
|
-
baton->numBindVars = bindNames->Length();
|
|
1058
|
-
}
|
|
1059
|
-
baton->bindVars = new njsVariable[baton->numBindVars];
|
|
1060
|
-
|
|
1061
|
-
// initialize bind variables (set position or name)
|
|
1062
|
-
for (uint32_t i = 0; i < baton->numBindVars; i++) {
|
|
1063
|
-
njsVariable *var = &baton->bindVars[i];
|
|
1064
|
-
if (byPosition) {
|
|
1065
|
-
var->pos = i + 1;
|
|
1066
|
-
} else {
|
|
1067
|
-
Local<Value> temp = Nan::Get(bindNames, i).ToLocalChecked();
|
|
1068
|
-
Nan::Utf8String v8str(temp->ToString());
|
|
1069
|
-
std::string str = std::string(*v8str,
|
|
1070
|
-
static_cast<size_t>(v8str.length()));
|
|
1071
|
-
var->name = ":" + str;
|
|
1072
|
-
}
|
|
1073
|
-
}
|
|
1074
|
-
|
|
1075
|
-
return true;
|
|
1076
|
-
}
|
|
1077
|
-
|
|
1078
|
-
|
|
1079
|
-
//-----------------------------------------------------------------------------
|
|
1080
|
-
// njsConnection::ProcessBindValue()
|
|
1081
|
-
// Process bind value from JS and copy it to the variable that was created.
|
|
1082
|
-
//-----------------------------------------------------------------------------
|
|
1083
|
-
bool njsConnection::ProcessBindValue(Local<Value> value, njsVariable *var,
|
|
1084
|
-
njsBaton *baton)
|
|
1085
|
-
{
|
|
1086
|
-
// scalar values can be handled directly
|
|
1087
|
-
if (!var->isArray)
|
|
1088
|
-
return ProcessScalarBindValue(value, var, 0, false, baton);
|
|
1089
|
-
|
|
1090
|
-
// only strings and numbers are currently allowed
|
|
1091
|
-
if (var->varTypeNum != DPI_ORACLE_TYPE_VARCHAR &&
|
|
1092
|
-
var->varTypeNum != DPI_ORACLE_TYPE_NUMBER &&
|
|
1093
|
-
var->varTypeNum != DPI_ORACLE_TYPE_NATIVE_INT) {
|
|
1094
|
-
baton->error = njsMessages::Get(errInvalidTypeForArrayBind);
|
|
1095
|
-
return false;
|
|
1096
|
-
}
|
|
1097
|
-
|
|
1098
|
-
/* Expecting an array value here */
|
|
1099
|
-
if ( !value->IsArray ()) {
|
|
1100
|
-
baton->error = njsMessages::Get ( errNonArrayProvided ) ;
|
|
1101
|
-
return false;
|
|
1102
|
-
}
|
|
1103
|
-
|
|
1104
|
-
// set the number of actual elements in the variable
|
|
1105
|
-
Nan::HandleScope scope;
|
|
1106
|
-
Local<Array> arrayVal = Local<Array>::Cast(value);
|
|
1107
|
-
if (dpiVar_setNumElementsInArray(var->dpiVarHandle,
|
|
1108
|
-
arrayVal->Length()) < 0) {
|
|
1109
|
-
baton->GetDPIError();
|
|
1110
|
-
return false;
|
|
1111
|
-
}
|
|
1112
|
-
|
|
1113
|
-
// process each element in the array
|
|
1114
|
-
for (uint32_t i = 0; i < arrayVal->Length(); i++) {
|
|
1115
|
-
Local<Value> elementValue = Nan::Get (arrayVal, i).ToLocalChecked ();
|
|
1116
|
-
if (!ProcessScalarBindValue(elementValue, var, i, false, baton))
|
|
1117
|
-
return false;
|
|
1118
|
-
}
|
|
1119
|
-
|
|
1120
|
-
return true;
|
|
1121
|
-
}
|
|
1122
|
-
|
|
1123
|
-
|
|
1124
|
-
//-----------------------------------------------------------------------------
|
|
1125
|
-
// njsConnection::ProcessScalarBindValue()
|
|
1126
|
-
// Process scalar bind value from JS and copy it to the variable at the given
|
|
1127
|
-
// position.
|
|
1128
|
-
//-----------------------------------------------------------------------------
|
|
1129
|
-
bool njsConnection::ProcessScalarBindValue(Local<Value> value,
|
|
1130
|
-
njsVariable *var, uint32_t pos, bool inExecuteMany, njsBaton *baton)
|
|
1131
|
-
{
|
|
1132
|
-
Nan::HandleScope scope;
|
|
1133
|
-
bool bindOk = false;
|
|
1134
|
-
dpiData *data;
|
|
1135
|
-
|
|
1136
|
-
// initialization
|
|
1137
|
-
data = &var->buffer.dpiVarData[pos];
|
|
1138
|
-
data->isNull = 0;
|
|
1139
|
-
|
|
1140
|
-
// nulls and undefined in JS are mapped to NULL in Oracle; no checks needed
|
|
1141
|
-
if (value->IsUndefined() || value->IsNull()) {
|
|
1142
|
-
data->isNull = 1;
|
|
1143
|
-
bindOk = true;
|
|
1144
|
-
|
|
1145
|
-
// value is a string, variable type should be a string
|
|
1146
|
-
} else if (value->IsString()) {
|
|
1147
|
-
bindOk = (var->varTypeNum == DPI_ORACLE_TYPE_VARCHAR ||
|
|
1148
|
-
var->varTypeNum == DPI_ORACLE_TYPE_CLOB);
|
|
1149
|
-
if (bindOk) {
|
|
1150
|
-
Nan::Utf8String utf8str(value);
|
|
1151
|
-
if (utf8str.length() == 0) {
|
|
1152
|
-
data->isNull = 1;
|
|
1153
|
-
} else if (inExecuteMany &&
|
|
1154
|
-
(uint32_t) utf8str.length() > var->maxSize) {
|
|
1155
|
-
baton->error = njsMessages::Get(errMaxSizeTooSmall,
|
|
1156
|
-
var->maxSize, utf8str.length(), pos);
|
|
1157
|
-
return false;
|
|
1158
|
-
} else if (dpiVar_setFromBytes(var->dpiVarHandle, pos, *utf8str,
|
|
1159
|
-
static_cast<uint32_t>( utf8str.length())) < 0) {
|
|
1160
|
-
baton->GetDPIError();
|
|
1161
|
-
return false;
|
|
1162
|
-
}
|
|
1163
|
-
}
|
|
1164
|
-
|
|
1165
|
-
// value is an integer
|
|
1166
|
-
} else if (value->IsInt32() || value->IsUint32()) {
|
|
1167
|
-
bindOk = (var->varTypeNum == DPI_ORACLE_TYPE_NUMBER);
|
|
1168
|
-
if (bindOk) {
|
|
1169
|
-
if (var->nativeTypeNum == DPI_NATIVE_TYPE_INT64) {
|
|
1170
|
-
if (value->IsInt32()) {
|
|
1171
|
-
data->value.asInt64 = Nan::To<int32_t>(value).FromJust();
|
|
1172
|
-
} else {
|
|
1173
|
-
data->value.asInt64 = Nan::To<uint32_t>(value).FromJust();
|
|
1174
|
-
}
|
|
1175
|
-
} else {
|
|
1176
|
-
if (value->IsInt32()) {
|
|
1177
|
-
data->value.asDouble = Nan::To<int32_t>(value).FromJust();
|
|
1178
|
-
} else {
|
|
1179
|
-
data->value.asDouble = Nan::To<uint32_t>(value).FromJust();
|
|
1180
|
-
}
|
|
1181
|
-
}
|
|
1182
|
-
}
|
|
1183
|
-
|
|
1184
|
-
// value is a floating point number
|
|
1185
|
-
} else if (value->IsNumber()) {
|
|
1186
|
-
bindOk = (var->varTypeNum == DPI_ORACLE_TYPE_NUMBER);
|
|
1187
|
-
if (bindOk)
|
|
1188
|
-
data->value.asDouble = value->NumberValue();
|
|
1189
|
-
|
|
1190
|
-
// value is a date
|
|
1191
|
-
} else if (value->IsDate()) {
|
|
1192
|
-
bindOk = (var->varTypeNum == DPI_ORACLE_TYPE_TIMESTAMP_LTZ);
|
|
1193
|
-
if (bindOk) {
|
|
1194
|
-
Local<Date> date = value.As<Date>();
|
|
1195
|
-
data->value.asDouble = date->NumberValue();
|
|
1196
|
-
}
|
|
1197
|
-
|
|
1198
|
-
// value is a buffer
|
|
1199
|
-
} else if (Buffer::HasInstance(value)) {
|
|
1200
|
-
bindOk = (var->varTypeNum == DPI_ORACLE_TYPE_RAW ||
|
|
1201
|
-
var->varTypeNum == DPI_ORACLE_TYPE_BLOB);
|
|
1202
|
-
if (bindOk) {
|
|
1203
|
-
Local<Object> obj = value->ToObject();
|
|
1204
|
-
if (inExecuteMany && Buffer::Length(obj) > var->maxSize) {
|
|
1205
|
-
baton->error = njsMessages::Get(errMaxSizeTooSmall,
|
|
1206
|
-
var->maxSize, Buffer::Length(obj), pos);
|
|
1207
|
-
return false;
|
|
1208
|
-
} else if (dpiVar_setFromBytes(var->dpiVarHandle, pos,
|
|
1209
|
-
Buffer::Data(obj), (uint32_t) Buffer::Length(obj)) < 0) {
|
|
1210
|
-
baton->GetDPIError();
|
|
1211
|
-
return false;
|
|
1212
|
-
}
|
|
1213
|
-
}
|
|
1214
|
-
|
|
1215
|
-
// value is a LOB
|
|
1216
|
-
} else if (njsILob::HasInstance(value)) {
|
|
1217
|
-
bindOk = (var->varTypeNum == DPI_ORACLE_TYPE_CLOB ||
|
|
1218
|
-
var->varTypeNum == DPI_ORACLE_TYPE_BLOB);
|
|
1219
|
-
if (bindOk) {
|
|
1220
|
-
njsILob *lob = njsILob::GetInstance(value);
|
|
1221
|
-
dpiLob *lobHandle = lob->GetDPILobHandle();
|
|
1222
|
-
dpiLob *tempLobHandle = NULL;
|
|
1223
|
-
|
|
1224
|
-
// for INOUT binds a copy of the LOB is made and the copy bound
|
|
1225
|
-
// the original IN value is also closed
|
|
1226
|
-
if (var->bindDir == NJS_BIND_INOUT) {
|
|
1227
|
-
if (dpiLob_copy(lobHandle, &tempLobHandle) < 0) {
|
|
1228
|
-
baton->GetDPIError();
|
|
1229
|
-
return false;
|
|
1230
|
-
}
|
|
1231
|
-
if (!lob->ClearDPILobHandle(baton))
|
|
1232
|
-
return false;
|
|
1233
|
-
lobHandle = tempLobHandle;
|
|
1234
|
-
}
|
|
1235
|
-
|
|
1236
|
-
// perform the bind
|
|
1237
|
-
if (dpiVar_setFromLob(var->dpiVarHandle, pos, lobHandle) < 0) {
|
|
1238
|
-
baton->GetDPIError();
|
|
1239
|
-
if (tempLobHandle)
|
|
1240
|
-
dpiLob_release(tempLobHandle);
|
|
1241
|
-
return false;
|
|
1242
|
-
}
|
|
1243
|
-
if (tempLobHandle)
|
|
1244
|
-
dpiLob_release(tempLobHandle);
|
|
1245
|
-
}
|
|
1246
|
-
}
|
|
1247
|
-
|
|
1248
|
-
// check bind was successful
|
|
1249
|
-
if (!bindOk) {
|
|
1250
|
-
if (var->isArray && !var->name.empty()) {
|
|
1251
|
-
baton->error = njsMessages::Get(errIncompatibleTypeArrayBind,
|
|
1252
|
-
pos, var->name.c_str());
|
|
1253
|
-
} else if (var->isArray) {
|
|
1254
|
-
baton->error = njsMessages::Get(errIncompatibleTypeArrayIndexBind,
|
|
1255
|
-
pos, var->pos);
|
|
1256
|
-
} else {
|
|
1257
|
-
baton->error = njsMessages::Get(errBindValueAndTypeMismatch);
|
|
1258
|
-
}
|
|
1259
|
-
return false;
|
|
1260
|
-
}
|
|
1261
|
-
|
|
1262
|
-
return true;
|
|
1263
|
-
}
|
|
1264
|
-
|
|
1265
|
-
|
|
1266
|
-
//-----------------------------------------------------------------------------
|
|
1267
|
-
// njsConnection::GetBindTypeAndSizeFromValue()
|
|
1268
|
-
// Get the bind type from the value that has been passed in. If no bind type
|
|
1269
|
-
// is supported at this point, 0 is returned.
|
|
1270
|
-
//-----------------------------------------------------------------------------
|
|
1271
|
-
bool njsConnection::GetBindTypeAndSizeFromValue(njsVariable *var,
|
|
1272
|
-
Local<Value> value, njsDataType *bindType, uint32_t *maxSize,
|
|
1273
|
-
njsBaton *baton, bool scalarOnly)
|
|
1274
|
-
{
|
|
1275
|
-
if (value->IsUndefined() || value->IsNull()) {
|
|
1276
|
-
*bindType = NJS_DATATYPE_STR;
|
|
1277
|
-
*maxSize = 1;
|
|
1278
|
-
} else if (value->IsString()) {
|
|
1279
|
-
*bindType = NJS_DATATYPE_STR;
|
|
1280
|
-
Nan::Utf8String utf8str(value->ToString());
|
|
1281
|
-
*maxSize = static_cast<uint32_t>(utf8str.length());
|
|
1282
|
-
} else if (value->IsInt32() || value->IsUint32()) {
|
|
1283
|
-
*bindType = NJS_DATATYPE_INT;
|
|
1284
|
-
} else if (value->IsNumber()) {
|
|
1285
|
-
*bindType = NJS_DATATYPE_NUM;
|
|
1286
|
-
} else if (value->IsDate()) {
|
|
1287
|
-
*bindType = NJS_DATATYPE_DATE;
|
|
1288
|
-
} else if (!scalarOnly && value->IsArray()) {
|
|
1289
|
-
Nan::HandleScope scope;
|
|
1290
|
-
Local<Array> arrayVal = Local<Array>::Cast(value);
|
|
1291
|
-
Local<Value> element;
|
|
1292
|
-
njsDataType elementBindType;
|
|
1293
|
-
uint32_t elementMaxSize;
|
|
1294
|
-
for (uint32_t i = 0; i < arrayVal->Length(); i++) {
|
|
1295
|
-
element = Nan::Get (arrayVal, i).ToLocalChecked ();
|
|
1296
|
-
if (element->IsUndefined() || element->IsNull())
|
|
1297
|
-
continue;
|
|
1298
|
-
if (!GetBindTypeAndSizeFromValue(var, element, &elementBindType,
|
|
1299
|
-
&elementMaxSize, baton, true))
|
|
1300
|
-
return false;
|
|
1301
|
-
if (*bindType == NJS_DATATYPE_DEFAULT)
|
|
1302
|
-
*bindType = elementBindType;
|
|
1303
|
-
if (elementMaxSize > *maxSize)
|
|
1304
|
-
*maxSize = elementMaxSize;
|
|
1305
|
-
}
|
|
1306
|
-
} else if (value->IsObject()) {
|
|
1307
|
-
if (Buffer::HasInstance(value)) {
|
|
1308
|
-
*bindType = NJS_DATATYPE_BUFFER;
|
|
1309
|
-
*maxSize = static_cast<uint32_t>(
|
|
1310
|
-
Buffer::Length(value->ToObject()));
|
|
1311
|
-
} else if (njsILob::HasInstance(value)) {
|
|
1312
|
-
njsILob *lob = njsILob::GetInstance(value);
|
|
1313
|
-
*bindType = lob->GetDataType();
|
|
1314
|
-
}
|
|
1315
|
-
} else {
|
|
1316
|
-
baton->error= njsMessages::Get(errInvalidBindDataType, 2);
|
|
1317
|
-
return false;
|
|
1318
|
-
}
|
|
1319
|
-
return true;
|
|
1320
|
-
}
|
|
1321
|
-
|
|
1322
|
-
|
|
1323
|
-
//-----------------------------------------------------------------------------
|
|
1324
|
-
// njsConnection::ProcessExecuteOptions()
|
|
1325
|
-
// Processing of options for connection.execute(). If an error is detected,
|
|
1326
|
-
// the baton error is populated and false is returned.
|
|
1327
|
-
//-----------------------------------------------------------------------------
|
|
1328
|
-
bool njsConnection::ProcessExecuteOptions(Local<Object> options,
|
|
1329
|
-
njsBaton *baton)
|
|
1330
|
-
{
|
|
1331
|
-
Nan::HandleScope scope;
|
|
1332
|
-
|
|
1333
|
-
// process the basic options
|
|
1334
|
-
if (!baton->GetUnsignedIntFromJSON(options, "maxRows", 2, &baton->maxRows))
|
|
1335
|
-
return false;
|
|
1336
|
-
if (!baton->GetPositiveIntFromJSON(options, "fetchArraySize", 2,
|
|
1337
|
-
&baton->fetchArraySize))
|
|
1338
|
-
return false;
|
|
1339
|
-
if (!baton->GetUnsignedIntFromJSON(options, "outFormat", 2,
|
|
1340
|
-
&baton->outFormat))
|
|
1341
|
-
return false;
|
|
1342
|
-
if (baton->outFormat != NJS_ROWS_ARRAY &&
|
|
1343
|
-
baton->outFormat != NJS_ROWS_OBJECT) {
|
|
1344
|
-
baton->error = njsMessages::Get(errInvalidPropertyValue, "outFormat");
|
|
1345
|
-
return false;
|
|
1346
|
-
}
|
|
1347
|
-
if (!baton->GetBoolFromJSON(options, "resultSet", 2, &baton->getRS))
|
|
1348
|
-
return false;
|
|
1349
|
-
if (!baton->GetBoolFromJSON(options, "autoCommit", 2, &baton->autoCommit))
|
|
1350
|
-
return false;
|
|
1351
|
-
if (!baton->GetBoolFromJSON(options, "extendedMetaData", 2,
|
|
1352
|
-
&baton->extendedMetaData))
|
|
1353
|
-
return false;
|
|
1354
|
-
|
|
1355
|
-
// process the fetchAs specifications, if applicable
|
|
1356
|
-
Local<Value> key = Nan::New<v8::String>("fetchInfo").ToLocalChecked();
|
|
1357
|
-
Local<Value> val;
|
|
1358
|
-
if (!Nan::Get(options, key).ToLocal(&val))
|
|
1359
|
-
return false;
|
|
1360
|
-
if (!val->IsUndefined() && !val->IsNull()) {
|
|
1361
|
-
Local<Object> jsFetchInfo = val->ToObject();
|
|
1362
|
-
Local<Array> keys = jsFetchInfo->GetOwnPropertyNames();
|
|
1363
|
-
baton->numFetchInfo = keys->Length();
|
|
1364
|
-
if (baton->numFetchInfo > 0)
|
|
1365
|
-
baton->fetchInfo = new njsFetchInfo[baton->numFetchInfo];
|
|
1366
|
-
for (uint32_t i = 0; i < baton->numFetchInfo; i++) {
|
|
1367
|
-
Local<Value> temp = Nan::Get(keys, i).ToLocalChecked();
|
|
1368
|
-
Nan::Utf8String utf8str(temp->ToString());
|
|
1369
|
-
baton->fetchInfo[i].name = std::string(*utf8str,
|
|
1370
|
-
static_cast<size_t>(utf8str.length()));
|
|
1371
|
-
Local<Object> colInfo =
|
|
1372
|
-
Nan::Get(jsFetchInfo, temp).ToLocalChecked()->ToObject();
|
|
1373
|
-
uint32_t tempType = static_cast<uint32_t>(NJS_DATATYPE_UNKNOWN);
|
|
1374
|
-
if (!baton->GetUnsignedIntFromJSON(colInfo, "type", 2, &tempType))
|
|
1375
|
-
return false;
|
|
1376
|
-
if (tempType == (uint32_t) NJS_DATATYPE_UNKNOWN) {
|
|
1377
|
-
baton->error = njsMessages::Get(errNoTypeForConversion);
|
|
1378
|
-
return false;
|
|
1379
|
-
} else if (tempType != NJS_DATATYPE_DEFAULT &&
|
|
1380
|
-
tempType != NJS_DATATYPE_STR &&
|
|
1381
|
-
tempType != NJS_DATATYPE_BUFFER) {
|
|
1382
|
-
baton->error = njsMessages::Get(errInvalidTypeForConversion);
|
|
1383
|
-
return false;
|
|
1384
|
-
}
|
|
1385
|
-
baton->fetchInfo[i].type = (njsDataType) tempType;
|
|
1386
|
-
}
|
|
1387
|
-
}
|
|
1388
|
-
|
|
1389
|
-
return true;
|
|
1390
|
-
}
|
|
1391
|
-
|
|
1392
|
-
|
|
1393
|
-
//-----------------------------------------------------------------------------
|
|
1394
|
-
// njsConnection::ProcessExecuteManyOptions()
|
|
1395
|
-
// Processing of options for connection.executeMany(). If an error is
|
|
1396
|
-
// detected, the baton error is populated and false is returned.
|
|
1397
|
-
//-----------------------------------------------------------------------------
|
|
1398
|
-
bool njsConnection::ProcessExecuteManyOptions(Local<Object> options,
|
|
1399
|
-
njsBaton *baton)
|
|
1400
|
-
{
|
|
1401
|
-
if (!baton->GetBoolFromJSON(options, "autoCommit", 2, &baton->autoCommit))
|
|
1402
|
-
return false;
|
|
1403
|
-
if (!baton->GetBoolFromJSON(options, "batchErrors", 2,
|
|
1404
|
-
&baton->batchErrors))
|
|
1405
|
-
return false;
|
|
1406
|
-
if (!baton->GetBoolFromJSON(options, "dmlRowCounts", 2,
|
|
1407
|
-
&baton->dmlRowCounts))
|
|
1408
|
-
return false;
|
|
1409
|
-
|
|
1410
|
-
return true;
|
|
1411
|
-
}
|
|
1412
|
-
|
|
1413
|
-
|
|
1414
|
-
//-----------------------------------------------------------------------------
|
|
1415
|
-
// njsConnection::ProcessSubscriptionOptions()
|
|
1416
|
-
// Processing of options for connection.subscribe(). If an error is detected,
|
|
1417
|
-
// the baton error is populated and false is returned.
|
|
1418
|
-
//-----------------------------------------------------------------------------
|
|
1419
|
-
bool njsConnection::ProcessSubscriptionOptions(Local<Object> options,
|
|
1420
|
-
njsBaton *baton)
|
|
1421
|
-
{
|
|
1422
|
-
Nan::HandleScope scope;
|
|
1423
|
-
uint32_t temp;
|
|
1424
|
-
|
|
1425
|
-
// if subscription doesn't exist, get options for creating subscription
|
|
1426
|
-
if (!baton->dpiSubscrHandle) {
|
|
1427
|
-
temp = DPI_SUBSCR_NAMESPACE_DBCHANGE;
|
|
1428
|
-
if (!baton->GetUnsignedIntFromJSON(options, "namespace", 1,
|
|
1429
|
-
&temp))
|
|
1430
|
-
return false;
|
|
1431
|
-
baton->subscription->SetNamespace((dpiSubscrNamespace) temp);
|
|
1432
|
-
if (!baton->GetStringFromJSON(options, "ipAddress", 1,
|
|
1433
|
-
baton->ipAddress))
|
|
1434
|
-
return false;
|
|
1435
|
-
if (!baton->GetUnsignedIntFromJSON(options, "port", 1,
|
|
1436
|
-
&baton->portNumber))
|
|
1437
|
-
return false;
|
|
1438
|
-
if (!baton->GetUnsignedIntFromJSON(options, "timeout", 1,
|
|
1439
|
-
&baton->timeout))
|
|
1440
|
-
return false;
|
|
1441
|
-
if (!baton->GetUnsignedIntFromJSON(options, "operations", 1,
|
|
1442
|
-
&baton->operations))
|
|
1443
|
-
return false;
|
|
1444
|
-
if (!baton->GetUnsignedIntFromJSON(options, "qos", 1, &baton->qos))
|
|
1445
|
-
return false;
|
|
1446
|
-
if (!baton->GetUnsignedIntFromJSON(options, "groupingClass", 1,
|
|
1447
|
-
&baton->subscrGroupingClass))
|
|
1448
|
-
return false;
|
|
1449
|
-
if (!baton->GetUnsignedIntFromJSON(options, "groupingValue", 1,
|
|
1450
|
-
&baton->subscrGroupingValue))
|
|
1451
|
-
return false;
|
|
1452
|
-
if (!baton->GetUnsignedIntFromJSON(options, "groupingType", 1,
|
|
1453
|
-
&baton->subscrGroupingType))
|
|
1454
|
-
return false;
|
|
1455
|
-
Local<Function> callback;
|
|
1456
|
-
if (!baton->GetFunctionFromJSON(options, "callback", 1, &callback))
|
|
1457
|
-
return false;
|
|
1458
|
-
if (callback.IsEmpty()) {
|
|
1459
|
-
baton->error = njsMessages::Get(errMissingSubscrCallback);
|
|
1460
|
-
} else {
|
|
1461
|
-
baton->subscription->SetCallback(callback);
|
|
1462
|
-
}
|
|
1463
|
-
}
|
|
1464
|
-
|
|
1465
|
-
// get options that are used for registering queries
|
|
1466
|
-
if (baton->subscription->GetNamespace() == DPI_SUBSCR_NAMESPACE_DBCHANGE) {
|
|
1467
|
-
if (!baton->GetStringFromJSON(options, "sql", 1, baton->sql))
|
|
1468
|
-
return false;
|
|
1469
|
-
if (baton->sql.empty()) {
|
|
1470
|
-
baton->error = njsMessages::Get(errMissingSubscrSql);
|
|
1471
|
-
return false;
|
|
1472
|
-
}
|
|
1473
|
-
Local<Value> binds;
|
|
1474
|
-
Local<String> key = Nan::New("binds").ToLocalChecked();
|
|
1475
|
-
if (!Nan::Get(options, key).ToLocal(&binds))
|
|
1476
|
-
return false;
|
|
1477
|
-
if (!ProcessExecuteBinds(binds.As<Object>(), baton))
|
|
1478
|
-
return false;
|
|
1479
|
-
}
|
|
1480
|
-
|
|
1481
|
-
return true;
|
|
1482
|
-
}
|
|
1483
|
-
|
|
1484
|
-
|
|
1485
|
-
//-----------------------------------------------------------------------------
|
|
1486
|
-
// njsConnection::GetScalarValueFromVar()
|
|
1487
|
-
// Get the value from the DPI variable of the specified type at the specified
|
|
1488
|
-
// position in the variable. Return true if the get was successful; if not, the
|
|
1489
|
-
// baton error has been populated with the error that was received from DPI.
|
|
1490
|
-
//-----------------------------------------------------------------------------
|
|
1491
|
-
bool njsConnection::GetScalarValueFromVar(njsBaton *baton, njsVariable *var,
|
|
1492
|
-
njsVariableBuffer *buffer, uint32_t pos, Local<Value> &value)
|
|
1493
|
-
{
|
|
1494
|
-
Nan::EscapableHandleScope scope;
|
|
1495
|
-
Local<Value> temp;
|
|
1496
|
-
|
|
1497
|
-
// LOBs make use of the njsProtoILob objects created in the worker thread
|
|
1498
|
-
if (buffer->lobs) {
|
|
1499
|
-
njsProtoILob *protoLob = &buffer->lobs[pos];
|
|
1500
|
-
if (!protoLob->dpiLobHandle) {
|
|
1501
|
-
temp = Nan::Null();
|
|
1502
|
-
} else {
|
|
1503
|
-
Local<Value> argv[1];
|
|
1504
|
-
argv[0] = njsILob::CreateFromProtoLob(protoLob);
|
|
1505
|
-
Local<Value> key = Nan::New<String>("newLob").ToLocalChecked();
|
|
1506
|
-
Local<Object> jsOracledb = Nan::New(baton->jsOracledb);
|
|
1507
|
-
Local<Function> fn = Local<Function>::Cast(Nan::Get( jsOracledb,
|
|
1508
|
-
key).ToLocalChecked());
|
|
1509
|
-
temp = fn->Call(jsOracledb, 1, argv);
|
|
1510
|
-
}
|
|
1511
|
-
value = scope.Escape(temp);
|
|
1512
|
-
return true;
|
|
1513
|
-
}
|
|
1514
|
-
|
|
1515
|
-
// get the value from ODPI-C
|
|
1516
|
-
uint32_t bufferRowIndex = baton->bufferRowIndex + pos;
|
|
1517
|
-
dpiData *data = &buffer->dpiVarData[bufferRowIndex];
|
|
1518
|
-
|
|
1519
|
-
// transform it to a JS value
|
|
1520
|
-
if (data->isNull) {
|
|
1521
|
-
value = scope.Escape(Nan::Null());
|
|
1522
|
-
return true;
|
|
1523
|
-
}
|
|
1524
|
-
switch (var->nativeTypeNum) {
|
|
1525
|
-
case DPI_NATIVE_TYPE_INT64:
|
|
1526
|
-
temp = Nan::New<Number>((double) data->value.asInt64);
|
|
1527
|
-
break;
|
|
1528
|
-
case DPI_NATIVE_TYPE_FLOAT:
|
|
1529
|
-
temp = Nan::New<Number>(data->value.asFloat);
|
|
1530
|
-
break;
|
|
1531
|
-
case DPI_NATIVE_TYPE_DOUBLE:
|
|
1532
|
-
if (var->varTypeNum == DPI_ORACLE_TYPE_TIMESTAMP_LTZ) {
|
|
1533
|
-
temp = Nan::New<Date>(data->value.asDouble).ToLocalChecked();
|
|
1534
|
-
} else {
|
|
1535
|
-
temp = Nan::New<Number>(data->value.asDouble);
|
|
1536
|
-
}
|
|
1537
|
-
break;
|
|
1538
|
-
case DPI_NATIVE_TYPE_BYTES:
|
|
1539
|
-
if (data->value.asBytes.length > var->maxSize) {
|
|
1540
|
-
baton->error = njsMessages::Get(errInsufficientBufferForBinds);
|
|
1541
|
-
return false;
|
|
1542
|
-
}
|
|
1543
|
-
if (data->value.asBytes.length == 0) {
|
|
1544
|
-
temp = Nan::Null();
|
|
1545
|
-
} else if (var->varTypeNum == DPI_ORACLE_TYPE_RAW ||
|
|
1546
|
-
var->varTypeNum == DPI_ORACLE_TYPE_LONG_RAW) {
|
|
1547
|
-
temp = Nan::CopyBuffer(data->value.asBytes.ptr,
|
|
1548
|
-
data->value.asBytes.length).ToLocalChecked();
|
|
1549
|
-
} else {
|
|
1550
|
-
temp = Nan::New<v8::String>(data->value.asBytes.ptr,
|
|
1551
|
-
data->value.asBytes.length).ToLocalChecked();
|
|
1552
|
-
}
|
|
1553
|
-
break;
|
|
1554
|
-
case DPI_NATIVE_TYPE_STMT:
|
|
1555
|
-
if (!njsResultSet::CreateFromRefCursor(baton, data->value.asStmt,
|
|
1556
|
-
var->queryVars, var->numQueryVars, temp))
|
|
1557
|
-
return false;
|
|
1558
|
-
var->queryVars = NULL;
|
|
1559
|
-
var->numQueryVars = 0;
|
|
1560
|
-
break;
|
|
1561
|
-
case DPI_NATIVE_TYPE_ROWID:
|
|
1562
|
-
uint32_t rowidValueLength;
|
|
1563
|
-
const char *rowidValue;
|
|
1564
|
-
if (dpiRowid_getStringValue(data->value.asRowid, &rowidValue,
|
|
1565
|
-
&rowidValueLength) < 0) {
|
|
1566
|
-
baton->GetDPIError();
|
|
1567
|
-
return false;
|
|
1568
|
-
}
|
|
1569
|
-
temp = Nan::New<v8::String>(rowidValue,
|
|
1570
|
-
rowidValueLength).ToLocalChecked();
|
|
1571
|
-
break;
|
|
1572
|
-
default:
|
|
1573
|
-
break;
|
|
1574
|
-
}
|
|
1575
|
-
value = scope.Escape(temp);
|
|
1576
|
-
return true;
|
|
1577
|
-
}
|
|
1578
|
-
|
|
1579
|
-
|
|
1580
|
-
//-----------------------------------------------------------------------------
|
|
1581
|
-
// njsConnection::GetArrayValueFromVar()
|
|
1582
|
-
// Get the value from the DPI variable of the specified type as an array.
|
|
1583
|
-
//-----------------------------------------------------------------------------
|
|
1584
|
-
bool njsConnection::GetArrayValueFromVar(njsBaton *baton, njsVariable *var,
|
|
1585
|
-
uint32_t pos, Local<Value> &value)
|
|
1586
|
-
{
|
|
1587
|
-
njsVariableBuffer *buffer = &var->buffer;
|
|
1588
|
-
|
|
1589
|
-
if (var->dmlReturningBuffers)
|
|
1590
|
-
buffer = &var->dmlReturningBuffers[pos];
|
|
1591
|
-
Nan::EscapableHandleScope scope;
|
|
1592
|
-
Local<Array> arrayVal = Nan::New<Array>(buffer->numElements);
|
|
1593
|
-
for (uint32_t i = 0; i < buffer->numElements; i++) {
|
|
1594
|
-
Local<Value> elementValue;
|
|
1595
|
-
if (!GetScalarValueFromVar(baton, var, buffer, i, elementValue))
|
|
1596
|
-
return false;
|
|
1597
|
-
Nan::Set(arrayVal, i, elementValue);
|
|
1598
|
-
}
|
|
1599
|
-
value = scope.Escape(arrayVal);
|
|
1600
|
-
return true;
|
|
1601
|
-
}
|
|
1602
|
-
|
|
1603
|
-
|
|
1604
|
-
//-----------------------------------------------------------------------------
|
|
1605
|
-
// njsConnection::GetExecuteOutBinds()
|
|
1606
|
-
// Get the out binds as an object/array.
|
|
1607
|
-
//-----------------------------------------------------------------------------
|
|
1608
|
-
bool njsConnection::GetExecuteOutBinds(Local<Value> &outBinds, njsBaton *baton)
|
|
1609
|
-
{
|
|
1610
|
-
uint32_t numOutBinds = baton->GetNumOutBinds();
|
|
1611
|
-
|
|
1612
|
-
if (numOutBinds > 0)
|
|
1613
|
-
return GetOutBinds(outBinds, numOutBinds, 0, baton);
|
|
1614
|
-
return true;
|
|
1615
|
-
}
|
|
1616
|
-
|
|
1617
|
-
|
|
1618
|
-
//-----------------------------------------------------------------------------
|
|
1619
|
-
// njsConnection::GetExecuteManyOutBinds()
|
|
1620
|
-
// Get the out binds as an object/array.
|
|
1621
|
-
//-----------------------------------------------------------------------------
|
|
1622
|
-
bool njsConnection::GetExecuteManyOutBinds(Local<Value> &outBinds,
|
|
1623
|
-
uint32_t numOutBinds, njsBaton *baton)
|
|
1624
|
-
{
|
|
1625
|
-
Nan::EscapableHandleScope scope;
|
|
1626
|
-
Local<Array> rows = Nan::New<Array>(baton->bindArraySize);
|
|
1627
|
-
Local<Value> row;
|
|
1628
|
-
|
|
1629
|
-
for (uint32_t i = 0; i < baton->bindArraySize; i++) {
|
|
1630
|
-
if (!GetOutBinds(row, numOutBinds, i, baton))
|
|
1631
|
-
return false;
|
|
1632
|
-
Nan::Set(rows, i, row);
|
|
1633
|
-
}
|
|
1634
|
-
outBinds = scope.Escape(rows);
|
|
1635
|
-
return true;
|
|
1636
|
-
}
|
|
1637
|
-
|
|
1638
|
-
|
|
1639
|
-
//-----------------------------------------------------------------------------
|
|
1640
|
-
// njsConnection::GetOutBinds()
|
|
1641
|
-
// Get the out binds as an object/array.
|
|
1642
|
-
//-----------------------------------------------------------------------------
|
|
1643
|
-
bool njsConnection::GetOutBinds(Local<Value> &outBinds, uint32_t numOutBinds,
|
|
1644
|
-
uint32_t pos, njsBaton *baton)
|
|
1645
|
-
{
|
|
1646
|
-
Nan::EscapableHandleScope scope;
|
|
1647
|
-
Local<Array> bindArray;
|
|
1648
|
-
Local<Object> bindObj;
|
|
1649
|
-
Local<Value> val;
|
|
1650
|
-
bool bindByPos, ok;
|
|
1651
|
-
njsVariable *var;
|
|
1652
|
-
|
|
1653
|
-
bindByPos = baton->bindVars[0].name.empty();
|
|
1654
|
-
if (bindByPos) {
|
|
1655
|
-
bindArray = Nan::New<Array>(numOutBinds);
|
|
1656
|
-
} else {
|
|
1657
|
-
bindObj = Nan::New<Object>();
|
|
1658
|
-
}
|
|
1659
|
-
uint32_t arrayPos = 0;
|
|
1660
|
-
for (uint32_t i = 0; i < baton->numBindVars; i++) {
|
|
1661
|
-
var = &baton->bindVars[i];
|
|
1662
|
-
if (var->bindDir == NJS_BIND_IN)
|
|
1663
|
-
continue;
|
|
1664
|
-
if (var->isArray || baton->isReturning) {
|
|
1665
|
-
ok = GetArrayValueFromVar(baton, var, pos, val);
|
|
1666
|
-
} else {
|
|
1667
|
-
ok = GetScalarValueFromVar(baton, var, &var->buffer, pos, val);
|
|
1668
|
-
}
|
|
1669
|
-
if (!ok)
|
|
1670
|
-
return false;
|
|
1671
|
-
if (bindByPos) {
|
|
1672
|
-
Nan::Set(bindArray, arrayPos++, val);
|
|
1673
|
-
} else {
|
|
1674
|
-
Local<String> key = Nan::New<String>(var->name.c_str() + 1,
|
|
1675
|
-
(int) var->name.length() - 1).ToLocalChecked();
|
|
1676
|
-
Nan::Set(bindObj, key, val);
|
|
1677
|
-
}
|
|
1678
|
-
}
|
|
1679
|
-
if (bindByPos) {
|
|
1680
|
-
outBinds = scope.Escape(bindArray);
|
|
1681
|
-
} else {
|
|
1682
|
-
outBinds = scope.Escape(bindObj);
|
|
1683
|
-
}
|
|
1684
|
-
|
|
1685
|
-
return true;
|
|
1686
|
-
}
|
|
1687
|
-
|
|
1688
|
-
|
|
1689
|
-
//-----------------------------------------------------------------------------
|
|
1690
|
-
// njsConnection::SetTextAttribute()
|
|
1691
|
-
// Set text attribute -- calls DPI passing the JS buffer provided, after
|
|
1692
|
-
// first validating the connection.
|
|
1693
|
-
//-----------------------------------------------------------------------------
|
|
1694
|
-
void njsConnection::SetTextAttribute(Nan::NAN_SETTER_ARGS_TYPE args,
|
|
1695
|
-
const char *attributeName, Local<Value> value,
|
|
1696
|
-
int (*setter)(dpiConn*, const char *, uint32_t))
|
|
1697
|
-
{
|
|
1698
|
-
njsConnection *connection = (njsConnection*) ValidateSetter(args);
|
|
1699
|
-
if (!connection)
|
|
1700
|
-
return;
|
|
1701
|
-
if (!value->IsString()) {
|
|
1702
|
-
string errMsg = njsMessages::Get(errInvalidPropertyValue,
|
|
1703
|
-
attributeName);
|
|
1704
|
-
Nan::ThrowError(errMsg.c_str());
|
|
1705
|
-
return;
|
|
1706
|
-
}
|
|
1707
|
-
Nan::Utf8String utfstr(value->ToString());
|
|
1708
|
-
uint32_t valueLength = static_cast<uint32_t>(utfstr.length());
|
|
1709
|
-
if ((*setter)(connection->dpiConnHandle, *utfstr, valueLength) < 0)
|
|
1710
|
-
njsOracledb::ThrowDPIError();
|
|
1711
|
-
}
|
|
1712
|
-
|
|
1713
|
-
|
|
1714
|
-
//-----------------------------------------------------------------------------
|
|
1715
|
-
// njsConnection::New()
|
|
1716
|
-
// Create new object accesible from JS. This is always called from within
|
|
1717
|
-
// Connnection::CreateFromBaton() and never from any external JS.
|
|
1718
|
-
//-----------------------------------------------------------------------------
|
|
1719
|
-
NAN_METHOD(njsConnection::New)
|
|
1720
|
-
{
|
|
1721
|
-
njsConnection *connection = new njsConnection();
|
|
1722
|
-
connection->Wrap(info.Holder());
|
|
1723
|
-
info.GetReturnValue().Set(info.Holder());
|
|
1724
|
-
}
|
|
1725
|
-
|
|
1726
|
-
|
|
1727
|
-
//-----------------------------------------------------------------------------
|
|
1728
|
-
// njsConnection::Execute()
|
|
1729
|
-
// Executes a statement on the connection.
|
|
1730
|
-
//
|
|
1731
|
-
// PARAMETERS
|
|
1732
|
-
// - SQL Statement
|
|
1733
|
-
// - Binds Object/Array (Optional)
|
|
1734
|
-
// - Options Object (Optional)
|
|
1735
|
-
// - JS callback which will receive (error, result set)
|
|
1736
|
-
//-----------------------------------------------------------------------------
|
|
1737
|
-
NAN_METHOD(njsConnection::Execute)
|
|
1738
|
-
{
|
|
1739
|
-
njsConnection *connection;
|
|
1740
|
-
njsOracledb *oracledb;
|
|
1741
|
-
std::string sql;
|
|
1742
|
-
njsBaton *baton;
|
|
1743
|
-
|
|
1744
|
-
connection = (njsConnection*) ValidateArgs(info, 4, 4);
|
|
1745
|
-
if (!connection)
|
|
1746
|
-
return;
|
|
1747
|
-
if (!connection->GetStringArg(info, 0, sql))
|
|
1748
|
-
return;
|
|
1749
|
-
baton = connection->CreateBaton(info);
|
|
1750
|
-
if (!baton)
|
|
1751
|
-
return;
|
|
1752
|
-
Nan::TryCatch tryCatch;
|
|
1753
|
-
bool ok = baton->error.empty();
|
|
1754
|
-
if (ok) {
|
|
1755
|
-
baton->sql = sql;
|
|
1756
|
-
baton->SetDPIConnHandle(connection->dpiConnHandle);
|
|
1757
|
-
baton->jsOracledb.Reset(connection->jsOracledb);
|
|
1758
|
-
oracledb = baton->GetOracledb();
|
|
1759
|
-
baton->maxRows = oracledb->getMaxRows();
|
|
1760
|
-
baton->fetchArraySize = oracledb->getFetchArraySize();
|
|
1761
|
-
oracledb->SetFetchAsStringTypesOnBaton(baton);
|
|
1762
|
-
oracledb->SetFetchAsBufferTypesOnBaton(baton);
|
|
1763
|
-
baton->outFormat = oracledb->getOutFormat();
|
|
1764
|
-
baton->autoCommit = oracledb->getAutoCommit();
|
|
1765
|
-
baton->extendedMetaData = oracledb->getExtendedMetaData();
|
|
1766
|
-
}
|
|
1767
|
-
if (ok)
|
|
1768
|
-
ok = ProcessExecuteBinds(info[1].As<Object>(), baton);
|
|
1769
|
-
if (ok)
|
|
1770
|
-
ProcessExecuteOptions(info[2].As<Object>(), baton);
|
|
1771
|
-
baton->CheckJSException(&tryCatch);
|
|
1772
|
-
baton->QueueWork("Execute", Async_Execute, Async_AfterExecute, 2);
|
|
1773
|
-
}
|
|
1774
|
-
|
|
1775
|
-
|
|
1776
|
-
//-----------------------------------------------------------------------------
|
|
1777
|
-
// njsConnection::Async_Execute()
|
|
1778
|
-
// Worker function for njsConnection::Execute() method.
|
|
1779
|
-
//-----------------------------------------------------------------------------
|
|
1780
|
-
void njsConnection::Async_Execute(njsBaton *baton)
|
|
1781
|
-
{
|
|
1782
|
-
dpiExecMode mode;
|
|
1783
|
-
|
|
1784
|
-
// prepare statement and perform any binds that are needed
|
|
1785
|
-
if (!PrepareAndBind(baton))
|
|
1786
|
-
return;
|
|
1787
|
-
|
|
1788
|
-
// execute statement
|
|
1789
|
-
mode = (baton->autoCommit) ? DPI_MODE_EXEC_COMMIT_ON_SUCCESS :
|
|
1790
|
-
DPI_MODE_EXEC_DEFAULT;
|
|
1791
|
-
if (dpiStmt_execute(baton->dpiStmtHandle, mode,
|
|
1792
|
-
&baton->numQueryVars) < 0) {
|
|
1793
|
-
baton->GetDPIError();
|
|
1794
|
-
return;
|
|
1795
|
-
}
|
|
1796
|
-
|
|
1797
|
-
// for queries, perform defines
|
|
1798
|
-
if (baton->numQueryVars > 0) {
|
|
1799
|
-
|
|
1800
|
-
// perform defines
|
|
1801
|
-
baton->queryVars = new njsVariable[baton->numQueryVars];
|
|
1802
|
-
if (!ProcessQueryVars(baton, baton->dpiStmtHandle, baton->queryVars,
|
|
1803
|
-
baton->numQueryVars))
|
|
1804
|
-
return;
|
|
1805
|
-
|
|
1806
|
-
// for all other statements, determine the number of rows affected
|
|
1807
|
-
// and process any LOBS for out binds, as needed
|
|
1808
|
-
} else {
|
|
1809
|
-
if (dpiStmt_getRowCount(baton->dpiStmtHandle,
|
|
1810
|
-
&baton->rowsAffected) < 0) {
|
|
1811
|
-
baton->GetDPIError();
|
|
1812
|
-
return;
|
|
1813
|
-
}
|
|
1814
|
-
baton->bufferRowIndex = 0;
|
|
1815
|
-
if (!ProcessVars(baton, baton->bindVars, baton->numBindVars, 1))
|
|
1816
|
-
return;
|
|
1817
|
-
}
|
|
1818
|
-
}
|
|
1819
|
-
|
|
1820
|
-
|
|
1821
|
-
//-----------------------------------------------------------------------------
|
|
1822
|
-
// njsConnection::Async_AfterExecute()
|
|
1823
|
-
// Returns result to JS by invoking JS callback.
|
|
1824
|
-
//-----------------------------------------------------------------------------
|
|
1825
|
-
void njsConnection::Async_AfterExecute(njsBaton *baton, Local<Value> argv[])
|
|
1826
|
-
{
|
|
1827
|
-
Nan::EscapableHandleScope scope;
|
|
1828
|
-
Local<Object> result = Nan::New<v8::Object>();
|
|
1829
|
-
|
|
1830
|
-
// handle queries
|
|
1831
|
-
if (baton->queryVars) {
|
|
1832
|
-
Nan::Set(result, Nan::New<v8::String>("metaData").ToLocalChecked(),
|
|
1833
|
-
GetMetaData(baton->queryVars, baton->numQueryVars,
|
|
1834
|
-
baton->extendedMetaData));
|
|
1835
|
-
Local<Object> resultSet = njsResultSet::CreateFromBaton(baton);
|
|
1836
|
-
Nan::Set(result, Nan::New<String>("resultSet").ToLocalChecked(),
|
|
1837
|
-
resultSet);
|
|
1838
|
-
|
|
1839
|
-
} else {
|
|
1840
|
-
Local<Value> outBinds = Nan::Undefined();
|
|
1841
|
-
GetExecuteOutBinds(outBinds, baton);
|
|
1842
|
-
if (!outBinds->IsUndefined()) {
|
|
1843
|
-
Nan::DefineOwnProperty(result,
|
|
1844
|
-
Nan::New<v8::String>("outBinds").ToLocalChecked(),
|
|
1845
|
-
outBinds, v8::ReadOnly);
|
|
1846
|
-
}
|
|
1847
|
-
if (!baton->isPLSQL) {
|
|
1848
|
-
Nan::DefineOwnProperty(result,
|
|
1849
|
-
Nan::New<v8::String>("rowsAffected").ToLocalChecked(),
|
|
1850
|
-
Nan::New<v8::Integer>( (unsigned int) baton->rowsAffected),
|
|
1851
|
-
v8::ReadOnly);
|
|
1852
|
-
}
|
|
1853
|
-
}
|
|
1854
|
-
argv[1] = scope.Escape(result);
|
|
1855
|
-
}
|
|
1856
|
-
|
|
1857
|
-
|
|
1858
|
-
//-----------------------------------------------------------------------------
|
|
1859
|
-
// njsConnection::ExecuteMany()
|
|
1860
|
-
// Executes a statement on the connection multiple times, once for each row
|
|
1861
|
-
// of data that is passed.
|
|
1862
|
-
//
|
|
1863
|
-
// PARAMETERS
|
|
1864
|
-
// - SQL Statement
|
|
1865
|
-
// - Array of Binds
|
|
1866
|
-
// - Options Object (Optional)
|
|
1867
|
-
// - JS callback which will receive (error, result)
|
|
1868
|
-
//-----------------------------------------------------------------------------
|
|
1869
|
-
NAN_METHOD(njsConnection::ExecuteMany)
|
|
1870
|
-
{
|
|
1871
|
-
njsConnection *connection;
|
|
1872
|
-
njsOracledb *oracledb;
|
|
1873
|
-
std::string sql;
|
|
1874
|
-
njsBaton *baton;
|
|
1875
|
-
|
|
1876
|
-
connection = (njsConnection*) ValidateArgs(info, 4, 4);
|
|
1877
|
-
if (!connection)
|
|
1878
|
-
return;
|
|
1879
|
-
if (!connection->GetStringArg(info, 0, sql))
|
|
1880
|
-
return;
|
|
1881
|
-
baton = connection->CreateBaton(info);
|
|
1882
|
-
if (!baton)
|
|
1883
|
-
return;
|
|
1884
|
-
Nan::TryCatch tryCatch;
|
|
1885
|
-
bool ok = baton->error.empty();
|
|
1886
|
-
if (ok) {
|
|
1887
|
-
baton->sql = sql;
|
|
1888
|
-
baton->SetDPIConnHandle(connection->dpiConnHandle);
|
|
1889
|
-
baton->jsOracledb.Reset(connection->jsOracledb);
|
|
1890
|
-
oracledb = baton->GetOracledb();
|
|
1891
|
-
baton->autoCommit = oracledb->getAutoCommit();
|
|
1892
|
-
}
|
|
1893
|
-
if (ok)
|
|
1894
|
-
ok = ProcessExecuteManyOptions(info[2].As<Object>(), baton);
|
|
1895
|
-
if (ok) {
|
|
1896
|
-
Local<Array> binds;
|
|
1897
|
-
if (info[1]->IsUint32()) {
|
|
1898
|
-
baton->bindArraySize = Nan::To<uint32_t>(info[1]).FromJust();
|
|
1899
|
-
} else {
|
|
1900
|
-
binds = info[1].As<Array>();
|
|
1901
|
-
baton->bindArraySize = binds->Length();
|
|
1902
|
-
}
|
|
1903
|
-
ProcessExecuteManyBinds(binds, info[2].As<Object>(), baton);
|
|
1904
|
-
}
|
|
1905
|
-
baton->CheckJSException(&tryCatch);
|
|
1906
|
-
baton->QueueWork("ExecuteMany", Async_ExecuteMany,
|
|
1907
|
-
Async_AfterExecuteMany, 2);
|
|
1908
|
-
}
|
|
1909
|
-
|
|
1910
|
-
|
|
1911
|
-
//-----------------------------------------------------------------------------
|
|
1912
|
-
// njsConnection::Async_ExecuteMany()
|
|
1913
|
-
// Worker function for njsConnection::ExecuteMany() method.
|
|
1914
|
-
//-----------------------------------------------------------------------------
|
|
1915
|
-
void njsConnection::Async_ExecuteMany(njsBaton *baton)
|
|
1916
|
-
{
|
|
1917
|
-
uint32_t mode;
|
|
1918
|
-
|
|
1919
|
-
// prepare statement and perform any binds that are needed
|
|
1920
|
-
if (!PrepareAndBind(baton))
|
|
1921
|
-
return;
|
|
1922
|
-
|
|
1923
|
-
// execute statement
|
|
1924
|
-
mode = (baton->autoCommit) ? DPI_MODE_EXEC_COMMIT_ON_SUCCESS :
|
|
1925
|
-
DPI_MODE_EXEC_DEFAULT;
|
|
1926
|
-
if (baton->batchErrors)
|
|
1927
|
-
mode |= DPI_MODE_EXEC_BATCH_ERRORS;
|
|
1928
|
-
if (baton->dmlRowCounts)
|
|
1929
|
-
mode |= DPI_MODE_EXEC_ARRAY_DML_ROWCOUNTS;
|
|
1930
|
-
if (dpiStmt_executeMany(baton->dpiStmtHandle, (dpiExecMode) mode,
|
|
1931
|
-
baton->bindArraySize) < 0) {
|
|
1932
|
-
baton->GetDPIError();
|
|
1933
|
-
return;
|
|
1934
|
-
}
|
|
1935
|
-
|
|
1936
|
-
// process any LOBS for out binds, as needed
|
|
1937
|
-
if (dpiStmt_getRowCount(baton->dpiStmtHandle,
|
|
1938
|
-
&baton->rowsAffected) < 0) {
|
|
1939
|
-
baton->GetDPIError();
|
|
1940
|
-
return;
|
|
1941
|
-
}
|
|
1942
|
-
baton->bufferRowIndex = 0;
|
|
1943
|
-
if (!ProcessVars(baton, baton->bindVars, baton->numBindVars,
|
|
1944
|
-
baton->bindArraySize))
|
|
1945
|
-
return;
|
|
1946
|
-
|
|
1947
|
-
// get DML row counts if option was enabled
|
|
1948
|
-
if (baton->dmlRowCounts) {
|
|
1949
|
-
if (dpiStmt_getRowCounts(baton->dpiStmtHandle, &baton->numRowCounts,
|
|
1950
|
-
&baton->rowCounts) < 0) {
|
|
1951
|
-
baton->GetDPIError();
|
|
1952
|
-
return;
|
|
1953
|
-
}
|
|
1954
|
-
}
|
|
1955
|
-
|
|
1956
|
-
// get batch errors, if option was enabled
|
|
1957
|
-
if (baton->batchErrors) {
|
|
1958
|
-
if (dpiStmt_getBatchErrorCount(baton->dpiStmtHandle,
|
|
1959
|
-
&baton->numBatchErrorInfos) < 0) {
|
|
1960
|
-
baton->GetDPIError();
|
|
1961
|
-
return;
|
|
1962
|
-
}
|
|
1963
|
-
if (baton->numBatchErrorInfos > 0) {
|
|
1964
|
-
baton->batchErrorInfos =
|
|
1965
|
-
new dpiErrorInfo[baton->numBatchErrorInfos];
|
|
1966
|
-
if (dpiStmt_getBatchErrors(baton->dpiStmtHandle,
|
|
1967
|
-
baton->numBatchErrorInfos, baton->batchErrorInfos) < 0) {
|
|
1968
|
-
baton->GetDPIError();
|
|
1969
|
-
return;
|
|
1970
|
-
}
|
|
1971
|
-
}
|
|
1972
|
-
}
|
|
1973
|
-
|
|
1974
|
-
}
|
|
1975
|
-
|
|
1976
|
-
|
|
1977
|
-
//-----------------------------------------------------------------------------
|
|
1978
|
-
// njsConnection::Async_AfterExecuteMany()
|
|
1979
|
-
// Returns result to JS by invoking JS callback.
|
|
1980
|
-
//-----------------------------------------------------------------------------
|
|
1981
|
-
void njsConnection::Async_AfterExecuteMany(njsBaton *baton,
|
|
1982
|
-
Local<Value> argv[])
|
|
1983
|
-
{
|
|
1984
|
-
Nan::EscapableHandleScope scope;
|
|
1985
|
-
Local<Object> result = Nan::New<v8::Object>();
|
|
1986
|
-
|
|
1987
|
-
// get out binds
|
|
1988
|
-
uint32_t numOutBinds = baton->GetNumOutBinds();
|
|
1989
|
-
Local<Value> outBinds;
|
|
1990
|
-
if (numOutBinds > 0) {
|
|
1991
|
-
if (GetExecuteManyOutBinds(outBinds, numOutBinds, baton)) {
|
|
1992
|
-
Local<String> key = Nan::New<String>("outBinds").ToLocalChecked();
|
|
1993
|
-
Nan::DefineOwnProperty(result, key, outBinds, v8::ReadOnly);
|
|
1994
|
-
}
|
|
1995
|
-
}
|
|
1996
|
-
|
|
1997
|
-
// get total number of rows affected
|
|
1998
|
-
if (!baton->isPLSQL)
|
|
1999
|
-
Nan::DefineOwnProperty(result,
|
|
2000
|
-
Nan::New<v8::String>("rowsAffected").ToLocalChecked(),
|
|
2001
|
-
Nan::New<v8::Integer>( (unsigned int) baton->rowsAffected),
|
|
2002
|
-
v8::ReadOnly);
|
|
2003
|
-
|
|
2004
|
-
// get DML row counts if option was enabled
|
|
2005
|
-
if (baton->dmlRowCounts && baton->numRowCounts > 0) {
|
|
2006
|
-
Local<Array> rowCountsObj = Nan::New<Array>(baton->numRowCounts);
|
|
2007
|
-
for (uint32_t i = 0; i < baton->numRowCounts; i++) {
|
|
2008
|
-
Local<Value> rowCountObj =
|
|
2009
|
-
Nan::New<Integer>((unsigned int) baton->rowCounts[i]);
|
|
2010
|
-
Nan::Set(rowCountsObj, i, rowCountObj);
|
|
2011
|
-
}
|
|
2012
|
-
Nan::DefineOwnProperty(result,
|
|
2013
|
-
Nan::New<v8::String>("dmlRowCounts").ToLocalChecked(),
|
|
2014
|
-
rowCountsObj, v8::ReadOnly);
|
|
2015
|
-
}
|
|
2016
|
-
|
|
2017
|
-
// get batch errors, if option was enabled
|
|
2018
|
-
if (baton->batchErrors && baton->numBatchErrorInfos > 0) {
|
|
2019
|
-
Local<Array> batchErrorsObj =
|
|
2020
|
-
Nan::New<Array>(baton->numBatchErrorInfos);
|
|
2021
|
-
for (uint32_t i = 0; i < baton->numBatchErrorInfos; i++) {
|
|
2022
|
-
dpiErrorInfo *info = &baton->batchErrorInfos[i];
|
|
2023
|
-
std::string errorStr =
|
|
2024
|
-
std::string(info->message, info->messageLength);
|
|
2025
|
-
Local<String> errorStrObj =
|
|
2026
|
-
Nan::New<String>(errorStr).ToLocalChecked();
|
|
2027
|
-
Local<Object> errorObj =
|
|
2028
|
-
v8::Exception::Error(errorStrObj).As<Object>();
|
|
2029
|
-
Nan::Set(errorObj,
|
|
2030
|
-
Nan::New<v8::String>("errorNum").ToLocalChecked(),
|
|
2031
|
-
Nan::New<v8::Number>(info->code));
|
|
2032
|
-
Nan::Set(errorObj,
|
|
2033
|
-
Nan::New<v8::String>("offset").ToLocalChecked(),
|
|
2034
|
-
Nan::New<v8::Number>(info->offset));
|
|
2035
|
-
Nan::Set(batchErrorsObj, i, errorObj);
|
|
2036
|
-
}
|
|
2037
|
-
Nan::DefineOwnProperty(result,
|
|
2038
|
-
Nan::New<v8::String>("batchErrors").ToLocalChecked(),
|
|
2039
|
-
batchErrorsObj, v8::ReadOnly);
|
|
2040
|
-
}
|
|
2041
|
-
|
|
2042
|
-
argv[1] = scope.Escape(result);
|
|
2043
|
-
}
|
|
2044
|
-
|
|
2045
|
-
|
|
2046
|
-
//-----------------------------------------------------------------------------
|
|
2047
|
-
// njsConnection::GetStatementInfo()
|
|
2048
|
-
// Parses a statement on the connection and returns information about the
|
|
2049
|
-
// statement.
|
|
2050
|
-
//
|
|
2051
|
-
// PARAMETERS
|
|
2052
|
-
// - SQL Statement
|
|
2053
|
-
// - JS callback which will receive (error, result)
|
|
2054
|
-
//-----------------------------------------------------------------------------
|
|
2055
|
-
NAN_METHOD(njsConnection::GetStatementInfo)
|
|
2056
|
-
{
|
|
2057
|
-
njsConnection *connection;
|
|
2058
|
-
std::string sql;
|
|
2059
|
-
njsBaton *baton;
|
|
2060
|
-
|
|
2061
|
-
connection = (njsConnection*) ValidateArgs(info, 2, 2);
|
|
2062
|
-
if (!connection)
|
|
2063
|
-
return;
|
|
2064
|
-
if (!connection->GetStringArg(info, 0, sql))
|
|
2065
|
-
return;
|
|
2066
|
-
baton = connection->CreateBaton(info);
|
|
2067
|
-
if (!baton)
|
|
2068
|
-
return;
|
|
2069
|
-
if (baton->error.empty()) {
|
|
2070
|
-
baton->sql = sql;
|
|
2071
|
-
baton->extendedMetaData = true;
|
|
2072
|
-
baton->SetDPIConnHandle(connection->dpiConnHandle);
|
|
2073
|
-
baton->jsOracledb.Reset(connection->jsOracledb);
|
|
2074
|
-
}
|
|
2075
|
-
baton->QueueWork("GetStatementInfo", Async_GetStatementInfo,
|
|
2076
|
-
Async_AfterGetStatementInfo, 2);
|
|
2077
|
-
}
|
|
2078
|
-
|
|
2079
|
-
|
|
2080
|
-
//-----------------------------------------------------------------------------
|
|
2081
|
-
// njsConnection::Async_GetStatementInfo()
|
|
2082
|
-
// Worker function for njsConnection::GetStatementInfo() method.
|
|
2083
|
-
//-----------------------------------------------------------------------------
|
|
2084
|
-
void njsConnection::Async_GetStatementInfo(njsBaton *baton)
|
|
2085
|
-
{
|
|
2086
|
-
dpiExecMode mode;
|
|
2087
|
-
|
|
2088
|
-
// prepare DPI statement for use
|
|
2089
|
-
if (dpiConn_prepareStmt(baton->dpiConnHandle, 0, baton->sql.c_str(),
|
|
2090
|
-
(uint32_t) baton->sql.length(), NULL, 0,
|
|
2091
|
-
&baton->dpiStmtHandle) < 0) {
|
|
2092
|
-
baton->GetDPIError();
|
|
2093
|
-
return;
|
|
2094
|
-
}
|
|
2095
|
-
|
|
2096
|
-
// parse the statement
|
|
2097
|
-
if (dpiStmt_getInfo(baton->dpiStmtHandle, &baton->stmtInfo) < 0) {
|
|
2098
|
-
baton->GetDPIError();
|
|
2099
|
-
return;
|
|
2100
|
-
}
|
|
2101
|
-
if (!baton->stmtInfo.isDDL) {
|
|
2102
|
-
if (baton->stmtInfo.isQuery) {
|
|
2103
|
-
mode = DPI_MODE_EXEC_DESCRIBE_ONLY;
|
|
2104
|
-
} else {
|
|
2105
|
-
mode = DPI_MODE_EXEC_PARSE_ONLY;
|
|
2106
|
-
}
|
|
2107
|
-
if (dpiStmt_execute(baton->dpiStmtHandle, mode,
|
|
2108
|
-
&baton->numQueryVars) < 0) {
|
|
2109
|
-
baton->GetDPIError();
|
|
2110
|
-
return;
|
|
2111
|
-
}
|
|
2112
|
-
}
|
|
2113
|
-
|
|
2114
|
-
// for queries, process query variables to get metadata
|
|
2115
|
-
if (baton->numQueryVars > 0) {
|
|
2116
|
-
baton->queryVars = new njsVariable[baton->numQueryVars];
|
|
2117
|
-
if (!ProcessQueryVars(baton, baton->dpiStmtHandle, baton->queryVars,
|
|
2118
|
-
baton->numQueryVars))
|
|
2119
|
-
return;
|
|
2120
|
-
}
|
|
2121
|
-
}
|
|
2122
|
-
|
|
2123
|
-
|
|
2124
|
-
//-----------------------------------------------------------------------------
|
|
2125
|
-
// njsConnection::Async_AfterGetStatementInfo()
|
|
2126
|
-
// Returns result to JS by invoking JS callback.
|
|
2127
|
-
//-----------------------------------------------------------------------------
|
|
2128
|
-
void njsConnection::Async_AfterGetStatementInfo(njsBaton *baton,
|
|
2129
|
-
Local<Value> argv[])
|
|
2130
|
-
{
|
|
2131
|
-
Nan::EscapableHandleScope scope;
|
|
2132
|
-
Local<Object> result = Nan::New<v8::Object>();
|
|
2133
|
-
Local<Object> callingObj, rows;
|
|
2134
|
-
Local<Function> callback;
|
|
2135
|
-
uint32_t numBinds;
|
|
2136
|
-
|
|
2137
|
-
// add metadata (queries only)
|
|
2138
|
-
if (baton->queryVars) {
|
|
2139
|
-
Nan::Set(result, Nan::New<v8::String>("metaData").ToLocalChecked(),
|
|
2140
|
-
GetMetaData(baton->queryVars, baton->numQueryVars,
|
|
2141
|
-
baton->extendedMetaData));
|
|
2142
|
-
}
|
|
2143
|
-
|
|
2144
|
-
// add list of bind variable names
|
|
2145
|
-
if (dpiStmt_getBindCount(baton->dpiStmtHandle, &numBinds) < 0) {
|
|
2146
|
-
baton->GetDPIError();
|
|
2147
|
-
return;
|
|
2148
|
-
}
|
|
2149
|
-
uint32_t *bindNameLengths = new uint32_t[numBinds];
|
|
2150
|
-
const char **bindNames = new const char *[numBinds];
|
|
2151
|
-
if (dpiStmt_getBindNames(baton->dpiStmtHandle, &numBinds, bindNames,
|
|
2152
|
-
bindNameLengths) < 0) {
|
|
2153
|
-
baton->GetDPIError();
|
|
2154
|
-
delete [] bindNames;
|
|
2155
|
-
delete [] bindNameLengths;
|
|
2156
|
-
return;
|
|
2157
|
-
}
|
|
2158
|
-
Local<Array> bindNamesArray = Nan::New<Array>(numBinds);
|
|
2159
|
-
for (uint32_t i = 0; i < numBinds; i++) {
|
|
2160
|
-
Local<String> bindName = Nan::New<String>(bindNames[i],
|
|
2161
|
-
(int) bindNameLengths[i]).ToLocalChecked();
|
|
2162
|
-
Nan::Set(bindNamesArray, i, bindName);
|
|
2163
|
-
}
|
|
2164
|
-
delete [] bindNames;
|
|
2165
|
-
delete [] bindNameLengths;
|
|
2166
|
-
Nan::Set(result, Nan::New<v8::String>("bindNames").ToLocalChecked(),
|
|
2167
|
-
bindNamesArray);
|
|
2168
|
-
|
|
2169
|
-
// add statement type
|
|
2170
|
-
Nan::Set(result, Nan::New<v8::String>("statementType").ToLocalChecked(),
|
|
2171
|
-
Nan::New(static_cast<int>(baton->stmtInfo.statementType)));
|
|
2172
|
-
|
|
2173
|
-
argv[1] = scope.Escape(result);
|
|
2174
|
-
}
|
|
2175
|
-
|
|
2176
|
-
|
|
2177
|
-
//-----------------------------------------------------------------------------
|
|
2178
|
-
// njsConnection::Close()
|
|
2179
|
-
// Releases the connection from use by JS. This releases the connection back
|
|
2180
|
-
// to the pool or closes the standalone connection so further use is not
|
|
2181
|
-
// possible. The reference to the DPI handle is transferred to the baton so
|
|
2182
|
-
// that it will be cleared automatically upon success and so that the
|
|
2183
|
-
// connection is marked as invalid immediately.
|
|
2184
|
-
//
|
|
2185
|
-
// PARAMETERS
|
|
2186
|
-
// - JS callback which will receive (error)
|
|
2187
|
-
//-----------------------------------------------------------------------------
|
|
2188
|
-
NAN_METHOD(njsConnection::Close)
|
|
2189
|
-
{
|
|
2190
|
-
njsConnection *connection;
|
|
2191
|
-
njsBaton *baton;
|
|
2192
|
-
|
|
2193
|
-
connection = (njsConnection*) ValidateArgs(info, 1, 1);
|
|
2194
|
-
if (!connection)
|
|
2195
|
-
return;
|
|
2196
|
-
baton = connection->CreateBaton(info);
|
|
2197
|
-
if (!baton)
|
|
2198
|
-
return;
|
|
2199
|
-
baton->dpiConnHandle = connection->dpiConnHandle;
|
|
2200
|
-
connection->dpiConnHandle = NULL;
|
|
2201
|
-
baton->QueueWork("Close", Async_Close, NULL, 1);
|
|
2202
|
-
}
|
|
2203
|
-
|
|
2204
|
-
|
|
2205
|
-
//-----------------------------------------------------------------------------
|
|
2206
|
-
// njsConnection::Async_Close()
|
|
2207
|
-
// Worker function for njsConnection::Close() method. If the attempt to
|
|
2208
|
-
// close fails, the reference to the DPI handle is transferred back from the
|
|
2209
|
-
// baton to the connection.
|
|
2210
|
-
//-----------------------------------------------------------------------------
|
|
2211
|
-
void njsConnection::Async_Close(njsBaton *baton)
|
|
2212
|
-
{
|
|
2213
|
-
if (dpiConn_close(baton->dpiConnHandle, DPI_MODE_CONN_CLOSE_DEFAULT, NULL,
|
|
2214
|
-
0) < 0) {
|
|
2215
|
-
njsConnection *connection = (njsConnection*) baton->callingObj;
|
|
2216
|
-
connection->dpiConnHandle = baton->dpiConnHandle;
|
|
2217
|
-
baton->dpiConnHandle = NULL;
|
|
2218
|
-
baton->GetDPIError();
|
|
2219
|
-
}
|
|
2220
|
-
}
|
|
2221
|
-
|
|
2222
|
-
|
|
2223
|
-
//-----------------------------------------------------------------------------
|
|
2224
|
-
// njsConnection::Async_AfterClose()
|
|
2225
|
-
// Finishes close by cleaning up references.
|
|
2226
|
-
//-----------------------------------------------------------------------------
|
|
2227
|
-
void njsConnection::Async_AfterClose(njsBaton *baton, Local<Value> argv[])
|
|
2228
|
-
{
|
|
2229
|
-
njsConnection *connection = (njsConnection*) baton->callingObj;
|
|
2230
|
-
connection->jsOracledb.Reset();
|
|
2231
|
-
}
|
|
2232
|
-
|
|
2233
|
-
|
|
2234
|
-
//-----------------------------------------------------------------------------
|
|
2235
|
-
// njsConnection::Commit()
|
|
2236
|
-
// Commits the active transaction.
|
|
2237
|
-
//
|
|
2238
|
-
// PARAMETERS
|
|
2239
|
-
// - JS callback which will receive (error)
|
|
2240
|
-
//-----------------------------------------------------------------------------
|
|
2241
|
-
NAN_METHOD(njsConnection::Commit)
|
|
2242
|
-
{
|
|
2243
|
-
njsConnection *connection;
|
|
2244
|
-
njsBaton *baton;
|
|
2245
|
-
|
|
2246
|
-
connection = (njsConnection*) ValidateArgs(info, 1, 1);
|
|
2247
|
-
if (!connection)
|
|
2248
|
-
return;
|
|
2249
|
-
baton = connection->CreateBaton(info);
|
|
2250
|
-
if (!baton)
|
|
2251
|
-
return;
|
|
2252
|
-
if (baton->error.empty())
|
|
2253
|
-
baton->SetDPIConnHandle(connection->dpiConnHandle);
|
|
2254
|
-
baton->QueueWork("Commit", Async_Commit, NULL, 1);
|
|
2255
|
-
}
|
|
2256
|
-
|
|
2257
|
-
|
|
2258
|
-
//-----------------------------------------------------------------------------
|
|
2259
|
-
// njsConnection::Async_Commit()
|
|
2260
|
-
// Worker function for njsConnection::Commit() method.
|
|
2261
|
-
//-----------------------------------------------------------------------------
|
|
2262
|
-
void njsConnection::Async_Commit(njsBaton *baton)
|
|
2263
|
-
{
|
|
2264
|
-
if (dpiConn_commit(baton->dpiConnHandle) < 0)
|
|
2265
|
-
baton->GetDPIError();
|
|
2266
|
-
}
|
|
2267
|
-
|
|
2268
|
-
|
|
2269
|
-
//-----------------------------------------------------------------------------
|
|
2270
|
-
// njsConnection::Rollback()
|
|
2271
|
-
// Rolls back the active transaction.
|
|
2272
|
-
//
|
|
2273
|
-
// PARAMETERS
|
|
2274
|
-
// - JS callback which will receive (error)
|
|
2275
|
-
//-----------------------------------------------------------------------------
|
|
2276
|
-
NAN_METHOD(njsConnection::Rollback)
|
|
2277
|
-
{
|
|
2278
|
-
njsConnection *connection;
|
|
2279
|
-
njsBaton *baton;
|
|
2280
|
-
|
|
2281
|
-
connection = (njsConnection*) ValidateArgs(info, 1, 1);
|
|
2282
|
-
if (!connection)
|
|
2283
|
-
return;
|
|
2284
|
-
baton = connection->CreateBaton(info);
|
|
2285
|
-
if (!baton)
|
|
2286
|
-
return;
|
|
2287
|
-
if (baton->error.empty())
|
|
2288
|
-
baton->SetDPIConnHandle(connection->dpiConnHandle);
|
|
2289
|
-
baton->QueueWork("Rollback", Async_Rollback, NULL, 1);
|
|
2290
|
-
}
|
|
2291
|
-
|
|
2292
|
-
|
|
2293
|
-
//-----------------------------------------------------------------------------
|
|
2294
|
-
// njsConnection::Async_Rollback()
|
|
2295
|
-
// Worker function for njsConnection::Rollback() method.
|
|
2296
|
-
//-----------------------------------------------------------------------------
|
|
2297
|
-
void njsConnection::Async_Rollback(njsBaton *baton)
|
|
2298
|
-
{
|
|
2299
|
-
if (dpiConn_rollback(baton->dpiConnHandle) < 0)
|
|
2300
|
-
baton->GetDPIError();
|
|
2301
|
-
}
|
|
2302
|
-
|
|
2303
|
-
|
|
2304
|
-
//-----------------------------------------------------------------------------
|
|
2305
|
-
// njsConnection::Break()
|
|
2306
|
-
// Break (interrupt) the currently executing operation.
|
|
2307
|
-
//
|
|
2308
|
-
// PARAMETERS
|
|
2309
|
-
// - JS callback which will receive (error)
|
|
2310
|
-
//-----------------------------------------------------------------------------
|
|
2311
|
-
NAN_METHOD(njsConnection::Break)
|
|
2312
|
-
{
|
|
2313
|
-
njsConnection *connection;
|
|
2314
|
-
njsBaton *baton;
|
|
2315
|
-
|
|
2316
|
-
connection = (njsConnection*) ValidateArgs(info, 1, 1);
|
|
2317
|
-
if (!connection)
|
|
2318
|
-
return;
|
|
2319
|
-
baton = connection->CreateBaton(info);
|
|
2320
|
-
if (!baton)
|
|
2321
|
-
return;
|
|
2322
|
-
if (baton->error.empty())
|
|
2323
|
-
baton->SetDPIConnHandle(connection->dpiConnHandle);
|
|
2324
|
-
baton->QueueWork("Break", Async_Break, NULL, 1);
|
|
2325
|
-
}
|
|
2326
|
-
|
|
2327
|
-
|
|
2328
|
-
//-----------------------------------------------------------------------------
|
|
2329
|
-
// njsConnection::Async_Break()
|
|
2330
|
-
// Worker function for njsConnection::Break() method.
|
|
2331
|
-
//-----------------------------------------------------------------------------
|
|
2332
|
-
void njsConnection::Async_Break(njsBaton *baton)
|
|
2333
|
-
{
|
|
2334
|
-
if (dpiConn_breakExecution(baton->dpiConnHandle) < 0)
|
|
2335
|
-
baton->GetDPIError();
|
|
2336
|
-
}
|
|
2337
|
-
|
|
2338
|
-
|
|
2339
|
-
//-----------------------------------------------------------------------------
|
|
2340
|
-
// njsConnection::CreateLob()
|
|
2341
|
-
// Create a new temporary LOB and return it for use by the application.
|
|
2342
|
-
//
|
|
2343
|
-
// PARAMETERS
|
|
2344
|
-
// - JS callback which will receive (error)
|
|
2345
|
-
//-----------------------------------------------------------------------------
|
|
2346
|
-
NAN_METHOD(njsConnection::CreateLob)
|
|
2347
|
-
{
|
|
2348
|
-
njsConnection *connection;
|
|
2349
|
-
uint32_t lobType;
|
|
2350
|
-
njsBaton *baton;
|
|
2351
|
-
|
|
2352
|
-
connection = (njsConnection*) ValidateArgs(info, 2, 2);
|
|
2353
|
-
if (!connection)
|
|
2354
|
-
return;
|
|
2355
|
-
baton = connection->CreateBaton(info);
|
|
2356
|
-
if (!baton)
|
|
2357
|
-
return;
|
|
2358
|
-
if (!connection->GetUnsignedIntArg(info, 0, &lobType))
|
|
2359
|
-
return;
|
|
2360
|
-
if (lobType != NJS_DATATYPE_CLOB && lobType != NJS_DATATYPE_BLOB) {
|
|
2361
|
-
string errMsg = njsMessages::Get(errInvalidParameterValue, 1);
|
|
2362
|
-
Nan::ThrowError(errMsg.c_str());
|
|
2363
|
-
return;
|
|
2364
|
-
}
|
|
2365
|
-
if (baton->error.empty()) {
|
|
2366
|
-
baton->jsOracledb.Reset(connection->jsOracledb);
|
|
2367
|
-
baton->SetDPIConnHandle(connection->dpiConnHandle);
|
|
2368
|
-
baton->protoILob = new njsProtoILob();
|
|
2369
|
-
baton->protoILob->dataType = (njsDataType) lobType;
|
|
2370
|
-
}
|
|
2371
|
-
baton->QueueWork("CreateLob", Async_CreateLob, Async_AfterCreateLob, 2);
|
|
2372
|
-
}
|
|
2373
|
-
|
|
2374
|
-
|
|
2375
|
-
//-----------------------------------------------------------------------------
|
|
2376
|
-
// njsConnection::Async_CreateLob()
|
|
2377
|
-
// Worker function for njsConnection::CreateLob() method.
|
|
2378
|
-
//-----------------------------------------------------------------------------
|
|
2379
|
-
void njsConnection::Async_CreateLob(njsBaton *baton)
|
|
2380
|
-
{
|
|
2381
|
-
dpiOracleTypeNum typeNum;
|
|
2382
|
-
dpiLob *tempLob;
|
|
2383
|
-
|
|
2384
|
-
typeNum = (baton->protoILob->dataType == NJS_DATATYPE_CLOB) ?
|
|
2385
|
-
DPI_ORACLE_TYPE_CLOB : DPI_ORACLE_TYPE_BLOB;
|
|
2386
|
-
if (dpiConn_newTempLob(baton->dpiConnHandle, typeNum, &tempLob) < 0)
|
|
2387
|
-
baton->GetDPIError();
|
|
2388
|
-
baton->protoILob->PopulateFromDPI(baton, tempLob, false);
|
|
2389
|
-
baton->protoILob->isAutoClose = false;
|
|
2390
|
-
}
|
|
2391
|
-
|
|
2392
|
-
|
|
2393
|
-
//-----------------------------------------------------------------------------
|
|
2394
|
-
// njsConnection::Async_AfterCreateLob()
|
|
2395
|
-
// Returns result to JS by invoking JS callback.
|
|
2396
|
-
//-----------------------------------------------------------------------------
|
|
2397
|
-
void njsConnection::Async_AfterCreateLob(njsBaton *baton, Local<Value> argv[])
|
|
2398
|
-
{
|
|
2399
|
-
Nan::EscapableHandleScope scope;
|
|
2400
|
-
Local<Value> tempArgv[1];
|
|
2401
|
-
|
|
2402
|
-
tempArgv[0] = njsILob::CreateFromProtoLob(baton->protoILob);
|
|
2403
|
-
Local<Value> key = Nan::New<String>("newLob").ToLocalChecked();
|
|
2404
|
-
Local<Object> jsOracledb = Nan::New(baton->jsOracledb);
|
|
2405
|
-
Local<Function> fn = Local<Function>::Cast(Nan::Get(jsOracledb,
|
|
2406
|
-
key).ToLocalChecked());
|
|
2407
|
-
Local<Value> temp = fn->Call(jsOracledb, 1, tempArgv);
|
|
2408
|
-
argv[1] = scope.Escape(temp);
|
|
2409
|
-
}
|
|
2410
|
-
|
|
2411
|
-
|
|
2412
|
-
//-----------------------------------------------------------------------------
|
|
2413
|
-
// njsConnection::ChangePassword()
|
|
2414
|
-
// Change the password on the connection.
|
|
2415
|
-
//
|
|
2416
|
-
// PARAMETERS
|
|
2417
|
-
// - JS callback which will receive (error)
|
|
2418
|
-
//-----------------------------------------------------------------------------
|
|
2419
|
-
NAN_METHOD(njsConnection::ChangePassword)
|
|
2420
|
-
{
|
|
2421
|
-
std::string user, password, newPassword;
|
|
2422
|
-
njsConnection *connection;
|
|
2423
|
-
njsBaton *baton;
|
|
2424
|
-
|
|
2425
|
-
connection = (njsConnection*) ValidateArgs(info, 4, 4);
|
|
2426
|
-
if (!connection)
|
|
2427
|
-
return;
|
|
2428
|
-
if (!connection->GetStringArg(info, 0, user))
|
|
2429
|
-
return;
|
|
2430
|
-
if (!connection->GetStringArg(info, 1, password))
|
|
2431
|
-
return;
|
|
2432
|
-
if (!connection->GetStringArg(info, 2, newPassword))
|
|
2433
|
-
return;
|
|
2434
|
-
baton = connection->CreateBaton(info);
|
|
2435
|
-
if (!baton)
|
|
2436
|
-
return;
|
|
2437
|
-
if (baton->error.empty()) {
|
|
2438
|
-
baton->SetDPIConnHandle(connection->dpiConnHandle);
|
|
2439
|
-
baton->user = user;
|
|
2440
|
-
baton->password = password;
|
|
2441
|
-
baton->newPassword = newPassword;
|
|
2442
|
-
}
|
|
2443
|
-
baton->QueueWork("ChangePassword", Async_ChangePassword, NULL, 1);
|
|
2444
|
-
}
|
|
2445
|
-
|
|
2446
|
-
|
|
2447
|
-
//-----------------------------------------------------------------------------
|
|
2448
|
-
// njsConnection::Async_ChangePassword()
|
|
2449
|
-
// Worker function for njsConnection::ChangePassword() method.
|
|
2450
|
-
//-----------------------------------------------------------------------------
|
|
2451
|
-
void njsConnection::Async_ChangePassword(njsBaton *baton)
|
|
2452
|
-
{
|
|
2453
|
-
if (dpiConn_changePassword(baton->dpiConnHandle, baton->user.c_str(),
|
|
2454
|
-
(uint32_t) baton->user.length(), baton->password.c_str(),
|
|
2455
|
-
(uint32_t) baton->password.length(), baton->newPassword.c_str(),
|
|
2456
|
-
(uint32_t) baton->newPassword.length()) < 0)
|
|
2457
|
-
baton->GetDPIError();
|
|
2458
|
-
}
|
|
2459
|
-
|
|
2460
|
-
|
|
2461
|
-
//-----------------------------------------------------------------------------
|
|
2462
|
-
// njsConnection::Ping()
|
|
2463
|
-
// Ping the database to see if it is "alive".
|
|
2464
|
-
//
|
|
2465
|
-
// PARAMETERS
|
|
2466
|
-
// - JS callback which will receive (error)
|
|
2467
|
-
//-----------------------------------------------------------------------------
|
|
2468
|
-
NAN_METHOD(njsConnection::Ping)
|
|
2469
|
-
{
|
|
2470
|
-
njsConnection *connection;
|
|
2471
|
-
njsBaton *baton;
|
|
2472
|
-
|
|
2473
|
-
connection = (njsConnection*) ValidateArgs(info, 1, 1);
|
|
2474
|
-
if (!connection)
|
|
2475
|
-
return;
|
|
2476
|
-
baton = connection->CreateBaton(info);
|
|
2477
|
-
if (!baton)
|
|
2478
|
-
return;
|
|
2479
|
-
if (baton->error.empty())
|
|
2480
|
-
baton->SetDPIConnHandle(connection->dpiConnHandle);
|
|
2481
|
-
baton->QueueWork("Ping", Async_Ping, NULL, 1);
|
|
2482
|
-
}
|
|
2483
|
-
|
|
2484
|
-
|
|
2485
|
-
//-----------------------------------------------------------------------------
|
|
2486
|
-
// njsConnection::Async_Ping()
|
|
2487
|
-
// Worker function for njsConnection::Ping() method.
|
|
2488
|
-
//-----------------------------------------------------------------------------
|
|
2489
|
-
void njsConnection::Async_Ping(njsBaton *baton)
|
|
2490
|
-
{
|
|
2491
|
-
if (dpiConn_ping(baton->dpiConnHandle) < 0)
|
|
2492
|
-
baton->GetDPIError();
|
|
2493
|
-
}
|
|
2494
|
-
|
|
2495
|
-
|
|
2496
|
-
//-----------------------------------------------------------------------------
|
|
2497
|
-
// njsConnection::Subscribe()
|
|
2498
|
-
// Subscribe to events from the database. The provided callback will be
|
|
2499
|
-
// invoked each time a notification is received. The name is used to uniquely
|
|
2500
|
-
// identify a subscription and a reference is stored on the oracledb instance
|
|
2501
|
-
// for use by subsequent calls to subscribe() or unsubscribe().
|
|
2502
|
-
//
|
|
2503
|
-
// PARAMETERS
|
|
2504
|
-
// - JS callback which will receive (error)
|
|
2505
|
-
//-----------------------------------------------------------------------------
|
|
2506
|
-
NAN_METHOD(njsConnection::Subscribe)
|
|
2507
|
-
{
|
|
2508
|
-
njsConnection *connection;
|
|
2509
|
-
std::string name;
|
|
2510
|
-
njsBaton *baton;
|
|
2511
|
-
|
|
2512
|
-
connection = (njsConnection*) ValidateArgs(info, 3, 3);
|
|
2513
|
-
if (!connection)
|
|
2514
|
-
return;
|
|
2515
|
-
if (!connection->GetStringArg(info, 0, name))
|
|
2516
|
-
return;
|
|
2517
|
-
baton = connection->CreateBaton(info);
|
|
2518
|
-
if (!baton)
|
|
2519
|
-
return;
|
|
2520
|
-
baton->name = name;
|
|
2521
|
-
baton->SetDPIConnHandle(connection->dpiConnHandle);
|
|
2522
|
-
baton->subscription = njsOracledb::GetSubscription(name);
|
|
2523
|
-
if (baton->subscription) {
|
|
2524
|
-
baton->subscription->SetDPISubscrHandle(baton);
|
|
2525
|
-
} else {
|
|
2526
|
-
Local<Object> obj = njsSubscription::Create();
|
|
2527
|
-
baton->subscription = Nan::ObjectWrap::Unwrap<njsSubscription>(obj);
|
|
2528
|
-
baton->jsSubscription.Reset(obj);
|
|
2529
|
-
}
|
|
2530
|
-
Local<Object> options = info[1].As<Object>();
|
|
2531
|
-
ProcessSubscriptionOptions(options, baton);
|
|
2532
|
-
baton->QueueWork("Subscribe", Async_Subscribe, Async_AfterSubscribe, 1);
|
|
2533
|
-
}
|
|
2534
|
-
|
|
2535
|
-
|
|
2536
|
-
//-----------------------------------------------------------------------------
|
|
2537
|
-
// njsConnection::Async_Subscribe()
|
|
2538
|
-
// Worker function for njsConnection::Subscribe() method.
|
|
2539
|
-
//-----------------------------------------------------------------------------
|
|
2540
|
-
void njsConnection::Async_Subscribe(njsBaton *baton)
|
|
2541
|
-
{
|
|
2542
|
-
// create subscription, if necessary
|
|
2543
|
-
if (!baton->dpiSubscrHandle) {
|
|
2544
|
-
dpiSubscrCreateParams params;
|
|
2545
|
-
dpiContext *context = njsOracledb::GetDPIContext();
|
|
2546
|
-
if (dpiContext_initSubscrCreateParams(context, ¶ms) < 0) {
|
|
2547
|
-
baton->GetDPIError();
|
|
2548
|
-
return;
|
|
2549
|
-
}
|
|
2550
|
-
params.subscrNamespace = baton->subscription->GetNamespace();
|
|
2551
|
-
params.name = baton->name.c_str();
|
|
2552
|
-
params.nameLength = baton->name.length();
|
|
2553
|
-
params.protocol = DPI_SUBSCR_PROTO_CALLBACK;
|
|
2554
|
-
params.callback = (dpiSubscrCallback) njsSubscription::EventHandler;
|
|
2555
|
-
params.callbackContext = baton->subscription;
|
|
2556
|
-
params.ipAddress = baton->ipAddress.c_str();
|
|
2557
|
-
params.ipAddressLength = baton->ipAddress.length();
|
|
2558
|
-
params.portNumber = baton->portNumber;
|
|
2559
|
-
params.timeout = baton->timeout;
|
|
2560
|
-
params.qos = (dpiSubscrQOS) baton->qos;
|
|
2561
|
-
params.operations = (dpiOpCode) baton->operations;
|
|
2562
|
-
params.groupingClass = (uint8_t) baton->subscrGroupingClass;
|
|
2563
|
-
params.groupingValue = baton->subscrGroupingValue;
|
|
2564
|
-
params.groupingType = (uint8_t) baton->subscrGroupingType;
|
|
2565
|
-
if (dpiConn_subscribe(baton->dpiConnHandle, ¶ms,
|
|
2566
|
-
&baton->dpiSubscrHandle) < 0) {
|
|
2567
|
-
baton->GetDPIError();
|
|
2568
|
-
return;
|
|
2569
|
-
}
|
|
2570
|
-
}
|
|
2571
|
-
|
|
2572
|
-
// register query if applicable
|
|
2573
|
-
if (!baton->sql.empty()) {
|
|
2574
|
-
|
|
2575
|
-
// prepare statement for registration
|
|
2576
|
-
if (dpiSubscr_prepareStmt(baton->dpiSubscrHandle, baton->sql.c_str(),
|
|
2577
|
-
(uint32_t) baton->sql.length(), &baton->dpiStmtHandle) < 0) {
|
|
2578
|
-
baton->GetDPIError();
|
|
2579
|
-
return;
|
|
2580
|
-
}
|
|
2581
|
-
|
|
2582
|
-
// perform any binds necessary
|
|
2583
|
-
for (uint32_t i = 0; i < baton->numBindVars; i++) {
|
|
2584
|
-
int status;
|
|
2585
|
-
njsVariable *var = &baton->bindVars[i];
|
|
2586
|
-
if (var->name.empty()) {
|
|
2587
|
-
status = dpiStmt_bindByPos(baton->dpiStmtHandle, var->pos,
|
|
2588
|
-
var->dpiVarHandle);
|
|
2589
|
-
} else {
|
|
2590
|
-
status = dpiStmt_bindByName(baton->dpiStmtHandle,
|
|
2591
|
-
var->name.c_str(), (uint32_t) var->name.length(),
|
|
2592
|
-
var->dpiVarHandle);
|
|
2593
|
-
}
|
|
2594
|
-
if (status < 0) {
|
|
2595
|
-
baton->GetDPIError();
|
|
2596
|
-
return;
|
|
2597
|
-
}
|
|
2598
|
-
}
|
|
2599
|
-
|
|
2600
|
-
// perform execute (which registers the query)
|
|
2601
|
-
if (dpiStmt_execute(baton->dpiStmtHandle, DPI_MODE_EXEC_DEFAULT,
|
|
2602
|
-
NULL) < 0)
|
|
2603
|
-
baton->GetDPIError();
|
|
2604
|
-
|
|
2605
|
-
}
|
|
2606
|
-
}
|
|
2607
|
-
|
|
2608
|
-
|
|
2609
|
-
//-----------------------------------------------------------------------------
|
|
2610
|
-
// njsConnection::Async_AfterSubscribe()
|
|
2611
|
-
// Returns result to JS by invoking JS callback.
|
|
2612
|
-
//-----------------------------------------------------------------------------
|
|
2613
|
-
void njsConnection::Async_AfterSubscribe(njsBaton *baton, Local<Value> argv[])
|
|
2614
|
-
{
|
|
2615
|
-
baton->subscription->StartNotifications(baton);
|
|
2616
|
-
}
|
|
2617
|
-
|
|
2618
|
-
|
|
2619
|
-
//-----------------------------------------------------------------------------
|
|
2620
|
-
// njsConnection::Unsubscribe()
|
|
2621
|
-
// Unsubscribe from events in the database that were originally subscribed
|
|
2622
|
-
// with a call to connection.subscribe().
|
|
2623
|
-
//
|
|
2624
|
-
// PARAMETERS
|
|
2625
|
-
// - JS callback which will receive (error)
|
|
2626
|
-
//-----------------------------------------------------------------------------
|
|
2627
|
-
NAN_METHOD(njsConnection::Unsubscribe)
|
|
2628
|
-
{
|
|
2629
|
-
njsConnection *connection;
|
|
2630
|
-
std::string name;
|
|
2631
|
-
njsBaton *baton;
|
|
2632
|
-
|
|
2633
|
-
connection = (njsConnection*) ValidateArgs(info, 2, 2);
|
|
2634
|
-
if (!connection)
|
|
2635
|
-
return;
|
|
2636
|
-
if (!connection->GetStringArg(info, 0, name))
|
|
2637
|
-
return;
|
|
2638
|
-
baton = connection->CreateBaton(info);
|
|
2639
|
-
if (!baton)
|
|
2640
|
-
return;
|
|
2641
|
-
baton->name = name;
|
|
2642
|
-
baton->subscription = njsOracledb::GetSubscription(name);
|
|
2643
|
-
if (baton->subscription) {
|
|
2644
|
-
baton->subscription->SetDPISubscrHandle(baton);
|
|
2645
|
-
baton->SetDPIConnHandle(connection->dpiConnHandle);
|
|
2646
|
-
} else {
|
|
2647
|
-
baton->error = njsMessages::Get(errInvalidSubscription);
|
|
2648
|
-
}
|
|
2649
|
-
baton->QueueWork("Unsubscribe", Async_Unsubscribe, NULL, 1);
|
|
2650
|
-
}
|
|
2651
|
-
|
|
2652
|
-
|
|
2653
|
-
//-----------------------------------------------------------------------------
|
|
2654
|
-
// njsConnection::Async_Unsubscribe()
|
|
2655
|
-
// Worker function for njsConnection::Unsubscribe() method.
|
|
2656
|
-
//-----------------------------------------------------------------------------
|
|
2657
|
-
void njsConnection::Async_Unsubscribe(njsBaton *baton)
|
|
2658
|
-
{
|
|
2659
|
-
if (dpiConn_unsubscribe(baton->dpiConnHandle,
|
|
2660
|
-
baton->dpiSubscrHandle) < 0) {
|
|
2661
|
-
baton->GetDPIError();
|
|
2662
|
-
} else {
|
|
2663
|
-
baton->dpiSubscrHandle = NULL;
|
|
2664
|
-
baton->subscription->StopNotifications();
|
|
2665
|
-
}
|
|
2666
|
-
baton->subscription = NULL;
|
|
2667
|
-
}
|
|
2668
|
-
|
|
2669
|
-
|
|
2670
|
-
//-----------------------------------------------------------------------------
|
|
2671
|
-
// njsConnection::GetSodaDatabase()
|
|
2672
|
-
// Creates a top-level soda obect (pseudo) associated with the connection.
|
|
2673
|
-
//-----------------------------------------------------------------------------
|
|
2674
|
-
NAN_METHOD(njsConnection::GetSodaDatabase)
|
|
2675
|
-
{
|
|
2676
|
-
njsConnection *connection;
|
|
2677
|
-
dpiSodaDb *dbHandle;
|
|
2678
|
-
|
|
2679
|
-
connection = (njsConnection *) ValidateArgs(info, 0, 0);
|
|
2680
|
-
if (!connection)
|
|
2681
|
-
return;
|
|
2682
|
-
|
|
2683
|
-
if (dpiConn_getSodaDb(connection->dpiConnHandle, &dbHandle) < 0) {
|
|
2684
|
-
njsOracledb::ThrowDPIError();
|
|
2685
|
-
return;
|
|
2686
|
-
}
|
|
2687
|
-
|
|
2688
|
-
Local<Object> jsOracledb = Nan::New(connection->jsOracledb);
|
|
2689
|
-
Local<Object> dbObj = njsSodaDatabase::CreateFromHandle(jsOracledb,
|
|
2690
|
-
dbHandle);
|
|
2691
|
-
info.GetReturnValue().Set(dbObj);
|
|
2692
|
-
}
|
|
2693
|
-
|
|
2694
|
-
|
|
2695
|
-
//-----------------------------------------------------------------------------
|
|
2696
|
-
// njsConnection::GetStmtCacheSize()
|
|
2697
|
-
// Get accessor of "stmtCacheSize" property.
|
|
2698
|
-
//-----------------------------------------------------------------------------
|
|
2699
|
-
NAN_GETTER(njsConnection::GetStmtCacheSize)
|
|
2700
|
-
{
|
|
2701
|
-
njsConnection *connection = (njsConnection*) ValidateGetter(info);
|
|
2702
|
-
if (!connection)
|
|
2703
|
-
return;
|
|
2704
|
-
if (!connection->IsValid()) {
|
|
2705
|
-
info.GetReturnValue().Set(Nan::Undefined());
|
|
2706
|
-
return;
|
|
2707
|
-
}
|
|
2708
|
-
uint32_t cacheSize;
|
|
2709
|
-
if (dpiConn_getStmtCacheSize(connection->dpiConnHandle, &cacheSize) < 0) {
|
|
2710
|
-
njsOracledb::ThrowDPIError();
|
|
2711
|
-
return;
|
|
2712
|
-
}
|
|
2713
|
-
info.GetReturnValue().Set(cacheSize);
|
|
2714
|
-
}
|
|
2715
|
-
|
|
2716
|
-
|
|
2717
|
-
//-----------------------------------------------------------------------------
|
|
2718
|
-
// njsConnection::SetStmtCacheSize()
|
|
2719
|
-
// Set accessor of "stmtCacheSize" property.
|
|
2720
|
-
//-----------------------------------------------------------------------------
|
|
2721
|
-
NAN_SETTER(njsConnection::SetStmtCacheSize)
|
|
2722
|
-
{
|
|
2723
|
-
PropertyIsReadOnly("stmtCacheSize");
|
|
2724
|
-
}
|
|
2725
|
-
|
|
2726
|
-
|
|
2727
|
-
//-----------------------------------------------------------------------------
|
|
2728
|
-
// njsConnection::GetClientId()
|
|
2729
|
-
// Get accessor of "clientId" property. This is a write-only property,
|
|
2730
|
-
// returning NULL for debugging purposes in case of read.
|
|
2731
|
-
//-----------------------------------------------------------------------------
|
|
2732
|
-
NAN_GETTER(njsConnection::GetClientId)
|
|
2733
|
-
{
|
|
2734
|
-
info.GetReturnValue().SetNull();
|
|
2735
|
-
}
|
|
2736
|
-
|
|
2737
|
-
|
|
2738
|
-
//-----------------------------------------------------------------------------
|
|
2739
|
-
// njsConnection::SetClientId()
|
|
2740
|
-
// Set accessor of "clientId" property.
|
|
2741
|
-
//-----------------------------------------------------------------------------
|
|
2742
|
-
NAN_SETTER(njsConnection::SetClientId)
|
|
2743
|
-
{
|
|
2744
|
-
SetTextAttribute(info, "clientId", value, dpiConn_setClientIdentifier);
|
|
2745
|
-
}
|
|
2746
|
-
|
|
2747
|
-
|
|
2748
|
-
//-----------------------------------------------------------------------------
|
|
2749
|
-
// njsConnection::GetModule()
|
|
2750
|
-
// Get accessor of "module" property. This is a write-only property,
|
|
2751
|
-
// returning NULL for debugging purposes in case of read.
|
|
2752
|
-
//-----------------------------------------------------------------------------
|
|
2753
|
-
NAN_GETTER(njsConnection::GetModule)
|
|
2754
|
-
{
|
|
2755
|
-
info.GetReturnValue().SetNull();
|
|
2756
|
-
}
|
|
2757
|
-
|
|
2758
|
-
|
|
2759
|
-
//-----------------------------------------------------------------------------
|
|
2760
|
-
// njsConnection::SetModule()
|
|
2761
|
-
// Set accessor of "module" property.
|
|
2762
|
-
//-----------------------------------------------------------------------------
|
|
2763
|
-
NAN_SETTER(njsConnection::SetModule)
|
|
2764
|
-
{
|
|
2765
|
-
SetTextAttribute(info, "module", value, dpiConn_setModule);
|
|
2766
|
-
}
|
|
2767
|
-
|
|
2768
|
-
|
|
2769
|
-
//-----------------------------------------------------------------------------
|
|
2770
|
-
// njsConnection::GetAction()
|
|
2771
|
-
// Get accessor of "action" property. This is a write-only property,
|
|
2772
|
-
// returning NULL for debugging purposes in case of read.
|
|
2773
|
-
//-----------------------------------------------------------------------------
|
|
2774
|
-
NAN_GETTER(njsConnection::GetAction)
|
|
2775
|
-
{
|
|
2776
|
-
info.GetReturnValue().SetNull();
|
|
2777
|
-
}
|
|
2778
|
-
|
|
2779
|
-
|
|
2780
|
-
//-----------------------------------------------------------------------------
|
|
2781
|
-
// njsConnection::SetAction()
|
|
2782
|
-
// Set accessor of "action" property.
|
|
2783
|
-
//-----------------------------------------------------------------------------
|
|
2784
|
-
NAN_SETTER(njsConnection::SetAction)
|
|
2785
|
-
{
|
|
2786
|
-
SetTextAttribute(info, "action", value, dpiConn_setAction);
|
|
2787
|
-
}
|
|
2788
|
-
|
|
2789
|
-
|
|
2790
|
-
//-----------------------------------------------------------------------------
|
|
2791
|
-
// njsConnection::GetOracleServerVersion()
|
|
2792
|
-
// Get accessor of "oracleServerVersion" property.
|
|
2793
|
-
//-----------------------------------------------------------------------------
|
|
2794
|
-
NAN_GETTER(njsConnection::GetOracleServerVersion)
|
|
2795
|
-
{
|
|
2796
|
-
njsConnection *connection = (njsConnection*) ValidateGetter(info);
|
|
2797
|
-
if (!connection)
|
|
2798
|
-
return;
|
|
2799
|
-
if (!connection->IsValid()) {
|
|
2800
|
-
info.GetReturnValue().Set(Nan::Undefined());
|
|
2801
|
-
return;
|
|
2802
|
-
}
|
|
2803
|
-
dpiVersionInfo versionInfo;
|
|
2804
|
-
uint32_t releaseStringLength;
|
|
2805
|
-
const char *releaseString;
|
|
2806
|
-
if (dpiConn_getServerVersion(connection->dpiConnHandle, &releaseString,
|
|
2807
|
-
&releaseStringLength, &versionInfo) < 0) {
|
|
2808
|
-
njsOracledb::ThrowDPIError();
|
|
2809
|
-
return;
|
|
2810
|
-
}
|
|
2811
|
-
uint32_t oracleServerVersion = static_cast<uint32_t> (
|
|
2812
|
-
100000000 * versionInfo.versionNum +
|
|
2813
|
-
1000000 * versionInfo.releaseNum + 10000 * versionInfo.updateNum +
|
|
2814
|
-
100 * versionInfo.portReleaseNum + versionInfo.portUpdateNum);
|
|
2815
|
-
info.GetReturnValue().Set(oracleServerVersion);
|
|
2816
|
-
}
|
|
2817
|
-
|
|
2818
|
-
|
|
2819
|
-
//-----------------------------------------------------------------------------
|
|
2820
|
-
// njsConnection::SetOracleServerVersion()
|
|
2821
|
-
// Set accessor of "oracleServerVersion" property.
|
|
2822
|
-
//-----------------------------------------------------------------------------
|
|
2823
|
-
NAN_SETTER(njsConnection::SetOracleServerVersion)
|
|
2824
|
-
{
|
|
2825
|
-
PropertyIsReadOnly("oracleServerVersion");
|
|
2826
|
-
}
|
|
2827
|
-
|
|
2828
|
-
|
|
2829
|
-
//-----------------------------------------------------------------------------
|
|
2830
|
-
// njsConnection::GetOracleServerVersionString()
|
|
2831
|
-
// Get accessor of "oracleServerVersionString" property.
|
|
2832
|
-
//-----------------------------------------------------------------------------
|
|
2833
|
-
NAN_GETTER(njsConnection::GetOracleServerVersionString)
|
|
2834
|
-
{
|
|
2835
|
-
njsConnection *connection = (njsConnection*) ValidateGetter(info);
|
|
2836
|
-
if (!connection)
|
|
2837
|
-
return;
|
|
2838
|
-
if (!connection->IsValid()) {
|
|
2839
|
-
info.GetReturnValue().Set(Nan::Undefined());
|
|
2840
|
-
return;
|
|
2841
|
-
}
|
|
2842
|
-
dpiVersionInfo versionInfo;
|
|
2843
|
-
uint32_t releaseStringLength;
|
|
2844
|
-
const char *releaseString;
|
|
2845
|
-
if (dpiConn_getServerVersion(connection->dpiConnHandle, &releaseString,
|
|
2846
|
-
&releaseStringLength, &versionInfo) < 0) {
|
|
2847
|
-
njsOracledb::ThrowDPIError();
|
|
2848
|
-
return;
|
|
2849
|
-
}
|
|
2850
|
-
char versionString[40];
|
|
2851
|
-
(void) sprintf(versionString, "%d.%d.%d.%d.%d", versionInfo.versionNum,
|
|
2852
|
-
versionInfo.releaseNum, versionInfo.updateNum,
|
|
2853
|
-
versionInfo.portReleaseNum, versionInfo.portUpdateNum);
|
|
2854
|
-
Local<String> value = Nan::New<v8::String>(versionString).ToLocalChecked();
|
|
2855
|
-
info.GetReturnValue().Set(value);
|
|
2856
|
-
}
|
|
2857
|
-
|
|
2858
|
-
|
|
2859
|
-
//-----------------------------------------------------------------------------
|
|
2860
|
-
// njsConnection::SetOracleServerVersionString()
|
|
2861
|
-
// Set accessor of "oracleServerVersionString" property.
|
|
2862
|
-
//-----------------------------------------------------------------------------
|
|
2863
|
-
NAN_SETTER(njsConnection::SetOracleServerVersionString)
|
|
2864
|
-
{
|
|
2865
|
-
PropertyIsReadOnly("oracleServerVersionString");
|
|
2866
|
-
}
|
|
2867
|
-
|
|
2868
|
-
|
|
2869
|
-
//-----------------------------------------------------------------------------
|
|
2870
|
-
// njsConnection::GetCallTimeout()
|
|
2871
|
-
// Get accessor of "callTimeout" property.
|
|
2872
|
-
//-----------------------------------------------------------------------------
|
|
2873
|
-
NAN_GETTER(njsConnection::GetCallTimeout)
|
|
2874
|
-
{
|
|
2875
|
-
uint32_t callTimeout;
|
|
2876
|
-
|
|
2877
|
-
njsConnection *connection = (njsConnection*) ValidateGetter(info);
|
|
2878
|
-
if (!connection)
|
|
2879
|
-
return;
|
|
2880
|
-
if (!connection->IsValid()) {
|
|
2881
|
-
info.GetReturnValue().Set(Nan::Undefined());
|
|
2882
|
-
return;
|
|
2883
|
-
}
|
|
2884
|
-
|
|
2885
|
-
// if an Oracle Client less than 18.1 is being used, return undefined
|
|
2886
|
-
dpiVersionInfo versionInfo;
|
|
2887
|
-
dpiContext *context = njsOracledb::GetDPIContext();
|
|
2888
|
-
if (dpiContext_getClientVersion(context, &versionInfo) < 0) {
|
|
2889
|
-
njsOracledb::ThrowDPIError();
|
|
2890
|
-
return;
|
|
2891
|
-
}
|
|
2892
|
-
if (versionInfo.versionNum < 18) {
|
|
2893
|
-
info.GetReturnValue().Set(Nan::Undefined());
|
|
2894
|
-
return;
|
|
2895
|
-
}
|
|
2896
|
-
|
|
2897
|
-
if (dpiConn_getCallTimeout(connection->dpiConnHandle, &callTimeout) < 0) {
|
|
2898
|
-
njsOracledb::ThrowDPIError();
|
|
2899
|
-
return;
|
|
2900
|
-
}
|
|
2901
|
-
info.GetReturnValue().Set(callTimeout);
|
|
2902
|
-
}
|
|
2903
|
-
|
|
2904
|
-
|
|
2905
|
-
//-----------------------------------------------------------------------------
|
|
2906
|
-
// njsConnection::SetCallTimeout()
|
|
2907
|
-
// Set accessor of "callTimeout" property.
|
|
2908
|
-
//-----------------------------------------------------------------------------
|
|
2909
|
-
NAN_SETTER(njsConnection::SetCallTimeout)
|
|
2910
|
-
{
|
|
2911
|
-
uint32_t callTimeout;
|
|
2912
|
-
|
|
2913
|
-
njsConnection *connection = (njsConnection*) ValidateSetter(info);
|
|
2914
|
-
if (!connection)
|
|
2915
|
-
return;
|
|
2916
|
-
if (!value->IsUint32()) {
|
|
2917
|
-
string errMsg = njsMessages::Get(errInvalidPropertyValue,
|
|
2918
|
-
"callTimeout");
|
|
2919
|
-
Nan::ThrowError(errMsg.c_str());
|
|
2920
|
-
return;
|
|
2921
|
-
}
|
|
2922
|
-
callTimeout = Nan::To<uint32_t>(value).FromJust();
|
|
2923
|
-
if (dpiConn_setCallTimeout(connection->dpiConnHandle, callTimeout) < 0)
|
|
2924
|
-
njsOracledb::ThrowDPIError();
|
|
2925
|
-
}
|
|
2926
|
-
|