oracledb 6.3.0 → 6.5.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/LICENSE.txt +1 -1
- package/NOTICE.txt +1 -1
- package/README.md +3 -3
- package/build/Release/oracledb-6.5.0-darwin-x64.node +0 -0
- package/build/Release/oracledb-6.5.0-darwin-x64.node-buildinfo.txt +1 -0
- package/build/Release/oracledb-6.5.0-js-buildinfo.txt +1 -0
- package/build/Release/oracledb-6.5.0-linux-arm64.node +0 -0
- package/build/Release/oracledb-6.5.0-linux-arm64.node-buildinfo.txt +1 -0
- package/build/Release/oracledb-6.5.0-linux-x64.node +0 -0
- package/build/Release/oracledb-6.5.0-linux-x64.node-buildinfo.txt +1 -0
- package/build/Release/oracledb-6.5.0-win32-x64.node +0 -0
- package/build/Release/oracledb-6.5.0-win32-x64.node-buildinfo.txt +1 -0
- package/examples/README.md +3 -0
- package/lib/aqQueue.js +8 -8
- package/lib/connection.js +65 -22
- package/lib/constants.js +7 -1
- package/lib/dbObject.js +72 -1
- package/lib/errors.js +51 -10
- package/lib/impl/connection.js +2 -1
- package/lib/{thin/protocol → impl/datahandlers}/buffer.js +36 -32
- package/lib/impl/datahandlers/constants.js +106 -0
- package/lib/{thin/protocol → impl/datahandlers}/oson.js +320 -151
- package/lib/impl/datahandlers/vector.js +137 -0
- package/lib/impl/pool.js +9 -0
- package/lib/impl/resultset.js +34 -17
- package/lib/lob.js +22 -6
- package/lib/oracledb.js +35 -1
- package/lib/pool.js +17 -2
- package/lib/poolStatistics.js +3 -1
- package/lib/settings.js +31 -6
- package/lib/sodaDocCursor.js +14 -1
- package/lib/thin/connection.js +120 -193
- package/lib/thin/dbObject.js +4 -2
- package/lib/thin/lob.js +6 -6
- package/lib/thin/pool.js +84 -10
- package/lib/thin/protocol/capabilities.js +20 -6
- package/lib/thin/protocol/constants.js +34 -54
- package/lib/thin/protocol/messages/auth.js +2 -2
- package/lib/thin/protocol/messages/base.js +28 -27
- package/lib/thin/protocol/messages/dataType.js +4 -2
- package/lib/thin/protocol/messages/execute.js +5 -1
- package/lib/thin/protocol/messages/{connectionCookie.js → fastAuth.js} +18 -16
- package/lib/thin/protocol/messages/fetch.js +4 -0
- package/lib/thin/protocol/messages/index.js +2 -2
- package/lib/thin/protocol/messages/protocol.js +9 -1
- package/lib/thin/protocol/messages/withData.js +40 -11
- package/lib/thin/protocol/packet.js +93 -8
- package/lib/thin/protocol/protocol.js +10 -5
- package/lib/thin/protocol/utils.js +11 -18
- package/lib/thin/sqlnet/constants.js +5 -2
- package/lib/thin/sqlnet/ezConnectResolver.js +9 -5
- package/lib/thin/sqlnet/navNodes.js +4 -3
- package/lib/thin/sqlnet/networkSession.js +27 -4
- package/lib/thin/sqlnet/packet.js +2 -5
- package/lib/thin/statement.js +43 -7
- package/lib/thin/statementCache.js +190 -0
- package/lib/thin/util.js +2 -2
- package/lib/transformer.js +21 -6
- package/lib/types.js +21 -3
- package/lib/util.js +30 -1
- package/lib/version.js +2 -2
- package/package.json +1 -1
- package/build/Release/oracledb-6.3.0-darwin-x64.node +0 -0
- package/build/Release/oracledb-6.3.0-darwin-x64.node-buildinfo.txt +0 -1
- package/build/Release/oracledb-6.3.0-js-buildinfo.txt +0 -1
- package/build/Release/oracledb-6.3.0-linux-arm64.node +0 -0
- package/build/Release/oracledb-6.3.0-linux-arm64.node-buildinfo.txt +0 -1
- package/build/Release/oracledb-6.3.0-linux-x64.node +0 -0
- package/build/Release/oracledb-6.3.0-linux-x64.node-buildinfo.txt +0 -1
- package/build/Release/oracledb-6.3.0-win32-x64.node +0 -0
- package/build/Release/oracledb-6.3.0-win32-x64.node-buildinfo.txt +0 -1
package/lib/thin/connection.js
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
// Copyright (c) 2022,
|
|
1
|
+
// Copyright (c) 2022, 2024, Oracle and/or its affiliates.
|
|
2
2
|
|
|
3
3
|
//-----------------------------------------------------------------------------
|
|
4
4
|
//
|
|
@@ -31,7 +31,7 @@ const ConnectionImpl = require('../impl/connection.js');
|
|
|
31
31
|
const ThinResultSetImpl = require('./resultSet.js');
|
|
32
32
|
const ThinLobImpl = require("./lob.js");
|
|
33
33
|
const Protocol = require("./protocol/protocol.js");
|
|
34
|
-
const { BaseBuffer } = require('
|
|
34
|
+
const { BaseBuffer } = require('../impl/datahandlers/buffer.js');
|
|
35
35
|
const {NetworkSession: nsi} = require("./sqlnet/networkSession.js");
|
|
36
36
|
const { Statement } = require("./statement");
|
|
37
37
|
const thinUtil = require('./util');
|
|
@@ -41,6 +41,7 @@ const process = require('process');
|
|
|
41
41
|
const types = require('../types.js');
|
|
42
42
|
const errors = require("../errors.js");
|
|
43
43
|
const messages = require('./protocol/messages');
|
|
44
|
+
const StatementCache = require('./statementCache.js');
|
|
44
45
|
|
|
45
46
|
const finalizationRegistry = new global.FinalizationRegistry((heldValue) => {
|
|
46
47
|
heldValue.disconnect();
|
|
@@ -49,8 +50,6 @@ const finalizationRegistry = new global.FinalizationRegistry((heldValue) => {
|
|
|
49
50
|
class TDSBuffer extends BaseBuffer {
|
|
50
51
|
}
|
|
51
52
|
|
|
52
|
-
const connectionCookies = new Map();
|
|
53
|
-
|
|
54
53
|
class ThinConnectionImpl extends ConnectionImpl {
|
|
55
54
|
|
|
56
55
|
/**
|
|
@@ -63,12 +62,10 @@ class ThinConnectionImpl extends ConnectionImpl {
|
|
|
63
62
|
if (this._protocol.txnInProgress) {
|
|
64
63
|
await this.rollback();
|
|
65
64
|
}
|
|
66
|
-
this._protocol.callTimeout = 0; // not applicable for close
|
|
67
65
|
if (this._drcpEnabled) {
|
|
68
66
|
await this._sessRelease();
|
|
69
67
|
this._drcpEstablishSession = true;
|
|
70
68
|
}
|
|
71
|
-
|
|
72
69
|
if (this._pool && !this._dropSess) {
|
|
73
70
|
await this._pool.release(this);
|
|
74
71
|
} else {
|
|
@@ -94,13 +91,13 @@ class ThinConnectionImpl extends ConnectionImpl {
|
|
|
94
91
|
}
|
|
95
92
|
|
|
96
93
|
//---------------------------------------------------------------------------
|
|
97
|
-
//
|
|
94
|
+
// _getElementTypeObj()
|
|
98
95
|
//
|
|
99
|
-
//
|
|
96
|
+
// Get the element type's object type. This is needed when processing
|
|
100
97
|
// collections with an object as the element type since this information is
|
|
101
98
|
// not available in the TDS.
|
|
102
99
|
//---------------------------------------------------------------------------
|
|
103
|
-
async
|
|
100
|
+
async _getElementTypeObj(info) {
|
|
104
101
|
const binds = [
|
|
105
102
|
{
|
|
106
103
|
name: "owner",
|
|
@@ -184,12 +181,20 @@ class ThinConnectionImpl extends ConnectionImpl {
|
|
|
184
181
|
message.numExecs = numIters;
|
|
185
182
|
message.arrayDmlRowCounts = options.dmlRowCounts;
|
|
186
183
|
message.batchErrors = options.batchErrors;
|
|
187
|
-
|
|
184
|
+
|
|
185
|
+
// if a PL/SQL statement requires a full execute, perform only a single
|
|
186
|
+
// iteration in order to allow the determination of input/output binds
|
|
187
|
+
// to be completed; after that, an execution of the remaining iterations
|
|
188
|
+
// can be performed.
|
|
189
|
+
if (statement.isPlSql && (statement.cursorId === 0 ||
|
|
190
|
+
statement.requiresFullExecute)) {
|
|
188
191
|
message.numExecs = 1;
|
|
192
|
+
message.noImplicitRelease = true;
|
|
189
193
|
await this._protocol._processMessage(message);
|
|
190
194
|
statement.requiresFullExecute = false;
|
|
191
195
|
message.numExecs = numIters - 1;
|
|
192
196
|
message.offset = 1;
|
|
197
|
+
message.noImplicitRelease = false;
|
|
193
198
|
}
|
|
194
199
|
if (message.numExecs > 0) {
|
|
195
200
|
await this._protocol._processMessage(message);
|
|
@@ -255,60 +260,77 @@ class ThinConnectionImpl extends ConnectionImpl {
|
|
|
255
260
|
}
|
|
256
261
|
|
|
257
262
|
//---------------------------------------------------------------------------
|
|
258
|
-
//
|
|
263
|
+
// _parseTDSAttr()
|
|
259
264
|
//
|
|
260
|
-
//
|
|
265
|
+
// Returns the DB type and fills metadata from the TDS buffer.
|
|
261
266
|
//---------------------------------------------------------------------------
|
|
262
|
-
|
|
263
|
-
let oraTypeNum, csfrm;
|
|
264
|
-
|
|
267
|
+
_parseTDSAttr(buf, metaData) {
|
|
268
|
+
let oraTypeNum, csfrm, attrType;
|
|
269
|
+
|
|
270
|
+
// skip until a type code that is of interest
|
|
271
|
+
for (;;) {
|
|
272
|
+
attrType = buf.readUInt8();
|
|
273
|
+
if (attrType === constants.TNS_OBJ_TDS_TYPE_EMBED_ADT_INFO) {
|
|
274
|
+
buf.skipBytes(1); // flags
|
|
275
|
+
} else if (attrType !== constants.TNS_OBJ_TDS_TYPE_SUBTYPE_MARKER) {
|
|
276
|
+
break;
|
|
277
|
+
}
|
|
278
|
+
}
|
|
279
|
+
|
|
280
|
+
// process the type code.
|
|
265
281
|
switch (attrType) {
|
|
266
282
|
case constants.TNS_OBJ_TDS_TYPE_NUMBER:
|
|
283
|
+
metaData.precision = buf.readInt8();
|
|
284
|
+
metaData.scale = buf.readInt8();
|
|
285
|
+
return types.DB_TYPE_NUMBER;
|
|
267
286
|
case constants.TNS_OBJ_TDS_TYPE_FLOAT:
|
|
268
|
-
|
|
269
|
-
|
|
287
|
+
metaData.precision = buf.readInt8();
|
|
288
|
+
return types.DB_TYPE_NUMBER;
|
|
270
289
|
case constants.TNS_OBJ_TDS_TYPE_VARCHAR:
|
|
271
290
|
case constants.TNS_OBJ_TDS_TYPE_CHAR:
|
|
272
|
-
|
|
291
|
+
metaData.maxSize = buf.readUInt16BE(); // maximum length
|
|
273
292
|
oraTypeNum = (attrType === constants.TNS_OBJ_TDS_TYPE_VARCHAR) ?
|
|
274
293
|
constants.TNS_DATA_TYPE_VARCHAR : constants.TNS_DATA_TYPE_CHAR;
|
|
275
294
|
csfrm = buf.readUInt8();
|
|
276
|
-
|
|
277
|
-
|
|
295
|
+
csfrm = csfrm & 0x7f;
|
|
296
|
+
buf.skipBytes(2); // character set
|
|
297
|
+
return types.getTypeByOraTypeNum(oraTypeNum, csfrm);
|
|
278
298
|
case constants.TNS_OBJ_TDS_TYPE_RAW:
|
|
279
|
-
|
|
280
|
-
|
|
299
|
+
metaData.maxSize = buf.readUInt16BE(); // maximum length
|
|
300
|
+
return types.DB_TYPE_RAW;
|
|
281
301
|
case constants.TNS_OBJ_TDS_TYPE_BINARY_FLOAT:
|
|
282
|
-
|
|
283
|
-
break;
|
|
302
|
+
return types.DB_TYPE_BINARY_FLOAT;
|
|
284
303
|
case constants.TNS_OBJ_TDS_TYPE_BINARY_DOUBLE:
|
|
285
|
-
|
|
286
|
-
break;
|
|
304
|
+
return types.DB_TYPE_BINARY_DOUBLE;
|
|
287
305
|
case constants.TNS_OBJ_TDS_TYPE_DATE:
|
|
288
|
-
|
|
289
|
-
break;
|
|
306
|
+
return types.DB_TYPE_DATE;
|
|
290
307
|
case constants.TNS_OBJ_TDS_TYPE_TIMESTAMP:
|
|
291
|
-
|
|
292
|
-
|
|
308
|
+
buf.skipBytes(1); // precision
|
|
309
|
+
return types.DB_TYPE_TIMESTAMP;
|
|
293
310
|
case constants.TNS_OBJ_TDS_TYPE_TIMESTAMP_LTZ:
|
|
294
|
-
|
|
295
|
-
|
|
311
|
+
buf.skipBytes(1); // precision
|
|
312
|
+
return types.DB_TYPE_TIMESTAMP_LTZ;
|
|
296
313
|
case constants.TNS_OBJ_TDS_TYPE_TIMESTAMP_TZ:
|
|
297
|
-
|
|
298
|
-
|
|
314
|
+
buf.skipBytes(1); // precision
|
|
315
|
+
return types.DB_TYPE_TIMESTAMP_TZ;
|
|
299
316
|
case constants.TNS_OBJ_TDS_TYPE_BOOLEAN:
|
|
300
|
-
|
|
301
|
-
break;
|
|
317
|
+
return types.DB_TYPE_BOOLEAN;
|
|
302
318
|
case constants.TNS_OBJ_TDS_TYPE_CLOB:
|
|
303
|
-
|
|
304
|
-
break;
|
|
319
|
+
return types.DB_TYPE_CLOB;
|
|
305
320
|
case constants.TNS_OBJ_TDS_TYPE_BLOB:
|
|
306
|
-
|
|
307
|
-
break;
|
|
321
|
+
return types.DB_TYPE_BLOB;
|
|
308
322
|
case constants.TNS_OBJ_TDS_TYPE_OBJ:
|
|
309
|
-
|
|
310
|
-
|
|
311
|
-
|
|
323
|
+
buf.skipBytes(5);
|
|
324
|
+
return types.DB_TYPE_OBJECT;
|
|
325
|
+
case constants.TNS_OBJ_TDS_TYPE_START_EMBED_ADT:
|
|
326
|
+
// loop until end type, TNS_OBJ_TDS_TYPE_END_EMBED_ADT
|
|
327
|
+
// is received.
|
|
328
|
+
while (this._parseTDSAttr(buf, {}) !== 0) {
|
|
329
|
+
continue;
|
|
330
|
+
}
|
|
331
|
+
return types.DB_TYPE_OBJECT;
|
|
332
|
+
case constants.TNS_OBJ_TDS_TYPE_END_EMBED_ADT:
|
|
333
|
+
return 0;
|
|
312
334
|
default:
|
|
313
335
|
errors.throwErr(errors.ERR_TDS_TYPE_NOT_SUPPORTED, attrType);
|
|
314
336
|
}
|
|
@@ -317,12 +339,9 @@ class ThinConnectionImpl extends ConnectionImpl {
|
|
|
317
339
|
//---------------------------------------------------------------------------
|
|
318
340
|
// _parseTDS()
|
|
319
341
|
//
|
|
320
|
-
// Parses the TDS
|
|
321
|
-
// if the TDS is determined to be for an object type, the remaining
|
|
322
|
-
// information is ignored.
|
|
342
|
+
// Parses the TDS (type descriptor segment) for the type.
|
|
323
343
|
//---------------------------------------------------------------------------
|
|
324
344
|
async _parseTDS(tds, info) {
|
|
325
|
-
|
|
326
345
|
// parse initial TDS bytes
|
|
327
346
|
const buf = new TDSBuffer(tds);
|
|
328
347
|
buf.skipBytes(4); // end offset
|
|
@@ -332,10 +351,6 @@ class ThinConnectionImpl extends ConnectionImpl {
|
|
|
332
351
|
// if the number of attributes exceeds 1, the type cannot refer to a
|
|
333
352
|
// collection, so nothing further needs to be done
|
|
334
353
|
const numAttrs = buf.readUInt16BE();
|
|
335
|
-
if (numAttrs > 1) {
|
|
336
|
-
info.isCollection = false;
|
|
337
|
-
return;
|
|
338
|
-
}
|
|
339
354
|
|
|
340
355
|
// continue parsing TDS bytes to discover if type refers to a collection
|
|
341
356
|
buf.skipBytes(1); // TDS attributes?
|
|
@@ -343,23 +358,41 @@ class ThinConnectionImpl extends ConnectionImpl {
|
|
|
343
358
|
buf.skipBytes(2); // ADT number (always zero)
|
|
344
359
|
buf.skipBytes(4); // offset to index table
|
|
345
360
|
|
|
346
|
-
//
|
|
347
|
-
//
|
|
348
|
-
|
|
349
|
-
|
|
350
|
-
|
|
351
|
-
|
|
352
|
-
|
|
353
|
-
|
|
354
|
-
|
|
355
|
-
|
|
356
|
-
|
|
357
|
-
if (info.collectionType === constants.TNS_OBJ_PLSQL_INDEX_TABLE) {
|
|
358
|
-
info.collectionFlags = constants.TNS_OBJ_HAS_INDEXES;
|
|
361
|
+
// check to see if type refers to a collection (only one attribute is
|
|
362
|
+
// present in that case).
|
|
363
|
+
info.isCollection = false;
|
|
364
|
+
if (numAttrs === 1) {
|
|
365
|
+
const pos = buf.pos;
|
|
366
|
+
const attrType = buf.readUInt8();
|
|
367
|
+
if (attrType === constants.TNS_OBJ_TDS_TYPE_COLL) {
|
|
368
|
+
info.isCollection = true;
|
|
369
|
+
} else {
|
|
370
|
+
buf.pos = pos;
|
|
371
|
+
}
|
|
359
372
|
}
|
|
360
|
-
buf.pos = elementPos;
|
|
361
373
|
|
|
362
|
-
|
|
374
|
+
// Handle collections
|
|
375
|
+
if (info.isCollection) {
|
|
376
|
+
// continue parsing TDS to determine element type
|
|
377
|
+
const elementPos = buf.readUInt32BE();
|
|
378
|
+
info.maxNumElements = buf.readUInt32BE();
|
|
379
|
+
info.collectionType = buf.readUInt8();
|
|
380
|
+
if (info.collectionType === constants.TNS_OBJ_PLSQL_INDEX_TABLE) {
|
|
381
|
+
info.collectionFlags = constants.TNS_OBJ_HAS_INDEXES;
|
|
382
|
+
}
|
|
383
|
+
buf.pos = elementPos;
|
|
384
|
+
info.elementTypeInfo = {};
|
|
385
|
+
info.elementType = this._parseTDSAttr(buf, info.elementTypeInfo);
|
|
386
|
+
if (info.elementType === types.DB_TYPE_OBJECT) {
|
|
387
|
+
await this._getElementTypeObj(info);
|
|
388
|
+
}
|
|
389
|
+
} else {
|
|
390
|
+
if (info.attributes) { // skip for XML type as it has no attributes.
|
|
391
|
+
for (const attr of info.attributes) {
|
|
392
|
+
this._parseTDSAttr(buf, attr);
|
|
393
|
+
}
|
|
394
|
+
}
|
|
395
|
+
}
|
|
363
396
|
}
|
|
364
397
|
|
|
365
398
|
//---------------------------------------------------------------------------
|
|
@@ -485,9 +518,9 @@ class ThinConnectionImpl extends ConnectionImpl {
|
|
|
485
518
|
|
|
486
519
|
// process TDS and attributes cursor
|
|
487
520
|
info.version = result.outBinds.version;
|
|
488
|
-
await this._parseTDS(result.outBinds.tds, info);
|
|
489
521
|
const attrRows = await result.outBinds.attrs_rc.getRows(1000, {});
|
|
490
522
|
if (attrRows.length > 0) {
|
|
523
|
+
// Its an object not a collection.
|
|
491
524
|
info.attributes = [];
|
|
492
525
|
for (const row of attrRows) {
|
|
493
526
|
const attr = { name: row[1] };
|
|
@@ -503,8 +536,9 @@ class ThinConnectionImpl extends ConnectionImpl {
|
|
|
503
536
|
info.attributes.push(attr);
|
|
504
537
|
}
|
|
505
538
|
}
|
|
506
|
-
info.partial = false;
|
|
507
539
|
|
|
540
|
+
await this._parseTDS(result.outBinds.tds, info);
|
|
541
|
+
info.partial = false;
|
|
508
542
|
return info;
|
|
509
543
|
|
|
510
544
|
}
|
|
@@ -560,26 +594,6 @@ class ThinConnectionImpl extends ConnectionImpl {
|
|
|
560
594
|
return (this._pool) ? true : false;
|
|
561
595
|
}
|
|
562
596
|
|
|
563
|
-
//---------------------------------------------------------------------------
|
|
564
|
-
// getConnectionCookieByUUID()
|
|
565
|
-
//
|
|
566
|
-
// It fetches from map which keeps keyname as UUID+ServiceName.
|
|
567
|
-
// UUID identifies the CDB instance and ServiceName identifies the
|
|
568
|
-
// entity within a PDB which uniquely identifies a pdb instance.
|
|
569
|
-
//---------------------------------------------------------------------------
|
|
570
|
-
getConnectionCookieByUUID(uuid) {
|
|
571
|
-
let cookie;
|
|
572
|
-
if (uuid) {
|
|
573
|
-
const key = uuid + ((this.serviceName) ? this.serviceName : this.sid);
|
|
574
|
-
cookie = connectionCookies.get(key);
|
|
575
|
-
if (!cookie) {
|
|
576
|
-
cookie = {};
|
|
577
|
-
connectionCookies.set(key, cookie);
|
|
578
|
-
}
|
|
579
|
-
}
|
|
580
|
-
return cookie;
|
|
581
|
-
}
|
|
582
|
-
|
|
583
597
|
/**
|
|
584
598
|
*
|
|
585
599
|
* @param {object} params Configuration of the connection
|
|
@@ -599,11 +613,8 @@ class ThinConnectionImpl extends ConnectionImpl {
|
|
|
599
613
|
this.statementCache = null;
|
|
600
614
|
this.currentSchema = "";
|
|
601
615
|
this.invokeSessionCallback = true;
|
|
602
|
-
this.statementCache = new Map();
|
|
603
616
|
this.statementCacheSize = params.stmtCacheSize;
|
|
604
|
-
this._numCursorsToClose = 0;
|
|
605
617
|
this._currentSchemaModified = false;
|
|
606
|
-
this._cursorsToClose = new Set();
|
|
607
618
|
this._tempLobsToClose = [];
|
|
608
619
|
this._tempLobsTotalSize = 0;
|
|
609
620
|
this._drcpEstablishSession = false;
|
|
@@ -667,37 +678,24 @@ class ThinConnectionImpl extends ConnectionImpl {
|
|
|
667
678
|
}
|
|
668
679
|
|
|
669
680
|
try {
|
|
670
|
-
const cookie = this.getConnectionCookieByUUID(this.nscon.dbUUID);
|
|
671
|
-
this.nscon.dbUUID = null;
|
|
672
681
|
const protocolMessage = new messages.ProtocolMessage(this);
|
|
673
682
|
const dataTypeMessage = new messages.DataTypeMessage(this);
|
|
674
683
|
const authMessage = new messages.AuthMessage(this, params);
|
|
675
|
-
|
|
676
|
-
|
|
677
|
-
|
|
678
|
-
|
|
679
|
-
|
|
680
|
-
|
|
681
|
-
|
|
682
|
-
|
|
683
|
-
|
|
684
|
+
if (this.nscon.supportsFastAuth) {
|
|
685
|
+
const fastAuthMessage = new messages.FastAuthMessage(this);
|
|
686
|
+
fastAuthMessage.protocolMessage = protocolMessage;
|
|
687
|
+
fastAuthMessage.dataTypeMessage = dataTypeMessage;
|
|
688
|
+
fastAuthMessage.authMessage = authMessage;
|
|
689
|
+
await this._protocol._processMessage(fastAuthMessage);
|
|
690
|
+
if (fastAuthMessage.reNegotiate) {
|
|
691
|
+
// Fast Authentication failed.
|
|
692
|
+
await this._protocol._processMessage(dataTypeMessage);
|
|
693
|
+
await this._protocol._processMessage(authMessage);
|
|
694
|
+
}
|
|
684
695
|
} else {
|
|
685
696
|
await this._protocol._processMessage(protocolMessage);
|
|
686
|
-
}
|
|
687
|
-
if (!sentCookie || !cookie.populated) {
|
|
688
697
|
await this._protocol._processMessage(dataTypeMessage);
|
|
689
|
-
// Does OSESSKEY for non-token Authentication else OAUTH
|
|
690
698
|
await this._protocol._processMessage(authMessage);
|
|
691
|
-
if (cookie && !cookie.populated) {
|
|
692
|
-
cookie.protocolVersion = protocolMessage.serverVersion;
|
|
693
|
-
cookie.serverBanner = protocolMessage.serverBanner;
|
|
694
|
-
cookie.charsetID = this._protocol.caps.charSetID;
|
|
695
|
-
cookie.ncharsetID = this._protocol.caps.nCharsetId;
|
|
696
|
-
cookie.flags = protocolMessage.serverFlags;
|
|
697
|
-
cookie.compileCaps = Buffer.from(protocolMessage.serverCompileCaps);
|
|
698
|
-
cookie.runtimeCaps = Buffer.from(protocolMessage.serverRunTimeCaps);
|
|
699
|
-
cookie.populated = true;
|
|
700
|
-
}
|
|
701
699
|
}
|
|
702
700
|
if (!params.token) { // non-token Authentication
|
|
703
701
|
await this._protocol._processMessage(authMessage); // OAUTH
|
|
@@ -707,6 +705,7 @@ class ThinConnectionImpl extends ConnectionImpl {
|
|
|
707
705
|
throw err;
|
|
708
706
|
}
|
|
709
707
|
|
|
708
|
+
this.statementCache = new StatementCache(this.statementCacheSize);
|
|
710
709
|
// maintain a list of partially populated database object types
|
|
711
710
|
this._partialDbObjectTypes = [];
|
|
712
711
|
|
|
@@ -719,51 +718,10 @@ class ThinConnectionImpl extends ConnectionImpl {
|
|
|
719
718
|
}
|
|
720
719
|
|
|
721
720
|
//---------------------------------------------------------------------------
|
|
722
|
-
//
|
|
721
|
+
// Return the statement to the statement cache, if applicable
|
|
723
722
|
//---------------------------------------------------------------------------
|
|
724
723
|
_returnStatement(statement) {
|
|
725
|
-
|
|
726
|
-
statement.bindInfoList.forEach(bindInfo => {
|
|
727
|
-
bindInfo.bindVar = null;
|
|
728
|
-
});
|
|
729
|
-
}
|
|
730
|
-
if (statement.queryVars) {
|
|
731
|
-
statement.queryVars.forEach(queryVar => {
|
|
732
|
-
queryVar.values.fill(null);
|
|
733
|
-
});
|
|
734
|
-
}
|
|
735
|
-
if (statement.returnToCache) {
|
|
736
|
-
statement.inUse = false;
|
|
737
|
-
} else if (statement.cursorId !== 0) {
|
|
738
|
-
this._addCursorToClose(statement.cursorId);
|
|
739
|
-
}
|
|
740
|
-
}
|
|
741
|
-
|
|
742
|
-
//---------------------------------------------------------------------------
|
|
743
|
-
// Adds the cursors that needs to be closed to the _cursorsToClose set
|
|
744
|
-
//---------------------------------------------------------------------------
|
|
745
|
-
_addCursorToClose(cursorId) {
|
|
746
|
-
if (this._cursorsToClose.has(cursorId)) {
|
|
747
|
-
const reason = `attempt to close cursor ${cursorId} twice`;
|
|
748
|
-
errors.throwErr(errors.ERR_INTERNAL, reason);
|
|
749
|
-
}
|
|
750
|
-
this._cursorsToClose.add(cursorId);
|
|
751
|
-
}
|
|
752
|
-
|
|
753
|
-
//---------------------------------------------------------------------------
|
|
754
|
-
// Adjusts the statement cache to remove least recently used statements
|
|
755
|
-
//---------------------------------------------------------------------------
|
|
756
|
-
_adjustStatementCache() {
|
|
757
|
-
while (this.statementCache.size > this.statementCacheSize) {
|
|
758
|
-
const sql = this.statementCache.keys().next().value;
|
|
759
|
-
const stmt = this.statementCache.get(sql);
|
|
760
|
-
this.statementCache.delete(sql);
|
|
761
|
-
if (stmt.inUse) {
|
|
762
|
-
stmt.returnToCache = false;
|
|
763
|
-
} else if (stmt.cursorId !== 0) {
|
|
764
|
-
this._addCursorToClose(stmt.cursorId);
|
|
765
|
-
}
|
|
766
|
-
}
|
|
724
|
+
this.statementCache.returnStatement(statement);
|
|
767
725
|
}
|
|
768
726
|
|
|
769
727
|
//---------------------------------------------------------------------------
|
|
@@ -873,14 +831,6 @@ class ThinConnectionImpl extends ConnectionImpl {
|
|
|
873
831
|
return resultSet;
|
|
874
832
|
}
|
|
875
833
|
|
|
876
|
-
//---------------------------------------------------------------------------
|
|
877
|
-
// Clears the statement cache for the connection
|
|
878
|
-
//---------------------------------------------------------------------------
|
|
879
|
-
resetStatementCache() {
|
|
880
|
-
this.statementCache.clear();
|
|
881
|
-
this._cursorsToClose.clear();
|
|
882
|
-
}
|
|
883
|
-
|
|
884
834
|
//---------------------------------------------------------------------------
|
|
885
835
|
// getDbObjectClass()
|
|
886
836
|
//
|
|
@@ -945,31 +895,8 @@ class ThinConnectionImpl extends ConnectionImpl {
|
|
|
945
895
|
// new session is going to be used.
|
|
946
896
|
//---------------------------------------------------------------------------
|
|
947
897
|
_getStatement(sql, cacheStatement = false) {
|
|
948
|
-
|
|
949
|
-
|
|
950
|
-
statement = new Statement();
|
|
951
|
-
statement._prepare(sql);
|
|
952
|
-
if (cacheStatement && !this._drcpEstablishSession && !statement.isDdl &&
|
|
953
|
-
this.statementCacheSize > 0) {
|
|
954
|
-
statement.returnToCache = true;
|
|
955
|
-
this.statementCache.set(sql, statement);
|
|
956
|
-
this._adjustStatementCache();
|
|
957
|
-
}
|
|
958
|
-
} else if (statement.inUse || !cacheStatement ||
|
|
959
|
-
this._drcpEstablishSession) {
|
|
960
|
-
if (!cacheStatement) {
|
|
961
|
-
this.statementCache.delete(sql);
|
|
962
|
-
statement.returnToCache = false;
|
|
963
|
-
}
|
|
964
|
-
if (statement.inUse || this._drcpEstablishSession) {
|
|
965
|
-
statement = statement._copy();
|
|
966
|
-
}
|
|
967
|
-
} else {
|
|
968
|
-
this.statementCache.delete(sql);
|
|
969
|
-
this.statementCache.set(sql, statement);
|
|
970
|
-
}
|
|
971
|
-
statement.inUse = true;
|
|
972
|
-
return statement;
|
|
898
|
+
return this.statementCache.getStatement(sql, cacheStatement,
|
|
899
|
+
this._drcpEstablishSession);
|
|
973
900
|
}
|
|
974
901
|
|
|
975
902
|
//---------------------------------------------------------------------------
|
|
@@ -1064,7 +991,7 @@ class ThinConnectionImpl extends ConnectionImpl {
|
|
|
1064
991
|
// the connection object
|
|
1065
992
|
//---------------------------------------------------------------------------
|
|
1066
993
|
getStmtCacheSize() {
|
|
1067
|
-
return this.
|
|
994
|
+
return this.statementCache._maxSize;
|
|
1068
995
|
}
|
|
1069
996
|
|
|
1070
997
|
setCallTimeout(timeout) {
|
|
@@ -1121,7 +1048,7 @@ class ThinConnectionImpl extends ConnectionImpl {
|
|
|
1121
1048
|
// Returns boolean based on this._protocol.txnInProgress value.
|
|
1122
1049
|
//---------------------------------------------------------------------------
|
|
1123
1050
|
getTransactionInProgress() {
|
|
1124
|
-
return this._protocol.txnInProgress
|
|
1051
|
+
return this._protocol.txnInProgress;
|
|
1125
1052
|
}
|
|
1126
1053
|
|
|
1127
1054
|
//---------------------------------------------------------------------------
|
package/lib/thin/dbObject.js
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
// Copyright (c) 2023, Oracle and/or its affiliates.
|
|
1
|
+
// Copyright (c) 2023, 2024, Oracle and/or its affiliates.
|
|
2
2
|
|
|
3
3
|
//-----------------------------------------------------------------------------
|
|
4
4
|
//
|
|
@@ -31,7 +31,7 @@ const constants = require('./protocol/constants.js');
|
|
|
31
31
|
const errors = require('../errors.js');
|
|
32
32
|
const types = require('../types.js');
|
|
33
33
|
const DbObjectImpl = require('../impl/dbObject.js');
|
|
34
|
-
const { GrowableBuffer } = require('
|
|
34
|
+
const { GrowableBuffer } = require('../impl/datahandlers/buffer.js');
|
|
35
35
|
const ThinLobImpl = require('./lob.js');
|
|
36
36
|
|
|
37
37
|
class DbObjectPickleBuffer extends GrowableBuffer {
|
|
@@ -280,9 +280,11 @@ class ThinDbObjectImpl extends DbObjectImpl {
|
|
|
280
280
|
buf.writeBytesWithLength(value);
|
|
281
281
|
break;
|
|
282
282
|
case types.DB_TYPE_BINARY_DOUBLE:
|
|
283
|
+
buf.writeUInt8(8);
|
|
283
284
|
buf.writeBinaryDouble(value);
|
|
284
285
|
break;
|
|
285
286
|
case types.DB_TYPE_BINARY_FLOAT:
|
|
287
|
+
buf.writeUInt8(4);
|
|
286
288
|
buf.writeBinaryFloat(value);
|
|
287
289
|
break;
|
|
288
290
|
case types.DB_TYPE_DATE:
|
package/lib/thin/lob.js
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
// Copyright (c) 2022,
|
|
1
|
+
// Copyright (c) 2022, 2024, Oracle and/or its affiliates.
|
|
2
2
|
|
|
3
3
|
//-----------------------------------------------------------------------------
|
|
4
4
|
//
|
|
@@ -89,11 +89,11 @@ class ThinLobImpl extends LobImpl {
|
|
|
89
89
|
return this.dbType;
|
|
90
90
|
}
|
|
91
91
|
|
|
92
|
-
async getData() {
|
|
93
|
-
if (
|
|
94
|
-
|
|
92
|
+
async getData(offset = 1, len = this._length) {
|
|
93
|
+
if (!len) {
|
|
94
|
+
len = this._length;
|
|
95
95
|
}
|
|
96
|
-
return await this.read(
|
|
96
|
+
return await this.read(offset, len);
|
|
97
97
|
}
|
|
98
98
|
|
|
99
99
|
async read(offset, length) {
|
|
@@ -157,7 +157,7 @@ class ThinLobImpl extends LobImpl {
|
|
|
157
157
|
|
|
158
158
|
checkConn() {
|
|
159
159
|
if (!this.conn.nscon.connected)
|
|
160
|
-
errors.throwErr(errors.
|
|
160
|
+
errors.throwErr(errors.ERR_INVALID_CONNECTION);
|
|
161
161
|
}
|
|
162
162
|
|
|
163
163
|
close() {
|