oracledb 6.5.1 → 6.6.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 (53) hide show
  1. package/README.md +2 -2
  2. package/build/Release/oracledb-6.6.0-darwin-arm64.node +0 -0
  3. package/build/Release/oracledb-6.6.0-darwin-arm64.node-buildinfo.txt +1 -0
  4. package/build/Release/oracledb-6.6.0-darwin-x64.node +0 -0
  5. package/build/Release/oracledb-6.6.0-darwin-x64.node-buildinfo.txt +1 -0
  6. package/build/Release/oracledb-6.6.0-js-buildinfo.txt +1 -0
  7. package/build/Release/oracledb-6.6.0-linux-arm64.node +0 -0
  8. package/build/Release/oracledb-6.6.0-linux-arm64.node-buildinfo.txt +1 -0
  9. package/build/Release/oracledb-6.6.0-linux-x64.node +0 -0
  10. package/build/Release/oracledb-6.6.0-linux-x64.node-buildinfo.txt +1 -0
  11. package/build/Release/oracledb-6.6.0-win32-x64.node +0 -0
  12. package/build/Release/oracledb-6.6.0-win32-x64.node-buildinfo.txt +1 -0
  13. package/examples/README.md +2 -0
  14. package/lib/configProviders/azure.js +167 -0
  15. package/lib/configProviders/base.js +99 -0
  16. package/lib/configProviders/ociobject.js +203 -0
  17. package/lib/connection.js +28 -12
  18. package/lib/constants.js +1 -0
  19. package/lib/errors.js +56 -1
  20. package/lib/impl/datahandlers/constants.js +3 -1
  21. package/lib/impl/datahandlers/vector.js +24 -9
  22. package/lib/impl/lob.js +27 -0
  23. package/lib/impl/resultset.js +26 -1
  24. package/lib/lob.js +52 -1
  25. package/lib/oracledb.js +54 -0
  26. package/lib/thin/connection.js +232 -16
  27. package/lib/thin/dbObject.js +4 -0
  28. package/lib/thin/lob.js +193 -1
  29. package/lib/thin/pool.js +15 -0
  30. package/lib/thin/protocol/capabilities.js +2 -0
  31. package/lib/thin/protocol/constants.js +29 -1
  32. package/lib/thin/protocol/messages/index.js +5 -1
  33. package/lib/thin/protocol/messages/lobOp.js +17 -5
  34. package/lib/thin/protocol/messages/transactionChangeState.js +99 -0
  35. package/lib/thin/protocol/messages/transactionSwitch.js +139 -0
  36. package/lib/thin/protocol/messages/withData.js +26 -6
  37. package/lib/thin/sqlnet/networkSession.js +2 -1
  38. package/lib/thin/sqlnet/paramParser.js +87 -50
  39. package/lib/thin/sqlnet/sessionAtts.js +13 -1
  40. package/lib/transformer.js +1 -2
  41. package/lib/types.js +1 -1
  42. package/lib/util.js +34 -2
  43. package/lib/version.js +2 -2
  44. package/package.json +1 -1
  45. package/build/Release/oracledb-6.5.1-darwin-x64.node +0 -0
  46. package/build/Release/oracledb-6.5.1-darwin-x64.node-buildinfo.txt +0 -1
  47. package/build/Release/oracledb-6.5.1-js-buildinfo.txt +0 -1
  48. package/build/Release/oracledb-6.5.1-linux-arm64.node +0 -0
  49. package/build/Release/oracledb-6.5.1-linux-arm64.node-buildinfo.txt +0 -1
  50. package/build/Release/oracledb-6.5.1-linux-x64.node +0 -0
  51. package/build/Release/oracledb-6.5.1-linux-x64.node-buildinfo.txt +0 -1
  52. package/build/Release/oracledb-6.5.1-win32-x64.node +0 -0
  53. package/build/Release/oracledb-6.5.1-win32-x64.node-buildinfo.txt +0 -1
@@ -492,12 +492,17 @@ module.exports = {
492
492
  TNS_LOB_OP_CLOSE: 0x10000,
493
493
  TNS_LOB_OP_IS_OPEN: 0x11000,
494
494
  TNS_LOB_OP_ARRAY: 0x80000,
495
+ TNS_LOB_OP_FILE_OPEN: 0x0100,
496
+ TNS_LOB_OP_FILE_CLOSE: 0x0200,
497
+ TNS_LOB_OP_FILE_ISOPEN: 0x0400,
498
+ TNS_LOB_OP_FILE_EXISTS: 0x0800,
495
499
 
496
500
  // LOB locator constants
497
501
  TNS_LOB_LOC_OFFSET_FLAG_1: 4,
498
502
  TNS_LOB_LOC_OFFSET_FLAG_3: 6,
499
503
  TNS_LOB_LOC_OFFSET_FLAG_4: 7,
500
504
  TNS_LOB_QLOCATOR_VERSION: 4,
505
+ TNS_LOB_LOC_FIXED_OFFSET: 16,
501
506
 
502
507
  // LOB locator flags (byte 1)
503
508
  TNS_LOB_LOC_FLAGS_BLOB: 0x01,
@@ -513,6 +518,7 @@ module.exports = {
513
518
 
514
519
  // other LOB constants
515
520
  TNS_LOB_OPEN_READ_WRITE: 2,
521
+ TNS_LOB_OPEN_READ_ONLY: 11,
516
522
  TNS_LOB_PREFETCH_FLAG: 0x2000000,
517
523
 
518
524
  // base JSON constants
@@ -548,6 +554,8 @@ module.exports = {
548
554
  TNS_FUNC_SESSION_RELEASE: 163,
549
555
  TNS_FUNC_SESSION_STATE: 176, // piggyback fn
550
556
  TNS_FUNC_CANCEL_ALL: 120, // piggyback fn
557
+ TNS_FUNC_TPC_TXN_SWITCH: 103,
558
+ TNS_FUNC_TPC_TXN_CHANGE_STATE: 104,
551
559
 
552
560
  // character sets and encodings
553
561
  TNS_CHARSET_UTF8: 873,
@@ -578,7 +586,8 @@ module.exports = {
578
586
  TNS_CCAP_TTC4: 40,
579
587
  TNS_CCAP_LOB2: 42,
580
588
  TNS_CCAP_TTC5: 44,
581
- TNS_CCAP_MAX: 51,
589
+ TNS_CCAP_VECTOR_FEATURES: 52,
590
+ TNS_CCAP_MAX: 53,
582
591
 
583
592
  // compile time capability values
584
593
  TNS_CCAP_SQL_VERSION_MAX: 6,
@@ -634,6 +643,7 @@ module.exports = {
634
643
  TNS_CCAP_LOB2_2GB_PREFETCH: 0x04,
635
644
  TNS_CCAP_CTB_IMPLICIT_POOL: 0x08,
636
645
  TNS_CCAP_VECTOR_SUPPORT: 0x08,
646
+ TNS_CCAP_VECTOR_FEATURE_BINARY: 0x01,
637
647
 
638
648
  // runtime capability indices
639
649
  TNS_RCAP_COMPAT: 0,
@@ -660,6 +670,24 @@ module.exports = {
660
670
  TNS_EOCS_FLAGS_TXN_IN_PROGRESS: 0x00000002,
661
671
  TNS_EOCS_FLAGS_SESS_RELEASE: 0x00008000,
662
672
 
673
+ // transaction switching op codes
674
+ TNS_TPC_TXN_START: 0x01,
675
+ TNS_TPC_TXN_DETACH: 0x02,
676
+
677
+ // transaction change state op codes
678
+ TNS_TPC_TXN_COMMIT: 0x01,
679
+ TNS_TPC_TXN_ABORT: 0x02,
680
+ TNS_TPC_TXN_PREPARE: 0x03,
681
+ TNS_TPC_TXN_FORGET: 0x04,
682
+
683
+ // transaction states
684
+ TNS_TPC_TXN_STATE_PREPARE: 0,
685
+ TNS_TPC_TXN_STATE_REQUIRES_COMMIT: 1,
686
+ TNS_TPC_TXN_STATE_COMMITTED: 2,
687
+ TNS_TPC_TXN_STATE_ABORTED: 3,
688
+ TNS_TPC_TXN_STATE_READ_ONLY: 4,
689
+ TNS_TPC_TXN_STATE_FORGOTTEN: 5,
690
+
663
691
  // other constants
664
692
  TNS_ESCAPE_CHAR: 253,
665
693
  TNS_LONG_LENGTH_INDICATOR: dataHandlerConstants.TNS_LONG_LENGTH_INDICATOR,
@@ -38,6 +38,8 @@ const ProtocolMessage = require('./protocol.js');
38
38
  const RollbackMessage = require('./rollback.js');
39
39
  const SessionReleaseMessage = require('./sessionRelease.js');
40
40
  const FastAuthMessage = require('./fastAuth.js');
41
+ const TransactionChangeStateMessage = require('./transactionChangeState.js');
42
+ const TransactionSwitchMessage = require('./transactionSwitch.js');
41
43
 
42
44
  module.exports = {
43
45
  AuthMessage,
@@ -51,5 +53,7 @@ module.exports = {
51
53
  PingMessage,
52
54
  ProtocolMessage,
53
55
  RollbackMessage,
54
- SessionReleaseMessage
56
+ SessionReleaseMessage,
57
+ TransactionChangeStateMessage,
58
+ TransactionSwitchMessage
55
59
  };
@@ -90,8 +90,13 @@ class LobOpMessage extends Message {
90
90
  buf.writeUInt8(0);
91
91
  }
92
92
  buf.writeUInt8(0);
93
- if (this.operation === constants.TNS_LOB_OP_CREATE_TEMP
94
- || this.operation === constants.TNS_LOB_OP_IS_OPEN) {
93
+ const operations = [
94
+ constants.TNS_LOB_OP_CREATE_TEMP,
95
+ constants.TNS_LOB_OP_IS_OPEN,
96
+ constants.TNS_LOB_OP_FILE_EXISTS,
97
+ constants.TNS_LOB_OP_FILE_ISOPEN,
98
+ ];
99
+ if (operations.includes(this.operation)) {
95
100
  buf.writeUInt8(1);
96
101
  } else {
97
102
  buf.writeUInt8(0);
@@ -152,7 +157,10 @@ class LobOpMessage extends Message {
152
157
  const oraTypeNum = this.sourceLobImpl.dbType._oraTypeNum;
153
158
  let data = buf.readBytesWithLength();
154
159
  if (data !== null) {
155
- if (oraTypeNum === constants.TNS_DATA_TYPE_BLOB) {
160
+ if (
161
+ oraTypeNum === constants.TNS_DATA_TYPE_BLOB ||
162
+ oraTypeNum === constants.TNS_DATA_TYPE_BFILE
163
+ ) {
156
164
  data = Buffer.from(data);
157
165
  } else if (this.sourceLobImpl.getCsfrm() === constants.CSFRM_NCHAR) {
158
166
  data = Buffer.from(data).swap16().toString('utf16le');
@@ -189,8 +197,12 @@ class LobOpMessage extends Message {
189
197
  } else if (this.sendAmount) {
190
198
  this.amount = buf.readSB8();
191
199
  }
192
- if (this.operation === constants.TNS_LOB_OP_IS_OPEN) {
193
- temp8 = buf.readUB1();
200
+ if (
201
+ this.operation === constants.TNS_LOB_OP_IS_OPEN
202
+ || this.operation === constants.TNS_LOB_OP_FILE_EXISTS
203
+ || this.operation === constants.TNS_LOB_OP_FILE_ISOPEN
204
+ ) {
205
+ temp8 = buf.readUInt8();
194
206
  this.boolFlag = temp8 > 0;
195
207
  }
196
208
  }
@@ -0,0 +1,99 @@
1
+ // Copyright (c) 2024, Oracle and/or its affiliates.
2
+
3
+ //-----------------------------------------------------------------------------
4
+ //
5
+ // This software is dual-licensed to you under the Universal Permissive License
6
+ // (UPL) 1.0 as shown at https://oss.oracle.com/licenses/upl and Apache License
7
+ // 2.0 as shown at http://www.apache.org/licenses/LICENSE-2.0. You may choose
8
+ // either license.
9
+ //
10
+ // If you elect to accept the software under the Apache License, Version 2.0,
11
+ // the following applies:
12
+ //
13
+ // Licensed under the Apache License, Version 2.0 (the "License");
14
+ // you may not use this file except in compliance with the License.
15
+ // You may obtain a copy of the License at
16
+ //
17
+ // https://www.apache.org/licenses/LICENSE-2.0
18
+ //
19
+ // Unless required by applicable law or agreed to in writing, software
20
+ // distributed under the License is distributed on an "AS IS" BASIS,
21
+ // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
22
+ // See the License for the specific language governing permissions and
23
+ // limitations under the License.
24
+ //
25
+ //-----------------------------------------------------------------------------
26
+
27
+ 'use strict';
28
+
29
+ const Message = require("./base.js");
30
+ const constants = require("../constants.js");
31
+
32
+ /**
33
+ * Used for two-phase commit (TPC) transaction change state: commit, rollback,
34
+ * forget, etc.
35
+ *
36
+ * @class TransactionChangeStateMessage
37
+ * @extends {Message}
38
+ */
39
+ class TransactionChangeStateMessage extends Message {
40
+
41
+ constructor(connImpl) {
42
+ super(connImpl);
43
+ this.functionCode = constants.TNS_FUNC_TPC_TXN_CHANGE_STATE;
44
+ }
45
+
46
+ processReturnParameter(buf) {
47
+ // process the parameters returned by the datatabase
48
+ this.state = buf.readUB4();
49
+ }
50
+
51
+ encode(buf) {
52
+ // writes the message to the database
53
+ // acquire data to send to the server
54
+ let xidBytes;
55
+ if (this.xid) {
56
+ xidBytes = Buffer.alloc(128);
57
+ this.xid.globalTransactionId.copy(xidBytes);
58
+ this.xid.branchQualifier.copy(xidBytes,
59
+ this.xid.globalTransactionId.length);
60
+ }
61
+
62
+ this.writeFunctionHeader(buf);
63
+ buf.writeUB4(this.operation);
64
+ if (this.context) {
65
+ buf.writeUInt8(1);
66
+ buf.writeUB4(this.context.length);
67
+ } else {
68
+ buf.writeUInt8(0);
69
+ buf.writeUB4(0);
70
+ }
71
+
72
+ if (this.xid) {
73
+ buf.writeUB4(this.xid.formatId);
74
+ buf.writeUB4(this.xid.globalTransactionId.length);
75
+ buf.writeUB4(this.xid.branchQualifier.length);
76
+ buf.writeUInt8(1);
77
+ buf.writeUB4(xidBytes.length);
78
+ } else {
79
+ buf.writeUB4(0);
80
+ buf.writeUB4(0);
81
+ buf.writeUB4(0);
82
+ buf.writeUInt8(0);
83
+ buf.writeUB4(0);
84
+ }
85
+ buf.writeUB4(0);
86
+ buf.writeUB4(this.state);
87
+ buf.writeUInt8(1);
88
+ buf.writeUB4(this.flags);
89
+
90
+ if (this.context) {
91
+ buf.writeBytes(this.context);
92
+ }
93
+ if (this.xid) {
94
+ buf.writeBytes(xidBytes);
95
+ }
96
+ }
97
+ }
98
+
99
+ module.exports = TransactionChangeStateMessage;
@@ -0,0 +1,139 @@
1
+ // Copyright (c) 2024, Oracle and/or its affiliates.
2
+
3
+ //-----------------------------------------------------------------------------
4
+ //
5
+ // This software is dual-licensed to you under the Universal Permissive License
6
+ // (UPL) 1.0 as shown at https://oss.oracle.com/licenses/upl and Apache License
7
+ // 2.0 as shown at http://www.apache.org/licenses/LICENSE-2.0. You may choose
8
+ // either license.
9
+ //
10
+ // If you elect to accept the software under the Apache License, Version 2.0,
11
+ // the following applies:
12
+ //
13
+ // Licensed under the Apache License, Version 2.0 (the "License");
14
+ // you may not use this file except in compliance with the License.
15
+ // You may obtain a copy of the License at
16
+ //
17
+ // https://www.apache.org/licenses/LICENSE-2.0
18
+ //
19
+ // Unless required by applicable law or agreed to in writing, software
20
+ // distributed under the License is distributed on an "AS IS" BASIS,
21
+ // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
22
+ // See the License for the specific language governing permissions and
23
+ // limitations under the License.
24
+ //
25
+ //-----------------------------------------------------------------------------
26
+
27
+ 'use strict';
28
+
29
+ const Message = require("./base.js");
30
+ const constants = require("../constants.js");
31
+
32
+ /**
33
+ * Used for two-phase commit (TPC) transaction start, attach and detach.
34
+ *
35
+ * @class TransactionSwitchMessage
36
+ * @extends {Message}
37
+ */
38
+ class TransactionSwitchMessage extends Message {
39
+
40
+ constructor(connImpl) {
41
+ super(connImpl);
42
+ this.functionCode = constants.TNS_FUNC_TPC_TXN_SWITCH;
43
+ this.applicationValue = 0;
44
+ this.internalName = connImpl.internalName;
45
+ if (this.internalName) {
46
+ this.internalName = Buffer.from(this.internalName);
47
+ }
48
+ this.externalName = connImpl.externalName;
49
+ if (this.externalName) {
50
+ this.externalName = Buffer.from(this.externalName);
51
+ }
52
+ }
53
+
54
+ processReturnParameter(buf) {
55
+ // process the parameters returned by the datatabase
56
+ this.applicationValue = buf.readUB4();
57
+ this.contextLen = buf.readUB2();
58
+ if (this.contextLen > 0) {
59
+ this.context = Buffer.from(buf.readBytes(this.contextLen));
60
+ }
61
+ }
62
+
63
+ encode(buf) {
64
+ // writes the message to the database
65
+ // acquire data to send to the server
66
+ let xidBytes;
67
+ if (this.xid) {
68
+ xidBytes = Buffer.alloc(128);
69
+ this.xid.globalTransactionId.copy(xidBytes);
70
+ this.xid.branchQualifier.copy(xidBytes,
71
+ this.xid.globalTransactionId.length);
72
+ }
73
+
74
+ // write message
75
+ this.writeFunctionHeader(buf);
76
+ buf.writeUB4(this.operation);
77
+ if (this.context) {
78
+ buf.writeUInt8(1); // pointer (transaction context)
79
+ buf.writeUB4(this.context.length);
80
+ } else {
81
+ buf.writeUInt8(0); // pointer (transaction context)
82
+ buf.writeUB4(0); // transaction context length
83
+ }
84
+
85
+ if (this.xid) {
86
+ buf.writeUB4(this.xid.formatId);
87
+ buf.writeUB4(this.xid.globalTransactionId.length);
88
+ buf.writeUB4(this.xid.branchQualifier.length);
89
+ buf.writeUInt8(1); // pointer (XID)
90
+ buf.writeUB4(xidBytes.length);
91
+ } else {
92
+ buf.writeUB4(0); // format id
93
+ buf.writeUB4(0); // global transaction id length
94
+ buf.writeUB4(0); // branch qualifier length
95
+ buf.writeUInt8(0); // pointer (XID)
96
+ buf.writeUB4(0); // XID length
97
+ }
98
+
99
+ buf.writeUB4(this.flags);
100
+ buf.writeUB4(this.timeout);
101
+ buf.writeUInt8(1); // pointer (application value)
102
+ buf.writeUInt8(1); // pointer (return context)
103
+ buf.writeUInt8(1); // pointer (return context length)
104
+
105
+ if (this.internalName) {
106
+ buf.writeUInt8(1); // pointer (internal name)
107
+ buf.writeUB4(this.internalName.length);
108
+ } else {
109
+ buf.writeUInt8(0); // pointer (internal name)
110
+ buf.writeUB4(0); // length of internal name
111
+ }
112
+
113
+ if (this.externalName) {
114
+ buf.writeUInt8(1); // pointer (external name)
115
+ buf.writeUB4(this.externalName.length);
116
+ } else {
117
+ buf.writeUInt8(0); // pointer (external name)
118
+ buf.writeUB4(0); // length of external name
119
+ }
120
+
121
+ if (this.context) {
122
+ buf.writeBytes(this.context);
123
+ }
124
+ if (this.xid) {
125
+ buf.writeBytes(xidBytes);
126
+ }
127
+ buf.writeUB4(this.applicationValue);
128
+
129
+ if (this.internalName) {
130
+ buf.writeBytes(this.internalName);
131
+ }
132
+
133
+ if (this.externalName) {
134
+ buf.writeBytes(this.externalName);
135
+ }
136
+ }
137
+ }
138
+
139
+ module.exports = TransactionSwitchMessage;
@@ -140,7 +140,11 @@ class MessageWithData extends Message {
140
140
  if ((cVar.fetchInfo.dbType._oraTypeNum === constants.TNS_DATA_TYPE_CLOB
141
141
  && pVar.fetchInfo.fetchType._oraTypeNum === constants.TNS_DATA_TYPE_LONG)
142
142
  || (cVar.fetchInfo.dbType._oraTypeNum === constants.TNS_DATA_TYPE_BLOB
143
- && pVar.fetchInfo.fetchType._oraTypeNum === constants.TNS_DATA_TYPE_LONG_RAW)) {
143
+ && pVar.fetchInfo.fetchType._oraTypeNum === constants.TNS_DATA_TYPE_LONG_RAW)
144
+ || (cVar.fetchInfo.dbType._oraTypeNum === constants.TNS_DATA_TYPE_JSON
145
+ && pVar.fetchInfo.fetchType._oraTypeNum === constants.TNS_DATA_TYPE_VARCHAR)
146
+ || (cVar.fetchInfo.dbType._oraTypeNum === constants.TNS_DATA_TYPE_VECTOR
147
+ && pVar.fetchInfo.fetchType._oraTypeNum === constants.TNS_DATA_TYPE_LONG)) {
144
148
  cVar.type = pVar.fetchInfo.fetchType;
145
149
  cVar.maxSize = pVar.maxSize;
146
150
  }
@@ -498,12 +502,22 @@ class MessageWithData extends Message {
498
502
  }
499
503
  } else if (oraTypeNum === constants.TNS_DATA_TYPE_BOOLEAN) {
500
504
  colValue = buf.readBool();
501
- } else if (oraTypeNum === constants.TNS_DATA_TYPE_CLOB || oraTypeNum === constants.TNS_DATA_TYPE_BLOB) {
505
+ } else if (
506
+ oraTypeNum === constants.TNS_DATA_TYPE_CLOB ||
507
+ oraTypeNum === constants.TNS_DATA_TYPE_BLOB ||
508
+ oraTypeNum === constants.TNS_DATA_TYPE_BFILE
509
+ ) {
510
+ let length = 0;
511
+ let chunkSize = 0;
502
512
  const bvalue = buf.readUB4();
503
513
  if (bvalue > 0) { // Non Null data in column
504
514
  colValue = new ThinLobImpl();
505
- const length = buf.readUB8();
506
- const chunkSize = buf.readUB4();
515
+ if (oraTypeNum === constants.TNS_DATA_TYPE_BFILE) {
516
+ buf.skipUB4();
517
+ } else {
518
+ length = buf.readUB8();
519
+ chunkSize = buf.readUB4();
520
+ }
507
521
  const locator = Buffer.from(buf.readBytesWithLength());
508
522
  colValue.init(this.connection, locator, dbType, length, chunkSize);
509
523
  }
@@ -619,6 +633,7 @@ class MessageWithData extends Message {
619
633
  if (variable.type === types.DB_TYPE_CLOB ||
620
634
  variable.type === types.DB_TYPE_NCLOB ||
621
635
  variable.type === types.DB_TYPE_BLOB ||
636
+ variable.type === types.DB_TYPE_BFILE ||
622
637
  variable.type === types.DB_TYPE_JSON ||
623
638
  variable.type === types.DB_TYPE_VECTOR) {
624
639
  if (variable.type !== variable.fetchInfo.fetchType) {
@@ -700,7 +715,8 @@ class MessageWithData extends Message {
700
715
  let contFlag = 0;
701
716
  if (variable.type === types.DB_TYPE_BLOB ||
702
717
  variable.type === types.DB_TYPE_CLOB ||
703
- variable.type === types.DB_TYPE_NCLOB) {
718
+ variable.type === types.DB_TYPE_NCLOB ||
719
+ variable.type === types.DB_TYPE_BFILE) {
704
720
  contFlag = constants.TNS_LOB_PREFETCH_FLAG;
705
721
  } else if (variable.type === types.DB_TYPE_JSON) {
706
722
  contFlag = constants.TNS_LOB_PREFETCH_FLAG;
@@ -852,7 +868,11 @@ class MessageWithData extends Message {
852
868
  } else {
853
869
  buf.writeUInt16BE(0x0100);
854
870
  }
855
- } else if (oraTypeNum === constants.TNS_DATA_TYPE_CLOB || oraTypeNum === constants.TNS_DATA_TYPE_BLOB) {
871
+ } else if (
872
+ oraTypeNum === constants.TNS_DATA_TYPE_CLOB ||
873
+ oraTypeNum === constants.TNS_DATA_TYPE_BLOB ||
874
+ oraTypeNum === constants.TNS_DATA_TYPE_BFILE
875
+ ) {
856
876
  buf.writeUB4(value._locator.length);
857
877
  buf.writeBytesWithLength(value._locator);
858
878
  } else if ([constants.TNS_DATA_TYPE_ROWID, constants.TNS_DATA_TYPE_UROWID].includes(oraTypeNum)) {
@@ -301,7 +301,7 @@ class NetworkSession {
301
301
  this.markerPkt = new Packet.MarkerPacket(this.sAtts.largeSDU);
302
302
  this.controlPkt = new Packet.ControlPacket();
303
303
  this.ntAdapter.largeSDU = this.sAtts.largeSDU;
304
- this.sAtts.nt.wallet = null;
304
+ this.sAtts.clearWallet();
305
305
  this.sAtts.nt.walletPassword = null;
306
306
  return (true);
307
307
  }
@@ -328,6 +328,7 @@ class NetworkSession {
328
328
  this.ntAdapter.disconnect(constants.NSFIMM);
329
329
  this.ntAdapter = null;
330
330
  }
331
+ this.sAtts.clearWallet();
331
332
  connected = false;
332
333
  savedErr = err;
333
334
  try {
@@ -32,6 +32,7 @@ const process = require('process');
32
32
  const readline = require('readline');
33
33
  const errors = require("../../errors.js");
34
34
 
35
+ const MAX_IFILE_DEPTH = 4;
35
36
  /**
36
37
  * Returns File path of the tnsnames.ora if it exists.
37
38
  */
@@ -59,9 +60,12 @@ function tnsnamesFilePath(configDir) {
59
60
  }
60
61
  }
61
62
 
62
- let prevmtime = 0;
63
-
64
63
  class NLParamParser {
64
+
65
+ constructor() {
66
+ this.waiters = [];
67
+ this.readInProgress = false;
68
+ }
65
69
  /**
66
70
  * Reads the given file line by line and stores the
67
71
  * network service names mapped to connect descriptors in the hashtable.
@@ -69,13 +73,29 @@ class NLParamParser {
69
73
  * @returns {Promise}
70
74
  */
71
75
  async initializeNlpa(file_path) {
72
- const stat = fs.statSync(file_path);
73
-
74
- if (!(stat.mtime - prevmtime)) {
75
- /* File has been read */
76
+ if (this.readInProgress) {
77
+ await new Promise((resolve) => {
78
+ this.waiters.push(resolve);
79
+ });
80
+ }
81
+ if (!this.checkModfTime()) {
82
+ /* No File has been modified */
76
83
  return this.ht;
77
84
  }
85
+ this.ht = new Map();
86
+ this.modTime = new Map(); //stores modified time of each IFile
87
+ this.readInProgress = true;
88
+ await this.start(file_path, 0); //start with 0 depth (tnsnames.ora)
89
+ return this.ht;
90
+ }
91
+
92
+ async start(file_path, depth) {
78
93
 
94
+ if (depth > MAX_IFILE_DEPTH)
95
+ return; //ignore after max depth
96
+ const stat = fs.statSync(file_path);
97
+ // store file path and its modified time.
98
+ this.modTime.set(file_path, stat.mtime);
79
99
  // Creating a readable stream from file
80
100
  // readline module reads line by line
81
101
  // but from a readable stream only.
@@ -84,52 +104,49 @@ class NLParamParser {
84
104
  output: process.stdout,
85
105
  terminal: false
86
106
  });
87
- this.ht = new Map();
88
-
89
- const start = async () =>{
90
- let nvElem = "";
91
- for await (let line of file) {
92
- if (line.length == 0) { // ignore empty lines
93
- continue;
94
- } else if (line[0] == '#') { // comment line
107
+ let nvElem = "";
108
+ for await (let line of file) {
109
+ if (line.length == 0) { // ignore empty lines
110
+ continue;
111
+ } else if (line[0] == '#') { // comment line
112
+ continue;
113
+ } else if ((line[0] == ' ') || // continued input on new line
114
+ (line[0] == '\t') ||
115
+ (line[0] == ')') ||
116
+ (line[0] == '(')) {
117
+ line = line.replace(/\s+/g, '');
118
+ line = this.checkNLPforComments(line);
119
+ if (line.length == 0)
95
120
  continue;
96
- } else if ((line[0] == ' ') || // continued input on new line
97
- (line[0] == '\t') ||
98
- (line[0] == ')') ||
99
- (line[0] == '(')) {
100
- line = line.replace(/\s+/g, '');
101
- line = this.checkNLPforComments(line);
102
- if (line.length == 0)
103
- continue;
104
- else {
105
- nvElem = nvElem + line;
106
- }
121
+ else {
122
+ nvElem = nvElem + line;
123
+ }
107
124
 
108
- } else { // new NV Element starting here
109
- if (nvElem.length == 0) {
125
+ } else { // new NV Element starting here
126
+ if (nvElem.length == 0) {
110
127
 
111
- line = this.checkNLPforComments(line);
112
- nvElem = nvElem + line;
128
+ line = this.checkNLPforComments(line);
129
+ nvElem = nvElem + line;
113
130
 
114
- } else if (nvElem.length != 0) {
115
- this.addNLPListElement(nvElem); // Add Parameter to Hashtable
116
- nvElem = ""; // Clear first, before storing current line
131
+ } else if (nvElem.length != 0) {
132
+ await this.addNLPListElement(nvElem, depth); // Add Parameter to Hashtable
133
+ nvElem = ""; // Clear first, before storing current line
117
134
 
118
- line = this.checkNLPforComments(line);
119
- nvElem = nvElem + line;
120
- }
135
+ line = this.checkNLPforComments(line);
136
+ nvElem = nvElem + line;
121
137
  }
122
138
  }
123
- if (nvElem.length != 0) { // at eof, still one more parameter to read
124
- this.addNLPListElement(nvElem);
125
- nvElem = ""; // clear nvElem buffer after added
126
- }
127
- prevmtime = stat.mtime;
128
- return this.ht;
129
- };
130
- return await start();
139
+ }
140
+ if (nvElem.length != 0) { // at eof, still one more parameter to read
141
+ await this.addNLPListElement(nvElem, depth);
142
+ nvElem = ""; // clear nvElem buffer after added
143
+ }
144
+ this.readInProgress = false;
145
+ let waiter;
146
+ while ((waiter = this.waiters.pop())) {
147
+ waiter();
148
+ }
131
149
  }
132
-
133
150
  /**
134
151
  * Given a string, this method looks if the '#' character is present.
135
152
  * If true, the line is truncated from that point onwards until the end
@@ -155,11 +172,28 @@ class NLParamParser {
155
172
  }
156
173
  return str1.join('');
157
174
  }
175
+ // check if any of the IFiles has been changed
176
+ checkModfTime() {
177
+ if (this.modTime) {
178
+ for (const [key, value] of this.modTime) {
179
+ if (fs.existsSync(key)) {
180
+ const stat = fs.statSync(key);
181
+ if ((stat.mtime - value > 0)) {
182
+ return true;
183
+ }
184
+ } else
185
+ return true;
186
+ }
187
+ } else {
188
+ return true;
189
+ }
190
+ return false;
191
+ }
158
192
  /**
159
193
  * adds name value pairs from the input buffer into the hash table.
160
194
  * @param {string} ibuf
161
195
  */
162
- addNLPListElement(ibuf) {
196
+ async addNLPListElement(ibuf, depth) {
163
197
  const res = ibuf.split(/\r?\n/).filter(element => element);
164
198
  for (let i = 0; i < res.length; i++) {
165
199
  if (res[i].charAt(0) != '(') {
@@ -169,14 +203,17 @@ class NLParamParser {
169
203
  const name = nvp.name;
170
204
  const uname = name.toUpperCase();
171
205
  nvp.name = uname;
172
- const unames = uname.split(","); //multiple aliases (alias1, alias2, alias3)
173
- for (let i = 0; i < unames.length; i++) {
174
- this.ht.set(unames[i], nvp);
206
+ // support for ifile
207
+ if (uname == 'IFILE') {
208
+ await this.start(nvp.atom, depth + 1);
209
+ } else {
210
+ const unames = uname.split(","); //multiple aliases (alias1, alias2, alias3)
211
+ for (let i = 0; i < unames.length; i++) {
212
+ this.ht.set(unames[i], nvp);
213
+ }
175
214
  }
176
215
  }
177
216
  }
178
-
179
-
180
217
  toString() {
181
218
  let out = "";
182
219
  this.ht.forEach((value) => {