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.
Files changed (71) hide show
  1. package/LICENSE.txt +1 -1
  2. package/NOTICE.txt +1 -1
  3. package/README.md +3 -3
  4. package/build/Release/oracledb-6.5.0-darwin-x64.node +0 -0
  5. package/build/Release/oracledb-6.5.0-darwin-x64.node-buildinfo.txt +1 -0
  6. package/build/Release/oracledb-6.5.0-js-buildinfo.txt +1 -0
  7. package/build/Release/oracledb-6.5.0-linux-arm64.node +0 -0
  8. package/build/Release/oracledb-6.5.0-linux-arm64.node-buildinfo.txt +1 -0
  9. package/build/Release/oracledb-6.5.0-linux-x64.node +0 -0
  10. package/build/Release/oracledb-6.5.0-linux-x64.node-buildinfo.txt +1 -0
  11. package/build/Release/oracledb-6.5.0-win32-x64.node +0 -0
  12. package/build/Release/oracledb-6.5.0-win32-x64.node-buildinfo.txt +1 -0
  13. package/examples/README.md +3 -0
  14. package/lib/aqQueue.js +8 -8
  15. package/lib/connection.js +65 -22
  16. package/lib/constants.js +7 -1
  17. package/lib/dbObject.js +72 -1
  18. package/lib/errors.js +51 -10
  19. package/lib/impl/connection.js +2 -1
  20. package/lib/{thin/protocol → impl/datahandlers}/buffer.js +36 -32
  21. package/lib/impl/datahandlers/constants.js +106 -0
  22. package/lib/{thin/protocol → impl/datahandlers}/oson.js +320 -151
  23. package/lib/impl/datahandlers/vector.js +137 -0
  24. package/lib/impl/pool.js +9 -0
  25. package/lib/impl/resultset.js +34 -17
  26. package/lib/lob.js +22 -6
  27. package/lib/oracledb.js +35 -1
  28. package/lib/pool.js +17 -2
  29. package/lib/poolStatistics.js +3 -1
  30. package/lib/settings.js +31 -6
  31. package/lib/sodaDocCursor.js +14 -1
  32. package/lib/thin/connection.js +120 -193
  33. package/lib/thin/dbObject.js +4 -2
  34. package/lib/thin/lob.js +6 -6
  35. package/lib/thin/pool.js +84 -10
  36. package/lib/thin/protocol/capabilities.js +20 -6
  37. package/lib/thin/protocol/constants.js +34 -54
  38. package/lib/thin/protocol/messages/auth.js +2 -2
  39. package/lib/thin/protocol/messages/base.js +28 -27
  40. package/lib/thin/protocol/messages/dataType.js +4 -2
  41. package/lib/thin/protocol/messages/execute.js +5 -1
  42. package/lib/thin/protocol/messages/{connectionCookie.js → fastAuth.js} +18 -16
  43. package/lib/thin/protocol/messages/fetch.js +4 -0
  44. package/lib/thin/protocol/messages/index.js +2 -2
  45. package/lib/thin/protocol/messages/protocol.js +9 -1
  46. package/lib/thin/protocol/messages/withData.js +40 -11
  47. package/lib/thin/protocol/packet.js +93 -8
  48. package/lib/thin/protocol/protocol.js +10 -5
  49. package/lib/thin/protocol/utils.js +11 -18
  50. package/lib/thin/sqlnet/constants.js +5 -2
  51. package/lib/thin/sqlnet/ezConnectResolver.js +9 -5
  52. package/lib/thin/sqlnet/navNodes.js +4 -3
  53. package/lib/thin/sqlnet/networkSession.js +27 -4
  54. package/lib/thin/sqlnet/packet.js +2 -5
  55. package/lib/thin/statement.js +43 -7
  56. package/lib/thin/statementCache.js +190 -0
  57. package/lib/thin/util.js +2 -2
  58. package/lib/transformer.js +21 -6
  59. package/lib/types.js +21 -3
  60. package/lib/util.js +30 -1
  61. package/lib/version.js +2 -2
  62. package/package.json +1 -1
  63. package/build/Release/oracledb-6.3.0-darwin-x64.node +0 -0
  64. package/build/Release/oracledb-6.3.0-darwin-x64.node-buildinfo.txt +0 -1
  65. package/build/Release/oracledb-6.3.0-js-buildinfo.txt +0 -1
  66. package/build/Release/oracledb-6.3.0-linux-arm64.node +0 -0
  67. package/build/Release/oracledb-6.3.0-linux-arm64.node-buildinfo.txt +0 -1
  68. package/build/Release/oracledb-6.3.0-linux-x64.node +0 -0
  69. package/build/Release/oracledb-6.3.0-linux-x64.node-buildinfo.txt +0 -1
  70. package/build/Release/oracledb-6.3.0-win32-x64.node +0 -0
  71. package/build/Release/oracledb-6.3.0-win32-x64.node-buildinfo.txt +0 -1
@@ -1,4 +1,4 @@
1
- // Copyright (c) 2022, 2023, Oracle and/or its affiliates.
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('./protocol/buffer.js');
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
- // _determineElementObjType()
94
+ // _getElementTypeObj()
98
95
  //
99
- // Determine the element type's object type. This is needed when processing
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 _determineElementObjType(info) {
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
- if (statement.isPlSql && statement.requiresFullExecute) {
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
- // _parseElementType()
263
+ // _parseTDSAttr()
259
264
  //
260
- // Parses the element type from the TDS buffer.
265
+ // Returns the DB type and fills metadata from the TDS buffer.
261
266
  //---------------------------------------------------------------------------
262
- async _parseElementType(buf, info) {
263
- let oraTypeNum, csfrm;
264
- const attrType = buf.readUInt8();
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
- info.elementType = types.DB_TYPE_NUMBER;
269
- break;
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
- info.maxSize = buf.readUInt16BE();
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
- info.elementType = types.getTypeByOraTypeNum(oraTypeNum, csfrm);
277
- break;
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
- info.elementType = types.DB_TYPE_RAW;
280
- break;
299
+ metaData.maxSize = buf.readUInt16BE(); // maximum length
300
+ return types.DB_TYPE_RAW;
281
301
  case constants.TNS_OBJ_TDS_TYPE_BINARY_FLOAT:
282
- info.elementType = types.DB_TYPE_BINARY_FLOAT;
283
- break;
302
+ return types.DB_TYPE_BINARY_FLOAT;
284
303
  case constants.TNS_OBJ_TDS_TYPE_BINARY_DOUBLE:
285
- info.elementType = types.DB_TYPE_BINARY_DOUBLE;
286
- break;
304
+ return types.DB_TYPE_BINARY_DOUBLE;
287
305
  case constants.TNS_OBJ_TDS_TYPE_DATE:
288
- info.elementType = types.DB_TYPE_DATE;
289
- break;
306
+ return types.DB_TYPE_DATE;
290
307
  case constants.TNS_OBJ_TDS_TYPE_TIMESTAMP:
291
- info.elementType = types.DB_TYPE_TIMESTAMP;
292
- break;
308
+ buf.skipBytes(1); // precision
309
+ return types.DB_TYPE_TIMESTAMP;
293
310
  case constants.TNS_OBJ_TDS_TYPE_TIMESTAMP_LTZ:
294
- info.elementType = types.DB_TYPE_TIMESTAMP_LTZ;
295
- break;
311
+ buf.skipBytes(1); // precision
312
+ return types.DB_TYPE_TIMESTAMP_LTZ;
296
313
  case constants.TNS_OBJ_TDS_TYPE_TIMESTAMP_TZ:
297
- info.elementType = types.DB_TYPE_TIMESTAMP_TZ;
298
- break;
314
+ buf.skipBytes(1); // precision
315
+ return types.DB_TYPE_TIMESTAMP_TZ;
299
316
  case constants.TNS_OBJ_TDS_TYPE_BOOLEAN:
300
- info.elementType = types.DB_TYPE_BOOLEAN;
301
- break;
317
+ return types.DB_TYPE_BOOLEAN;
302
318
  case constants.TNS_OBJ_TDS_TYPE_CLOB:
303
- this._determineElementTypeCharsetForm(info);
304
- break;
319
+ return types.DB_TYPE_CLOB;
305
320
  case constants.TNS_OBJ_TDS_TYPE_BLOB:
306
- info.elementType = types.DB_TYPE_BLOB;
307
- break;
321
+ return types.DB_TYPE_BLOB;
308
322
  case constants.TNS_OBJ_TDS_TYPE_OBJ:
309
- info.elementType = types.DB_TYPE_OBJECT;
310
- await this._determineElementObjType(info);
311
- break;
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 for the type. This is only needed for collection types, so
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
- // if type of first attribute is not a collection, nothing further needs
347
- // to be done
348
- const attrType = buf.readUInt8();
349
- info.isCollection = (attrType === constants.TNS_OBJ_TDS_TYPE_COLL);
350
- if (!info.isCollection)
351
- return;
352
-
353
- // continue parsing TDS to determine element type
354
- const elementPos = buf.readUInt32BE();
355
- info.maxNumElements = buf.readUInt32BE();
356
- info.collectionType = buf.readUInt8();
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
- await this._parseElementType(buf, info);
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
- let sentCookie = false;
676
- if (cookie && cookie.populated) {
677
- const cookieMessage = new messages.ConnectionCookieMessage(this);
678
- cookieMessage.cookie = cookie;
679
- cookieMessage.protocolMessage = protocolMessage;
680
- cookieMessage.dataTypeMessage = dataTypeMessage;
681
- cookieMessage.authMessage = authMessage;
682
- await this._protocol._processMessage(cookieMessage);
683
- sentCookie = true;
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
- // Sets that a statement is no longer in use
721
+ // Return the statement to the statement cache, if applicable
723
722
  //---------------------------------------------------------------------------
724
723
  _returnStatement(statement) {
725
- if (statement.bindInfoList) {
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
- let statement = this.statementCache.get(sql);
949
- if (!statement) {
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.statementCacheSize;
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 === constants.TNS_TXN_IN_PROGRESS;
1051
+ return this._protocol.txnInProgress;
1125
1052
  }
1126
1053
 
1127
1054
  //---------------------------------------------------------------------------
@@ -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('./protocol/buffer.js');
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, 2023, Oracle and/or its affiliates.
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 (this._length < 0) {
94
- errors.throwErr(errors.ERR_INVALID_LOB);
92
+ async getData(offset = 1, len = this._length) {
93
+ if (!len) {
94
+ len = this._length;
95
95
  }
96
- return await this.read(1, this._length);
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.ERR_LOB_CLOSED);
160
+ errors.throwErr(errors.ERR_INVALID_CONNECTION);
161
161
  }
162
162
 
163
163
  close() {