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.
Files changed (112) hide show
  1. package/CHANGELOG.md +135 -8
  2. package/README.md +6 -4
  3. package/build/Release/oracledb-abi48-darwin-x64.node +0 -0
  4. package/build/Release/oracledb-abi48-darwin-x64.node-buildinfo.txt +1 -0
  5. package/build/Release/oracledb-abi48-linux-x64.node +0 -0
  6. package/build/Release/oracledb-abi48-linux-x64.node-buildinfo.txt +1 -0
  7. package/build/Release/oracledb-abi48-win32-x64.node +0 -0
  8. package/build/Release/oracledb-abi48-win32-x64.node-buildinfo.txt +1 -0
  9. package/build/Release/oracledb-abi57-darwin-x64.node +0 -0
  10. package/build/Release/oracledb-abi57-darwin-x64.node-buildinfo.txt +1 -0
  11. package/build/Release/oracledb-abi57-linux-x64.node +0 -0
  12. package/build/Release/oracledb-abi57-linux-x64.node-buildinfo.txt +1 -0
  13. package/build/Release/oracledb-abi57-win32-x64.node +0 -0
  14. package/build/Release/oracledb-abi57-win32-x64.node-buildinfo.txt +1 -0
  15. package/build/Release/oracledb-abi64-darwin-x64.node +0 -0
  16. package/build/Release/oracledb-abi64-darwin-x64.node-buildinfo.txt +1 -0
  17. package/build/Release/oracledb-abi64-linux-x64.node +0 -0
  18. package/build/Release/oracledb-abi64-linux-x64.node-buildinfo.txt +1 -0
  19. package/build/Release/oracledb-abi64-win32-x64.node +0 -0
  20. package/build/Release/oracledb-abi64-win32-x64.node-buildinfo.txt +1 -0
  21. package/build/Release/oracledb-abi67-darwin-x64.node +0 -0
  22. package/build/Release/oracledb-abi67-darwin-x64.node-buildinfo.txt +1 -0
  23. package/build/Release/oracledb-abi67-linux-x64.node +0 -0
  24. package/build/Release/oracledb-abi67-linux-x64.node-buildinfo.txt +1 -0
  25. package/build/Release/oracledb-abi67-win32-x64.node +0 -0
  26. package/build/Release/oracledb-abi67-win32-x64.node-buildinfo.txt +1 -0
  27. package/lib/connection.js +18 -4
  28. package/lib/oracledb.js +44 -92
  29. package/lib/pool.js +36 -2
  30. package/lib/sodaCollection.js +1 -1
  31. package/lib/sodaDatabase.js +1 -1
  32. package/lib/util.js +82 -5
  33. package/package/README.md +32 -101
  34. package/package/install.js +139 -0
  35. package/package/prunebinaries.js +51 -0
  36. package/package.json +4 -11
  37. package/binding.gyp +0 -162
  38. package/lib/rel.txt +0 -1
  39. package/odpi/.npmignore +0 -4
  40. package/odpi/LICENSE.md +0 -218
  41. package/odpi/README.md +0 -61
  42. package/odpi/embed/README.md +0 -4
  43. package/odpi/embed/dpi.c +0 -50
  44. package/odpi/include/dpi.h +0 -1748
  45. package/odpi/src/dpiConn.c +0 -2089
  46. package/odpi/src/dpiContext.c +0 -296
  47. package/odpi/src/dpiData.c +0 -797
  48. package/odpi/src/dpiDebug.c +0 -184
  49. package/odpi/src/dpiDeqOptions.c +0 -370
  50. package/odpi/src/dpiEnqOptions.c +0 -174
  51. package/odpi/src/dpiEnv.c +0 -189
  52. package/odpi/src/dpiError.c +0 -204
  53. package/odpi/src/dpiErrorMessages.h +0 -86
  54. package/odpi/src/dpiGen.c +0 -303
  55. package/odpi/src/dpiGlobal.c +0 -292
  56. package/odpi/src/dpiHandleList.c +0 -117
  57. package/odpi/src/dpiHandlePool.c +0 -118
  58. package/odpi/src/dpiImpl.h +0 -1707
  59. package/odpi/src/dpiLob.c +0 -506
  60. package/odpi/src/dpiMsgProps.c +0 -386
  61. package/odpi/src/dpiObject.c +0 -897
  62. package/odpi/src/dpiObjectAttr.c +0 -115
  63. package/odpi/src/dpiObjectType.c +0 -326
  64. package/odpi/src/dpiOci.c +0 -3527
  65. package/odpi/src/dpiOracleType.c +0 -492
  66. package/odpi/src/dpiPool.c +0 -549
  67. package/odpi/src/dpiRowid.c +0 -136
  68. package/odpi/src/dpiSodaColl.c +0 -685
  69. package/odpi/src/dpiSodaCollCursor.c +0 -143
  70. package/odpi/src/dpiSodaDb.c +0 -432
  71. package/odpi/src/dpiSodaDoc.c +0 -230
  72. package/odpi/src/dpiSodaDocCursor.c +0 -143
  73. package/odpi/src/dpiStmt.c +0 -1797
  74. package/odpi/src/dpiSubscr.c +0 -674
  75. package/odpi/src/dpiUtils.c +0 -410
  76. package/odpi/src/dpiVar.c +0 -1794
  77. package/package/MAKEPKG.BAT +0 -156
  78. package/package/Makefile +0 -85
  79. package/package/createpackage.js +0 -186
  80. package/package/extractpackage.js +0 -76
  81. package/package/getversion.js +0 -37
  82. package/package/oracledbinstall.js +0 -497
  83. package/package/package.json +0 -54
  84. package/package/util.js +0 -286
  85. package/src/njsCommon.cpp +0 -1055
  86. package/src/njsCommon.h +0 -484
  87. package/src/njsConnection.cpp +0 -2926
  88. package/src/njsConnection.h +0 -227
  89. package/src/njsIntLob.cpp +0 -618
  90. package/src/njsIntLob.h +0 -179
  91. package/src/njsMessages.cpp +0 -122
  92. package/src/njsMessages.h +0 -118
  93. package/src/njsOracle.cpp +0 -1274
  94. package/src/njsOracle.h +0 -237
  95. package/src/njsPool.cpp +0 -482
  96. package/src/njsPool.h +0 -132
  97. package/src/njsResultSet.cpp +0 -478
  98. package/src/njsResultSet.h +0 -120
  99. package/src/njsSodaCollection.cpp +0 -507
  100. package/src/njsSodaCollection.h +0 -128
  101. package/src/njsSodaDatabase.cpp +0 -335
  102. package/src/njsSodaDatabase.h +0 -108
  103. package/src/njsSodaDocCursor.cpp +0 -203
  104. package/src/njsSodaDocCursor.h +0 -94
  105. package/src/njsSodaDocument.cpp +0 -412
  106. package/src/njsSodaDocument.h +0 -105
  107. package/src/njsSodaOperation.cpp +0 -557
  108. package/src/njsSodaOperation.h +0 -123
  109. package/src/njsSubscription.cpp +0 -388
  110. package/src/njsSubscription.h +0 -111
  111. package/src/njsUtils.cpp +0 -158
  112. package/src/njsUtils.h +0 -68
@@ -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, &params) < 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, &params,
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
-